网站前台后台模板,wordpress小工具功能,公司做免费网站,企业解决方案是什么意思啊ARM学习#xff08;31#xff09;编译器对overlay方式的支持 1、overlay介绍
overlay#xff1a;重叠得意思#xff0c;就是可以重复利用得空间#xff0c;一般在内存上使用这种空间。比如以Windows操作系统为例#xff0c;其存储空间#xff08;ROM/FLASH#xff09;… ARM学习31编译器对overlay方式的支持 1、overlay介绍
overlay重叠得意思就是可以重复利用得空间一般在内存上使用这种空间。比如以Windows操作系统为例其存储空间ROM/FLASH一般相对较大但是内存相对较少内存要加载Flash上面得较多数据就得空间上面重复使用。
比如一个游侠里面油很多动态链接库dll内存有限只能加载一部分dll库当用到一些库时就会将一些库覆盖掉然后调用这些库当然这里有很多替换得算法比如LRUleast recently used最近最少使用得会被替换由于被替换得库不确定所以加载得地址不确定这就要求dll可以动态加载根据加载得地址进行偏移寻址这就是PIC位置无关dll里面得代码均使用相对寻址所以加载到任何地址均可以使用理论上。
嵌入式系统为了运行效率高往往会在ram上面执行代码相对Flash所以ram既要放代码也要存放数据相对比较紧张就会将内存空间重复使用。
嵌入式系统当中往往使用绝对地址寻址不采用相对地址笔者这里以不带Linux操作系统得应用场景为例。所以如果需要这种重复利用内存空间就需要确定一块重复利用得地址然后加载到这块得代码都需要采用这块得地址来进行编译即在链接脚本里面指定绝对地址。 以上图为例有4个功能代码1-4都需要运行到动态内存地址则笔者需要将这4个地址都编译到同一个动态内存的地址然后需要哪个函数的时候就将哪个函数搬到对应的地址然后再跳转过去执行。
2、编译器armcc/armclang对overlay的支持
armcc/armclang编译器支持overlay主要是链接脚本这块的支持通常情况下
如果两个.o文件放到同一块地址或者两个函数放到同一块地址都会报错误 如下两个overlay区域有重叠因为链接器的作业就是分配运行地址当然不能重叠否则该怎么放置代码和执行code呢
LR_OVERLAY0 0x30000000 0x1000
{ER_OVERLAY0 0x2001E000 0x1000 {overlay0.o(BANK_SEC, FIRST)overlay0.o(RO)overlay0.o(.text)}
}LR_OVERLAY1 0x30001000 0x1000
{ER_OVERLAY1 0x2001E000 0x1000 {overlay1.o(BANK_SEC, FIRST)overlay1.o(RO)overlay1.o(.text)}
}LR_OVERLAY2 0x30002000 0x1000
{ER_OVERLAY2 0x2001E000 0x1000 {overlay2.o(BANK_SEC, FIRST)overlay2.o(RO)overlay2.o(.text)}
}AdvanceClock.sct, line 32 (column 17): Warning: L6329W: Pattern overlay0.o(RO) only matches removed unused sections.
AdvanceClock.sct, line 33 (column 16): Warning: L6314W: No section matches pattern overlay0.o(.text).
AdvanceClock.sct, line 42 (column 17): Warning: L6329W: Pattern overlay1.o(RO) only matches removed unused sections.
AdvanceClock.sct, line 43 (column 16): Warning: L6314W: No section matches pattern overlay1.o(.text).
AdvanceClock.sct, line 52 (column 17): Warning: L6329W: Pattern overlay2.o(RO) only matches removed unused sections.
AdvanceClock.sct, line 53 (column 16): Warning: L6314W: No section matches pattern overlay2.o(.text).
Error: L6221E: Execution region ER_OVERLAY0 with Execution range [0x2001e000,0x2001e080) overlaps with Execution region ER_OVERLAY1 with Execution range [0x2001e000,0x2001e074).
Error: L6221E: Execution region ER_OVERLAY0 with Execution range [0x2001e000,0x2001e080) overlaps with Execution region ER_OVERLAY2 with Execution range [0x2001e000,0x2001e074).
Error: L6221E: Execution region ER_OVERLAY1 with Execution range [0x2001e000,0x2001e074) overlaps with Execution region ER_OVERLAY2 with Execution range [0x2001e000,0x2001e074).
Finished: 0 information, 6 warning and 3 error messages.
make: *** [out/AdvancedClock.axf] Error 1为了让链接器识别这种情况把相同的地址放置多个函数就必须加一个关键字笔者找到手册上面的关键字overlay。
如下面例子所述只要在多个想要执行地址的域空间描述上面加上overlay的关键字该错误就不会报 笔者做了尝试果然是这样
LR_OVERLAY0 0x30000000 0x1000
{ER_OVERLAY0 0x2001E000 OVERLAY 0x1000 { overlay0.o(OVERLAY_SEC, FIRST)overlay0.o(RO)overlay0.o(.text)}
}LR_OVERLAY1 0x30001000 0x1000
{ER_OVERLAY1 0x2001E000 OVERLAY 0x1000 {overlay1.o(OVERLAY_SEC, FIRST)overlay1.o(RO)overlay1.o(.text)}
}LR_OVERLAY2 0x30002000 0x1000
{ER_OVERLAY2 0x2001E000 OVERLAY 0x1000 {overlay2.o(OVERLAY_SEC, FIRST)overlay2.o(RO)overlay2.o(.text)}
}需要注意两点 1、如果是独立设置加载域则需要将入口函数声明为root属性不然跳转的地址异常可能跑飞等 2、保证函数声明为used不然链接器会将overlay里面的函数stripped掉删除掉因为没有用到。 3、注意声明的OVERLAY 属性要放在执行域 长度属性的前面不然会报错 4、因为笔者用的cm4架构跳转的时候需要注意使用奇地址不然可能会跑飞。
LR_OVERLAY0 0x30000000 0x1000
{ER_OVERLAY0 0x2001E000 OVERLAY 0x1000 { overlay0.o(RO)overlay0.o(.text)}
}LR_OVERLAY1 0x30001000 0x1000
{ER_OVERLAY1 0x2001E000 OVERLAY 0x1000 {overlay1.o(RO)overlay1.o(.text)}
}LR_OVERLAY2 0x30002000 0x1000
{ER_OVERLAY2 0x2001E000 OVERLAY 0x1000 {overlay2.o(RO)overlay2.o(.text)}
}overlay1函数实例没有root属性只有used属性。
__attribute__((used)) static void overlay_handler(u8 overlay_id, u8 func_id)
{switch(func_id){case 1:{rt_kprintf(this is overlay func,overlay id%d func id%d\r\n, overlay_id, func_id);}break;default:rt_kprintf(this is overlay func,func id%d,err\r\n, func_id);break;}
}笔者尝试了如果不加root属性则overlay1和overlay则会入口函数是编译器生成的code会异常。 编译器生成的code如下不是压栈所操作入口地址变成了2001E00C所以可能导致跑飞
正常的code应该如下所示
如果不加used以及根区属性则符号都没有被链接进来因为overlay的函数本身需要运行态来决定运行哪个函数的所以静态编译的时候编译器并不知道链接哪个不过不指定used属性则就会全部strpped掉。 static void overlay_handler(u8 overlay_id, u8 func_id)
{switch(func_id){case 2:{rt_kprintf(this is overlay func,overlay id%d func id%d\r\n, overlay_id, func_id);}break;default:rt_kprintf(this is overlay func,func id%d,err\r\n, func_id);break;}
}如果overlay属性位置放错就会报如下错误。
AdvanceClock.sct, line 29 (column 36): Error: L6228E: Expected {, found O....
AdvanceClock.sct, line 29 (column 36): Error: L6228E: Expected }, found EOF.
Not enough information to list the image map.
Finished: 1 information, 0 warning and 2 error messages.
make: *** [out/AdvancedClock.axf] Error 1关于链接脚本的其他关于overlay的写法如下图所示
region1 不是overlay属性则region2的地址是region1地址的末地址region1 是overlay属性且offset是0则region2和region1的地址一样region1 是overlay属性且offset不是0则region2是region1末地址offset 跳转的时候使用奇地址不然会报错因为cm4使用thumb指令
overlay_handler_fun overlay_handler_func (overlay_handler_fun)(overlay_EXEC_ADDR1);笔者写了一个参考例子如下 overlay manager: set_overlay_id会请求切换当前的bank overlay_process会处理当前的请求并执行函数。
#include main.h#define overlay_EXEC_ADDR 0x2001E000#define overlay0_SAVE_ADDR 0x08020000
#define overlay1_SAVE_ADDR 0x08020400
#define overlay2_SAVE_ADDR 0x08020800
#define overlay_FLASH_BASE overlay0_SAVE_ADDRtypedef void (*overlay_handler_fun)(u8 overlay_id,u8 func_id);u8 current_overlay_id_g 0;
u8 set_overlay_id_g 0;
void overlay_init()
{u32 current_overlay_flash_addr overlay_FLASH_BASE current_overlay_id_g*0x400;STMFLASH_Read(current_overlay_flash_addr, (u32*)overlay_EXEC_ADDR, 0x400);overlay_handler_fun overlay_handler_func (overlay_handler_fun)(overlay_EXEC_ADDR1);(*overlay_handler_func)(current_overlay_id_g, current_overlay_id_g);
}void set_overlay_id(u8 req_overlay_id)
{set_overlay_id_g req_overlay_id;
}void overlay_process()
{if(set_overlay_id_g ! current_overlay_id_g){current_overlay_id_g set_overlay_id_g;u32 current_overlay_flash_addr overlay_FLASH_BASE current_overlay_id_g*0x400;STMFLASH_Read(current_overlay_flash_addr, (u32*)overlay_EXEC_ADDR, 0x400);overlay_handler_fun overlay_handler_func (overlay_handler_fun)(overlay_EXEC_ADDR1);(*overlay_handler_func)(current_overlay_id_g, current_overlay_id_g);}
}#include main.hoverlay0.c
__attribute__((section(overlay_SEC),used)) static void overlay_handler(u8 overlay_id, u8 func_id)
{switch(func_id){case 0:{rt_kprintf(this is overlay func,overlay id%d func id%d\r\n, overlay_id, func_id);}break;default:rt_kprintf(this is overlay func,func id%d,err\r\n, func_id);break;}
}
overlay1.c
__attribute__((section(overlay_SEC),used)) static void overlay_handler(u8 overlay_id, u8 func_id)
{switch(func_id){case 1:{rt_kprintf(this is overlay func,overlay id%d func id%d\r\n, overlay_id, func_id);}break;default:rt_kprintf(this is overlay func,func id%d,err\r\n, func_id);break;}
}
overlay2.c__attribute__((section(overlay_SEC),used)) static void overlay_handler(u8 overlay_id, u8 func_id)
{switch(func_id){case 2:{rt_kprintf(this is overlay func,overlay id%d func id%d\r\n, overlay_id, func_id);}break;default:rt_kprintf(this is overlay func,func id%d,err\r\n, func_id);break;}
}
实际效果如下 如果有Trace32调试器可以通过Trace32对overlay的支持来进行调试。 trace32 设置指令
system.option.ovarlay ONsymbol.overlay.AUTOID 自动识别IDsymbol.overlay.list 查看当前处于哪个overlay 由下图可以可以看到笔者的overlay 处于overlay1根据右边的打印然后trace32调试器也显示的overlay1. 笔者切到overlay2则对应的调试器显示overlay2。
3、参考
armcc官方手册 DUI0472M_armcc_user_guide DUI0474M_armlink_user_guide