想要搞清这个问题,需要重点研究startup_cm.s文件。
启动时,RAM数据的初始化主要包括两个过程:
- RAM区域初始化(数据清0);
- 有初始值的变量需要从flash中加载到ram中。
RAM区域初始化
这一段代码由汇编实现,在startup_cm.s中,主要由DTCM_Init和RamInit实现的,贴一段DTCM_Init的代码:
DTCM_Init:
/* Initialize DTCM ECC */
LDR R0, =__DTCM_INIT
CMP R0, #0
/* Skip if __DTCM_INIT is not set */
beq DTCM_LOOP_END
LDR R1, =__INT_DTCM_START
LDR R2, =__INT_DTCM_END
SUBS R2, R1
SUBS R2, #1
BLE DTCM_LOOP_END
MOVS R0, #0
MOVS R3, #0
DTCM_LOOP:
STM R1!, {R0, R3}
SUBS R2, #8
BGE DTCM_LOOP
DTCM_LOOP_END:
加载变量
在startup_cm.s中有个函数_DATA_INIT,通过该函数跳转到C代码startup.c,由init_data_bss这个函数实现。分析init_data_bss的代码,可以发现__INIT_TABLE作为.init_table起始地址的标签,会被强转为Sys_CopyLayoutType *结构体指针,
typedef struct
{
uint32 * ram_start; /*!< Start address of section in RAM */
uint32 * rom_start; /*!< Start address of section in ROM */
uint32 * rom_end; /*!< End address of section in ROM */
} Sys_CopyLayoutType;
然后访问该结构体的成员,就得到了相应区域的ram起始地址,rom起始地址,rom结束地址,从而实现数据从flash加载到ram中。
最后贴一下__INIT_TABLE,可以发现每三行正好对应结构体的3个成员:
__INIT_TABLE
DCD 9
DCD rwBlock$$Base
DCD cacheable_data_init$$Base
DCD cacheable_data_init$$Limit
DCD rwMcalDataBlock$$Base
DCD cacheable_mcal_data_init$$Base
DCD cacheable_mcal_data_init$$Limit
DCD ramCodeBlock$$Base
DCD cacheable_code_init$$Base
DCD cacheable_code_init$$Limit
DCD dataNcBlock$$Base
DCD non_cacheable_data_init$$Base
DCD non_cacheable_data_init$$Limit
DCD constNcBlock$$Base
DCD non_cacheable_const_init$$Base
DCD non_cacheable_const_init$$Limit
DCD dataShBlock$$Base
#if (!defined(CORE0) && defined(MULTIPLE_IMAGE))
DCD 0
DCD 0
#else
DCD shareable_data_init$$Base
DCD shareable_data_init$$Limit
#endif
DCD intcVectorBlock$$Base
DCD interrupt_vector_init$$Base
DCD interrupt_vector_init$$Limit
DCD dataDtcmBlock$$Base
DCD dtcmDataBlock_init$$Base
DCD dtcmDataBlock_init$$Limit
DCD textItcmBlock$$Base
DCD itcmCodeBlock_init$$Base
DCD itcmCodeBlock_init$$Limit
__INIT_TABLE_END