一 、 背景
在最近的一次项目中,使用的是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)
}
}
此时编译通过,程序运行正常。
写笔记的目的其实就是当再次遇到同一个问题,时间久了可能会忘记处理方法,同时也可以解决大家在项目中碰到此类问题,给以快速解决方案。赠人玫瑰,手有余香。养成做笔记的习惯。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/Porter_007/article/details/146230194
|