从Zephyr代码和数据重定位–1使用方法一文中“基本概念介绍”我们知道代码和数据的重定位是通过修改linker.ld和启动代码拷贝完成,Zephyr的实现就是将这一过程自动化,主要的流程如下cmake函数zephyr_code_relocate
调用gen_relocate_app.py
生成如下文件:
linker_relocate.ld
linker_sram_data_relocate.ld
linker_sram_bss_relocate.ld
code_relocation.c
*.ld文件将被include到linker.ld
,code_relocation.c
提供的拷贝函数data_copy_xip_relocation
被zephyr/kernel/xip.c
调用,提供bss初始化函数bss_zeroing_relocation
被zephyr/kernel/init.c
调用。
文件生成
在CMakeList.txt中使用zephyr_code_relocate
指定文件被重定位的地方
1 | zephyr_code_relocate(FILES file1.c file2.c LOCATION SRAM_TEXT) |
zephyr_code_relocate
定义在cmake/modules/extensions.cmake
内,实现解析如下
1 | function(zephyr_code_relocate) |
生成的结果放在code_data_relocation_target
变量中
1 | SRAM_TEXT:COPY:file1.c;file2.c |
在执行toolchain_ld_relocation
时使用.zephyr/CMakeLists.txt
在启用CONFIG_CODE_DATA_RELOCATION
的情况下调用toolchain_ld_relocation
1 | if(CONFIG_CODE_DATA_RELOCATION) |
zephyr/cmake/linker/ld/target_relocation.cmake
中定义了宏toolchain_ld_relocation
,在该宏中调用脚本gen_relocate_app.py
,实现解析如下
1 | macro(toolchain_ld_relocation) |
gen_relocate_app.py
的路径为zephyr/scripts/build/gen_relocate_app.py
主要参数:
- -d 指向编译结果目录
- -i 传入
code_data_relocation_target
,也就是这种形式SRAM_TEXT:COPY:file1.c;file2.c
- -o 输出
linker_relocate.ld
- -s 输出
linker_sram_data_relocate.ld
- -b 输出
linker_sram_bss_relocate.ld
- -c 输出
code_relocation.c
- –default_ram_region 指定默认RAM区的名称为:RAM,如果不指定该参数默认为SRAM,该名称应出现在linker.ld的MEMORY中
gen_relocate_app.py
的内容比较多,不列出分析,说明主要流程
get_obj_filename
找出要重定位文件对应的obj文件find_sections
找出obj中的sectionassign_to_correct_mem_region
根据内存区域的段信息参数(_section, 例如SDRAM2_TEXT中的_TEXT)提取出需要的section信息generate_linker_script
根据提取的section信息生成ld文件generate_memcpy_code
根据提取的section文件生成拷贝c文件内容,同时会参考no_copy参数dump_header_file
将c文件内容写入文件
gen_relocate_app.py
生成的文件放在构建目录build/zephyr/include/generated/
下,生成的ld文件有
linker_relocate.ld
linker_sram_data_relocate.ld
linker_sram_bss_relocate.ld
主要就是做section的放置,这里不列出细节。
生成的code_relocation.c
主要内容如下, 可以看到就是各个section的拷贝: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
43void data_copy_xip_relocation(void)
{
z_early_memcpy(&__dtcm_data_start, &__dtcm_data_rom_start,
(size_t) &__dtcm_data_size);
z_early_memcpy(&__itcm_text_start, &__itcm_text_rom_start,
(size_t) &__itcm_text_size);
z_early_memcpy(&__ram_text_start, &__ram_text_rom_start,
(size_t) &__ram_text_size);
z_early_memcpy(&__ram_rodata_start, &__ram_rodata_rom_start,
(size_t) &__ram_rodata_size);
z_early_memcpy(&__sram2_text_start, &__sram2_text_rom_start,
(size_t) &__sram2_text_size);
z_early_memcpy(&__sram2_rodata_start, &__sram2_rodata_rom_start,
(size_t) &__sram2_rodata_size);
z_early_memcpy(&__sram2_data_start, &__sram2_data_rom_start,
(size_t) &__sram2_data_size);
}
void bss_zeroing_relocation(void)
{
z_early_memset(&__dtcm_bss_start, 0,
(size_t) &__dtcm_bss_size);
z_early_memset(&__sram2_bss_start, 0,
(size_t) &__sram2_bss_size);
}
生成文件的引用
ld文件的引用
不同soc在自己的linker.ld中引用生成ld文件,例如可以在zephyr/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld
中可以看到如下内容
1 | #ifdef CONFIG_CODE_DATA_RELOCATION |
c文件的应用
在zephyr/cmake/linker/ld/target_relocation.cmake
中通过下面方式将code_relocation.c
加入构建
1 | set(MEM_RELOCATION_CODE "${PROJECT_BINARY_DIR}/code_relocation.c") |
code_relocation.c
内的函数在启动代码中的调用如下:
在zephyr/kernel/xip.c
中执行代码和数据段拷贝
1 | void z_data_copy(void) |
在zephyr/kernel/init.c
中执行bss初始化
1 | void z_bss_zero(void) |
参考
https://docs.zephyrproject.org/latest/kernel/code-relocation.html