Keil生成的Map文件分析及存储使用情况分析

1 引入

相信有较大项目开发经验的朋友都曾遇到内存溢出的问题,那么大家都是如何分析这类问题的呢?大家遇到HardFault_Handler 有对map分析过吗?

出现HardFault_Handler原因:

  • 数组越界操作;
  • 内存溢出,访问越界;
  • 堆栈溢出,程序跑飞;
  • 中断处理错误;

解决办法:参考链接:https://blog.csdn.net/electrocrazy/article/details/78173558

首先讲述一下关于map在MDK-ARM中的配置。其实,在MDK-ARM中,我们可以根据自己的情况(不同配置),在map文件中输出对应(我们需要)的内容。默认情况下,输出所有信息。

Project -> Options for Target -> Listing:会看到如下配置界面:

img

看到上图,相信都应该明白map文件大概有哪些内容了吧?

img

map文件里面内容大致分为五大类(按照map文件分类的顺序):

1.Section Cross References:模块、段(入口)交叉引用;

2.Removing Unused input sections from the image:移除未使用的模块;

3.Image Symbol Table:映射符号表;

4.Memory Map of the image:内存(映射)分布;

5.Image component sizes:存储组成大小。


2 Section Cross References:模块、段(入口)交叉引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Component: Arm Compiler for Embedded 6.22 Tool: armlink [5ee90200]

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

Section Cross References

startup_stm32f215xx.o(RESET) refers to startup_stm32f215xx.o(STACK) for __initial_sp
startup_stm32f215xx.o(RESET) refers to startup_stm32f215xx.o(.text) for Reset_Handler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.NMI_Handler) for NMI_Handler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.HardFault_Handler) for HardFault_Handler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.MemManage_Handler) for MemManage_Handler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.BusFault_Handler) for BusFault_Handler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.UsageFault_Handler) for UsageFault_Handler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.SVC_Handler) for SVC_Handler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.DebugMon_Handler) for DebugMon_Handler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.PendSV_Handler) for PendSV_Handler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.SysTick_Handler) for SysTick_Handler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.DMA1_Stream0_IRQHandler) for DMA1_Stream0_IRQHandler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.DMA1_Stream2_IRQHandler) for DMA1_Stream2_IRQHandler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.DMA1_Stream4_IRQHandler) for DMA1_Stream4_IRQHandler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.DMA1_Stream5_IRQHandler) for DMA1_Stream5_IRQHandler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.DMA1_Stream6_IRQHandler) for DMA1_Stream6_IRQHandler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.TIM1_BRK_TIM9_IRQHandler) for TIM1_BRK_TIM9_IRQHandler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.USART2_IRQHandler) for USART2_IRQHandler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.DMA1_Stream7_IRQHandler) for DMA1_Stream7_IRQHandler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.UART4_IRQHandler) for UART4_IRQHandler
startup_stm32f215xx.o(RESET) refers to stm32f2xx_it.o(.text.UART5_IRQHandler) for UART5_IRQHandler
startup_stm32f215xx.o(.text) refers to system_stm32f2xx.o(.text.SystemInit) for SystemInit
startup_stm32f215xx.o(.text) refers to entry.o(.ARM.Collect$$$$00000000) for __main
main.o(.text.main) refers to stm32f2xx_hal.o(.text.HAL_Init) for HAL_Init
main.o(.text.main) refers to stm32f2xx_hal_rcc.o(.text.HAL_RCC_OscConfig) for HAL_RCC_OscConfig
main.o(.text.main) refers to stm32f2xx_hal_rcc.o(.text.HAL_RCC_ClockConfig) for HAL_RCC_ClockConfig
main.o(.text.main) refers to gpio.o(.text.MX_GPIO_Init) for MX_GPIO_Init
main.o(.text.main) refers to dma.o(.text.MX_DMA_Init) for MX_DMA_Init
main.o(.text.main) refers to usart.o(.text.MX_UART4_Init) for MX_UART4_Init
......

配置中需勾选上:Cross Reference

Section Cross References:模块、段(入口)交叉引用,指的是各个源文件生成的模块、段(定义的入口)之间相互引用的关系。

