TMS320F280049C 学习笔记9 CMD文件 程序从FLASH复制到RAM中运行

您所在的位置:网站首页 dsp的cmd文件下载 TMS320F280049C 学习笔记9 CMD文件 程序从FLASH复制到RAM中运行

TMS320F280049C 学习笔记9 CMD文件 程序从FLASH复制到RAM中运行

2024-07-07 21:24| 来源: 网络整理| 查看: 265

文章目录 动机CMD文件结构与语法MEMORY和SECTIONS指令MEMORY指令SECTIONS指令 程序与数据段已初始化段未初始化段 其他指令 #pragma指令的使用程序从FLASH复制到RAM中运行方法备份 关于_BIOS.cmd 和 _nonBIOS.cmd文件参考文献 实现程序从FLASH复制到RAM中运行的方法(要求使用新编译器): 在函数声明前添加一行代码:

__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个 ): 在这里插入图片描述 以下表格出自: 在这里插入图片描述

CMD文件结构与语法

建议首先阅读[2],这是一份写于2009年的文档,适合入门。 进一步的学习资料可以参考[3],本小节根据[3]的内容并结合280049C的实际进行总结。 280049C的片上存储器包含256KB (128KW)的ROM和100KB(50KW)的RAM。

MEMORY和SECTIONS指令

MEMORY和SECTIONS指令是CMD文件中的核心指令。 MEMORY指令用来指示存储空间,SECTIONS指令用来分配“段”到存储空间,即指定“段”的实际硬件空间。 本节的代码示例来自28004x_generic_ram_lnk.cmd

MEMORY指令

作用:指示存储空间

MEMORY { PAGE 0 : name 0[(attr)]:orgin=constant , length=constant; PAGE n : name n[(attr)]:orgin=constant , length=constant; } MEMOR PAGE n表示把可用的资源空间再划分成几个大块,最多允许分256块,从PAGE 0到 PAGE 255。通常习惯于把PAGE 0作为程序空间,把 PAGE 1作为数据空间。name n为存储空间名;orgin用来标明该段的起始地址;length用来指示该段的长度。 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字符是复数形式。

SECTIONS { name 0 :> 存储空间名称 , PAGE = 页数; name n :> 存储空间名称 , PAGE = 页数; } name n为段名;“: >”为内存分配符,等效于load =,代表数段的存储位置,有时也会用到run关键字,代表段的运行位置;">>"表示多片空间串起来“存储空间名称”为MEMORY中已经分配好的存储空间名称。 /*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]。

已初始化段 .text C语言编译后生成的二进制指令代码段。我们编写的main主函数,子函数或子程序,中断服务程序,都会产生指令代码,都属于这个段;.cinit 存放初始化的全局和静态变量;.const 字符串常量和const定义的全局和静态变量;.econst 字符串常量和far const定义的全局和静态变量;.pinit 全局变量的构造函数(C++语言)程序列表,在新标准中有时用.init_array段表示;.switch 存放switch语句产生的常数表格;.vectors 中断向量段,也就是中断服务程序的入口地址段。 未初始化段 .bss 为全局变量和局部变量保留的空间,在程序上电时.cinit空间中的数据复制出来并存储到.bss空间中;.ebss 为使用大寄存器模式时的全局变量和静态变量预留的空间,在程序上电时,cinit空间中的数据复制出来并存储在.ebss中;.stack 堆栈空间,主要用于函数传递变量或为局部变量分配空间;.sysmem 为动态存储分配保留的空间(malloc),如果有宏函数,此空间被占用;.esysmen 为动态存储分配保留的空间(far malloc),如果有far函数,此空间会被占用。 其他指令

于2022年1月6日更新本小节,更全面的介绍可以参考TI官方的中文图书《TMS320C28X系列DSP指令和编程指南》

ALIGN 位对齐[13],常用于FFT。另外,TI推荐在第3代DSP中不再适用ALIGN(4),而是全部适用ALIGN(8) [14] #pragma指令的使用

上一节讨论了CMD文件的结构,通常程序中的每一个变量和函数都会被编译器自动连接至指定的区域。但通过一些指令,也可以由用户自行指定某个函数或数据的存储位置。 实现方式参考文献[4],其中提到的手册为[5]。

注意: 不能在函数体内声明#pragma; 必须在符号被定义和使用之前声明#pragma 程序从FLASH复制到RAM中运行

这个东西网上的教程大多讲的十分复杂,比较新的教程可以参考[6]。 但其实这个需求TI已经给出了解决方案[7],在传统教程中提到的包括段定义、延时函数修改等一系列内容,在新版的库函数都已经给出了定义,不再需要我们自己添加[8]。

方法

具体来说,只需要在函数声明前添加:

__attribute__((ramfunc))

举例:

__attribute__((ramfunc)) // 需要添加的代码 __interrupt void adcA1ISR(void) // 想要复制到ram的程序,以ADC中断程序为例 { }

代码的效果很容易验证,只需要对比添加前后Debug文件夹下.map文件的内容即可。该文件描述了如何在ram和rom中分配代码中各个函数和变量的存储位置。

备份

TI的wiki页面上说将在今年底关闭网站,所以将[7]的内容截图备份如下: 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

关于_BIOS.cmd 和 _nonBIOS.cmd文件

于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.

参考文献 28377D中代码在RAM和FLASH中执行时,效率差多远cmd文件原理——玄德CMD文件详解与DSP存储空间#pragma DATA_SECTION与#pragma CODE_SECTION的使用Programming TMS320x28xx and TMS320x28xxx Peripherals in CC++DSP28377S_程序从FLASH部分复制到RAM中运行详解Placing functions in RAMTMS320F28069: attribute((ramfunc)) this method does not require memcpy like older #pragma method nedded?Copying Compiler Sections From Flash to RAM on the TMS320F28xxx DSCs把DSP TMS320F28XXX的程序段从flash复制到ram中运行C2000™ Key Technology GuideCompiler/TMS320F28075: [Warnings] #10247-D creating output section “xxxxx” without a SECTION specification如何理解CMD文件中的ALIGN?TMS320F28388D: ALIGN(4) vs. ALIGN(8) in cmd filesTMS320F280049C: 自问自答: 怎么在cmd文件中将.lib库中的部分文件链接至ram运行区?


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3