编程, 调试

在IAR工具链中使用overlay命令进行SMP多核工程TCM配置

  • IAR
  • 14分钟阅读
<span id="hs_cos_wrapper_name" class="hs_cos_wrapper hs_cos_wrapper_meta_field hs_cos_wrapper_type_text" style="" data-hs-cos-general-type="meta_field" data-hs-cos-type="text" >在IAR工具链中使用overlay命令进行SMP多核工程TCM配置</span>

随着嵌入式设备的智能化需求越来越高,对MCU的性能要求也越来越高。一方面可以通过提高MCU的主频来提升MCU的性能,但是这会使MCU的设计变得更复杂。另一方面可以通过多核的方式来提升MCU的性能,目前多核MCU已在市场上广泛应用。另外越来越多的高性能MCU会配有TCM(Tightly Coupled Memory,紧耦合内存),相比于传统的 SRAM,TCM凭借其与内核零延迟的访问特性,成为高频调用和关键控制路径程序的最佳载体。

本文主要介绍如何在IAR工具链中使用overlay命令进行SMP多核工程TCM配置:即把SMP多核工程中对应代码和数据放到TCM相同地址。

TCM 地址映射机制简介

这里以NXP S32K324​ 为例介绍TCM,不同CPU内核之间ITCMInstruction Tightly Coupled Memory,指令紧耦合存储器)和DTCMData Instruction Tightly Coupled Memory,数据紧耦合存储器)的地址是一样的:

ITCM

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-1

DTCM

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-2

如何在链接脚本中正确配置TCM

利用IAR链接脚本语法,define overlay指令用于创建可容纳多个覆盖映像的内存区域。这样可以使得在相同的TCM地址上,分配多个代码段或者数据段,供不同的CPU内核运行:

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-3

本示例将定义如下代码段和数据段,分配到对应的CPU内核TCM:

.dtcm_data_core0:分配到core 0DTCM

.itcm_text_core0:分配到core 0ITCM

.dtcm_data_core1:分配到core 1DTCM

.itcm_text_core1:分配到core 1ITCM

.dtcm_data_core0/1中变量说明:

val_core0/1:当前core特征值,初始化后,val_core0=0x1100val_core1=0x1101

cnt_core0/1:计数值,每进入一次task_core0/1函数,数值加1

.itcm_text_core0/1中函数说明:

task_core0/1:打印当前内核信息。flag用于控制避免打印操作竞争。

1.在代码中定义要分配到TCM的代码段和数据段。China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-4

2. 链接脚本(.icf)中配置
- 将.dtcm_data_core0,.dtcm_data_core1定义到overlay dataDtcmBlock

define overlay dataDtcmBlock with fixed order, alignment = 4 {section .dtcm_data_core0};

define overlay dataDtcmBlock with fixed order, alignment = 4 {section .dtcm_data_core1};

- 将.itcm_text_core0,itcm_text_core1定义到overlay textItcmBlock

define overlay textItcmBlock with fixed order, alignment = 4 {section .itcm_text_core0};

define overlay textItcmBlock with fixed order, alignment = 4 {section .itcm_text_core1};

- 定义.dtcm_data_core0,.dtcm_data_core1,.itcm_text_core0,.itcm_text_core1需要进行初始化。

1)由于TCM是易失性存储器,断电后存储内容无法保持。因此需要启动阶段将代码段和数据段初始内容从Flash拷贝到TCM。因此这一配置非常重要,它向链接器明确界定了这些段的加载地址(LMA)和运行地址(VMA)是不同的。链接器会自动为各个段创建一个ro属性的副本,副本段名为xxx_init,例如.dtcm_data_core0(VMA)对应.dtcm_data_core0_init(LMA)

2)initialize manually 是指需要用户在程序代码中实现初始化函数

initialize manually {section .dtcm_data_core0, section .dtcm_data_core1};

