TMS320F280049C 学习笔记9 CMD文件 程序从FLASH复制到RAM中运行
文章目录
- 动机
- 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 = 0x000002RAMM0 : origin = 0x0000F3, length = 0x00030DRAMLS0 : origin = 0x008000, length = 0x000800RAMLS1 : origin = 0x008800, length = 0x000800RAMLS2 : origin = 0x009000, length = 0x000800RAMLS3 : origin = 0x009800, length = 0x000800RAMLS4 : origin = 0x00A000, length = 0x000800RESET : 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 = 0x000800RAMLS6 : origin = 0x00B000, length = 0x000800RAMLS7 : origin = 0x00B800, length = 0x000800RAMGS0 : origin = 0x00C000, length = 0x002000RAMGS1 : origin = 0x00E000, length = 0x002000RAMGS2 : origin = 0x010000, length = 0x002000RAMGS3 : 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
#endiframgs0 : > RAMGS0, PAGE = 1ramgs1 : > 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 RAM
- TMS320F28069: 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 Guide
- Compiler/TMS320F28075: [Warnings] #10247-D creating output section “xxxxx” without a SECTION specification
- 如何理解CMD文件中的ALIGN?
- TMS320F28388D: ALIGN(4) vs. ALIGN(8) in cmd files
- TMS320F280049C: 自问自答: 怎么在cmd文件中将.lib库中的部分文件链接至ram运行区?
TMS320F280049C 学习笔记9 CMD文件 程序从FLASH复制到RAM中运行相关推荐
- DSP28377S_程序从FLASH部分复制到RAM中运行详解
程序从FLASH部分复制到RAM中运行详解 为什么要复制到RAM中运行 CMD文件中对存储空间的分配 CMD文件中对段的定义 CMD文件中FLASH部分复制到RAM中的定义 main中的操作 编译后如 ...
- MDK生成的BIN文件用DNW通过USB下载RAM中运行的问题
通过Keil编译生成的Bin文件如何用DNW的USB下载到RAM中去执行: 这里要保证DNW的设置中的USB的DOWNLOAD ADDRESS的值和KEIL工程的分散加载文件的RO的地址要一致,否则将 ...
- [python教程入门学习]python学习笔记(CMD执行文件并传入参数)
本文章向大家介绍python学习笔记(CMD执行文件并传入参数),主要包括python学习笔记(CMD执行文件并传入参数)使用实例.应用技巧.基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋 ...
- TMS320F280049C 学习笔记19 可配置逻辑块 (CLB) 软件配置
文章目录 CLB tool 简介 CLB配置过程概述 软件安装 GNU Compiler Install the Simulation Viewer 使用CLB tool 导入空CLB工程 更新变量路 ...
- C++学习笔记之对文件的操作2
转载自** https://www.cnblogs.com/uniqueliu/archive/2011/08/03/2126680.html ** 什么都不说了,继续<C++学习笔记之对文件的 ...
- TMS320F280049C 学习笔记31 控制率加速器 CLA 学习随笔
文章目录 前言 文献阅读记录 整数比较时的注意点 参考文献 前言 去年在入门DSP的时候曾对控制率加速器(Control Law Accelerator, CLA)做过初步的学习[1][2],但后来的 ...
- Python学习笔记D9(文件)
Python学习笔记D9(文件) 文件 1.打开文件 open(file, mode='r') 接收两个参数:文件名(file)和模式(mode),用于打开一个文件,并返回文件对象,如果该文件无法被打 ...
- 【FastDDS学习笔记】HelloWorld示例程序编译和运行
目录 第一章:[FastDDS学习笔记]Ubuntu22上安装fastDDS环境 第二章:[FastDDS学习笔记]HelloWorld示例程序编译和运行 第三章:[FastDDS学习笔记]Fast- ...
- Keras学习笔记---保存model文件和载入model文件
Keras学习笔记---保存model文件和载入model文件 保存keras的model文件和载入keras文件的方法有很多.现在分别列出,以便后面查询. keras中的模型主要包括model和we ...
最新文章
- Effective C++学习笔记(Part Five:Item 26-31)
- 嵌入式学习笔记之XMODEM
- 刚刚,科学家发现了一大堆解释人类进化的基因...
- html根据文档定位,html文档中的location对象属性理解及常见的用法
- 应用程序窗口hwnd初始化_Golang OpenGL 跨平台图形程序开发(2)你好,窗口
- srpg 胜利条件设定_英雄联盟获胜条件
- codesys raspberry pi_pi进不去的几种解决方法!
- Spring Data JPA 从入门到精通~如何配置多数据源
- java 大小固定_为什么Java堆的最大大小是固定的?
- lvs-nat负载均衡实验
- oracle aq hang,AQ: dequeue的时候hang住
- ks线切割编程系统3.13完整版-2次加密注册码
- 02333自考软件工程知识点总结、考点串讲、考前复习
- 微信服务号的模板消息有哪些优势和使用限制?
- 计算机网络:应用层 - 万维网 WWW、HTTP 协议以及 HTML 语言
- 《科学》:基因编辑婴儿入选年度“科学崩坏”事件
- strstr()函数
- sd卡tf卡进入spi模式
- Tomcat 环境变量配置
- 请问有什么控件可以方便的实现呢