《高级DSP软件技术》PPT课件.ppt_第1页
《高级DSP软件技术》PPT课件.ppt_第2页
《高级DSP软件技术》PPT课件.ppt_第3页
《高级DSP软件技术》PPT课件.ppt_第4页
《高级DSP软件技术》PPT课件.ppt_第5页
已阅读5页,还剩85页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第二课 入门实例,课件地址,网址: 用户名: 密码:100081,简单回顾,Part1,上次课的内容1,课程的简单介绍 又是一门DSP的课 以TigerSHARC DSP及相关硬件平台为实例 需要若干本科课程作为预备知识 信号处理及DSP技术概述 以一个最最简单的例子(音频滤波)的3种解决方法(模拟、硬件、软件),引出工程实践中对DSP处理器的需求:嵌入式、简单、快速 DSP的传统技术特点(MAC、哈佛、可预测、集成) DSP的发展现状、面临的问题、解决的措施,上次课的内容2,DSP软件开发的概述 特点:交叉编译、特殊语言扩展、资源有限、注重代码效率(实时性)、与硬件关联 三种编程方式:汇编、C/C+、RTOS 为什么提倡使用C?,今天的内容,Part2,一个单处理器编程实例,针对一个单处理器系统,演示软件的最简单开发过程 关心的重点: 典型系统结构 自顶向下的设计流程 基本操作手段的感性认识,整个开发过程纵览,编写一个信号处理系统的软件,主要过程与一般的软件开发类似: 了解系统 由于牵涉硬件,又是专用系统,所以这部分作为独立于需求分析的步骤单独提出 需求分析 和一般软件开发类似 对速度和容量的需求需要说的比较明确 详细设计 和一般软件开发类似 有时不得不深入硬件,看芯片手册、与硬件人员反复交流 建立框架 和一般软件开发类似 一般是结构化的框架,而不是面向对象的 编码 和一般软件开发类似 为了优化,有时不得不写一些汇编代码 在写底层部分时,芯片手册要常备参考 细化和优化 优化上所作的工作会比较多,包括手工和自动,硬件和系统概述,Part3,应用环境,如下图,一个典型“自动运行”的系统 传感器得到外界信号 信号处理机进行处理,得到所需信息 动作器根据处理结果进行相应 例如,导弹的导引头: 传感器 雷达、红外 处理机 处理得到目标相对飞行方向的偏移角度 动作器 飞控系统的舵机,处理机干什么?,一个单处理器系统 A/D采集输入的视频(泛意的)信号 DSP做处理 处理结果D/A转换为模拟量输出 在这里: A/D采集的是某个雷达前端的回波信号 DSP对回波信号做处理,找到目标,并给出目标的角度信息 把角度偏移量用模拟电压的形式从D/A输出 回想上堂课中“3种典型方法”的讨论,然后了解硬件,硬件系统的三大部分: 输入 按照一定的时序关系采集输入的模拟信号,转换成数字量,并缓存 处理 一片DSP及其相关外围,完成处理算法 输出 将处理结果的数字量转换成模拟量,硬件系统框图,从芯片的角度看,按照数据的流向排列: 输入的运算放大器 对模拟信号进行缓冲放大 A/D 转换模拟电压为数字量 双口RAM 保存采集到的数字量,左口进右口出 CPLD 控制整个输入模块的时序: 一次采集多少数据?存到双口RAM的什么位置?怎样通知DSP? DSP 不说啦 FlashROM 存储DSP的程序,上电复位时加载到DSP中运行 D/A 转换DSP给出的数字量到模拟电压 输出的放大器 驱动,数据流关系,从DSP看系统,软件的运行环境,或者说设计约束 外总线上的3个设备 双口RAM 起始地址、结束地址 数据格式(几bit?编码方式?) 时序选项 D/A芯片 D/A芯片内部数据寄存器的地址 数据格式(电压1.0V=数字量多少?) 时序选项 FlashROM 用于存储程序,运行时不使用 来自CPLD的“双口RAM内一帧数据就绪”信号 是个中断信号,软件上可以作为中断使用,也可以查询,软件需求分析,功能 读取A/D数据,做xx处理,从D/A输出 处理算法,不讨论 接口 双口RAM、D/A芯片、中断 速度和容量 速度: 每帧数据的处理延迟小于一帧数据的采集时间 其他特殊要求(例如出于整个闭环控制系统传递函数的需要,对处理延迟有特殊要求) 容量: 代码容量+数据存储容量 DSP内存,工具,通用工具 VisualDSP+集成环境 源码编辑 工程管理 编译器 软件仿真器 硬件仿真器界面 硬件仿真器(Emulator) JTAG接口 JTAG:IEEE 1149.1标准,最广泛的电子产品测试和调试手段,其基本思想是用一个串行的菊花链结构来访问所有想看想改资源,具体不用再说了 其他工具 一个好用的文本编辑器(UltraEdit、SourceInsight) 二进制文件编辑器( UltraEdit、 WinHex) Matlab,做算法仿真或者数据处理 计算机编程工具,编一些辅助小程序(VC、BCB),Emulator实物,操作步骤和演示,Part4,新建一个工程,启动VisualDSP 菜单Project/New,设置工程选项,需作修改: 处理器类型 选择自己用的那个型号 高级语言的好处开始体现 输出文件类型 DSP loader file 编译形式 Debug Release 主要牵涉到是否优化,先用Debug,关于文件类型,VisualDSP可以选择下列输出文件类型: DSP executable file 可执行文件(*.dxe),ELF格式,内部记录了代码信息和数据对象信息 用途:JTAG加载和调试 DSP loader file 加载文件(*.ldr),二进制或者文本格式,直接存机器码和初始化数据 用途:最终的代码文件,例如前述例子的FlashROM就可以烧这个文件 DSP library file 库文件(*.dlb),相当于多数编译器的*.lib文件 实际上是对象文件的集合,用于向他人发布非源码的可调用程序 DSP object file 对象文件(*.doj),编译结果,还没有链接 VDSE library file 用于大规模的代码共享和重用,不考虑,ELF格式文件,UNIX类操作系统中普遍采用的目标文件格式ELF(Executable and Linkable Format),目前,很多嵌入式处理器的开发工具链都支持这种格式。 可执行链接格式(Executable and Linking Format)最初是由UNIX系统实验室(UNIX System Laboratories,USL)开发并发布的,作为应用程序二进制接口(Application Binary Interface,ABI)的一部分。工具接口标准(Tool Interface Standards,TIS)委员会将还在发展的ELF标准选作为一种可移植的目标文件格式。,ELF目标文件类型,可重定位文件(Relocatable File) 可执行文件(Executable File) 共享目标文件(Shared Object File) 目标文件全部是程序的二进制表示,目的是直接在某种处理器上直接执行,ELF格式文件类型,可重定位文件 可执行文件 共享的目标文件,可执行ELF格式文件结构,1、ELF头 固定在文件的起始位置,其它各部分的位置由ELF头及其它相关信息获得 固定的长度,52个字节,包含14个值 包括ELF文件标识, ELF文件的类型,程序头表和节头表的位置、长度等信息,ELF头结构,typedef struct unsigned char e_identEI_NIDENT; /*16/ ELF “magic number“ */ Elf32_Half e_type; /* 2/ Identifies object file type */ Elf32_Half e_machine; /* 2/ Specifies required architecture */ Elf32_Word e_version; /* 4/ Identifies object file version */ Elf32_Addr e_entry; /* 4/ Entry point virtual address */ Elf32_Off e_phoff; /* 4/ Program header table file offset */ Elf32_Off e_shoff; /* 4/ Section header table file offset */ Elf32_Word e_flags; /* 4/ Processor-specific flags */ Elf32_Half e_ehsize; /* 2/ ELF header size in bytes */ Elf32_Half e_phentsize; /* 2/ Program header table entry size */ Elf32_Half e_phnum; /* 2/ Program header table entry count */ Elf32_Half e_shentsize; /* 2/ Section header table entry size */ Elf32_Half e_shnum; /* 2/ Section header table entry count */ Elf32_Half e_shstrndx; /* 2/ Section header string table index */ Elf32_Ehdr;,可执行ELF格式文件结构,2、 程序头 ELF文件被分成许多个段 每个段保存着用于不同目的的数据 包括段在文件中的位置,段在内存中的起始虚拟地址,段的长度及其它属性 调试器根据程序头表中的信息来确定需要下载到目标机上的目标文件内容(指令与数据)及其在目标机中的内存地址,程序头结构,typedef struct Elf32_Word p_type; /* Type of segment */ Elf32_Off p_offset; /* Offset in file */ Elf32_Addr p_vaddr; /* Virtual address in memory */ Elf32_Addr p_paddr; /* Reserved */ Elf32_Xword p_filesz; /* Size of segment in file */ Elf32_Xword p_memsz; /* Size of segment in memory */ Elf32_Word p_flags; /* Segment attributes */ Elf32_Xword p_align; /* Alignment of segment */ Elf32_Phdr;,开发工具、步骤和文件的内在关系,从源文件到最终程序运行,在计算机上要做的事情包含三步: 编译 Compiler 链接 Linker 加载 Loader VisualDSP某种程度上屏蔽了这些细节,但是我们有必要了解,编译(Compile)选项,只说常用的: 优化 下一页讲 生成调试信息 在DEX文件里 必须钩上,否则无法使用多数的高级调试功能,优化的概念,优化的含意很多 简单的理解: 去掉无用的逻辑 去掉无用的数据 用并发指令提高速度 看右侧的简单例子,int a; main() a = 1; a = 2; a = 3; /到编译器里看看结果,链接(Link)选项,生成符号表文件 是一个XML表格文件 报告了Link完成后,整个程序的内存使用状况、符号地址等等 大程序,关心内存使用状况的,需要经常看看,加载(Load)选项,生成最终的代码文件(*.ldr) PROM Host Link 本例中,就是生成放在FlashROM中的数据 LDR文件怎样写到Flash中? 硬件编程器 用DSP自己在线写(高级),题外话:DSP加载,4种方式: EPROM/FLASH引导: TigerSHARC作为主动方,用外部口输出地址、读、BMS等控制信号,从EPROM或FLASH中加载代码 主机引导: TigerSHARC作为被动方,不向外部输出控制信号,外部主机或其它设备向TigerSHARC的主机、链路口传送要加载的代码 链路口引导: 通过处理器的链路口实现程序的引导和加载; 非引导: 通过外部不同的Strap信号,从内部存储器的不同地址开始执行程序。,在四种方式中,前三种需要引导程序内核,而且都有相同的引导过程: TigerSHARC自动启动一个DMA,自动把256字(32位)传送到内部存储器的地址0x000xFF 内核执行上述256字指令(称为加载核),加载核启动其它DMA,把后续指令和数据加载到内部或外部存储器 最后加载核自我覆盖,TS201加载核,一段加载核程序,描述DSP执行加载核程序 如何启动AutoDMA进行收数逻辑设计 如何根据收到数据的类型对后续的指令和数据加载到内部或外部存储器 最后进行加载核的自我覆盖的实现过程 参看C:Program FilesAnalog DevicesVisualDSP 5.0TSldrTS201_host工程内的主机加载工程,加载核原理,(1)寄存器初始化和锁定总线 (2) 对DSP做一些相关设置,以匹配处理器复位后的芯片状态 关闭全局中断,关闭所有Link收发中断通道,外部口DMA中断通道0 没有对AutoDMA通道进行关闭 关闭Cache 重设置SQCTL寄存器,使能全局中断,运行处理器响应中断 建立AutoDMA0中断向量表,挂AutoDMA0中断服务程序 加载后续指令和数据时要用到的一些寄存器的初始化 (3) 启动DMA数据传输,传输结束后自动进入中断函启动下一次传输 (4)对接收到的数据进行分析及处理,小结,至此,一个工程的基本设置完成了 简单回顾一下 下面要做的事情: 软件详细设计 编码、调试 作为演示,只做与硬件无关的上层,顶层流程,如右图 初始化 设置整个运行环境 等待数据 等待CPLD给出中断 读入数据 从双口RAM读入一帧数据 处理 一般这部分的代码量是最大的 输出结果 将处理得到的角度值适当转换后写入D/A输出 万变不离其宗 是一个“数据驱动”的流程 有一帧数据(中断)就动一下 可以动手编程序了,步骤 - 初始化,在初始化中,要做这些事情: 设置外总线时序选项 DSP的外总线,一般都可以有多种时序可选 选哪个,问硬件设计者 怎么设置,看手册 安装中断服务程序 如果程序用到了中断,则中断服务程序一般在一开始的时候设定 本例中,中断用查询方式,不需要安装 初始化系统中的其它芯片 要问问硬件设计者,有没有需要初始化的芯片 操作,硬件相关,不讲了 其它的设置. 具体情况具体分析,步骤 等待数据,读出中断捕获寄存器,检查其中的对应位是否置位 关于中断 看手册 系统中用了那个中断线 ?- 问硬件 怎样操作? - 以后再说,读入数据,在外总线时序模式设置正确后,读入数据就是一次存储器搬移 从外存搬到内存 这里用memcpy() 外存地址多少? - 问硬件 搬移长度多少? - 1帧 读入的数据就是A/D采样结果,需要转换为DSP能够直接用来计算的格式,比如浮点 A/D输出数据格式?(bit数,编码方式),看A/D手册 怎么转? DSP都会有一些特殊的位操作指令集,可以快速转换 以后再说,步骤 - 处理,忠实的实现算法 一般都是代码量最大的地方 也是将来速度优化的重点,步骤-输出,类似于输入,不多说 本质就是操作外部总线上的某个地址,调试,刚开始时可以用Simulator进行脱机调试,演示 用dex文件 可以利用Simulator的一些高级功能,比如文件I/O 简单的,可以自己造点数据,跑跑看 两个关心的重点:正确性、实时性 实时性,看处理的耗时 利用“周期计数功能” 也可以自己操作DSP的定时器,不讲了 如果外围条件允许,比如硬件都已经调通了,则可以用Emulator直接在线调试,不讲了,关于运行速度,正常情况下,纯C程序,不优化,很有可能无法满足要求 否则就说明芯片选的太好了,系统性价比有问题 还有哪些可以优化? 顶层流程上,利用DMA功能将数据I/O与处理并行起来 不说了 算法代码,用编译器优化 算法代码,用汇编底层函数优化,最后的工作,把生成的Ldr文件,烧写到Flash里面 具体方法: 用Flash专用的编程器 用DSP自己烧(编一个专门的程序),回顾一下,新建一个工程 做好基本的设置 新建一个源文件 编写代码框架 对框架的各个部分填空 长时间 编译链接、脱机调试、在线调试 最长时间 烧写,小结,今天的内容:一个单片典型系统的编程实例 基本保持在与具体芯片无关的状态 后面的课程发展方向(软件部分) 单片的具体方法 多片并行编程,调试信息查看方法,Simulator环境 以文件作为输入数据 单步、断点时察看内存、外存、变量值 运行时printf打印中间结果(编程实现) Emulator环境(JTAG或PCI) 通过外设接口来接收数据 单步、断点时察看内存、外存、变量值 运行时printf打印中间结果(编程实现) 实际运行时多板卡并行调试 通过外设接口发送中间结果(编程实现) 通过外设显示中间结果(编程实现闪灯),1:如何“闪灯”,“灯”嵌入式系统中的最重要的器件之一,主要起指示作用,通常为LED: 电源指示灯、程序状态指示灯 处理器如何驱动“灯” 本节课使用TigerSHARC处理器的FLAG信号线 TS101板卡使用FLAG2 TS201板卡使用FLAG3,板卡、处理器、灯TS101,0,1,2,3,FLAG 0,板卡、处理器、灯TS201,0,1,2,3,FLAG 3,TS101驱动FLAG信号线,需要操作的寄存器:SQCTL Program sequencer control register 操作流程: 读出sqctl寄存器 置FLAG0输出使能 置FLAG0输出状态 1为高,0为低 更新sqctl寄存器,TS201驱动FLAG信号线,需要操作的寄存器:FLAGREG 操作流程与TS101类似,FLAG高或低 vs. 灯亮或灭,当TS更新内部相应寄存器时,外部FLAG管脚的电平状态就得到改变: Output的值为1高电平 Output的值为0低电平 灯的物理接法可能不同,需要确定输出高电平是否对应着亮灯。,TS101汇编代码段,亮灯: xr0 = sqctl; xr0 = bset r0 by 20; /output enable sqctl = xr0; xr0 = bset r0 by 24; /output high sqctl = xr0; 灭灯: xr0 = sqctl; xr0 = bset r0 by 20; /output enable sqctl = xr0; xr0 = bclr r0 by 24; /output low sqctl = xr0;,不直观的数字,TS201汇编代码段,亮灯: xr0 = FLAGREG; xr0 = bset r0 by FLAGREG_FLAG3_EN_P; FLAGREG = xr0; xr0 = bset r0 by FLAGREG_FLAG3_OUT_P; FLAGREG = xr0; 灭灯: xr0 = FLAGREG; xr0 = bset r0 by FLAGREG_FLAG3_EN_P; FLAGREG = xr0; xr0 = bclr r0 by FLAGREG_FLAG3_OUT_P; FLAGREG = xr0;,容易理解的宏,数字 vs. 宏定义,数字和宏在汇编指令行中都是立即数 数字不易阅读、记忆和维护,可能导致失误 TS101:VDSPincludedefts101.h #define SQCTL_FLAG0_EN_P (20) #define SQCTL_FLAG0_OUT_P (24) TS201: VDSPincludedefts201.h #define FLAGREG_FLAG3_EN_P (3) #define FLAGREG_FLAG3_OUT_P (7),这里用到的Shifter指令,Rs = BCLR Rn BY Rm/ Rs = BSET Rn BY Rm/ 说明见指令集手册,C可调的汇编函数,前面的程序是最简单的纯汇编代码 如何将其改写成一个C可调用的函数呢? 只需要以下的简单改动即可。,亮灯、灭灯的代码段-函数,.global _led_light; .global _led_dark; .section program; _led_light: xr0 = sqctl; xr0 = bset r0 by 20; sqctl = xr0; xr0 = bset r0 by 24; sqctl = xr0; cjmp(abs)(np); _led_dark: xr0 = sqctl; xr0 = bset r0 by 20; sqctl = xr0; xr0 = bclr r0 by 24; sqctl = xr0; cjmp(abs)(np);,延迟的代码段-函数,.global _delay; .section program; _delay: lc0 = j4; .align_code 4; hehe: nop; nop; nop; nop; if nlc0e, jump hehe; nop; nop; nop; cjmp(abs)(np);,C语言的闪灯程序,Void led_light(); Void led_dark(); Void delay(int cycles); Void main(void) while(1) led_light(); delay(10000000); led_dark(); delay(10000000); /while(1) /void main,使用toggle使c程序更为简洁,Rs = BTGL Rn BY Rm/ Void led_toggle(); Void delay(int cycles); Void main(void) while(1) led_toggle(); delay(10000000); /while(1) /void main,2 编译选项,在VisualDSP IDE中有如下设置: 开启/关闭优化 指定编译进度(useless) 指定预编译的宏定义(useless) 指定头文件的位置(useless) 设定警告级别(useless) 指定保留寄存器(advanced) double float的位数32/64 char的位数(32/8) C Complier有更多的命令行选项,3 寄存器使用,X,Y计算块寄存器:X,Y前缀 寻址寄存器:J,K前缀 程序控制寄存器:CJMP、SQSTAT等 链路口寄存器 :LCTLx,LSTATx DMA寄存器:DCSx 外部端口控制和状态寄存器 调试寄存器:CCNT、WPxCTL、TRCBx,编译器寄存器,通用寄存器中,编译器会使用下列寄存器: j16 - j25, k16 - k25 x24 - x31, y24 - y31 如果用户代码需要显式的(嵌入汇编等)使用上述寄存器,则首先要保存它们,用完后恢复它们的值 典型的备份位置:堆栈,草稿寄存器,编译器不会使用这些寄存器: j0-j15, k0-k15, j28-j30, k28-k30, x0-x23, y0-y23 jB0-jB3, kB0-kB3, jL0-jL3, kL0-kL3 xMR0-xMR4, yMR0-yMR4 xPR0-xPR1, yPR0-yPR1 LC0, LC1, xDAB, yDAB xBFOTMP, yBFOTMP iSF0-iSF1, xSF0-xSF1, ySF0-ySF1 所以,在用户的汇编代码(汇编函数、嵌入汇编语句)中使用它们,不会造成冲突,4 内存分配,内存映射的寄存器访问,1. 片内存储器 TS201提供了24M片内存储器,可以按 48/32/16位进行访问 2. 多处理器的存储空间 支持多达8片的多片总线共享连接 3. 片外存储器 分6组:组0、组1、组2、组3和2组通用存储空间,广播空间和多处理器空间的作用,多DSP间直接内存操作 锁定、释放总线 芯片处理同步 计算结果共享,汇编语言程序设计,标识符和运算符 标识符:以字母或者_开头,可包括数字,区分大小写 运算符:()、求补、-、*/%+-、&与、|或、异或 预处理伪指 #define 定义宏,必须在一行内写完,超过时行末加 来续 #include “文件名”,defts201.h重要头文件,汇编伪指令 .segment = .section 标记段的起始 .var 定义变量或缓冲 .global 使一个符号全局化 .extern 使一个符号外部化(由其他文件定义),行嵌入式汇编语句 asm(“汇编指令”):直接形式 asm(模板:输出操作数,.:输入操作数,:选中寄存器) 操作数用%0,%1,%2等表示,输出操作数前用=注明 例:asm(“r9=%1;r10=%2;%0=r9+r10;”:“=d”(result): “d”(from),“d”(to):“r9”,“r10”); 注意分行时用续行标志 ,C程序设计,输入输出文件 .c c源文件 .h 头文件 .cpp,.cxx c+源文件 .pch 编译预处理头文件 支持的数据类型 (unsigned)int/long/short、char、float、double 32位 long double 64位,扩展特性 inline:将制定的函数代码集成到程序代码中 asm:将汇编指令嵌入到c中 dm pm:制定静态、全局变量、受限指针的存储器位置,分别指定到DM和PM,无说明时指向DM 如: int pm ab 将ab定位到PM int dm cd 将cd定位到DM int ef 将sf定位到DM section:代替segment,存储器段及其含义,seg_ pmco:指令代码段,用于存放指令代码 seg_ data:数据存储段,存放全局和静态变量 seg_ init:初始化数据段,用来存放初始化数据 seg_ stack:实时堆栈段,用于存储局部变量、保存

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论