initialize manually {section .itcm_text_core0, section .itcm_text_core1};

- 将.dtcm_data_core0,.dtcm_data_core1,.itcm_text_core0,.itcm_text_core1;以及.dtcm_data_core0_init,.dtcm_data_core1_init,.itcm_text_core0_init,.itcm_text_core1_init分配到对应的memory中。

//将.dtcm_data_core0_init,.dtcm_data_core1_init定义到block dtcmDataBlock_init

define block dtcmDataBlock_init with fixed order, alignment =4 { section .dtcm_data_core0_init, section .dtcm_data_core1_init};

//将.itcm_text_core0_init,.itcm_text_core1_init定义到block itcmCodeBlock_init

define block itcmCodeBlock_init with fixed order, alignment =4 { section .itcm_text_core0_init, section .itcm_text_core1_init};

//将block和overlay分配到对应的flash/dtcm/itcm区域

place in int_flash_region { block dtcmDataBlock_init, block itcmCodeBlock_init};

place in int_dtcm_region { overlay dataDtcmBlock };

place in int_itcm_region { overlay textItcmBlock };

3. 程序中加入初始化代码
China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-5

4. 编译后,我们可以在map文件中验证TCM数据和代码分配是否正确

.itcm_text_core0和.itcm_text_core1均正确分配到0x0开始的ITCM区域

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-6

.dtcm_data_core0和.dtcm_data_core1均正确分配到0x20000000开始的DTCM区域

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-7

.itcm_text_core0_init,.itcm_text_core1_init,.dtcm_data_core0_init和.dtcm_data_core1_init均被均正确分配到Flash区域

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-8

如何调试TCM中的数据和代码

1. 进入多核调试界面后,勾选I-jet菜单的“Disable Debugger Cache”,以确保切换内核调试时,调试器会刷新对应的memory/watch/Disassembly窗口的数据

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-9

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-10

2. DTCM数据段数据变量访问

打开View菜单->watch->watch 1窗口,输入Core 0 DTCM中变量val_core0和cnt_core0,以及Core 1 DTCM中变量val_core1和cnt_core1。可以看到val_core0和val_core1的地址均为0x20000408,cnt_core0和cnt_core1的地址均为0x2000040C。

打开View菜单->Cores窗口,通过鼠标双击其中的0:Cortex-M7和1:Cortex-M7,可以切换内核调试视角,切换到不同的内核,对应的Watch窗口的变量数据也会对应于不同的内核DTCM刷新而改变。

切换到core 0:

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-11

切换到core 1:

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-12

3. ITCM代码段程序调试

由于无法确定当前实际加载的是哪一部分代码,位于overlay区域的代码无法进行C语言级别的调试,但仍旧可以通过view菜单->Disassembly窗口进行汇编语言级别的调试。同样,通过Cores窗口中内核的切换,可以在Disassembly窗口看到不同内核的ITCM中的代码。

切换到core 0:

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-13

切换到core 1:

China-learn-using-overlay-in-IAR-toolchain-for-SMP-multi-core-TCM-14

总结

本文以NXP S32K324为例,介绍了如何在IAR工具链中使用overlay命令进行SMP多核工程TCM配置:即把SMP多核工程中对应代码和数据放到TCM相同地址。

本文讨论的TCM同样适用于Local RAM, LM(Local Memory)等,因为他们在IAR工具链里面的处理策略是一样的。

参考文献:

  1. NXP S32K3xx Reference Manual
  2. https://docs.iar.com/ewarm/9.7x/en/iar-c-c---development/the-linker-configuration-file/section-handling/define-overlay-directive.html
  3. https://www.iar.com/zh/knowledge/learn/initialization-in-iar-embedded-workbench
  4. https://docs.iar.com/ewarm/9.7x/en/c-spy-debugging/additional-information-on-c-spy-drivers/reference-information-on-the-c-spy-hardware-debugger-drivers/i-jet-menu.html