AG32下的分散加载 6 min read AG32其他文档 分散加载:在实际应用中,有时候需要强制把一段数据,或一段代码,固定到指定的一个地址。这个时候,就不能使用默认的编译配置,需要自己来配置连接属性。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 区域即可。 PREVIOUS ← AG32下SPI的扩展使用 NEXT STEP AG32 下使用freeRTOS 的参考 →