一、上电过程
引自:http://bbs.eeworld.com.cn/thread-262789-1-1.html
1:上电运行时根据MP/MC引脚的状态决定是从片外的3fffc0处读取复位向量或者时从片内的rom的3fffc0处读取
复位向量。MC方式下从片内读取,MP方式下从片外读取。
2:一般我们用的是MC方式,即从片内读取复位向量,在片内的rom 3fffc0处有一个地址为3ffc00。
3:复位后处理器从3fffc0处读取3ffc00这个地址,所以程序从3ffc00处开始执行
4:3ffc00处开始的就是initboot起始函数,根据IO管脚的状态判断该进入那一种引导方式,也就是根据引脚状
态来判断3ffc00处的跳转地址
5:在SCITXA引脚为高电平时就是flash boot方式,此时置3ffc00处存放的就是03F7FF6
6:在片内flash的3F7FF6和3F7FF7处有一个跳转指令,该跳转指令就是LB _c_int00,封装在"rts2800_ml.lib"
内的函数。
7:执行这个跳转指令后程序就开始运行c_int00这个函数了
8:这个函数就是建立一个c程序的运行环境,等建立完c运行环境后c_int00调用main函数,main函数的调用是由
c_int00这个函数来做的,不用我们自己操心,我们要做的就是把合适的引导程序放在3F7FF6处,实际需要做的
就是把codestart段定位到03F7FF6这个地址就行了
而codestart是怎么定位到c_int00这个函数的呢
看DSP281x_CodeStartBranch.asm汇编代码
.sect "codestart"
code_start:
.if WD_DISABLE == 1
LB wd_disable ;Branch to watchdog disable code 跳转到下面
.else
LB _c_int00 ;Branch to start of boot.asm in RTS library 跳转到 _c_init00
.endif
.if WD_DISABLE == 1
.text
wd_disable: //汇编禁止看门狗程序
SETC OBJMODE
EALLOW
MOVZ DP, #7029h>>6
MOV @7029h, #0068h
EDIS
LB _c_int00 跳转到 _c_init00
.endif
.end
在0x3F7FF6取出跳转指令,跳转到自己的制定地址或者C初始化的入口_C_INT00处,在C初始化的入口_C_INT00对
一些变量,堆栈和寄存器进行必要的设置,该函数在C的库函数内,封装在"rts2800_ml.lib",最后进入Main函数
;
9:main函数开始就是我们自己编写的应用程序了。
以上是2812上电(复位)后运行过程的描述
当GPIOF4==1时,InitBoot程序跳转到ox3f7ff6,同时将控制权交给编程人员.
因此.cmd文件如下:
{
......
BEGIN : origin = 0x3f7ff6, length = 0x000002
}
{
.......
codestart : > BEGIN, PAGE = 0
}
当需要用片内18K的RAM时行仿真时,可在0x3f7ff6处预先烧写一转跳指令(只需烧写一次).如:
LB 0x3F8000
上面这一步很可能是仿真器干的
使程序初始化后转跳至RAM空间.然后在RAM空间内写入仿真程序即可,此时.CMD 头文件如下:
MEMORY
{
PAGE 0 :
/* For this example, H0 is split between PAGE 0 and PAGE 1 */
/* BEGIN is used for the \"boot to HO\" bootloader mode */
/* RESET is loaded with the reset vector only if */
/* the boot is from XINTF Zone 7. Otherwise reset vector */
/* is fetched from boot ROM. See .reset section below */
RAMM0 : origin = 0x000000, length = 0x000400
BEGIN : origin = 0x3f8000, length = 0x000002 /*IN FLASH THE ORIGIN IS 0x3f7ff6, IN RAM
THE ORIGIN IS 0x3f8000 */
PRAMH0 : origin = 0x3f8002, length = 0x000ffd /* */
RESET : origin = 0x3FFFC0, length = 0x000002
RAML0 : origin = 0x8000, length = 0x001000
RAML1 : origin = 0x9000, length = 0x001000
PAGE 1 :
/* For this example, H0 is split between PAGE 0 and PAGE 1 */
ARAML0 : origin = 0x8000, length = 0x001000 /* */
RAMM1 : origin = 0x000400, length = 0x000400
DRAMH0 : origin = 0x3f9000, length = 0x001000
}
关于 reset段,描述如下
/* .reset is a standard section used by the compiler. It contains the */
/* the address of the start of _c_int00 for C Code. /*
/* When using the boot ROM this section and the CPU vector */
/* table is not needed. Thus the default type is set here to */
/* DSECT */
.reset : > RESET, PAGE = 0, TYPE = DSECT
vectors : > VECTORS PAGE = 0, TYPE = DSECT
reset段存储初始化函数(如_c_int00)的入口地址,如果引导模式选择的是boot ROM, 那么复位后自动跳转到
0x3fffc0处执行固化在rom里的引导程序,后又跳转到0x3f7ff6,执行用户程序(包括初始化程序),这时
候,.reset段就不需要,所以type = dsect。复位向量也是默认值,存储在ROM内,因此vectors段也没有用到。
但是如果引导模式在外部的存储区,此时的bootROM是ZONE7,即用户可以自定义引导程序,将引导程序入口地址
写到0x3fffc0,这个地址此时是ZONE7,然后再跳转到reset段,reset段就可以用到了,当然这个reset段的设置
肯定要自己实现。像DSP281x_CodeStartBranch.asm设置_c_int00一样。
RAM调试不存在上电过程,因此也就不存在bootloader这种东西的执行过程,因此可能是仿真器在设置/掌控这一
切,只需要把入口地址(codestart)设置在3f8000这个位置就好。点击运行的时候,就会跳转到这里,执行
_c_int00函数初始化c环境然后调用main函数。
二、CMD文件
引自:http://blog.csdn.net/u011392772/article/details/49760897
CMD:command命令,顾名思义就是命令文件指定存储区
域的分配.2812的CMD采用的是分页制,其中PAGE0用于存放程序空间,而PAGE1用于存放数据空间。
1.)#pragma ,CODE_SECTION和DATA_SECTION伪指令
#pragma DATA_SECTION(funcA,"dataA"); ------ 函数外声明
将funcA数据块定位于用户自定义的段"dataA"中 ------ 需要在CMD中指定dataA段的物理地址
2.)MEMORY和SECTIONS是命令文件中最常用的两伪指令。MEMORY伪指令用来表示实际存在目标系统中的可以使用
的存储器范围,在这里每个存储器都有自己的名字,起始地址和长度。SECTIONS伪指令是用来描述输入端是如何
组合到输出端内的。
CMD文件里有两个基本的段:初始化段和非初始化段。初始化段包含代码和常数等必须在DSP上电之后有效的数。
故初始化块必须保存在如片内FLASH等非遗失性存储器中,非初始化段中含有在程序运行过程中才像变量内写数
据进去,所以非初始化段必须链接到易失性存储器中如RAM。
已初始化的段:.text,.cinit,.const,.econst,..pinit和.switch..
.text:所有可以执行的代码和常量
.cinit:全局变量和静态变量的C初始化记录
.const:包含字符串常量和初始化的全局变量和静态变量(由const)的初始化和说明
.econst:包含字符串常量和初始化的全局变量和静态变量(由far const)的初始化和说明
.pinit:全局构造器(C++)程序列表
.switch:包含switch声明的列表
非初始化的段:.bss,.ebss,.stack,.sysmem,和esysmem.(更好的理解就是,这些段就是存储空间而已)
.bss: 为全局变量和局部变量保留的空间,在程序上电时.cinit空间中的数据复制出来并存储在.bss空间中。
.ebss:为使用大寄存器模式时的全局变量和静态变量预留的空间,在程序上电时,cinit空间中的数据复制出来
并存储在.ebss中
.stack:为系统堆栈保留的空间,用于和函数传递变量或为局部变量分配空间。
.sysmem:为动态存储分配保留的空间。如果有宏函数,此空间被宏函数占用,如果没有的话,此空间保留为0
.esysmem:为动态存储分配保留的空间。如果有far函数,此空间被相应的占用,如果没有的化,此空间保留为0.
对于程序在FLASH中运行时,需要注意的: DSP在150M时钟频率下,FLASH中只能提供大约120M的时钟频率,所以
有时候我们希望在RAM中运行时间敏感或计算量很大的子程序(比如AD采样)。但是我们所有代码都放在FLASH中
,这就必须在上电后将FLASH中的这段敏感程序复制到RAM中运行,加快速度。这是在.CMD文件就必须划分一段用
来设置RAM的载入和运行地址。程序代码如下:
SECTIONS {………
ramfuncs : LOAD = FLASHD,
RUN = RAML0,
LOAD_START(_RamfuncsLoadStart),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
PAGE = 0
}
cmd小技巧:
如果.text文件很大将其放在一段放不下,需将其放到两个程序段中
最长的一个length=0x002000,也放不下时.可以这样处理:
PAGE 0 :
PRAMH0 : origin = 0x3F8002, length = 0x0014FE
L0RAM : origin = 0x008000, length = 0x001000
SECTIONS
.text:{*(.text)} >>PRAMH0|L0RAM
这样就可以将.text文件放在两个定义段中。
查看段的分配及使用情况.map的链接器(存储器)分配映射文件,链接器的map文件描述以下内容: 通过map文
件可以查看各段的分配情况,包括段的起始地址,使用的字节数等配合cmd文件的使用,可确定各个段的使用情
况,从而保证程序的正常运行和最小的空间使用。