比如:

main.o(.text.main) refers to gpio.o(.text.MX_GPIO_Init) for MX_GPIO_Init

意思是:

main模块(main.o)中的main函数(.text.main),引用(或者说调用)了gpio模块(gpio.o)中的MX_GPIO_Init函数。

提示:

main.o是main.c源文件生成的目标文件模块;

.text.main是main函数的入口。


3 Removing Unused input sections from the image:移除未使用的模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
Removing Unused input sections from the image.

Removing startup_stm32f215xx.o(HEAP), (512 bytes).
Removing main.o(.text), (0 bytes).
Removing main.o(.ARM.exidx.text.main), (8 bytes).
Removing main.o(.text.SystemClock_Config), (108 bytes).
Removing main.o(.ARM.exidx.text.SystemClock_Config), (8 bytes).
Removing main.o(.ARM.exidx.text.Error_Handler), (8 bytes).
Removing main.o(.bss.one_byte), (1 bytes).
Removing main.o(.ARM.use_no_argv), (4 bytes).
Removing gpio.o(.text), (0 bytes).
Removing gpio.o(.ARM.exidx.text.MX_GPIO_Init), (8 bytes).
Removing dma.o(.text), (0 bytes).
Removing dma.o(.ARM.exidx.text.MX_DMA_Init), (8 bytes).
Removing tim.o(.text), (0 bytes).
Removing tim.o(.ARM.exidx.text.MX_TIM9_Init), (8 bytes).
Removing tim.o(.ARM.exidx.text.HAL_TIM_Base_MspInit), (8 bytes).
Removing tim.o(.text.HAL_TIM_Base_MspDeInit), (38 bytes).
Removing tim.o(.ARM.exidx.text.HAL_TIM_Base_MspDeInit), (8 bytes).
Removing tim.o(.ARM.exidx.text.HAL_TIM_PeriodElapsedCallback), (8 bytes).
Removing tim.o(.ARM.exidx.text.TIM9_Task), (8 bytes).
Removing usart.o(.text), (0 bytes).
Removing usart.o(.ARM.exidx.text.MX_UART4_Init), (8 bytes).
Removing usart.o(.ARM.exidx.text.MX_UART5_Init), (8 bytes).
Removing usart.o(.ARM.exidx.text.MX_USART2_UART_Init), (8 bytes).
Removing usart.o(.ARM.exidx.text.HAL_UART_MspInit), (8 bytes).
Removing usart.o(.text.HAL_UART_MspDeInit), (186 bytes).
Removing usart.o(.ARM.exidx.text.HAL_UART_MspDeInit), (8 bytes).
Removing usart.o(.ARM.exidx.text.HAL_UART_TxCpltCallback), (8 bytes).
Removing usart.o(.text.Wait_UART4_Tx_Complete), (32 bytes).
Removing usart.o(.ARM.exidx.text.Wait_UART4_Tx_Complete), (8 bytes).
Removing usart.o(.text.Wait_UART5_Tx_Complete), (32 bytes).
Removing usart.o(.ARM.exidx.text.Wait_UART5_Tx_Complete), (8 bytes).
Removing usart.o(.text.Wait_UART2_Tx_Complete), (32 bytes).
Removing usart.o(.ARM.exidx.text.Wait_UART2_Tx_Complete), (8 bytes).
Removing usart.o(.ARM.exidx.text.HAL_UART_RxCpltCallback), (8 bytes).
Removing usart.o(.text.Wait_UART4_Rx_Complete), (32 bytes).
Removing usart.o(.ARM.exidx.text.Wait_UART4_Rx_Complete), (8 bytes).
Removing usart.o(.text.Wait_UART5_Rx_Complete), (32 bytes).
Removing usart.o(.ARM.exidx.text.Wait_UART5_Rx_Complete), (8 bytes).
Removing usart.o(.text.Wait_UART2_Rx_Complete), (32 bytes).
Removing usart.o(.ARM.exidx.text.Wait_UART2_Rx_Complete), (8 bytes).
Removing usart.o(.text.Start_UART4_Recv), (50 bytes).
Removing usart.o(.ARM.exidx.text.Start_UART4_Recv), (8 bytes).
Removing usart.o(.text.Start_UART5_Recv), (50 bytes).
Removing usart.o(.ARM.exidx.text.Start_UART5_Recv), (8 bytes).
Removing usart.o(.ARM.exidx.text.Start_UART2_Recv), (8 bytes).
Removing usart.o(.ARM.exidx.text.HAL_UARTEx_RxEventCallback), (8 bytes).
Removing usart.o(.ARM.exidx.text.HAL_UART_ErrorCallback), (8 bytes).
Removing usart.o(.text.USART4_Read_Byte), (16 bytes).
Removing usart.o(.ARM.exidx.text.USART4_Read_Byte), (8 bytes).
Removing usart.o(.text.USART5_Read_Byte), (16 bytes).
Removing usart.o(.ARM.exidx.text.USART5_Read_Byte), (8 bytes).
Removing usart.o(.text.USART2_Read_Byte), (16 bytes).
Removing usart.o(.ARM.exidx.text.USART2_Read_Byte), (8 bytes).
Removing usart.o(.bss.uart4_rx_buffer), (128 bytes).
Removing usart.o(.bss.uart5_rx_buffer), (128 bytes).
Removing stm32f2xx_it.o(.text), (0 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.NMI_Handler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.HardFault_Handler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.MemManage_Handler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.BusFault_Handler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.UsageFault_Handler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.SVC_Handler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.DebugMon_Handler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.PendSV_Handler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.SysTick_Handler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.DMA1_Stream0_IRQHandler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.DMA1_Stream2_IRQHandler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.DMA1_Stream4_IRQHandler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.DMA1_Stream5_IRQHandler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.DMA1_Stream6_IRQHandler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.TIM1_BRK_TIM9_IRQHandler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.USART2_IRQHandler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.DMA1_Stream7_IRQHandler), (8 bytes).
Removing stm32f2xx_it.o(.ARM.exidx.text.UART4_IRQHandler), (8 bytes).
......
894 unused section(s) (total 46042 bytes) removed from the image.

