当前位置: 首页 > article >正文

嵌入式:Keil的Code、RW、RO、ZI段的解析

相关阅读

嵌入式icon-default.png?t=O83Ahttps://blog.csdn.net/weixin_45791458/category_12768532.html


// 例1
int main(void)
{
    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */
    delay_init(72);                             /* 初始化延时函数 */
    led_init();                                 /* 初始化LED */
    
    while(1)
    {
        LED0(0);                                /* LED0 亮 */
        LED1(1);                                /* LED1 灭 */
        delay_ms(500);
        LED0(1);                                /* LED0 灭 */
        LED1(0);                                /* LED1 亮 */
        delay_ms(500);
    }
}

        假设以例1所示的程序为例,在Keil编译它后,编译信息会有如下所示的提示。

Program Size: Code=5282 RO-data=362 RW-data=28 ZI-data=1900  

        在项目映射文件的底部,也可以找到类似的信息。

==============================================================================


      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   

      5282        292        362         28       1900     513189   Grand Totals
      5282        292        362         28       1900     513189   ELF Image Totals
      5282        292        362         28          0          0   ROM Totals

==============================================================================

    Total RO  Size (Code + RO Data)                 5644 (   5.51kB)
    Total RW  Size (RW Data + ZI Data)              1928 (   1.88kB)
    Total ROM Size (Code + RO Data + RW Data)       5672 (   5.54kB)

==============================================================================

        本文就将详细阐述Keil的Code、RW、RO、ZI段。

Code段

        通俗来讲,Code段存储了指令,因为程序的指令在运行过程中通常不需要修改,这个段通常是只读的,所以被存放在非易失性存储器中(ROM、Flash等)。

        例2在例1的基础上增加了一个新的函数并调用了它。

void func(void)
{
    LED0(0);                                /* LED0 亮 */
    return;
}


int main(void)
{
    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */
    delay_init(72);                             /* 初始化延时函数 */
    led_init();                                 /* 初始化LED */
    
    while(1)
    {
        LED0(0);                                /* LED0 亮 */
        func();
        LED1(1);                                /* LED1 灭 */
        delay_ms(500);
        LED0(1);                                /* LED0 灭 */
        LED1(0);                                /* LED1 亮 */
        delay_ms(500);
    }
}

        此时的编译结果如下所示,可以看到除了Code段有增加,其他段都没有变化。 

Program Size: Code=5310 RO-data=362 RW-data=28 ZI-data=1900  

        由于现在很多单片机采用XIP的方式执行程序,因此不再需要将Code段的代码从非易失性存储器搬到RAM中进行执行了。

RW段

        RW段存储了可读写数据,存放有初始值且没有const关键词修饰的全局变量和静态变量,这些变量的值需要保存在非易失性存储器中,在程序启动时会从非易失性存储器复制到RAM中(这个过程由Code段内的一些初始化函数完成),并且在程序运行时可以读写。

        需要特别注意的是,即使是函数内的静态变量也是保存在RW段的,这代表着即使函数还未被调用,它内部的静态变量就已经存在了。

        例3在例1的基础上增加了一个有初始值的全局变量和静态变量(没有const关键词修饰)。 

// 例3
int a __attribute__((used)) =  11111;
int main(void)
{
    static int b __attribute__((used)) = 11111;
    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */
    delay_init(72);                             /* 初始化延时函数 */
    led_init();                                 /* 初始化LED */
    
    while(1)
    {
        LED0(0);                                /* LED0 亮 */
        LED1(1);                                /* LED1 灭 */
        delay_ms(500);
        LED0(1);                                /* LED0 灭 */
        LED1(0);                                /* LED1 亮 */
        delay_ms(500);;
    }
}

        __attribute__((used))属性强制告诉编译器,这个变量必须保留,即使它没有被显式使用。此时的编译结果如下所示,可以看到RW段增加了8,也就是两个int类型数据所占用的空间。  

Program Size: Code=5282 RO-data=362 RW-data=36 ZI-data=1900  

