siyeb 发表于 2014-12-18 20:25:54

原创:28335的程序到底是在哪里运行的。

最近在研究28335的自升级问题,没想到自升级没结局,倒有了个新收获。

之前一直认为,程序在Flash中运行和在SRAM运行的主要不同点就在于以下的代码:

MemCopy(
      &RamfuncsLoadStart,
      &RamfuncsLoadEnd,
      &RamfuncsRunStart);

InitFlash();

由于当初理解的并不全面,囫囵吞枣,看程序能在FLASH中启动了也就没有再审追究。直到今天才有了新的认识。Σ( ° △ °|||)︴

先来看看在RAM中运行的CMD文件是什么样子的:

codestart      : > BEGIN,   PAGE = 0
ramfuncs         : > RAML0,   PAGE = 0
.text            : > RAML1,   PAGE = 0
.cinit         : > RAML0,   PAGE = 0
.pinit         : > RAML0,   PAGE = 0
.switch          : > RAML0,   PAGE = 0

.stack         : > RAMM1,   PAGE = 1
.ebss            : > RAML4,   PAGE = 1
.econst          : > RAML5,   PAGE = 1
.esysmem         : > RAMM1,   PAGE = 1

IQmath         : > RAML1,   PAGE = 0
IQmathTables   : > IQTABLES,PAGE = 0, TYPE = NOLOAD

可以看见所有字段均是在存储在RAM中,尤其注意.text(也就是程序存储运行位置),而固化到FLASH中的CMD文件又是什么样子嘞?

.cinit            : > FLASHA      PAGE = 0
   .pinit            : > FLASHA,   PAGE = 0
   .text               : > FLASHA      PAGE = 0
   codestart         : > BEGIN       PAGE = 0

   ramfuncs            : LOAD = FLASHD,   
                         RUN = RAML0,   
                         LOAD_START(_RamfuncsLoadStart),
                         LOAD_END(_RamfuncsLoadEnd),
                         RUN_START(_RamfuncsRunStart),
                         PAGE = 0
   .stack            : > RAMM1       PAGE = 1
   .ebss               : > RAML4       PAGE = 1
   .esysmem            : > RAMM1       PAGE = 1
   .econst             : > FLASHA      PAGE = 0
   .switch             : > FLASHA      PAGE = 0   

此时的函数存储运行空间已经变成了FLASH,也就是在无特殊声明的情况下,程序是在FLASH里面跑的。
此前一直错误的以为MemCopy() 函数时将flash中的所有程序均拷贝到内存中运行,现在可以比肩肯定的说:这完全是瞎扯。那真相是什么嘞?
真相就是,memcpy只是拷贝了FLASH中特定段内的内容到RAM中运行。在这里,拷贝的就是ramfuncs段中的函数。
通过查看.map文件可以得到:

ramfuncs   0    00320000    0000001f   RUN ADDR = 00008000
                  00320000    0000001b   DSP2833x_SysCtrl.obj (ramfuncs)
                  0032001b    00000004   DSP2833x_usDelay.obj (ramfuncs)

在ranfuncs中有两个函数,一个是usDelay();另外一个是InitFalsh();
在usDelay.asm文件中可以找到这么一句:
.sect "ramfuncs"
同样的,在DSP28x_usDelay.c中可以找到这句:
#pragma CODE_SECTION(InitFlash, "ramfuncs");
这两句就是对函数的运行空间做了具体的映射,也就是映射到ramfuncs段中。而在F28335.cmd文件中可以发现,这个字段是写在FLASHD里面的,通过memcpy函数的搬运,在运行时被加载到RAML0空间中去。
也就是说,在固化后,只有这两个函数是被放到RAM中运行的,其他函数还是跑在Flash里。

另,补充一下#pragma CODE_SECTION命令
格式 #pragma CODE_SECTION(func,"section")
其中func是函数名,section是此函数所存储的段名。如果要运用此命令,需要在CMD文件中写入相应的段名才行。

最后,不知道是不是只有我刚知道这个秘密,发出来也好让新学的同志们能多理解些~~~

lbblsws 发表于 2014-12-18 20:45:35

开玩笑,28335多少年的老片了,这也算秘密?

Nexus 发表于 2014-12-18 20:58:22

你可以任意设置你的代码放到RAM里面的。这个确实不是秘密了。我们实际使用的时候,是在RAM里面调试,在Flash里面固化的。

lljme 发表于 2014-12-18 21:57:36

能发现就好。

siyeb 发表于 2014-12-19 10:31:09

Nexus 发表于 2014-12-18 20:58
你可以任意设置你的代码放到RAM里面的。这个确实不是秘密了。我们实际使用的时候,是在RAM里面调试,在Flas ...

应该是之前理解的不透彻,这次是弄明白了~

siyeb 发表于 2014-12-19 10:31:54

lbblsws 发表于 2014-12-18 20:45
开玩笑,28335多少年的老片了,这也算秘密?

大牛莫嘲笑,昨天发现这个以后高兴了一下就发了个贴,没想到班门弄斧~见笑见笑~~~

siyeb 发表于 2014-12-19 10:33:37

lljme 发表于 2014-12-18 21:57
能发现就好。

握手,多些理解!

mpuhome 发表于 2014-12-19 10:37:14

理解了就很好哦
在线烧写FLASH,比如你想用CAN下载新的程序,需要将CAN总线相关代码及FLASH API相关代码放到RAM里运行,然后就可以实现了
可以参考FLASH API的例子

siyeb 发表于 2014-12-19 10:41:24

mpuhome 发表于 2014-12-19 10:37
理解了就很好哦
在线烧写FLASH,比如你想用CAN下载新的程序,需要将CAN总线相关代码及FLASH API相关代码放 ...

多谢提醒,正在弄这块儿,如有不懂的地方还望您多多指教!

Ticl4 发表于 2014-12-19 11:24:23

#pragma CODE_SECTION(func, "ramfuncs");

Ticl4 发表于 2014-12-19 11:26:03

Ticl4 发表于 2014-12-19 11:24
#pragma CODE_SECTION(func, "ramfuncs");

对想在RAM中运行的函数,加上上述编译语句就可以了,
当然还需要:
   MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
    InitFlash();

siyeb 发表于 2014-12-19 13:06:55

Ticl4 发表于 2014-12-19 11:26
对想在RAM中运行的函数,加上上述编译语句就可以了,
当然还需要:
   MemCopy(&RamfuncsLoadStart, &Ram ...

是这样的~~

tianyaxtutianya 发表于 2019-3-25 18:32:31

学习了谢谢分享
页: [1]
查看完整版本: 原创:28335的程序到底是在哪里运行的。