AG32下的分散加载与数组存放

首先要明确下需求:

1. 分配的静态全局数组,会占用sram空间(希望放到flash上去);

2. 希望把某部分代码或数组,强制放到某个flash地址去;

3. 希望在flash某段区域插入一个标记位;

.

在以上需求中,

需求1,是要把数组从sram中去除掉,减少对sram的使用。

这部分可以参考example_flash里的样例,在数组前,用 attribute((section(".flash.readonly"))) 修饰即可:

这种情况不用使用分散加载那么麻烦的设定。

需求2,把某段代码或某个数组强制放到flash指定的地方。

如果这段代码和数组要插入的地方在正常编译的代码端之外,可以使用“分散加载”来实现。

也就是说,如果code.bin编译完后是128K。那么你分散加载指定的这个地方,不能是0~128K之间的某个位置,必须要在128K以后。这个是gcc编译器本身的限制,目前没有绕开的方法。

比较合理的一个地方,是确定好大小后,可以放在logic.bin之前。

需求3,希望在flash某段区域插入一个标记位。

这个需求其实和“需求2”是一样的。只是存放固定的一个数据。

答案也和需求2是一样的:如果存放位置在code.bin之后是可以的,不能存放在code.bin中间。

.

如果确定需要分散加载功能,以下会详细讲到。

分散加载

在实际应用中,有时候需要强制把一段数据,或一段代码,固定到指定的一个地址。这个时候,就不能使用默认的编译配置,需要自己来配置连接属性。

AG32中可以通过修改ld配置,达成这样的目的。

分散加载在gcc下的限制:

不能插入到代码段,只能放到正常编译的bin后边(参后详述)。

.

在默认情况下,AG32编译时使用的连接配置文件是AgRV2K_FLASH.ld,位于:

AgRV_pio\packages\framework-agrv_sdk\misc\devices下。

打开该文件会看到,关联了另外两个文件:

其中,在AgRV2K_mem.ld中是多个自定义的标签:

而在mem.ld的定义中,则是对section的使用和分配:

以上的三个文件,总结:

  1. AgRV2K_FLASH.ld:关联到工程的,一般不要改动;
  2. AgRV2K_mem.ld:自定义标签的定义,如果要新增标签,需要改动;
  3. mem.ld:设置编译地址分配的地方,需要改动。

这里,相当于三个文件加在一起,组成一个完整的scat文件。

.

这里的语法都是标准的gcc ld语法,可自行网上搜索更全的使用方法。

下边只是个简单的举例供参考。

举例:把某个数组和某个函数指定编译到flash的某个位置,

比如,指定数组guSetting到152K的地方(地址为:0x80026000)

指定函数 testFuncToPos() 紧跟在数组后边。

需要做:

1. 在AgRV2K_FLASH.ld中定义一个新标签:

FLASH_E 和 FLASH_E_SIZE 

分别为起始地址0x80026000和4K大小;

同时定义FLASH_EXT段,后续会来使用;

如下图:

这里的flash位置使用时最好放到code的结尾处。

并且要考虑fpga部分的flash使用空间。

(如果不对fgpa的位置指定,fpga会默认占用flash的最后100K)

2. 在mem.ld中,根据上边定义的标签,定义section,如:

.flash : ALIGN(4)

  {

    *(.testSectionData);

    *(.testSectionCode);

  } > FLASH_EXT

如下图:

这里定义出来两个section:testSectionData和testSectionCode。这两个section名称, 就是在代码中使用的关联section。

3. 在代码中,对数组和函数进行section指定,方法如:

__used uint8_t guSetting[16] __section(".testSectionData") =

__used __section(".testSectionCode") void testFuncToPos(void)

如下图:

并且在项目中调用函数testFuncToPos。

4. 编译后,可以从工程的\.pio\build\release\路径下查看.readelf文件,

  (如果是dev方式编译,路径是:\.pio\build\dev\)

打开该文件后,可以看到guSetting和testFuncToPos正是在我们所期望的 位置上:

注意:这里对flash空间规划时,需要增加fpga(cpld)对空间的使用考虑。

附:

关于芯片flash大小:

不管所选型号的flash是多大,请注意最后100K是留给fpga使用的。

如果使用的芯片是256K的flash空间,那么就是156K程序+100K fpga,用户程序不能超过156K。如果超过156K编译是可以通过的,但烧录后会冲掉ve配置部分。

ve配置被冲掉后,程序运行会表现出各种异常(连系统时钟初始化都跑不过)。

如果程序使用的空间较大,fpga又刚好比较小,可以调整这个界限的值。调整方法如下:

board_logic.compress = true //(可选)对fpga部分进行压缩,更省空间

board_upload.logic_address = 0x80034000 //根据实际情况调整该边界值

flash的大小是在agrv2k_103.json 中定义的。

flash起始地址是0x80000000,ram是0x20000000。

另:

分散加载中,如果连AgRV2K_FLASH.ld都想自己指定,则需要修改platformio.ini中配置项:

board_build.ldscript = AgRV2K_FLASH.ld

.

分散加载在gcc下的限制:

在arm中,可以通过_attribute_( at(绝对地址) )的方式,把某个数组或某个函数强制编译到某个地址,并且不影响其他代码的编译。编译后整个bin空间看上去是连续的。

这是arm编译器支持的一个特性。

但gcc不支持这样的指定。

gcc使用ld指定的地址,不能在正常编译的code的区域内。这个地址只能放在没有用到的flash部分。

也就是说,新指定的位置,必须在正常的编译区域的后边。

实际操作时,代码些许的改动都会影响到bin的大小,所以这个指定的位置,往往会跟正常bin之间预留一些空间。所以,自定义ld文件的方式bin文件会增大一些。

从bin的角度看,code和指定区域,两段中间空出来的区域,会被填充成00。

最终bin增大的部分,就是这部分填充成0的size大小。

如果对bin的大小比较敏感,那就要缩小这段0的区域。可以在最终出包时,看下其他代码编译后的大小,然后把这段指定地址放的尽量近。

如果对bin的大小不太敏感,那就随意指定到没用到的flash区域即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值