自定义段注入示例
源码位置: samples/subsys/linker_script/custom_section 查看源码
功能说明
演示如何通过 listenai_add_linker_section() 注入自定义链接器段,并通过 listenai_add_linker_scatter() 注册启动时的数据复制。实现从 ROM 加载、在 RAM 中运行的自定义数据段。
硬件连接
无需外部连接,本示例仅演示链接脚本特性。
示例内容
编写
.ld片段文件定义.app_config段(>RAM AT>ROM)在 CMakeLists.txt 中注册段到 ROM slot
注册散加载表条目,启动代码自动将数据从 ROM 复制到 RAM
在 C 代码中将配置项放入该段,运行时通过链接器符号遍历
编译
重要提示:在编译前,请先确认您使用的开发板型号。SDK 目前支持以下开发板:
arcs_evb - ARCS EVB 评估板
arcs_mini - ARCS Mini 开发板
根据您的开发板型号,选择对应的编译命令:
在示例目录下执行编译:
# 使用 arcs_evb 开发板
./build.sh -C -DBOARD=arcs_evb
# 或使用 arcs_mini 开发板
./build.sh -C -DBOARD=arcs_mini
Note
如果在 SDK 根目录执行,需要指定示例路径:
# 使用 arcs_evb 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_evb
# 或使用 arcs_mini 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_mini
Note
确保已安装对应的工具链。
烧录
编译完成后,使用 SDK tools 目录下的 cskburn 工具烧录固件:
./tools/burn/cskburn -s /dev/ttyUSB0 -b 3000000 0x0 build/arcs.bin -C arcs
Note
烧录参数说明:
-s /dev/ttyUSB0:串口设备路径,需要根据实际情况修改 - Linux 系统:通常是/dev/ttyUSB0或/dev/ttyACM0- 可通过ls /dev/tty*命令查看可用串口设备 - 不同开发板或 USB 转串口芯片可能使用不同的设备名-b 3000000:烧录波特率(3Mbps)0x0:烧录起始地址build/arcs.bin:编译生成的固件路径-C arcs:芯片类型
注意事项:
确保开发板已正确连接到电脑
如果无法识别串口设备,请检查 USB 连接线是否正常,或尝试其他 USB 端口
预期输出
[I][section] === Custom Section Demo ===
[I][section] config[0]: baud_rate = 115200
[I][section] config[1]: retry_count = 3
[I][section] config[2]: timeout_ms = 5000
[I][section] Total config entries: 3
关键代码
.ld 片段文件
/* linker/app-config-sections.ld */
.app_config : ALIGN(4) {
. = ALIGN(4);
__app_config_start = .;
KEEP(*(.app_config))
KEEP(*(.app_config.*))
. = ALIGN(4);
__app_config_end = .;
} >RAM AT>ROM
CMakeLists.txt 注册
# 注入段定义到 ROM slot
listenai_add_linker_section(
FILE ${CMAKE_CURRENT_SOURCE_DIR}/linker/app-config-sections.ld
SLOT ROM
SORT_KEY "50-app"
)
# 注册散加载:启动时从 ROM 复制到 RAM
listenai_add_linker_scatter(SCATLOAD .app_config)
C 代码使用
/* 链接器导出的段起止符号 */
extern const app_config_entry_t __app_config_start[];
extern const app_config_entry_t __app_config_end[];
/* 将数据放入自定义段 */
#define APP_CONFIG_DEFINE(cfg_key, cfg_value) \
static const app_config_entry_t __app_cfg_##cfg_key \
__attribute__((used, section(".app_config." #cfg_key))) = { \
.key = #cfg_key, \
.value = (cfg_value), \
}
APP_CONFIG_DEFINE(baud_rate, 115200);
APP_CONFIG_DEFINE(timeout_ms, 5000);
/* 运行时遍历 */
for (entry = __app_config_start; entry < __app_config_end; entry++) {
LOGI(" %s = %ld", entry->key, (long)entry->value);
}
验证方法
# 确认最终链接脚本包含该段和散加载条目
grep app_config build/linker.ld
注意事项
KEEP() 必需:自定义段中的符号可能未被直接引用,必须用
KEEP()防止链接器垃圾回收SCATLOAD vs SCATZERO:
SCATLOAD用于从 ROM 复制到 RAM 的段,SCATZERO用于需要零填充的 BSS 段SLOT 选择:段定义必须放在正确的 SLOT 中,确保在链接脚本中的位置合理
attribute((used)):配合
KEEP()使用,防止编译器优化掉未直接引用的变量