配置中需勾选上:Unused Sections Info

这一选项很好理解,就是我们工程代码中,没有被调用的模块。

最后还有一个统计信息:

894 unused section(s) (total 46042 bytes) removed from the image.

1.总共有894段没有被调用;

2.没有被调用的大小为46042字节;


4 Image Symbol Table:映射符号表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Image Symbol Table

Local Symbols

Symbol Name Value Ov Type Size Object(Section)

../clib/division.s 0x00000000 Number 0 aeabi_sdiv.o ABSOLUTE
../clib/microlib/division.c 0x00000000 Number 0 uldiv.o ABSOLUTE
../clib/microlib/division.c 0x00000000 Number 0 uidiv.o ABSOLUTE
../clib/microlib/errno.c 0x00000000 Number 0 errno.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry2.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry5.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry7a.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry7b.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry8a.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry8b.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry9a.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry9b.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry10a.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry10b.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry11a.o ABSOLUTE
../clib/microlib/init/entry.s 0x00000000 Number 0 entry11b.o ABSOLUTE
../clib/microlib/longlong.c 0x00000000 Number 0 llshl.o ABSOLUTE
../clib/microlib/longlong.c 0x00000000 Number 0 llushr.o ABSOLUTE
../clib/microlib/longlong.c 0x00000000 Number 0 llsshr.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printfb.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printf0.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printf1.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printf2.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printf3.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printf4.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printf5.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printf6.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printf7.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printf8.o ABSOLUTE
../clib/microlib/printf/printf.c 0x00000000 Number 0 printfa.o ABSOLUTE
../clib/microlib/printf/stubs.s 0x00000000 Number 0 printfstubs.o ABSOLUTE
../clib/microlib/stdio/fputc.c 0x00000000 Number 0 fputc.o ABSOLUTE
../clib/microlib/stdio/fputc.c 0x00000000 Number 0 fputc_h.o ABSOLUTE
../clib/microlib/stdio/semi.s 0x00000000 Number 0 semi.o ABSOLUTE
../clib/microlib/stdio/streams.c 0x00000000 Number 0 stdout.o ABSOLUTE
../clib/microlib/string/memcpy.c 0x00000000 Number 0 memcpya.o ABSOLUTE
../clib/microlib/string/memcpy.c 0x00000000 Number 0 memcpyb.o ABSOLUTE
../clib/microlib/string/memset.c 0x00000000 Number 0 memseta.o ABSOLUTE
../clib/microlib/string/strlen.c 0x00000000 Number 0 strlen.o ABSOLUTE
../clib/microlib/stubs.s 0x00000000 Number 0 iusefp.o ABSOLUTE
../clib/microlib/stubs.s 0x00000000 Number 0 iusesemip.o ABSOLUTE

