草堂笔记ARM5到ARM6-分散文件加载错误问题
目录
【草堂笔记】ARM5到ARM6 分散文件加载错误问题
一 、 背景
在最近的一次项目中,使用的是ciu32L系列的单片机,因为初始化时,需要对flash进行一些数据写入,发现其使用的是ARM5编译
用官方的历程编译一切正常,但我项目使用的是ARM6编译器,所以我也试了下,直接将编译器改为ARM6,此时编译报了各警告
如下:
二、解决方案
2.1、 官方例程如下:
#if defined ( __CC_ARM ) #pragma arm section code = “FAST_PROGRAM” #elif defined ( ICCARM ) __ramfunc #elif defined ( GNUC ) attribute ((section (".RamFunc"))) #endif /**
- @brief Flash快速编程,往目标地址快速编程半页数据
- @param address 编程地址
- @param data_buf 编程数据
- @retval std_status_t 本函数执行结果 */ std_status_t bsp_flash_fast_write(uint32_t address, uint32_t data_buf) { std_status_t status = STD_OK; uint32_t prog_count = 0; / 启动快速编程模式 / FLASH->CR |= FLASH_CR_FSTPG_MODE; / 向目标地址写入数据 */ for (prog_count=0; prog_count < FSTPG_WORD_COUNT; prog_count++) { ((uint32_t )address)[prog_count] = data_buf[prog_count]; / 查询等待BSY标志被清除 / while ((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY); / 若出现错误,则退出编程循环 / if (FLASH->SR & FLASH_FLAG_ALL_ERR) { status = STD_ERR; break; } } / 查询等待FSTPG_MODE状态被自动清零 / while ((FLASH->CR & FLASH_CR_FSTPG_MODE) == FLASH_CR_FSTPG_MODE); / 清除Flash标志 */ FLASH->SR = (FLASH_FLAG_ALL_ERR | FLASH_SR_EOP); return (status); } #if defined ( __CC_ARM ) #pragma arm section #endif 分散加载文件如下: LR_IROM1 0x08000000 0x00040000 { ; load region size_region ER_IROM1 0x08000000 0x00040000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00001000 { ; RW data *.o(FAST_PROGRAM) .ANY (+RW +ZI) } } 注意:
在ARM6(即AC6编译器,基于LLVM/Clang)环境下,__CC_ARM 这个宏已被废弃,GNUC 也被Keil的ARM编译器6支持。但你遇到的问题的根本原因是,没有正确地在链接脚本和代码中统一声明和使用 .FAST_PROGRAM 段,导致编译时找不到匹配的 .o(FAST_PROGRAM) 段。
2.2、解决方案:
- 确保正确的编译器宏判断 ARM6 编译器在 Keil 中的宏是 __ARMCC_VERSION #if defined(__CC_ARM) // ARM Compiler 5 #pragma arm section code=“FAST_PROGRAM” #elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6000000) // ARM Compiler 6 attribute((section(".FAST_PROGRAM"), used)) #elif defined(ICCARM) // IAR __ramfunc #elif defined(GNUC) // GCC attribute((section(".FAST_PROGRAM"), used)) #endif 分散加载文件如下: LR_IROM1 0x08000000 0x00040000 { ; load region size_region ER_IROM1 0x08000000 0x00040000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00002000 { ; RW data *(FAST_PROGRAM) ; 让 .FAST_PROGRAM 段放入 RAM .ANY (+RW +ZI) } } 此时编译通过,程序运行正常。 写笔记的目的其实就是当再次遇到同一个问题,时间久了可能会忘记处理方法,同时也可以解决大家在项目中碰到此类问题,给以快速解决方案。赠人玫瑰,手有余香。养成做笔记的习惯。