赞
踩
__attribute__((ramfunc))
举例:
__attribute__((ramfunc)) // 需要添加的代码
__interrupt void adcA1ISR(void) // 想要复制到ram的程序,以ADC中断程序为例
{
}
本文后面的内容其实没必要看…………
一般建议将实时性要求比较高的代码,比如中断程序,和FLASH初始化相关的代码,放在RAM上运行。[1]
在F2837xD/37xS/07x系列芯片里,它们使用的Flash是最新的65nm工艺(相比之前的是180nm),其Flash运算速度和执行效率已经大幅提高,等待周期也可以减少,因此会非常接近RAM上的速度,根据不同的代码,你可以参考下面的相关数据(请注意,Flash wait states是根据工艺强制要求的,比如F28335运行150MHz主频时,必须至少要5个,而F2837x则只需要2个 ):
以下表格出自:
建议首先阅读[2],这是一份写于2009年的文档,适合入门。
进一步的学习资料可以参考[3],本小节根据[3]的内容并结合280049C的实际进行总结。
280049C的片上存储器包含256KB (128KW)的ROM和100KB(50KW)的RAM。
MEMORY和SECTIONS指令是CMD文件中的核心指令。
MEMORY指令用来指示存储空间,SECTIONS指令用来分配“段”到存储空间,即指定“段”的实际硬件空间。
本节的代码示例来自28004x_generic_ram_lnk.cmd
作用:指示存储空间
MEMORY
{
PAGE 0 :
name 0[(attr)]:orgin=constant , length=constant;
PAGE n :
name n[(attr)]:orgin=constant , length=constant;
}
MEMOR
MEMORY { PAGE 0 : /* BEGIN is used for the "boot to SARAM" bootloader mode */ BEGIN : origin = 0x000000, length = 0x000002 RAMM0 : origin = 0x0000F3, length = 0x00030D RAMLS0 : origin = 0x008000, length = 0x000800 RAMLS1 : origin = 0x008800, length = 0x000800 RAMLS2 : origin = 0x009000, length = 0x000800 RAMLS3 : origin = 0x009800, length = 0x000800 RAMLS4 : origin = 0x00A000, length = 0x000800 RESET : origin = 0x3FFFC0, length = 0x000002 /* Flash sectors: you can use FLASH for program memory when the RAM is filled up*/ /* BANK 0 */ FLASH_BANK0_SEC0 : origin = 0x080000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC1 : origin = 0x081000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC2 : origin = 0x082000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC3 : origin = 0x083000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC4 : origin = 0x084000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC5 : origin = 0x085000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC6 : origin = 0x086000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC7 : origin = 0x087000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC8 : origin = 0x088000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC9 : origin = 0x089000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC10 : origin = 0x08A000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC11 : origin = 0x08B000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC12 : origin = 0x08C000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC13 : origin = 0x08D000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC14 : origin = 0x08E000, length = 0x001000 /* on-chip Flash */ FLASH_BANK0_SEC15 : origin = 0x08F000, length = 0x001000 /* on-chip Flash */ /* BANK 1 */ FLASH_BANK1_SEC0 : origin = 0x090000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC1 : origin = 0x091000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC2 : origin = 0x092000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC3 : origin = 0x093000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC4 : origin = 0x094000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC5 : origin = 0x095000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC6 : origin = 0x096000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC7 : origin = 0x097000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC8 : origin = 0x098000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC9 : origin = 0x099000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC10 : origin = 0x09A000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC11 : origin = 0x09B000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC12 : origin = 0x09C000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC13 : origin = 0x09D000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC14 : origin = 0x09E000, length = 0x001000 /* on-chip Flash */ FLASH_BANK1_SEC15 : origin = 0x09F000, length = 0x001000 /* on-chip Flash */ PAGE 1 : BOOT_RSVD : origin = 0x000002, length = 0x0000F1 /* Part of M0, BOOT rom will use this for stack */ RAMM1 : origin = 0x000400, length = 0x0003F8 /* on-chip RAM block M1 */ // RAMM1_RSVD : origin = 0x0007F8, length = 0x000008 /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */ RAMLS5 : origin = 0x00A800, length = 0x000800 RAMLS6 : origin = 0x00B000, length = 0x000800 RAMLS7 : origin = 0x00B800, length = 0x000800 RAMGS0 : origin = 0x00C000, length = 0x002000 RAMGS1 : origin = 0x00E000, length = 0x002000 RAMGS2 : origin = 0x010000, length = 0x002000 RAMGS3 : origin = 0x012000, length = 0x001FF8 // RAMGS3_RSVD : origin = 0x013FF8, length = 0x000008 /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */ }
作用:分配段到存储空间,即指定段的实际硬件空间。
注意:SECTIONS字符是复数形式。
SECTIONS
{
name 0 :> 存储空间名称 , PAGE = 页数;
name n :> 存储空间名称 , PAGE = 页数;
}
/*You can arrange the .text, .cinit, .const, .pinit, .switch and .econst to FLASH when RAM is filled up.*/ SECTIONS { codestart : > BEGIN, PAGE = 0 .TI.ramfunc : > RAMM0, PAGE = 0 .text : >> RAMLS0 | RAMLS1 | RAMLS2 | RAMLS3 | RAMLS4, PAGE = 0 .cinit : > RAMM0, PAGE = 0 .switch : > RAMM0, PAGE = 0 .reset : > RESET, PAGE = 0, TYPE = DSECT /* not used, */ .stack : > RAMM1, PAGE = 1 #if defined(__TI_EABI__) .bss : > RAMLS5, PAGE = 1 .bss:output : > RAMLS5, PAGE = 1 .init_array : > RAMM0, PAGE = 0 .const : > RAMLS5, PAGE = 1 .data : > RAMLS5, PAGE = 1 .sysmem : > RAMLS5, PAGE = 1 .bss:cio : > RAMLS0, PAGE = 0 #else .pinit : > RAMM0, PAGE = 0 .ebss : > RAMLS5, PAGE = 1 .econst : > RAMLS5, PAGE = 1 .esysmem : > RAMLS5, PAGE = 1 .cio : > RAMLS0, PAGE = 0 #endif ramgs0 : > RAMGS0, PAGE = 1 ramgs1 : > RAMGS1, PAGE = 1 }
程序中存在众多的段,这些段分为两种:已初始化段和未初始化段。
部分段存在64KB大小的限制,关于这点可以参考[4]。
于2022年1月6日更新本小节,更全面的介绍可以参考TI官方的中文图书《TMS320C28X系列DSP指令和编程指南》
上一节讨论了CMD文件的结构,通常程序中的每一个变量和函数都会被编译器自动连接至指定的区域。但通过一些指令,也可以由用户自行指定某个函数或数据的存储位置。
实现方式参考文献[4],其中提到的手册为[5]。
这个东西网上的教程大多讲的十分复杂,比较新的教程可以参考[6]。
但其实这个需求TI已经给出了解决方案[7],在传统教程中提到的包括段定义、延时函数修改等一系列内容,在新版的库函数都已经给出了定义,不再需要我们自己添加[8]。
具体来说,只需要在函数声明前添加:
__attribute__((ramfunc))
举例:
__attribute__((ramfunc)) // 需要添加的代码
__interrupt void adcA1ISR(void) // 想要复制到ram的程序,以ADC中断程序为例
{
}
代码的效果很容易验证,只需要对比添加前后Debug文件夹下.map文件的内容即可。该文件描述了如何在ram和rom中分配代码中各个函数和变量的存储位置。
TI的wiki页面上说将在今年底关闭网站,所以将[7]的内容截图备份如下:
于2020年7月14日更新本小节。
在实际项目中偶然遇到编译器报如下警告:
#10247-D creating output section “AdcaRegsFile” without a SECTIONS specification
解决方案是根据芯片的不同,在工程中添加 F28xx_Headers_nonBIOS.cmd 即可[12]。
另外在[12]中有如下表述:
You can have two .cmd files in a project. The _BIOS or _nonBIOS cmd file defines the peripheral registers while the other .cmd file maps sections of memory and code.
The _BIOS cmd file is for DSP/BIOS and SYS/BIOS projects with an RTOS and does not have the PIE vector.
The _nonBIOS cmd file is for other projects and has the PIE vector table.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。