配置中需勾选上:Symbols

Image Symbol Table:映射符号表,也就是各个段所存储对应地址的表(这一项比较重要)。

Symbols分为两大类

1.Local Symbols局部

2.Global Symbols全局

内容要点

1.Symbol Name:符号名称

2.Value:存储对应的地址;

大家会发现有0x0800xxxx、0x2000xxxx这样的地址。

0x0800xxxx指存储在FLASH里面的代码、变量等。

0x2000xxxx指存储在内存RAM中的变量Data等。

3.Ov Type:符号对应的类型

符号类型大概有几种:Number、Section、Thumb Code、Data等;

细心的朋友会发现:全局、静态变量等位于0x2000xxxx的内存RAM中。

4.Size:存储大小

这个容易理解,我们怀疑内存溢出,可以查看代码存储大小来分析。

**5.Object(Section)**:段目标

这里一般指所在模块(所在源文件)。


5 Memory Map of the image:内存(映射)分布

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Memory Map of the image

Image Entry point : 0x08000185

Load Region LR_IROM1 (Base: 0x08000000, Size: 0x00003d30, Max: 0x000e0000, ABSOLUTE)

Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x00003d20, Max: 0x000e0000, ABSOLUTE)

Exec Addr Load Addr Size Type Attr Idx E Section Name Object

0x08000000 0x08000000 0x00000184 Data RO 3 RESET startup_stm32f215xx.o
0x08000184 0x08000184 0x00000000 Code RO 1276 * .ARM.Collect$$$$00000000 mc_w.l(entry.o)
0x08000184 0x08000184 0x00000004 Code RO 1595 .ARM.Collect$$$$00000001 mc_w.l(entry2.o)
0x08000188 0x08000188 0x00000004 Code RO 1598 .ARM.Collect$$$$00000004 mc_w.l(entry5.o)
0x0800018c 0x0800018c 0x00000000 Code RO 1600 .ARM.Collect$$$$00000008 mc_w.l(entry7b.o)
0x0800018c 0x0800018c 0x00000000 Code RO 1602 .ARM.Collect$$$$0000000A mc_w.l(entry8b.o)
0x0800018c 0x0800018c 0x00000008 Code RO 1603 .ARM.Collect$$$$0000000B mc_w.l(entry9a.o)
0x08000194 0x08000194 0x00000000 Code RO 1605 .ARM.Collect$$$$0000000D mc_w.l(entry10a.o)
0x08000194 0x08000194 0x00000000 Code RO 1607 .ARM.Collect$$$$0000000F mc_w.l(entry11a.o)
0x08000194 0x08000194 0x00000004 Code RO 1596 .ARM.Collect$$$$00002712 mc_w.l(entry2.o)
0x08000198 0x08000198 0x00000024 Code RO 4 .text startup_stm32f215xx.o
0x080001bc 0x080001bc 0x00000062 Code RO 1279 .text mc_w.l(uldiv.o)
0x0800021e 0x0800021e 0x00000024 Code RO 1281 .text mc_w.l(memcpya.o)
0x08000242 0x08000242 0x00000024 Code RO 1283 .text mc_w.l(memseta.o)
0x08000266 0x08000266 0x0000001e Code RO 1625 .text mc_w.l(llshl.o)
0x08000284 0x08000284 0x00000020 Code RO 1627 .text mc_w.l(llushr.o)
0x080002a4 0x080002a4 0x00000030 Code RO 1651 .text mc_w.l(init.o)
0x080002d4 0x080002d4 0x000000b6 Code RO 1177 .text.AD5362_Init ad5362.o
0x0800038a 0x0800038a 0x00000002 PAD
0x0800038c 0x0800038c 0x00000060 Code RO 1189 .text.AD5362_Write_To_DAC ad5362.o
0x080003ec 0x080003ec 0x00000060 Code RO 1216 .text.AD7328_Disable_Sequence_All10V_Setup ad7328.o
0x0800044c 0x0800044c 0x0000000e Code RO 1220 .text.AD7328_Disable_Sequence_All10V_Setup_U12 ad7328.o
0x0800045a 0x0800045a 0x00000002 PAD
0x0800045c 0x0800045c 0x00000070 Code RO 1200 .text.AD7328_Init ad7328.o
......


