DSP课件第八章C语言编程基础.ppt_第1页
DSP课件第八章C语言编程基础.ppt_第2页
DSP课件第八章C语言编程基础.ppt_第3页
DSP课件第八章C语言编程基础.ppt_第4页
DSP课件第八章C语言编程基础.ppt_第5页
已阅读5页,还剩48页未读 继续免费阅读

下载本文档

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

文档简介

第8章C语言编程基础 为了提高程序开发的效率 同时使程序能与高级语言接轨 目前所有生产DSP芯片的公司都提供了C语言编译器 这样 除了对于一些运算量较大或对运算时间要求很严格的程序代码外 一般性的代码都可采用C语言编程 从而缩短程序的开发周期 C编译器还同时提供了汇编语言接口 可使汇编模块方便地被C语言调用 1 C编译器 2 C代码优化 3 C代码链接 4 C语言 5 C运行环境和库函数 以上5部分不再关注C语言本身的语法 而是关注如何在CCS集成环境中对拥护已经编写好的C代码有效地进行编译 汇编和链接 以生成可执行代码这样的工程问题 8 1C编译器和C优化代码 8 1 1C编译器特性 C编译器的主要功能是将用户编写的C语言代码翻译为汇编语言程序 1 支持ANSI标准C 2 支持ANSI标准实时运行库 3 汇编程序输出 4 生成COFF目标文件 5 编译器的Shell程序 6 灵活的汇编语言接口 7 完整的预处理程序 8 最优化 9 初始化数据到ROM存储器中 10 原程序交互列表功能 11 库构造工具 CCS开发环境可以看成是一个大的软件包 里面包含了源代码编辑器 以及工程文件组织 编译和调试等一切功能模块 该软件包里 shell程序可以完成3个功能 编译 汇编和链接 shell程序缺省在C盘安装时 被安装在C ti c2400 cgtool子目录下 对应的文件名为dspcl exe 1 编辑器 包括分析器 优化器 代码产生器 把C语言程序编译成汇编语言程序 2 汇编器 把汇编语言源代码或C语言已经编译成汇编语言代码进行汇编 以产生COFF目标文件 3 链接器 将文件链接 产生可执行的目标文件 8 1 2Shell程序 8 1 3C代码优化 C编译器中含有一个C优化程序 启用C优化程序可以提高程序执行速度 减少C程序代码长度 对于C语言 可以采用简化循环 使用软件流水线 重新安排 语句和表达式以及将变量分配到寄存器等方法实施优化 在CCS中 选择菜单Project BuildOptions选项 可以直接在弹出的对话框中对优先级别进行设置 8 2C程序代码链接 C编译器和汇编语言工具为用户链接程序提供了以下两种方法 1 先编译各个模块 最后将他们链接在一起 2 一次执行Shell程序的dspcl命令 直接完成各个模块的编译 汇编和链接 在CCS集成环境下 还有少量设置CCS环境和工程文件组织工作需要人工干预 为链接C程序 需要DSP开发人员做以下工作 1 把运行支持库包含到工程文件中 2 指定程序运行时的初始化类型 3 确定如何将由C语言程序编译 汇编和链接产生出的可执行代码分配到物理存储器中 8 2 1把运行支持库包含到工程文件中 所有C程序都必须与运行支持库链接 因为运行支持库包含了标准C函数 如sin 函数 以及编译器用来创建和管理CCS中C语言运行环境的函数 运行支持库中包含了一个boot obj目标模块 C程序链接时必须与它链接 当C程序开始运行时 首先执行boot obj 链接时 链接器会自动提取boot obj并链接它 boot obj包含了用于初始化运行环境的代码和数据 该模块执行以下任务 1 建立堆栈 2 处理运行时 初始化表和自动初始化全局变量 3 调用C语言主程序main 4 当C语言主程序main 结束时 调用exit boot obj中有一个重要的汇编语言函数 c int0 它是boot obj中的起点 链接时 c int0被自动定义为程序的入口点 如果程序从复位开始运行 则应将复位向量转移到 c int0 以便DSP首先执行 c int0 8 2 2指定初始化类型 用C语言编程时 会根据需要定义全局变量和静态变量 有些全局变量和静态变量具有初始值 有些全局变量和静态变量没有初始值 C编译器对C程序编译后 为具有初始值的全局变量和静态变量建立了一个专门的数据块 cinit 该块在程序运行后调入到RAM的 bss中 cinit调入到RAM中有两种方法 1 在运行时 自动初始化全局变量和静态变量 2 在加载时 自动初始化全局变量和静态变量 当创建新工程时 第一种是缺省状态 8 2 3把块分配到物理存储器中 把块分配到物理存储器中就是把程序和数据分配到物理存储器中 当使用C编译器对C程序编译后 可产生数据块和代码块 这些块根据各种不同的应用系统硬件配置和扩展情况 可以使用不用的方法将这些块分配到物理存储器中 8 3创建C语言软件 8 3 1创建C语言寄存器头文件 与汇编语言相同 C语言编程也需要相应的头文件 2407控制寄存器数量较多 为了方便编程 可以将这些寄存器地址定义在一个头文件 h 中 这样 在编程时只要将该文件包含其中 直接引用寄存器在 h中定义的英文缩写名 而不必记它的地址 在该头文件中 寄存器是以指针方式进行寻址 8 3 2创建main 函数 在C语言应用软件中 用户必须定义一个main 函数作为自己应用程序的开始 因为系统完成C语言环境设置后 boot obj会自动调用main 函数作为程序的开始 因此 程序员在程序中编写main 函数是一种预定 也是一种强制 voidmain void sys ini for delay xf管脚置低 asm clrcxf delay xf管脚置高 asm setcxf 8 3 3创建2407芯片初始化函数 初始化内容包括 1 2407芯片初始化 2 工程应用中所甬道的片内外设初始化 3 片内外存储器初始化 4 应用系统硬件接口初始化 include exp4 2407 h voidsys ini 系统初始化子程序 关总中断 asm setcINTM 抑制符号位扩展 asm clrcSXM 累加器中结果正常溢出 asm clrcOVM 禁止看门狗 WDCR 0 x00E8 CLKIN 10M CLKOUT 40M SCSR1 0 x0000 8 3 4创建假中断处理函数 1 2407工作时 如果意外引发了内核级中断 但是却没有低层外设中断向量装入外设中断寄存器中时 假中断向量0000h装入PIVR 2 CPU执行一个软件中断指令INTR时 使用了参数1 6 企图用软件中断去服务于外设中断INT1 INT6 这显然是一个错误 这时 假中断向量装入PIVR 3 中断请求线发生故障 外设发出中断请求 而其INTn标志却在CPU应答请求之前被软件清0 此时 外设中断的请求可能还没有被中断控制器确认 中断控制器也不知道哪个外设中断向量应装PIVR 这时 假中断向量装入PIVR interruptvoidnothing 假中断子程序 return 8 3 5 c int0函数 在运行C程序之前 用户必须首先建立起C语言运行环境 建立C语言运行环境的函数在库rts2xx lib中 把 c int0函数作为硬件复位后的中断矢量入口来运行 c int0函数 rsvectB c int0这样 当系统复位后 通过执行一条无条件转移指令来调用 c int0函数 以建立C语言运行环境 c int0函数初始化C环境时执行了如下任务 1 为系统堆栈定义一个名为 stack的块 并建立初始化堆栈和帧指针 2 将 cinit块的初始化数据表中的数据复制到 bss块 对全局变量和静态变量进行初始化 3 调用main函数 开始运行C程序 8 4TMS320C240 xC语言 8 4 1数据类型 TMS320 x的C语言数据类型具有如下特征 1 所有的整形类型 包括char short和int及其它们对应的无符号类型 是16位二进制数 相互间是等价的 2 长整型和无符号长整型类型是32位二进制数 3 带符号类型以2进制补码表示 4 char类型等同于int类型 为带符号类型 5 enum类型的对象以16位值表示 在表达式中enum类型和int类型等同 6 所有浮点类型 float double和longdouble 是等价的类型 都以32位浮点格式表示 7 长整型和浮点数保存在存储器中 低位数值保存在低地址 8 4 2C语言标准库函数的使用 TI公司的C编译器提供了C语言标准库函数 它与boot asm等一起封装在rts2xx lib中 在使用标准库函数时 首先要声明这一函数 TI公司的所有标准库函数以分类的形式在不同的头文件中声明 全部声明库函数的头文件为assert h limits h stddef h ctype h math h stdlib h setjmp h string h stdarg h time h 和ioports h 为了使用一个库函数 用户必须首先使用 include来包含声明函数的头文件 8 5TMS320C24xC语言程序开发 TMS320C24xC语言具有特定的运行环境 为了确保C语言程序正确运行 C语言程序开发必须维护这个环境 8 5 1存储器模式 TMS320C24x的C编译器将存储器分为程序存储器和数据存储器 程序存储器包含可执行代码 数据存储器包含外部变量 静态变量和系统堆栈 由C程序生成的每一块代码或数据存放于存储空间的一个连续块中 存储器映射及代码和数据存储空间的分配由链接器决定 编译器不考虑可用存储空间类型 也不考虑存储空间是否可以被代码和数据使用或者存储空间是否保留以用于I O或控制 编译器只生成可重新分配的代码 链接器完成将代码和数据分配到合适的存储空间 C汇编器对C语言程序编译生成7个可以进行重定位的代码和数据块 text cinit const switch bss stack sysmem 1 C编译器生成的块 1 text块包含所有可执行代码和浮点常量 2 text块包含初始化变量和常量的表 3 const块包含字符串变量 明显初始化的全局和静态变量的定义和初始化 4 switch块包含switch语句表 5 bss块为全局和静态变量保留空间 6 stack块为C系统堆栈 7 sysmem块为动态存储器分配保留空间 text cinit和 switch块通常被链接到ROM或RAM 必须处于程序存储器中 const块可以被链接到ROM或RAM 但必须处于数据存储器中 bss stack和 sysmem块必须被链接到RAM 并必须处于数据存储器中 这些块根据不同的系统配置以不同的方式被放到存储器中 链接器将不同模块相同的块组合为输出块 完整的程序由这些输出块组成 包括汇编器的 data块 2 C系统堆栈 C编译器使用软件堆栈实现以下功能 1 分配局部变量 2 给函数传递参数 3 保存处理器状态 4 保存函数返回值 5 保存临时变量 6 保存寄存器 堆栈运行时从低地址向高地址增加 编译器使用2个辅助寄存器管理堆栈 1 AR1为堆栈指针 SP 指向当前堆栈顶部 2 AR0为帧指针 FP 指向当前帧的起始处 每个函数调用会在堆栈顶创建一个新的帧 用于保存局部和临时变量 局部帧是堆栈的一个区域 用于存储函数传递的变量和局部变量 每一个函数调用时都要在堆栈顶部创建一个新的局部帧 在调用C函数时 C环境会自动管理这些寄存器 堆栈的大小由链接器确定 全局符号 STACK SIZE的值等于堆栈长度 缺省值为1KB 3 动态存储空间的分配 编译器运行支持库提供了几个函数 可以在运行时为变量动态地分配存储空间 如malloc calloc realloc等 动态分配是由标准运行支持函数提供的 动态存储空间来自定义在 sysmem块中的全局池 pool 或堆 heap sysmem块的大小可在链接时由heap选项设定 同样 链接器也可创建一个名为 SYSMEM SIZE的全局符号 并将 sysmem块的大小符给该符号 对动态分配的目标一般通过指针对其进行访问 并且他们的存储区被分配在一个独立的段中 4 静态和全局变量的存储器分配 在C程序中说明的每一个外部或静态变量都是被分配给一个唯一的连续空间的 空间的地址由链接器确定 编译器保证这些变量的空间分配多个字 以便每个变量按字边界对准 5 结构的对准 编译器为结构分配空间时 它将分配足够的字以包含所有的结构成员 在一组结构中 每个结构开始于字边界 6 域的对准 非域类型对准于字的边界 对域分配足够多的位 相邻域组装进一个字的相邻位 但不跨越两个字 如果一个域要跨越两个字 则整个域将分配到下一个字中 8 5 2存储器规则 TMS320C2xx编译器严格规定 在C语言环境中 特殊的寄存器和特殊的操作联系在一起 如果要将汇编语言与C程序接口 必须遵循对这些寄存器的规定 寄存器规则定义编译器如何使用寄存器和在函数调用时如何保存值 上表列出了编译器如何使用寄存器 并说明了在函数调用时寄存器在保存值时所起的具体作用 上表列出了编译器所使用的所有状态位 预设值是编译器在函数进入和返回时的期望值 修改栏是编译器产生的代码是否修改该域 2 堆栈指针 帧指针和局部变量指针 编译器创建和使用自己的软件堆栈以用于保存函数返回地址 分配局部变量和给函数传递参数 当函数需要存储局部变量时 可以在堆栈中创建自己的工作空间 局部帧 局部帧在函数入口时分配 在函数返回时释放 系统提供堆栈指针 SP 帧指针 FP 和局部变量指针 LVP 3个寄存器来管理堆栈和局部帧 寄存器AR1用做堆栈指针 堆栈从低地址向高地址增长 SP指向堆栈中下一个可用的字 寄存器AR0用做帧指针 FP指向当前函数局部帧的起始地址 PF直接指向局部帧的第一个字 该字用做临时存储单元 可以用于实现寄存器到寄存器值的传递 同时在创建可重入C函数时也必须使用该存储单元 寄存器AR2用做局部变量指针 所有存储在局部帧的对象包括参数都要通过LVP间接引用 3 寄存器变量 寄存器变量是指存储于寄存器而不是RAM的局部变量或编译器临时变量 1 不使用优化器 不使用优化器时 编译器至多为使用register关键字的两个变量分配寄存器 变量必须在参数列表中或函数的第一块中定义 编译器采用AR6和AR7作寄存器变量寄存器 AR6保存第一个变量 AR7保存第二个变量 2 使用优化器 使用优化器时 所有寄存器变量定义将被忽略 由优化器决定寄存器分配 优化器直接将变量而不是地址分配给寄存器 优化器可以将AR5 AR6和AR7用作寄存器变量 AR5在函数调用时不保存 所以它在使用时可以跨越多个函数使用 4 表达式寄存器 编译器使用没有用做寄存器变量的寄存器来计算表达式值和存储临时结果 在函数调用时不保留表达式寄存器内容 在函数调用时 用做临时存储的寄存器保存到局部帧 被调函数不用保存和恢复表达式寄存器 5 返回值 如果函数返回值为标量类型 integer pointer或float 则返回值保存在累加器中 当返回值为16位类型变量时 返回值在累加器中符号扩展 8 5 3函数结构和调用规则 1 函数如何进行调用 主调函数在调用另一个函数时完成以下工作 ARP必须为AR1 1 主调函数以逆顺序将参数压入堆栈 最右边的参数最先压入 最左边的参数最后压入 函数调用时最左边的放在堆栈顶部 2 主调函数调用被调函数 3 主调函数假定在函数返回时ARP会被设定为AR1 4 当被调函数结束 主调函数用以下命令将参数弹出堆栈 SBRKn 2 被调函数响应 函数入口时ARP应该设为AR1 AR1用作SP 1 从硬件堆栈中弹出返回地址 并将其压入软件堆栈 2 将帧指针FP压入软件堆栈 3 分配局部帧 4 如果被调函数修改AR6或AR7 将其压入堆栈 其他被修改的寄存器可以不保存 5 执行函数代码 6 如果函数返回标量值 将返回值放入累加器 如果返回值为16位整型和指针 在用累加器保存返回值时进行正确的符号扩展 7 将ARP改为AR1 8 如果保存了AR6或AR7 则恢复AR6或AR7 9 释放局部帧 10 恢复FP 11 将返回地址从软件堆栈中弹出并压入硬件堆栈 12 返回 假定ARP AR1POPD 将返回地址从硬件堆栈弹出 压入软件堆栈SARAR0 将AR0 FP 压入堆栈SARAR1 SP SPLARAR0 SIZE FP 帧大小LARAR0 0 FP SP SP SIZE 分配局部帧空间SARAR6 AR6压栈SARAR7 AR7压栈 函数代码MAR AR1 设置ARP SPMAR 指针指向AR7LARAR7 弹出AR7LARAR6 弹出AR6SBRKSIZE 1 释放局部帧LARAR0 弹出局部帧指针FPPSHD 将返回地址从软件堆栈弹出 压入硬件堆栈RET 返回 8 5 4中断处理 遵循中断原则就是在不影响C环境的情况下实现中断处理并返回C代码 c int0为C程序入口点 它同时也是引导函数 用来完成C环境初始化 在初始化工作中 没有对中断进行任何处理 中断的全部控制寄存器和状态位处于缺省状态 在缺省状态下 中断没有使能 如果系统中要使用中断 用户必须作相应处理 使中断使能 这些操作很容易用asm语句实现 或调用汇编函数来实现 对C环境没有影响 调用中断程序时 首先应调用运行时支持库中的子程序I SAVE 这个子程序保存了所有的寄存器 同样 在中断程序返回时 应调用调用运行支持库中的子程序I RET 用于恢复被保存的寄存器 以上过程都是自动的 不需要用户编程时干预 interrupt是C编译器中的中断关键字 用来声明中断函数 格式如下 interruptvoidnothing 哑中断子程序 return 8 6C语言和汇编语言混合编程 用C语言和汇编语言的混合编程方法主要有以下四种 1 独立编写C程序和汇编程序 分开编译或汇编形成各自的目标代码模块 然后用链接器将C程序和汇编程序链接起来 2 直接在C语言程序的相应位置嵌入汇编程序 3 在C语言程序中使用汇编程序的变量 4 对C程序进行编译生成相应的汇编程序 然后对汇编程序进行手工优化和修改 8 6 1独立的C和汇编程序模块接口 1 不论是用C编写的函数还是汇编编写的函数 都必须遵守寄存器使用规则 2 必须保护C函数要用到的几个特定寄存器 3 如果要改变状态寄存器的任何位 必须确保恢复出它们的值 4 中断程序必须保护所有用到的寄存器 5 从汇编程序调用C函数时 以逆序方式将参数压入堆栈 调用之后 将参数弹出 6 调用C函数时 注意C函数只保护了几个特定的专用寄存器 其他寄存器C函数可以自由使用 7 长整型和俘点数在存储器中存放的顺序是低位字在低地址 高位字在高地址 8 如果函数有返回值 返回值存放在累加器ACC中 9 汇编模块不能改变由C产生的 cinit块 10 编译器在所有的标识符 函数名 变量名等 前加一下划线 因此 编写汇编语言程序时 必须在C程序可以访问的所有对象前加 11 任何在汇编中定义的对象或函数 如果需要在C中访问或调用 则必须用汇编指令 global定义 同样 如果在C中定义的对象或函数 需要在汇编中访问或调用 在汇编中也必须用 global定义 1 C主程序 cmian c externintasmfunc 定义外部的汇编函数intgvar 定义全局变量main inti i asmfunc i 调用函数 2 汇编语言函数 asmfunc asmsub c global asmfunc global gvar text asmfunc POPD 将返回地址保存至C堆栈SARAR0 保护FPSARAR1 保护SPLARAR0 1 帧长度LARAR 0 AR2 建立FP和SP LDP gvar 指向 gvarSETCSXMLACC gvarLARAR2 3 参数偏移MAR 0 指向参数ADD AR0 将参数加至gvarSACL gvarMAR AR1SBRK2LARAR0 恢复帧指针PSHD 返回地址压入C24x堆栈RET end 8 6 2在C语言中直接嵌入语句 是一种直接的C和汇编接口方法 可以在C程序中实现用C语言无法实现的一些硬件控制功能 asm 汇编语句 注意以下几点 1 防止嵌入的asm语句破坏C环境 2 在C代码中插入跳转或标号可能会影响代码产生器的寄存器跟踪算法 产生不可预测的结果 3 插入影响编译环境的伪指令也可能会造成麻烦 4 不要改变C变量值 但可以读取变量值 如上 在程序中直接嵌入汇编语句的典型应用是控制芯片的一些硬件资源 include exp4 2407 h voidsys ini 系统初始化子程序10008AA0POPD 100180A0SARAR0 10028180SARAR1 1003B001LARAR0 1h100400E0LARAR0 0 关总中断 asm setcINTM 1005BE41SETCINTM 抑制符号位扩展 asm clrcSXM 1006BE46CLRCSXM 累加器中结果正常溢出 asm clrcOVM 1007BE42CLRCOVM 禁止看门狗 WDCR 0 x00E8 1008BD00LDP 100h10090300LARAR3 0h100AB9E8LACL e8h100B8B8BMAR AR3100C908CSACL 0 AR4 CLKIN 10M CLKOUT 40M SCSR1 0 x0000 100D0401LARAR4 1h100EB900LACL 0h100F9089SACL 0 AR1 10107C02SBRK 2h10110090LARAR0 10127680PSHD 1013EF00RET voiddelay 10148AA0POPD 101580A0SARAR0 10168180SARAR1 1017B004LARAR0 4h101800EALARAR0 0 AR2 unsignedintk for k 0 k 60000 k 1019B900LACL 0h101AB201LARAR2 1h101B8BE0MAR 0 101C9080SACL 0101D6980LACL 101EE302BCND1020h NOV10208BA0MAR 10219

温馨提示

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

评论

0/150

提交评论