概述
ROM Library(ROM库)是嵌入式系统中一种特殊的代码组织形式,其核心思想是将稳定且不常修改的功能模块(如通信协议栈、数学库、硬件驱动)预先编译为二进制代码,并固定烧录到芯片的Flash/ROM区域。应用程序运行时,通过地址跳转或符号引用直接调用ROM库中的函数和访问其数据。与普通静态库(.a文件)不同,ROM库的代码和数据不链接到应用程序中,而是独立存在,应用程序仅引用其地址。
对于C语言开发者可能比较难理解这个过程,但对于有一些汇编开发基础就比较容易理解调用过程,这是由于C语言的抽象层将硬件细节(地址、内存布局)隐藏在编译器和链接器背后,而ROM库的实现恰恰需要开发者直面这些底层机制。汇编开发者由于长期与地址、寄存器、物理内存打交道,对ROM库的固定地址分配、显式初始化和符号绑定方式有天然的熟悉感。因此,理解ROM库的关键在于突破高级语言的抽象层,深入掌握链接脚本、内存映射和符号解析机制。对于C开发者,通过学习嵌入式系统的底层原理(如阅读.map文件分析内存分配),可以逐步缩小这一理解差距。
以下以STM32CubeIDE和STM32L432为例,详细阐述如何生成ROM LIB固件以及如何使用ROM LIB固件。
存储器规划
STM32L432内部FLASH以及RAM资源如下:
| 范围 | 大小 | |
|---|---|---|
| FLASH | 0x8000000~0x803ffff | 256KB |
| RAM | 0x20000000~0x2000bfff | 48KB |
| RAM2 | 0x10000000~0x10003fff | 16KB |
ROM lib固件使用资源如下:
| 范围 | 大小 | |
|---|---|---|
| FLASH | 0x8032000~0x803ffff | 56KB |
| RAM2 | 0x10000000~0x10003fff | 16KB |
生成ROM LIB固件
链接文件
/* Entry Point */
ENTRY(RomLib_Init)
/* Memories definition */
MEMORY
{
RAM2 (xrw) : ORIGIN = 0x10000000, LENGTH = 16K
FLASH (rx) : ORIGIN = 0x8032000, LENGTH = 56K
}
/* Sections */
SECTIONS
{
/* The program code and other data into "FLASH" Rom type memory */
.text : ALIGN(4)
{
FILL(0xff)
KEEP(*(.ROM_LIB_CODE)) /* do not discard anything marked as ROM Lib code */
KEEP(*(.ROM_LIB_CONST)) /* do not discard anything marked as ROM constant */
*(.text*)
*(.rodata .rodata.* .constdata .constdata.*)
. = ALIGN(4);
} >FLASH
/* Initialized data sections into "RAM" Ram type memory */
.data : ALIGN(4)
{
FILL(0xff)
KEEP(*(.ROM_LIB_RAM))
*(.data*)
. = ALIGN(4) ;
} >RAM2 AT>FLASH
/* Uninitialized data section into "RAM" Ram type memory */
.bss : ALIGN(4)
{
_bss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4) ;
_ebss = .;
} >RAM2 AT>RAM2
}
在链接文件中定义了三个段:.text段、.data段、.bss段,.text段存储可执行代码和只读数据(如常量),通常位于Flash中;.data段保存已初始化的全局/静态变量,其初始值从Flash拷贝到RAM运行;.bss段存放未初始化或零初始化的全局/静态变量,由启动代码在RAM中清零后使用。这三个段分别管理代码、初始化数据和未初始化数据,确保程序高效利用Flash和RAM资源。
源文件
#include "RomLibFun.h"
#define ROM_LIB_CODE __attribute__ ((section(".ROM_LIB_CODE"))) /* placed into ROM */
#define ROM_LIB_CONST __attribute__ ((section(".ROM_LIB_CONST"))) /* placed into ROM */
#define ROM_LIB_RAM __attribute__ ((section(".ROM_LIB_RAM"))) /* placed into RAM */
static int acc;
static int var_init = 10;
static const int data=12345;
ROM_LIB_CODE int RomLib_Acc(void)
{
return ++acc;
}
ROM_LIB_CODE int RomLib_Add(int a,int b)
{
return a+b;
}
ROM_LIB_CODE int RomLib_GetData(void)
{
return data;
}
ROM_LIB_CODE int RomLib_GetVarInit(void)
{
return var_init;
}
ROM_LIB_CODE void RomLib_Init(void)
{
acc = 0;
}
头文件
#ifndef __ROMLIBFUN_H
#define __ROMLIBFUN_H
#ifdef __cplusplus
extern "C" {
#endif
#define ROM_LIB_CODE __attribute__ ((section(".ROM_LIB_CODE"))) /* placed into ROM */
#define ROM_LIB_CONST __attribute__ ((section(".ROM_LIB_CONST"))) /* placed into ROM */
#define ROM_LIB_RAM __attribute__ ((section(".ROM_LIB_RAM"))) /* placed into RAM */
int RomLib_Add(int a,int b);
int RomLib_Acc(void);
int RomLib_GetData(void);
void RomLib_Init(void);
#ifdef __cplusplus
}
#endif
#endif

map文件分析
共包含3个段:.text、.data、.bss。.text段占124个字节包含RomLibFun.o中的4个函数(RomLib_Add、RomLib_Acc、RomLib_GetData、RomLib_Init);.data段占4个字节包含已初始化变量var_init;.bss段占用4个字节未初始化变量acc。map文件与源码定义一致。



使用ROM LIB
测试代码:
int main(void)
{
/* USER CODE BEGIN 1 */
int cnt = 0;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
HAL_Delay(100);
printf("Start test Romlib...\r\n");
RomLib_Init();
printf("RomLib_Add12+11=%d\r\n",RomLib_Add(12,11));
printf("RomLib_GetData=%d\r\n",RomLib_GetData());
printf("RomLib_GetVarInit=%d\r\n",RomLib_GetVarInit());
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
printf("acc:%d\r\n",RomLib_Acc());
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
工程配置:


直接下载:

由于没有下载GEN_ROM_STM32L432,调用RomLib_Init后就出现了异常。
再下载GEN_ROM_STM32L432中的hex到Flash中:

运行正常,但是RomLib_GetVarInit的返回值并不符合我们的预期,这是由于RomLib_GetVarInit返回的是全局初始化变量,存在data段中,一般情况需要从加载域加载初值,但是在ROM lib固件中这部分流程是缺失的,若需要初始化尽量才RomLib_Init实现变量的初始化。
调试ROM Lib
工程配置

ROM Lib仿真成功:

2663

被折叠的 条评论
为什么被折叠?