配置中需勾选上:Memory Map

Memory Map of the image:内存(映射)分布,内容相对较多,也是比较重要的一项

Image Entry point : 0x08000131:指映射入口地址。

Load Region LR_IROM1 (Base: 0x08000000, Size: 0x000004cc, Max: 0x00080000, ABSOLUTE):

指加载区域位于LR_IROM1开始地址0x08000000,大小有0x000004cc,这块区域最大为0x00080000.

执行区域

Execution Region ER_IROM1

Execution Region RW_IRAM1

这个区域,其实就是对应我们目标配置中的区域,如下如:

img

内容要点

1.Base Addr:存储地址

0x0800xxxxFLASH地址和0x2000xxxx内存RAM地址。

2.Size:存储大小

3.Type:类型

Data:数据类型

Code:代码类型

Zero:未初始化变量类型

PAD:这个类型在map文件中放在这个位置,其实它不能算这里的类型。要翻译的话,只能说的“补充类型”。

ARM处理器是32位的,如果定义一个8位或者16位变量就会剩余一部分,这里就是指的“补充”的那部分,会发现后面的其他几个选项都没有对应的值。

4.Attr:属性

RO:存储与ROM中的段

RW:存储与RAM中的段

5.Section Name:段名

这里也可以说为入口分类名,与第一章节“Section Cross References”指的模块、段一样。

大概包含:RESET、.ARM、 .text、 i、 .data、 .bss、 HEAP、 STACK等。

6.Object:目标


6 Image component sizes:存储组成大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
Image component sizes


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

278 0 0 0 32 4350 ad5362.o
222 0 0 0 64 13210 ad7328.o
136 0 0 0 0 3444 dma.o
140 0 0 0 0 3805 flash_handler.o
528 0 0 0 0 2402 gpio.o
18 0 0 0 0 1428 led.o
232 0 0 0 2056 5891 main.o
620 0 0 0 0 4878 my_spi.o
406 0 0 0 1024 7418 protocol_handler.o
246 0 0 0 4 3149 protocol_parsing.o
240 0 0 0 0 3157 ring_buffer.o
36 8 388 0 1024 780 startup_stm32f215xx.o
200 0 0 8 4 7269 stm32f2xx_hal.o
196 0 0 0 0 10592 stm32f2xx_hal_cortex.o
1146 6 8 0 0 10523 stm32f2xx_hal_dma.o
534 0 0 0 32 5565 stm32f2xx_hal_flash.o
394 0 0 0 0 5797 stm32f2xx_hal_flash_ex.o
442 0 0 0 0 4875 stm32f2xx_hal_gpio.o
56 0 0 0 0 1450 stm32f2xx_hal_msp.o
1410 0 0 0 0 8042 stm32f2xx_hal_rcc.o
1342 0 0 0 0 57328 stm32f2xx_hal_tim.o
4 0 0 0 0 21472 stm32f2xx_hal_tim_ex.o
3594 0 0 0 0 32059 stm32f2xx_hal_uart.o
140 0 0 0 0 6558 stm32f2xx_it.o
182 0 0 0 1024 1763 store.o
2 0 24 4 0 2119 system_stm32f2xx.o
252 0 0 1 76 8412 tim.o
1754 0 0 0 2044 12355 usart.o

