从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
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
73function(zephyr_code_relocate)
set(options NOCOPY) #可选参数
set(single_args LIBRARY LOCATION PHDR) //单一参数
set(multi_args FILES) //多参数
cmake_parse_arguments(CODE_REL "${options}" "${single_args}"
"${multi_args}" ${ARGN})
#解析参数后生成
#CODE_REL_FILES=file1.c file2.c
#CODE_REL_LOCATION=_TEXT
#CODE_REL_NOCOPY没有
# 参数验证
if(CODE_REL_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "zephyr_code_relocate(${ARGV0} ...) "
"given unknown arguments: ${CODE_REL_UNPARSED_ARGUMENTS}")
endif()
if((NOT CODE_REL_FILES) AND (NOT CODE_REL_LIBRARY))
message(FATAL_ERROR
"zephyr_code_relocate() requires either FILES or LIBRARY be provided")
endif()
if(CODE_REL_FILES AND CODE_REL_LIBRARY)
message(FATAL_ERROR "zephyr_code_relocate() only accepts "
"one argument between FILES and LIBRARY")
endif()
if(NOT CODE_REL_LOCATION)
message(FATAL_ERROR "zephyr_code_relocate() requires a LOCATION argument")
endif()
#库和文件的结果都解析出来放到file_list中,
if(CODE_REL_LIBRARY)
# Use cmake generator expression to convert library to file list
set(genex_src_dir "$<TARGET_PROPERTY:${CODE_REL_LIBRARY},SOURCE_DIR>")
set(genex_src_list "$<TARGET_PROPERTY:${CODE_REL_LIBRARY},SOURCES>")
set(file_list
"${genex_src_dir}/$<JOIN:${genex_src_list},$<SEMICOLON>${genex_src_dir}/>")
else()
# Check if CODE_REL_FILES is a generator expression, if so leave it
# untouched.
string(GENEX_STRIP "${CODE_REL_FILES}" no_genex)
if(CODE_REL_FILES STREQUAL no_genex)
# no generator expression in CODE_REL_FILES, check if list of files
# is absolute
foreach(file ${CODE_REL_FILES})
if(NOT IS_ABSOLUTE ${file})
set(file ${CMAKE_CURRENT_SOURCE_DIR}/${file})
endif()
list(APPEND file_list ${file})
endforeach()
else()
# Generator expression is present in file list. Leave the list untouched.
set(file_list ${CODE_REL_FILES})
endif()
endif()
# 是否复制的标记放在copy_flag中
if(NOT CODE_REL_NOCOPY)
set(copy_flag COPY)
else()
set(copy_flag NOCOPY)
endif()
if(CODE_REL_PHDR)
set(CODE_REL_LOCATION "${CODE_REL_LOCATION}\ :${CODE_REL_PHDR}")
endif()
#最后的的结果放在code_data_relocation_target中
get_property(code_rel_str TARGET code_data_relocation_target
PROPERTY COMPILE_DEFINITIONS)
set_property(TARGET code_data_relocation_target
PROPERTY COMPILE_DEFINITIONS
"${code_rel_str}|${CODE_REL_LOCATION}:${copy_flag}:${file_list}")
endfunction()
生成的结果放在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
2
3
4if(CONFIG_CODE_DATA_RELOCATION)
# @Intent: Linker script to relocate .text, data and .bss sections
toolchain_ld_relocation()
endif()
zephyr/cmake/linker/ld/target_relocation.cmake
中定义了宏toolchain_ld_relocation
,在该宏中调用脚本gen_relocate_app.py
,实现解析如下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
31macro(toolchain_ld_relocation)
set(MEM_RELOCATION_LD "${PROJECT_BINARY_DIR}/include/generated/linker_relocate.ld")
set(MEM_RELOCATION_SRAM_DATA_LD
"${PROJECT_BINARY_DIR}/include/generated/linker_sram_data_relocate.ld")
set(MEM_RELOCATION_SRAM_BSS_LD
"${PROJECT_BINARY_DIR}/include/generated/linker_sram_bss_relocate.ld")
set(MEM_RELOCATION_CODE "${PROJECT_BINARY_DIR}/code_relocation.c")
set(MEM_REGION_DEFAULT_RAM RAM)
#调用gen_relocate_app.py 按照code_data_relocation_target生成重定位相关文件
add_custom_command(
OUTPUT ${MEM_RELOCATION_CODE} ${MEM_RELOCATION_LD}
COMMAND
${PYTHON_EXECUTABLE}
${ZEPHYR_BASE}/scripts/build/gen_relocate_app.py
$<$<BOOL:${CMAKE_VERBOSE_MAKEFILE}>:--verbose>
-d ${APPLICATION_BINARY_DIR}
-i \"$<TARGET_PROPERTY:code_data_relocation_target,COMPILE_DEFINITIONS>\"
-o ${MEM_RELOCATION_LD}
-s ${MEM_RELOCATION_SRAM_DATA_LD}
-b ${MEM_RELOCATION_SRAM_BSS_LD}
-c ${MEM_RELOCATION_CODE}
--default_ram_region ${MEM_REGION_DEFAULT_RAM}
DEPENDS app kernel ${ZEPHYR_LIBS_PROPERTY}
)
add_library(code_relocation_source_lib STATIC ${MEM_RELOCATION_CODE})
target_include_directories(code_relocation_source_lib PRIVATE
${ZEPHYR_BASE}/kernel/include ${ARCH_DIR}/${ARCH}/include)
target_link_libraries(code_relocation_source_lib zephyr_interface)
endmacro()
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
2
3
4
5
6
7
8
9
10
11
12
13#ifdef CONFIG_CODE_DATA_RELOCATION
#include <linker_sram_bss_relocate.ld>
#endif
#ifdef CONFIG_CODE_DATA_RELOCATION
#include <linker_relocate.ld>
#endif /* CONFIG_CODE_DATA_RELOCATION */
#ifdef CONFIG_CODE_DATA_RELOCATION
#include <linker_sram_data_relocate.ld>
#endif
c文件的应用
在zephyr/cmake/linker/ld/target_relocation.cmake
中通过下面方式将code_relocation.c
加入构建1
2
3
4
5set(MEM_RELOCATION_CODE "${PROJECT_BINARY_DIR}/code_relocation.c")
add_library(code_relocation_source_lib STATIC ${MEM_RELOCATION_CODE})
target_include_directories(code_relocation_source_lib PRIVATE
${ZEPHYR_BASE}/kernel/include ${ARCH_DIR}/${ARCH}/include)
target_link_libraries(code_relocation_source_lib zephyr_interface)
code_relocation.c
内的函数在启动代码中的调用如下:
在zephyr/kernel/xip.c
中执行代码和数据段拷贝1
2
3
4
5
6
7
8void z_data_copy(void)
{
#ifdef CONFIG_CODE_DATA_RELOCATION
extern void data_copy_xip_relocation(void);
data_copy_xip_relocation();
#endif /* CONFIG_CODE_DATA_RELOCATION */
}
在zephyr/kernel/init.c
中执行bss初始化1
2
3
4
5
6
7
8void z_bss_zero(void)
{
#ifdef CONFIG_CODE_DATA_RELOCATION
extern void bss_zeroing_relocation(void);
bss_zeroing_relocation();
#endif /* CONFIG_CODE_DATA_RELOCATION */
}
参考
https://docs.zephyrproject.org/latest/kernel/code-relocation.html