资讯动态

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

发布时间:2026/10/27 1:16:21 来源:尧图企业网站定制
相关阅读嵌入式https://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: Code5282 RO-data362 RW-data28 ZI-data1900在项目映射文件的底部也可以找到类似的信息。 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段所有的实验在ARM编译器5下进行。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: Code5310 RO-data362 RW-data28 ZI-data1900由于现在很多单片机采用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: Code5282 RO-data362 RW-data36 ZI-data1900RO段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: Code5284 RO-data372 RW-data32 ZI-data1896要弄清楚为什么会有这种情况需要去看项目映射文件下面列出了例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段组成。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