RO段

        RO段存储了只读数据,存放有初始值且被const关键词修饰的全局变量和有初始值且被const关键词修饰、用指针指向的字符串字面量、printf/scanf函数中的格式字符串。这些值需要保存在非易失性存储器中,在程序启动时会从非易失性存储器复制到RAM中(这个过程由Code段内的一些初始化函数完成),并且在程序运行时只读。

        例4在例1的基础上增加了一个有初始值且被const关键词修饰的全局变量和静态变量,一个指针指向的字符串字面量。

// 例4
const int a __attribute__((used)) = 11111;
char * str __attribute__((used)) = "123";
int main(void)
{
    const static int b __attribute__((used)) = 11111;
    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */
    delay_init(72);                             /* 初始化延时函数 */
    led_init();                                 /* 初始化LED */
    
    while(1)
    {
        LED0(0);                                /* LED0 亮 */
        LED1(1);                                /* LED1 灭 */
        delay_ms(500);
        LED0(1);                                /* LED0 灭 */
        LED1(0);                                /* LED1 亮 */
        delay_ms(500);;
    }
}

        此时的编译结果如下所示,但是RO段只增加了10而不是预计的12,且Code段增加了2,它应该不变才对。

Program Size: Code=5284 RO-data=372 RW-data=32 ZI-data=1896

        要弄清楚为什么会有这种情况,需要去看项目映射文件,下面列出了例1和例4的.map文件。

// 例1的.map文件
Image component sizes


      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name

       102         10          0          4          0       1787   delay.o
       144         12          0          0          0        879   led.o
       108         10          0          0          0     452503   main.o
        64         26        304          0       1536        920   startup_stm32f103xe.o
       154         32          0          9          0       6279   stm32f1xx_hal.o
       272         22          0          0          0      28702   stm32f1xx_hal_cortex.o
       424         10          0          0          0       1215   stm32f1xx_hal_dma.o
       844         40          0          0          0       2664   stm32f1xx_hal_gpio.o
      1708         84          0          0          0       4336   stm32f1xx_hal_rcc.o
       796          6          0          0          0       6287   stm32f1xx_hal_uart.o
        32          0          0          0          0       3762   stm32f1xx_it.o
       102          0          0          0          0        699   sys.o
         2          0         24          4          0       1295   system_stm32f1xx.o
       176         28          0          7        264       3541   usart.o

    ----------------------------------------------------------------------
      4938        280        362         28       1800     514869   Object Totals
         0          0         32          0          0          0   (incl. Generated)
        10          0          2          4          0          0   (incl. Padding)

    ----------------------------------------------------------------------

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Member Name

         8          0          0          0          0         68   __main.o
         0          0          0          0          0          0   __rtentry.o
        12          0          0          0          0          0   __rtentry2.o
         6          0          0          0          0          0   __rtentry4.o
        52          8          0          0          0          0   __scatter.o
        26          0          0          0          0          0   __scatter_copy.o
        28          0          0          0          0          0   __scatter_zi.o
        18          0          0          0          0         80   exit.o
         6          0          0          0          0        152   heapauxi.o
         2          0          0          0          0          0   libinit.o
         2          0          0          0          0          0   libinit2.o
         2          0          0          0          0          0   libshutdown.o
         2          0          0          0          0          0   libshutdown2.o
         8          4          0          0         96         68   libspace.o
        78          0          0          0          0         80   rt_memclr_w.o
         2          0          0          0          0          0   rtexit.o
        10          0          0          0          0          0   rtexit2.o
        74          0          0          0          0         80   sys_stackheap_outer.o
         2          0          0          0          0         68   use_no_semi.o
         2          0          0          0          0         68   use_no_semi_2.o

    ----------------------------------------------------------------------
       344         12          0          0        100        664   Library Totals
         4          0          0          0          4          0   (incl. Padding)
// 例4的.map文件
Image component sizes


      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name

       102         10          0          4          0       1787   delay.o
       144         12          0          0          0        879   led.o
       108         10         12          4          0     452755   main.o
        64         26        304          0       1536        920   startup_stm32f103xe.o
       154         32          0          9          0       6279   stm32f1xx_hal.o
       272         22          0          0          0      28702   stm32f1xx_hal_cortex.o
       424         10          0          0          0       1215   stm32f1xx_hal_dma.o
       844         40          0          0          0       2664   stm32f1xx_hal_gpio.o
      1708         84          0          0          0       4336   stm32f1xx_hal_rcc.o
       796          6          0          0          0       6287   stm32f1xx_hal_uart.o
        32          0          0          0          0       3762   stm32f1xx_it.o
       102          0          0          0          0        699   sys.o
         2          0         24          4          0       1295   system_stm32f1xx.o
       176         28          0          7        264       3541   usart.o

    ----------------------------------------------------------------------
      4940        280        372         32       1800     515121   Object Totals
         0          0         32          0          0          0   (incl. Generated)
        12          0          0          4          0          0   (incl. Padding)

    ----------------------------------------------------------------------

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Member Name

         8          0          0          0          0         68   __main.o
         0          0          0          0          0          0   __rtentry.o
        12          0          0          0          0          0   __rtentry2.o
         6          0          0          0          0          0   __rtentry4.o
        52          8          0          0          0          0   __scatter.o
        26          0          0          0          0          0   __scatter_copy.o
        28          0          0          0          0          0   __scatter_zi.o
        18          0          0          0          0         80   exit.o
         6          0          0          0          0        152   heapauxi.o
         2          0          0          0          0          0   libinit.o
         2          0          0          0          0          0   libinit2.o
         2          0          0          0          0          0   libshutdown.o
         2          0          0          0          0          0   libshutdown2.o
         8          4          0          0         96         68   libspace.o
        78          0          0          0          0         80   rt_memclr_w.o
         2          0          0          0          0          0   rtexit.o
        10          0          0          0          0          0   rtexit2.o
        74          0          0          0          0         80   sys_stackheap_outer.o
         2          0          0          0          0         68   use_no_semi.o
         2          0          0          0          0         68   use_no_semi_2.o

    ----------------------------------------------------------------------
       344         12          0          0         96        664   Library Totals
         4          0          0          0          0          0   (incl. Padding)

        从中可以看出,main.c编译得到的目标文件main.o中code段大小是108,没有改变,而RO段确实从0变成了12。问题在于,例4的Code段的(incl. Padding)从10变成了12,因此造成了整体的Code段增加了2,例4的RO段的(incl. Padding)从2变成了0,因此造成了整体的RO段只增加了10。

ZI段

        ZI段存储了读写数据,存放没有初始值的全局变量和有初始值且被const关键词修饰。这些值不需要保存在非易失性存储器中,在程序启动时会直接在RAM中初始化为0(这个过程由Code段内的一些初始化函数完成)。

        例5在例1的基础上增加了一个无初始值的全局变量。

// 例5
int b __attribute__((used));
int main(void)
{
    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */
    delay_init(72);                             /* 初始化延时函数 */
    led_init();                                 /* 初始化LED */
    
    while(1)
    {
        LED0(0);                                /* LED0 亮 */
        LED1(1);                                /* LED1 灭 */
        delay_ms(500);
        LED0(1);                                /* LED0 灭 */
        LED1(0);                                /* LED1 亮 */
        delay_ms(500);
    }
}

        奇怪的是,似乎编译器将无初始值的全局变量放在了RW段,如下所示(这点尚不明确,希望有懂的大佬告诉我)。

