TMS320C54x软件开发C语言.ppt

上传人:max****ui 文档编号:8302971 上传时间:2020-03-28 格式:PPT 页数:58 大小:673KB
返回 下载 相关 举报
TMS320C54x软件开发C语言.ppt_第1页
第1页 / 共58页
TMS320C54x软件开发C语言.ppt_第2页
第2页 / 共58页
TMS320C54x软件开发C语言.ppt_第3页
第3页 / 共58页
点击查看更多>>
资源描述
第6章TMS320C54xC语言编程 6 1DSP的C语言简介6 2DSP的C语言特性6 3DSP的C语言与汇编语言混合编程6 4C语言调用汇编函数6 5汇编模块调用C函数 返回首页 6 1DSP的C语言简介 由DSP厂商及第三方为DSP软件开发提供了C编译器 使得利用高级语言开发DSP程序成为可能 在TI公司的DSP软件开发平台CCS中 提供了优化的C编译器 可以对C语言程序进行优化编译 提高程序效率 目前在某些应用中C语言优化编译的结果可以达到手工编写的汇编语言效率的90 以上 TMS320C54系列的有优化C编译器 支持ANSI的C语言标准 它是使用最广泛的C语言标准 ANSI标准具有一些受目标处理器 运行期环境或主机环境影响的C语言特性 从有效性或实现上考虑 这些特征在各种标准的C编译器之间可能有不同 6 2DSP的C语言特性 6 2 1TMS320C2000C语言的特征 1 标识符和常数所有标识符的前100个字符有意义 区分大小写 源 主机 和执行 目标 字符集为ASCII码 不存在多字节字符 具有多个字符的字符常数按序列中最后一个字符来编码 例如 abc c 和汇编语言不同 2 数据转换浮点到整数的转换取整数部分 指针和整数可以自由转换 3 表达式当两个有符号整数相除时 若其中一个为负 则其商为负 余数的符号与分子的符号相同 斜杠 用来求商 百分号 用来求余数 例如 10 3 3 10 3 3 10 3 1 10 3 1 4 声明寄存器变量对所有char short int和指针类型有效 interrupt关键字仅可用于没有参量的void函数 5 预处理预处理器忽略任何不支持的 pragma伪指令 预处理器支持的伪指令包括 CODE SECTOIN DATA SECTION FUNC EXT CALLED 6 2 2TMS320C2000C语言的数据类型注 在TMS320C2x C2xx C5xC语言中 字节长度为16位 sizeof操作符返回的对象长度是以16位为字节长度的字节数 例如sizeof int 1 5 6 2 3寄存器变量TMS320C54C编译器在一个函数中最多可以使用两个寄存器变量 寄存器变量的声明必须在变量列表或函数的起始处进行 在嵌套块中声明的寄存器变量被处理为一般的变量 编译器使用AR6和AR7作为寄存器变量 AR6被赋给第一个寄存器变量 AR7被赋给第二个寄存器变量 寄存器变量的地址会被放入分配的寄存器中 这样变量的访问速度会更快 16位类型的变量 char short int和指针 都可以被定义为寄存器变量 但在运行时 设置一个寄存器变量大约需要4条指令 为了更有效地使用这个功能 仅当变量被访问超过2次时 才使用寄存器变量 程序优化编译器也会定义寄存器变量 但使用方式不同 编译器会自己决定哪些变量作为寄存器变量 程序中声明的寄存器变量会全部被忽略 声明的格式为 registertypereg 6 2 4pragma伪指令pragma伪指令通知编译器的预处理器如何处理函数 TMS320C54C编译器支持下列pragma CODE SECTION DATA SECTION FUNC EXT CALLED 1 CODE SECTION这个伪指令在名称为sectionname的命名段中为symbol分配空间 语法为 pragmaCODE SECTION symbol sectionname 2 DATA SECTION这个伪指令在名称为sectionname的命名段中为symbol分配空间 语法为 pragmaDATA SECTION symbol sectionname 3 FUNC EXT CALLED当使用 pm选项时 编译器将使用程序级的优化 在这个优化层次中 编译器将删除所有未被main函数直接或间接调用的函数 而用户程序里可能包含要被手工编写的汇编语言程序调用而没有被main函数调用的函数 这时就应该用FUNC EXT CALLED来通知编译器保留此函数和被此函数调用到的函数 这些函数将作为C程序的入口点 这个伪指令必须出现在对要保留的函数的任何声明或引用之前 其语法为 pragmaFUNC EXT CALLED func 6 2 5asm语句TMS320C54C编译器可以在编译器输出的汇编语言程序中直接输出汇编指令或语句 利用asm语句嵌入汇编语言程序 可以实现一些C语言难以实现或实现起来比较麻烦的硬件控制功能 asm语句在语法上就象是调用一个函数名为asm的函数 函数参数是一个字符串 asm assemblertext 编译器会直接将参数字符串复制到输出的汇编语言程序中 因此必须保证参数双引号之间的字符串是一个有效的汇编语言指令 双引号之间的汇编指令必须以空格 制表符 TAB 标记符 LABEL 或注释开头 这和汇编语言编程的要求是一致的 编译器不会检查此汇编语句是否合法 如果语句中有错误 在汇编的过程中会被汇编器指出 使用asm指令的时候应小心不要破坏C语言的环境 如果C代码中插入跳转指令和标记符可能会引起不可预料的操作结果 能够改变段或其它影响C语言环境的指令也可能引起麻烦 对包含asm语句的程序使用优化器时要特别小心 尽管优化器不能删除asm指令 但它可以重新安排asm指令附近的代码顺序 这样就可能会引起不期望的结果 6 2 6访问I O空间读写I O空间的功能是TMS320C54C编译器对标准C的扩展 是利用关键字ioport I O端口 来实现的 该关键字的用法为 ioporttypeporthexnum 1 ioport指示这是定义个端口变量的关键字 2 type 类型 必须是char 字符 short 短整型 int 整型 或对应的无符号类型 3 porthexnum为定义的端口变量 其格式必须是 port 后面跟一个16进制数 如 port000A 是定义访问I O空间地址0Ah的变量 所有I O端口的定义必须在文件级完成 不支持在函数级声明的I O端口变量 利用ioport关键字定义的I O端口变量可以象一般变量一样进行赋值操作 ioportunsingedport10 访问I O空间10h的变量 port10 a 将a写到端口10h b port10 从端口10h读入b 端口变量的使用不仅限于赋值操作 事实上 用ioport关键字定义的I O端口变量可以象其它变量一样用在表达式中 a port10 b 读端口10h 加上b 结果赋给aport10 a 读端口10h 加上a 结果写回到端口10h在进行函数调用的时候 可以做I O端口变量的值传递 而不是引用 call port10 读端口10h 将其值传递给函数调用 call 引用传递无效 6 2 7访问数据空间访问DSP数据空间是利用指针来实现的 unsignedint 0 x1000 a 将a的值写入数据空间1000h地址 b unsignedint 0 x1000 读出数据空间1000h地址的值 赋给b 可见访问DSP数据空间地址不需要对要访问的单元预先定义 利用指针直接访问就可以了 这样 访问数据空间很容易实现循环结构 for i 0 i cnt i tmp unsignedint org i unsignedint org offset i tmp 6 2 8中断服务函数同传统的单片机中断处理方式类似 DSP中断的处理也有两种方式 1 查询法 可以更好地对程序进程进行控制 对中断的处理可以完全按照程序预定的方式进行 一般不会出现中断丢失或中断嵌套的问题 但由于中断发生时不会暂停当前正在执行的程序 而程序可能正处于复杂的处理或运算状态 只有结束当前处理才会去检查中断标志 因此中断实时性不容易保证 2 回调法 程序结构更为清晰 而且当有中断发生的时候会暂停当前正在执行的程序 中断实时性可以得到保证 但如果中断处理函数实现不当容易造成中断丢失或中断嵌套问题 影响系统的正常运行 回调法处理DSP中断需要定义中断服务函数 有两种方法 用关键字interrupt来实现 它的用法是 interruptvoidisr void 任何具有名为c intd的函数 d为0到9的数 都被假定为一个中断程序 如 voidc int1 void 无论哪种方法定义中断服务函数 都须注意以下问题 1 中断处理函数必须是void类型 而且不能有任何输入参数 2 进入中断服务函数 编译器将自动产生程序保护所有必要的寄存器 并在中断服务函数结束时恢复运行环境 3 进入中断服务函数 编译器只保护与运行上下文相关的寄存器 而不是保护所有的寄存器 中断服务函数可以任意修改不被保护的寄存器 如外设控制寄存器等 4 要注意IMR INTM使能和屏蔽等中断控制量的由程序员自己来设置 通常进入中断服务程序要设置相应寄存器将中断屏蔽 退出中断服务程序时再打开 避免中断嵌套 5 中断处理函数可以被其他C程序调用 但是效率较差 6 多个中断可以共用一个中断服务函数 除了c int0 c int0是DSP软件开发平台CCS提供的一个保留的复位中断处理函数 不会被调用 也不需要保护任何寄存器 7 使用中断处理函数和一些编译选项冲突 注意避免对包含中断处理函数的C程序采用这些编译选项 8 中断服务函数可以和一般函数一样访问全局变量 分配局部变量和调用其它函数等 9 要利用中断向量定义 将中断服务函数入口地址放在中断向量处以使中断服务函数可以被正确调用 即在相应的中断矢量中 放置一条转移指令 用 sect汇编伪指令建立一个简单的跳转指令表 10 中断服务函数要尽量短小 避免中断丢失 中断嵌套等问题 6 2 9动态分配内存TMS320C54C语言程序中可以调用malloc calloc或realloc函数来动态分配内存 例 unsignedint data data unsignedint malloc 100 sizeof unsignedint 动态分配的内存将分配在 system段 动态分配的内存只能通过指针进行访问 将大数组通过这种方式来分配可以节省 bss段的空间 通过链接器的 heap选项可以定义 system段的大小 6 2 10系统初始化C程序开始运行时 必须首先初始化C运行环境 这是通过c int0函数完成的 c int0函数是复位中断服务函数 这个函数在运行支持库 rts runtime supportlibrary 中提供 链接器会将这个函数的入口地址放置在复位中断向量处 使其可以在初始化时被调用 c int0函数进行以下工作以建立C运行环境 1 为系统堆栈产生 stack段 并初始化堆栈指针 2 从 cinit段将初始化数据复制到 bss段中相应的变量 3 调用main函数 开始运行C程序 用户的应用程序可以不用考虑上述问题 同利用其他开发平台开发C语言程序类似 认为程序从main函数开始执行就可以 用户可以对c int0函数进行修改 但修改后的函数必须完成以上任务 6 3DSP的C语言与汇编语言混合编程 C语言编写DSP程序对底层的了解要求较低 流程控制灵活 开发周期短 程序可读性 可移植性好 程序修改 升级方便 某些硬件控制功能不如汇编语言灵活 程序实时性不理想 很多核心程序可能仍然需要利用汇编语言来实现 利用两种语言进行混合编程主要有以下四种方式 1 C程序调用汇编函数 2 内嵌汇编语句 3 C程序访问汇编程序变量 4 修改C编译器输出 6 3 1程序运行环境在C语言和汇编语言混合编程中 必须保证C程序运行环境不会被汇编程序破坏 所有代码必须维护该环境 否则将难以保证C程序的正常执行 1 存储器模型TMS320C54的C编译器将存储器作为程序存储器和数据存储器两个线性区来处理 程序存储器 包含可执行的代码和常量 变量初值 数据存储器 包含外部变量 静态变量和系统堆栈 编译器产生可重定位的代码 允许链接器将代码和数据定位进合适的存储空间 C编译器对C语言编译后除生成3个基本段 text data bss外 还生成 cinit const stack sysmem cinit 包括初始化变量和常数表 const 包括字符串常数和const关键字定义数据 switch 包括switch语句的跳转表 stack 包括分配存储器用于彻底变量 sysmem 保留存储空间 用于动态存储器分配 用malloc calloc andrealloc函数 1 段的存储分配编译器产生可重新定位的代码段和数据段 包括 a 已初始化的段 包含数据和代码 包括 text cinit switch等 b 未初始化的段 为全局变量和静态变量保留空间 包括 bss stack system等 用户可以利用伪指令CODE SECTION和DATA SECTION来创建另外的段 段的存储分配和页的指定 2 系统堆栈 stack不同于DSP汇编指令定义的堆栈 DSP汇编程序中要将堆栈指针SP指向一块RAM 用于保存中断 调用时的返回地址 存放PUSH指令的压栈内容 C编译器使用软件堆栈进行如下工作 分配局部变量 向函数传递参数 保存处理器状态 保存函数的返回地址 保存暂时的结果 保存寄存器 堆栈从较低地址向较高地址生长 编译器使用两个寄存器管理堆栈 AR1 堆栈指针 SP stackpointer 指向当前堆栈顶 AR2 帧指针 FP framepointer 指向当前帧的起始点 每一个函数都会在堆栈顶部建立一个新的帧 用来保存局部的或临时的变量 C语言环境自动操作这两个寄存器 如果编写用到堆栈的汇编语言程序 一定要注意正确使用这两个寄存器 stack段大小可用链接器选项 stacksize设定 链接器还产生一个全局符号 STACK SIZE 并赋给它等于堆栈长度的值 以字为单位 缺省值为1K 注意 编译器不会检查堆栈溢出情况 堆栈溢出会破坏DSP运行环境 导致程序失败 编写DSP程序和配置DSP存储器资源要注意防止堆栈溢出的发生 2 寄存器规则TMS320 C5x运行环境对寄存器的使用有严格的规则 如果编写涉及到寄存器的汇编程序 必须严格遵守这些规则 否则可能造成系统工作异常 寄存器规则规定了编译器如何使用寄存器 和寄存器在函数调用的过程中如何进行保护 寄存器按照保护方式分为两种 调用保存 saveoncall 调用其它函数的函数负责保存这些寄存器的内容 入口保存 saveonentry 被调用的函数负责保存这些寄存器的内容 注 无论是否使用优化编译 都必须遵守这些寄存器规则 寄存器的使用和保护 状态寄存器 ST0 ST1 单元 对于有假定值 为0或为1 的状态寄存器单元 在进行函数调用和函数返回时必须保证其值为假定值 3个寄存器 堆栈指针 SP 帧指针 FP 和局部变量指针 LVP 管理堆栈和局部帧 AR6和AR7作为寄存器变量的寄存器 AR6被分配给第一个变量 AR7分配给第二个变量 编译器使用不用于寄存器变量的寄存器来计算表达式的值并保存临时结果 当函数的返回值是一个标量类型 整型 指针或浮点型 时 该值在函数返回时被放入累加器中 16位的数据类型 字符型 短整型 整型或指针型 连同正确的符号扩展被装载到累加器中 3 函数结构和调用规则C编译器对函数的调用有一系列严格的规定 除了特殊的运行支持函数外 任何调用者函数和被调用函数都要遵守这些规则 否则可能会破坏C环境并导致程序失败 1 函数如何产生调用一个函数 调用者函数 在调用其他函数 子函数 时执行以下任务 注意 ARP必须设置为1 a 调用者函数将参数以颠倒的顺序压入堆栈 最右边声明的参数第一个压入堆栈 最左边的参数最后一个压入堆栈 即函数调用时 最左边的参数放在栈顶单元或ACC b 调用者函数调用子函数 c 调用者函数假定当子函数执行完成返回时 ARP将被置为1 d 完成调用后 调用者函数将参数弹出堆栈 2 被调用函数如何响应a 将返回地址从硬件堆栈中弹出 压入软件堆栈 b 将FP压入软件堆栈 c 分配局部帧 d 如果函数修改了AR6和AR7 则将它们压入堆栈 其他的任何寄存器可以不用保存 任意修改 e 实现函数功能 f 如果函数返回标量数据 将它放入累加器 g 将ARP设定为AR1 h 如果保护了AR6 AR7 恢复这两个寄存器 i 删除局部帧 j 恢复FP k 从软件堆栈中弹出返回地址并压入硬件堆栈 l 返回 3 被调用函数的特殊情况被调用的函数有三种特殊情况 a 返回一个结构体 当函数的返回值为一个结构时 调用者函数负责分配存储空间 并将存储空间地址作为最后一个输入参数ACC传递给被调用函数 被调用函数将要返回的结构拷贝到这个参数或ACC所指向的内存空间 b 不将返回地址移到软件堆栈中 当被调用函数不再调用其它函数 或者确定调用深度不会超过8级 可以不用将返回地址移动到软件堆栈 c 不分配局部帧 如果函数没有输入参数 不使用局部变量 就不需要修改AR0 FP 因此也不需要对其进行保护 6 4C语言调用汇编函数 a 所有的函数 无论是C函数还是汇编语言函数 都必须遵循寄存器规则 b 必须保存被函数修改的任何专用寄存器 包括 AR0 FP AR1 SP AR6 AR7 如果正常使用堆栈 则不必明确保存SP 也就是说 用户可以自由地使用堆栈 弹出被压入的所有内容 用户可以自由使用所有其他的寄存器 而不必保留它们的内容 c 如果改变了任何一个寄存器位域状态的假定值 则必须确保恢复其假定值 尤其注意ARP应该被指定为AR1 d 中断子程序必须保存所有使用的寄存器 e 在从汇编语言中调用C函数时 将参数以倒序压入堆栈 函数调用后弹出堆栈 f 调用C函数时 只有专用的寄存器内容被保留 C函数可以改变其他任何寄存器的内容 g 函数必须返回累加器中的值 h 汇编模块使用 cinit段只能用于全局变量的初始化 boot c中的启动子程序假定 cinit段完全是由初始化表组成 在 cinit段中放入其他的信息会破坏初始化表而导致无法预知的后果 i 编译器将在所有的C语言对象标识符的开头添加下划线 在C语言中和汇编语言都要访问的对象必须在汇编语言中以下划线 作为前缀 例如 C语言中名为x的对象在汇编语言中为 x 仅在汇编语言模块中使用的对象可以使用不加下划线的标识符 不会和C语言中的标识符发生冲突 j 在C中被访问的任何汇编语言对象或在C中被调用的任何汇编语言函数必须在汇编代码中使用 global伪指令声明 这将声明该符号是外部的 允许链接器解决对它的引用 6 4 1内嵌汇编语句在TMS320C2000C语言中 可以使用asm语句在编译器产生的汇编语言文件中嵌入单行的汇编语句 一系列的asm语句可以将顺序的汇编语句插入到编译器的输出代码中 使用中的几点注意事项 a asm语句使用户可以访问某些用C语句无法访问的硬件特性 b 在使用asm语句的时候 要防止破坏C环境 编译器不会对嵌入代码进行检查和分析 c 在asm语句中使用跳转语句或标记符 LABEL 可能会产生无法预知的结果 d 不要改变C变量的值 但可以安全地读取任何变量的当前值 e 不要使用asm语句嵌入汇编伪指令 这会破坏汇编语言环境 f 在编译器的输出代码中嵌入注释时 asm语句是很有用的 可以用星号 作为汇编代码的开头 如 asm thisisanassemblylanguagecomment 6 4 2C程序访问汇编程序变量有时候需要在C程序中访问汇编语言变量 这通常有两种方式 1 访问 bss块中的变量 将要访问的变量定义在 bss块中 用 golbal修饰要访问的变量 在汇编语言中以下横线 为前缀声明要访问的变量 在C语言中将变量声明为外部变量 extern 就可以进行正常访问 例如下例 C语言调用汇编的变量和函数 mmregs bss var 1 Definethevariable global var Declareitasexternal global asmfunc Declareitasexternal text asmfunc PSHMST0PSHMST1LD 0030H A 将0030H装入累加器ASTLA var var 0030HFIREND POPMST1POPMST0RET end C程序externintvar externvoidasmfunc void voidmain inti asm STM 0 SWWSR asmfunc i var var 1 i var 2 访问非 bss块中的变量 要访问非 bss块中的变量 通常的办法是在汇编语言中定义一个查找表 然后在C语言中通过指针来访问 在汇编中首先定义变量 而且最好放在独立的初始化块中 再定义一个全局的标识指向对象的起始点 这样的对象可以分配在存储器空间的任何位置 在C中将这个对象定义为外部对象 extern 并且对象名称不带下横线 前缀 就可以对其进行正常访问 例如下例 C语言调用汇编的常量表 title 访问非 bss块中的变量 mmregs global sine 声明全局量 sect sine tab 声明独立的常量表 sine float0 2 float0 015987 float0 022145 float0 05 end externfloatsine C程序float sine p sine 声明指针voidmain floatf f sine 0 Accesssineasnormalarray f sine 1 Accesssineasnormalarray f sine 2 Accesssineasnormalarray f sine p 0 Accesssineasnormalarray f sine p 1 Accesssineasnormalarray f sine p 3 Accesssineasnormalarray f sine p 4 Accesssineasnormalarray 6 4 3C访问汇编语言中定义的常量符号在汇编语言中定义的常量符号 在C中只能用地址操作符 去取其值 或者说 汇编语言中定义的常量符号X 在C中只能用 X 去获得汇编语言的常量X的值 如下例 title C访问汇编语言中定义的常量符号 mmregs table size set10 definetheconstant global table size makeitglobal end externinttable size C程序 在汇编语言中定义的常量符号 C中只能用地址操作符 6 4 4修改C编译器的输出用户可以编译源程序 然后在汇编前对编译输出的汇编语言代码进行手动检查和修改 这种情况下 在C代码中利用asm语句插入适当的注释对理解C编译器输出的汇编语言代码是非常有帮助的 6 5汇编模块调用C函数 在编写独立的汇编程序时 必须注意以下几点 1 不论是用C语言编写的函数还是用汇编语言编写的函数 都必须遵循寄存器使用规则 2 调用C函数时 注意C函数只保护了几个特定的寄存器 而其他是可以自由使用的 汇编语言中必须保护C函数要用到的这些寄存器 3 从汇编程序调用C函数时 第一个参数 最左边 必须放入累加器A中 剩下的参数按自右向左的顺序压入堆栈 5 长整型和浮点数在存储器中存放的顺序是低位字在高地址 高位字在低地址 6 如果函数有返回值 返回值存放在累加器A中 7 汇编语言模块不能改变由C模块产生的 cinit段 如果改变其内容将会引起不可预测的后果 8 编译器在所有C标识符 函数名 变量名等 前加下划线 9 任何在汇编程序中定义的对象或函数 如果需要在C程序中访问或调用 则必须用汇编指令 global定义 10 编辑模式CPL指示采用何种指针寻址 如果CPL 1 则采用堆栈指针SP寻址 如果CPL 0 则选择页指针DP进行寻址 返回本节 6 6C语言的运行支持函数 rts C程序所执行的一些标准任务 如输入 输出 动态存储器配置 字符串操作以及三角函数等 由rts lib来提供 TMS320C54C编译器可以提供除了用于处理意外情况和地域相关问题 如基于当地的语言 民族或文化的程序 的工具之外的全部ANSI的标准库的内容 使用ANSI的标准库可以确保有一套统一的函数 a rts lib 运行期支持目标库 包含 ANSIC标准库 系统启动程序 c int0 允许C访问特殊指令的函数和宏b rts src 运行期支持资源库 包含运行期支持目标库的C语言和汇编语言程序源代码
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!