----------------------------------------------------------------------
14864 14 454 16 7384 250091 Object Totals
0 0 32 0 0 0 (incl. Generated)
114 0 2 3 0 0 (incl. Padding)

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

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

0 0 0 0 0 0 entry.o
0 0 0 0 0 0 entry10a.o
0 0 0 0 0 0 entry11a.o
8 4 0 0 0 0 entry2.o
4 0 0 0 0 0 entry5.o
0 0 0 0 0 0 entry7b.o
0 0 0 0 0 0 entry8b.o
8 4 0 0 0 0 entry9a.o
30 0 0 0 0 0 handlers.o
48 10 0 0 0 68 init.o
30 0 0 0 0 68 llshl.o
32 0 0 0 0 68 llushr.o
36 0 0 0 0 68 memcpya.o
36 0 0 0 0 108 memseta.o
98 0 0 0 0 92 uldiv.o

----------------------------------------------------------------------
330 18 0 0 0 472 Library Totals
0 0 0 0 0 0 (incl. Padding)

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

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

330 18 0 0 0 472 mc_w.l

----------------------------------------------------------------------
330 18 0 0 0 472 Library Totals

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

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


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

15194 32 454 16 7384 250039 Grand Totals
15194 32 454 16 7384 250039 ELF Image Totals
15194 32 454 16 0 0 ROM Totals

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

Total RO Size (Code + RO Data) 15648 ( 15.28kB)
Total RW Size (RW Data + ZI Data) 7400 ( 7.23kB)
Total ROM Size (Code + RO Data + RW Data) 15664 ( 15.30kB)

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

配置中需勾选上:Size Info

Image component sizes:存储组成大小,其实主要就是对模块进行汇总存储大小信息。

这一章节内容相信大家都能理解,我们编译工程后,在编译窗口一般会看到类似如下一段信息:

Program Size: Code=908 RO-data=320 RW-data=0 ZI-data=1024

各部分解析:

img

(1) Code(inc.Data) : 包含两部分,即代码和数据

- code,即程序代码部分

- inline data. For example, literal pools(文字常量池), and short strings(短字符串)等. 这个一般被忽略,请大家注意!!!

(2) RO Data: read-only data,只读的数据,如程序定义的(除了内联数据inline data之外)常量数据

Shows how many bytes are occupied by read-only data. This is in addition to the inline data included in the Code (inc. data) column. 除inline data 之外的所有只读数据。

(3) RW Data: read write data,可读写的数据,如已初始化的全局变量

Shows how many bytes are occupied by read-write data.

(4) ZI Data: zero initialized data,零初始化的可读写变量,如未初始化的全局变量

Shows how many bytes are occupied by zero-initialized data.

Code、Ro-data:位于FLASH中;

RW-data、ZI-data:位于RAM中;

提醒:RW-data已初始化的数据会存储在Flash中,上电会从FLASH搬移至RAM中。

关系如下:

RO Size = Code + RO Data

RW Size = RW Data + ZI Data

ROM Size = Code + RO Data + RW Data

RAM Size=RW Data + ZI Data

Q:这里RW-data为什么既占用flash,又占用ram呢?
A:这是因为已初始化的数据会存储在Flash中,上电会从FLASH搬移至RAM中。

Q:为什么ROM Size不包括ZI Data?
A:这是因为已经初始化的数据,在掉电后需要保存初始值,以便上电运行后重载,因此存在rom中。而ZI Data数据都是0,上电运行后直接清零即可,包含进去反而浪费存储空间。

为什么ROM Size不包括ZI Data?

Total ROM Size (Code + RO Data + RW Data)这样所写的程序占用的ROM的字节总数,也就是说程序所下载到ROM flash 中的大小。为什么Rom中还要存RW,因为掉电后RAM中所有数据都丢失了,每次上电RAM中的数据是被重新赋值的,每次这些固定的值就是存储在Rom中的,为什么不包含ZI段呢,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可。包含进去反而浪费存储空间。

更多具体内容可以参看文章:*Keil编译存储相关说明及拓展*

上面信息是比较全面的汇总,如果不想看那些模块的详细,只看汇总统计的信息可以在配置中只勾选“Totals Info”,对比信息: