ROM LIB

概述

ROM Library(ROM库)是嵌入式系统中一种特殊的代码组织形式,其核心思想是将稳定且不常修改的功能模块(如通信协议栈、数学库、硬件驱动)预先编译为二进制代码,并固定烧录到芯片的Flash/ROM区域。应用程序运行时,通过地址跳转或符号引用直接调用ROM库中的函数和访问其数据。与普通静态库(.a文件)不同,ROM库的代码和数据不链接到应用程序中,而是独立存在,应用程序仅引用其地址。

对于C语言开发者可能比较难理解这个过程,但对于有一些汇编开发基础就比较容易理解调用过程,这是由于C语言的抽象层将硬件细节(地址、内存布局)隐藏在编译器和链接器背后,而ROM库的实现恰恰需要开发者直面这些底层机制。汇编开发者由于长期与地址、寄存器、物理内存打交道,对ROM库的固定地址分配、显式初始化和符号绑定方式有天然的熟悉感。因此,理解ROM库的关键在于突破高级语言的抽象层,深入掌握链接脚本、内存映射和符号解析机制。对于C开发者,通过学习嵌入式系统的底层原理(如阅读.map文件分析内存分配),可以逐步缩小这一理解差距。

以下以STM32CubeIDE和STM32L432为例,详细阐述如何生成ROM LIB固件以及如何使用ROM LIB固件。

存储器规划

STM32L432内部FLASH以及RAM资源如下:

范围大小
FLASH0x8000000~0x803ffff256KB
RAM0x20000000~0x2000bfff48KB
RAM20x10000000~0x10003fff16KB

ROM lib固件使用资源如下:

范围大小
FLASH0x8032000~0x803ffff56KB
RAM20x10000000~0x10003fff16KB

生成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文件与源码定义一致。

text段

data段

bss段

使用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仿真成功:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值