RISC-V MCU将常量定义到指定的Flash地址 -- 以CH32V103为例
Keil MDK开发ARM 内核的MCU时,将常量定义到指定的Flash地址中,使用 _attribute_( at(绝对地址) )即可,如:
1 const u32 myConstVariable_1[128] __attribute__((at(0x08001000))) = {0x12345678,0x22221111};//定位在flash中,其他flash补充为0
沁恒RISC-V MCU ,通过Mounriver Studio(MRS)开发时,暂时不支持_attribute_( at(绝对地址) )命令。可通过如下步骤实现:
1、编辑ld链接文件,添加SECTIONS段
1 .flash_test_address : 2 { 3 . = ALIGN(4); /*4字节对齐*/ 4 . = ORIGIN(FLASH)+0x1000; /*ORIGIN(FLASH)为 MEMORY定义的FLASH的起始地址(CH32V103为0x08000000),指定到从FLASH起始的0x1000长度的位置*/ 5 KEEP(*(SORT_NONE(.test_address_1))) /*链接时*KEEP()可以使得被标记段的内容不被清除*/ 6 . = ALIGN(4); 7 } >FLASH AT>FLASH
如需将变量定义到Flash的最后,将此段添加到 .text段后面,注意指定的Flash地址要大于程序编译大小。
2、函数中使用__attribute__((section(".xxx")))定义常量
2.1 定义单字节常量
1 const uint8_t myConstVariable_1 __attribute__((section(".test_address_1"))) = 0x11;/*地址为0x00001000*/
查看map文件,常量地址如下:
sections .flash_test_address段中以4字节对齐,其余3字节补0。
二进制bin文件0x1000地址信息如下;
2.2 定义连续的多个单字节常量
1 const uint8_t myConstVariable_1 __attribute__((section(".test_address_1"))) = 0x11; /*地址为0x00001002*/ 2 const uint8_t myConstVariable_2 __attribute__((section(".test_address_1"))) = 0x22; /*地址为0x00001001*/ 3 const uint8_t myConstVariable_3 __attribute__((section(".test_address_1"))) = 0x33; /*地址为0x00001000*/
ld文件中flash_test_address 段默认从指定地址开始为其分配连续的地址,查看map文件,常量地址如下:
二进制bin文件0x1000地址信息如下;
2.3 定义多个不连续的常量
此时需要修改ld文件
1 .flash_test_address : 2 { 3 . = ALIGN(4); /*4字节对齐*/ 4 . = ORIGIN(FLASH)+0x1000; /*ORIGIN(FLASH)为 MEMORY定义的FLASH的起始地址(CH32V103为0x08000000),指定到从FLASH起始的0x1000长度的位置*/ 5 KEEP(*(SORT_NONE(.test_address_1))) /*链接时*KEEP()可以使得被标记段的内容不被清除*/ 6 . = ORIGIN(FLASH)+0x1040; /*ORIGIN(FLASH)为 MEMORY定义的FLASH的起始地址(CH32V103为0x08000000),指定到从FLASH起始的0x1040长度的位置*/ 7 KEEP(*(SORT_NONE(.test_address_2))) /*链接时*KEEP()可以使得被标记段的内容不被清除*/ 8 . = ALIGN(4); 9 } >FLASH AT>FLASH
在函数中定义两个指定地址的常量
1 const uint8_t myConstVariable_1[8] __attribute__((section(".test_address_1"))) = {0x11,0x22,0x33,0x44}; /*首地址为0x00001000*/ 2 const uint8_t myConstVariable_2[4] __attribute__((section(".test_address_2"))) = {0x55,0x66}; /*首地址为0x00001040*/
查看map文件,常量地址如下:
二进制bin文件0x1000地址信息如下;
这样指定的方式会造成中间段有56个字节的flash无法分配内容,浪费了,不建议这样指定,如果实在要这样做,需要严格把控,可根据间隔的大小,指定编译后小于该间隔的函数存储到该flash块。
如指定函数Delay_Init编译后存放test_address_1块内,紧跟定义的常量后。
1 /******************************************************************************* 2 * Function Name : Delay_Init 3 * Description : Initializes Delay Funcation. 4 * Input : None 5 * Return : None 6 *******************************************************************************/ 7 __attribute__((section(".test_address_1"))) void Delay_Init(void) 8 { 9 p_us=SystemCoreClock/8000000; 10 p_ms=(uint16_t)p_us*1000; 11 }
Delay_Init函数编译后的大小为0x2a,编译后的map文件如下:
二进制bin文件0x1000地址信息如下:
(新增的A2 4A 04 指令暂时不详)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?