// 例5的.map文件
Image component sizes


      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name

       102         10          0          4          0       1787   delay.o
       144         12          0          0          0        879   led.o
       120         12          0          4          0     452703   main.o
        64         26        304          0       1536        920   startup_stm32f103xe.o
       154         32          0          9          0       6279   stm32f1xx_hal.o
       272         22          0          0          0      28702   stm32f1xx_hal_cortex.o
       424         10          0          0          0       1215   stm32f1xx_hal_dma.o
       844         40          0          0          0       2664   stm32f1xx_hal_gpio.o
      1708         84          0          0          0       4336   stm32f1xx_hal_rcc.o
       796          6          0          0          0       6287   stm32f1xx_hal_uart.o
        32          0          0          0          0       3762   stm32f1xx_it.o
       102          0          0          0          0        699   sys.o
         2          0         24          4          0       1295   system_stm32f1xx.o
       176         28          0          7        264       3541   usart.o

    ----------------------------------------------------------------------
      4950        282        362         32       1800     515069   Object Totals
         0          0         32          0          0          0   (incl. Generated)
        10          0          2          4          0          0   (incl. Padding)

    ----------------------------------------------------------------------

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Member Name

         8          0          0          0          0         68   __main.o
         0          0          0          0          0          0   __rtentry.o
        12          0          0          0          0          0   __rtentry2.o
         6          0          0          0          0          0   __rtentry4.o
        52          8          0          0          0          0   __scatter.o
        26          0          0          0          0          0   __scatter_copy.o
        28          0          0          0          0          0   __scatter_zi.o
        18          0          0          0          0         80   exit.o
         6          0          0          0          0        152   heapauxi.o
         2          0          0          0          0          0   libinit.o
         2          0          0          0          0          0   libinit2.o
         2          0          0          0          0          0   libshutdown.o
         2          0          0          0          0          0   libshutdown2.o
         8          4          0          0         96         68   libspace.o
        78          0          0          0          0         80   rt_memclr_w.o
         2          0          0          0          0          0   rtexit.o
        10          0          0          0          0          0   rtexit2.o
        74          0          0          0          0         80   sys_stackheap_outer.o
         2          0          0          0          0         68   use_no_semi.o
         2          0          0          0          0         68   use_no_semi_2.o

    ----------------------------------------------------------------------
       344         12          0          0         96        664   Library Totals
         4          0          0          0          0          0   (incl. Padding)

        最后来说一下文章开头提到的项目映射文件的底部,项目整体的RO Size、RW Size和ROM Size。

  • RO Size是非易失存储器中保存只读数据的大小,由Code段和RO段组成。
  • RW Size是RAM中保存全局数据的大小,由RW段和ZI段组成。这不包括函数内部定义的局部变量,它们保存在寄存器或者堆栈中。
  • ROM Size是非易失存储器的最小大小,由Code段、RO段和RW段组成。

http://www.kler.cn/news/350689.html

相关文章:

  • hutool常用方法
  • 隨筆 20241025 Kafka数据一致性的韭菜比喻
  • 【数据分享】全国各省份农业-瓜果类面积(1993-2018年)
  • 弱口令与命令爆破+DVWA靶场+docker+ARL+Fofa+weakpass
  • 基于.NET 8.0,C#中Microsoft.Office.Interop.Excel来操作office365的excel
  • 设计模式---模版模式
  • 解决 Qt 中提升控件后样式表无法正确应用的问题
  • 导致动态代理无法使用的原因有哪些?
  • 牛市,路漫漫其修远兮
  • SSO 单点登录详解
  • 最短路问题之dijikstra算法
  • 【进阶OpenCV】 (16)-- 人脸识别 -- FisherFaces算法
  • Nordic-RT-Thread5.1.0移植笔记
  • 好玩的css按钮
  • 关于 GLFW、SDL2、Win32、GLUT 和 macOS(OSX)平台的介绍
  • UDP/TCP协议详解
  • Git 分支操作-开发规范
  • 条款2 理解auto类型的推导
  • 如何通过 Service Mesh 构建高效、安全的微服务系统
  • FFmpeg的简单使用【Windows】--- 视频倒叙播放
  • 一文详解线程池
  • R语言统计分析——折线图
  • 【uniapp】实现触底加载数据
  • Linux实验三
  • MySQL 数据库--查询
  • 《数据之海》