310 likes | 469 Views
实时信号处理系统设计. 第四讲 DSP 的软件开发 (1). 联系方式 :zyh@ccee.cqu.edu.cn 重庆大学通信工程学院. 本节内容 :. C6000 C 运行时环境. C6000 C run-time environment 定义. The run time parameters in which your program must function. These parameters are defined by 1.the memory conventions 2.register conventions
E N D
实时信号处理系统设计 第四讲 DSP的软件开发(1) 联系方式:zyh@ccee.cqu.edu.cn 重庆大学通信工程学院
本节内容: C6000 C 运行时环境
C6000 C run-time environment定义 The run time parameters in which your program must function. These parameters are defined by 1.the memory conventions 2.register conventions 3.stack organization, 4.function call conventions 5.system initialization.
存储器模型 • C6000编译器把整个存储区当作单个线性存储块,并将它分为代码区和数据区 • 编译器假定目标存储器的全部32-bit地址空间是可用的。 • 定义存储器映象并将代码和数据分配到目标存储器的是连接器,而非编译器。 • Cmd文件是linker使用的。 • 使用.map文件
段 & 已初始化段 编译器生成的可重定位的代码和数据块称为段(sections) 已初始化的段:包含数据和可执行代码。C/C++编译器生成的已初始化的段有: (1).cinit段:包括变量初始值和常量值。 (2).const段:包括字符串文字(string literals),浮点常量和在C/C++中被声明为const的数据(如果常量没有同时被声明为volatile)。 (3).switch段:包含大的switch语句的跳转表(jump table) (4).text段:包含所有的可执行代码。
未初始化段 • 未初始化的段:存储器(一般指RAM)中的保留空间。程序在运行时用它来创建和存储变量。C/C++编译器生成的未初始化的段有: • (1).bss段:为全局变量和静态变量保留。如果为连接器设定-c选项,则在程序的开始,C引导程序会将.cinit段的数据(可在ROM中)复制到.bss段。编译器定义全局符号$bss,并指定它为.bss段的起始地址。 • (2).far段:为声明为far的全局变量和静态变量保留。 • (3).stack段:系统堆栈。这个存储区用于传递函数的参数和为局部变量分配存储器空间。 • (4).sysmem段:为动态存储空间分配保留的存储区。提请动态存储空间分配要求的有malloc,calloc和realloc等函数。如果C/C++程序未使用这些函数,编译器便不生成该段。
不同的bss段地址,.cinit中不同的内容(.out文件中)不同的bss段地址,.cinit中不同的内容(.out文件中)
段的补充 • 汇编器产生默认的.text,.bss和.data段,但C/C++编译器不使用.data段。允许用CODE_SECTION和DATA_SECTION pragma来让编译器生成另外的段。 • 除了.text,.vectors段,各个初始化段和非初始化段均不能分配到内部程序存储器。
系统堆栈 编译器将堆栈用于: • Save function return addresses • Allocate local variables • Pass arguments to functions • Save temporary results 运行时堆栈增长方向是从高向低,编译器用B15寄存器来管理堆栈,即将它作为堆栈指针(SP),指向堆栈中下一个空闲的存储器位置。
初始化变量 • C/C++编译器生成的代码可固化到ROM中,.cinit段的初始化表也是贮存在ROM中。在系统初始化的时候,C/C++引导程序将表中的数据(ROM中)拷贝给.bss段中对应的变量(RAM中)。 • 如果程序是从目标文件直接载入存储器,然后运行时,可以无需.cinit段。加载器(loader)直接地从目标文件中读出初始化表(而不是从ROM中),在加载时完成初始化,而不是运行时。这个过程可以通过为连接器指定–cr选项来实现。
存储器模式 (-mln) • 小存储器模式和大存储器模式。它们的区别在于为.bss段分配存储空间的方式。 • 小存储器模式:.bss 32KByte,使用DP(B14)访问全局数据:LDW *+DP(0x7),B5 • 大存储器模式:不限制.bss段的大小,访问数据使用MVKL & MVKH:MVKL _x, A0 MVKH _x, A0 LDW *A0, B0
寄存器使用规范 • 在C/C++环境下,一些具体的操作要使用哪些的寄存器来完成,是有严格的规范的。 • 寄存器使用规范规定了编译器使用寄存器的方法以及函数调用过程中数值保存的方法。 • 要在C/C++程序中嵌入汇编语言,必须理解并遵循寄存器使用规范。
函数调用约定 • 函数(父函数)在调用另一个函数(子函数)的时候执行下列操作 • (1)将传递到子函数的参数放入寄存器或堆栈。
函数调用(父函数) • (2)如果需要,保存寄存器(a/b0~9)到堆栈。(调用子函数后要再用到其中的值) • (3)调用者(父函数)调用函数(子函数)。
函数调用(子函数) (1)被调函数(子函数)为所有的局部的变量、临时存储区和它调用的函数的参数分配足够的堆栈空间。 (2)如果被调函数还继续调用其他的函数,返回地址必须保存在堆栈中。 (3)如果被调函数修改寄存器A10到A15或者B10到B15的值,必须将它们保存。 (4)被调函数执行其代码。 (5)存放返回值在A5:A4中。 (6)恢复3中保留的寄存器值 (7)释放1分配的堆栈 (8)利用B3,跳转返回父函数
C/ C++与汇编语言的接口 • 使用独立的汇编代码模块,并将其与编译完的C/C++模块连接在一起 • 在C/C++源程序中使用内联函数(intrinsics),直接地调用汇编语句 • 使用内联(inline) 汇编语言直接嵌入C/C++源程序 • 在C/C++源程序中使用汇编程序变量和常量
内联函数(intrinsics) • C6000编译器可以识别若干内联函数。内联函数直接调用某些汇编语句,这些汇编语句在C/C++中实现起来是很繁复或难以表达的。 • int x1, x2, y;//饱和加法y = _sadd(x1, x2);
内联(inline)汇编语言 • asm(”;*** 这是汇编语言的注释”); • 要很小心不要破坏C/C++环境。对插入的汇编指令,编译器不做任何检查或者分析。
系统初始化 • 运行一个C/C++程序之前,必须建立C/C++运行环境。这个工作是由C/C++引导程序调用c_int00函数完成的。 • 系统运行开始时,跳转到或调用c_int00函数,但通常是硬件复位中断的中断服务程序调用它的。 • 1)定义系统堆栈.stack段并初始化堆栈指针。 • 2)定义.bss并初始化DP指针 • 3)初始化全局的变量,这是通过将.cinit段中的初始化表复制给.bss段中为变量分配的存储空间来完成的。如果是在加载时初始化变量(–cr选项),加载器(loader)在程序运行之前就完成了这个步骤(它不是通过引导程序执行的)。 • 4)调用main函数来运行C/C++程序。
C_int_00源码0 #define CINIT ((void*)&__cinit__) extern far int __cinit__; extern far int main(); extern far void exit(int status); extern far void _auto_init(const void *cinit); /*-----------------------------------------------------------------------*/ /* ALLOCATE THE MEMORY FOR THE SYSTEM STACK. THIS SECTION WILL BE SIZED */ /* BY THE LINKER. */ /*---------------------------------------------------------------------------*/ __asm("\t.global __STACK_SIZE"); #pragma DATA_ALIGN (_stack, 8); #pragma DATA_SECTION (_stack, ".stack"); char _stack[8];
C_int_00源码 1 extern void __interrupt c_int00() /*----------------------------------------------------------------*/ /* SET UP THE STACK POINTER IN B15. */ /* THE STACK POINTER POINTS 1 WORD PAST THE TOP OF THE STACK, SO SUBTRACT */ /* 1 WORD FROM THE SIZE. ALSO THE SP MUST BE ALIGNED ON AN 8-BYTE BOUNDARY*/ /*------------------------------------------------------------------------*/ __asm("\t MVKL\t\t __stack + __STACK_SIZE - 4, SP"); __asm("\t MVKH\t\t __stack + __STACK_SIZE - 4, SP"); __asm("\t AND\t\t ~7,SP,SP"); /*------------------------------------------------------------------------*/ /* SET UP THE GLOBAL PAGE POINTER IN B14. */ /*------------------------------------------------------------------------*/ __asm("\t MVKL\t\t $bss,DP"); __asm("\t MVKH\t\t $bss,DP");
C_int_00源码 2 /*------------------------------------------------------------------------*/ /* SET UP FLOATING POINT REGISTERS FOR C70 ONLY */ /*------------------------------------------------------------------------*/ #ifdef _TMS320C6700 FADCR = 0; FMCR = 0; #endif /*------------------------------------------------------------------------*/ /* CALL THE AUTOINITIALIZATION ROUTINE. */ /*----------------------------------------------------------------------*/ _auto_init(CINIT); /*------------------------------------------------------------------------*/ /* CALL THE USER'S PROGRAM. */ /*------------------------------------------------------------------------*/ main(); /*------------------------------------------------------------------------*/ /* CALL EXIT. */ /*------------------------------------------------------------------------*/ exit(1); }
Boot.obj 完成工作: • Sets up the system stack and configuration registers • Processes the run-time .cinit initialization table and autoinitializes globalvariables (when the linker is invoked with the –c option) • Disables interrupts and calls _main
c_int00 function The c_int00 function performs the following tasks to initialize the environment: 1) It defines a section called .stack for the system stack and sets up the initial stack pointers. 2) It initializes global variables by copying the data from the initialization tables in the .cinit section to the storage allocated for the variables in the.bss section. If you are initializing variables at load time (–cr option), a loader performs this step before the program runs (it is not performed by the boot routine). 3) It calls the function main to run the C/C++ program.
参考文献 1. TMS320C6000 Assembly Language Tools User's Guide, SPRU186; 2. TMS320C6000 Optimizing Compiler User's Guide, SPRU187;