sct文件即分散加载文件,是ARMCC编译器使用的链接脚本文件,等同于GCC编译器的ld链接脚本。MDK IDE使用的是ARMCC。

支持NorFlash中运行代码(XIP)的MCU例如STM32,一般将所有代码(text段)都放在FLash中,但是Flash的访问速度低于和CPU、RAM,如下图(STM32F103):

【嵌入式】MDK使用sct文件将代码段放入RAM中执行_单片机

当CPU主频为72Mhz的时候,为了弥补CPU和Flash之间的速度差异,需要在访问Flash的时候插入等待周期,否则Flash访问会有问题。因此在整个MCU的运行速度的木桶短板为Flash存储器的访问速度。为了提高代码运行速度,可以将代码装入RAM中,MCU的RAM速度和CPU速度没有差异(不像MPU,中间需要使用cache弥补CPU和RAM之间的速度差异),因此从RAM中执行代码可以提高运行速度。同时在进行Flash编程擦写的时候,Flash是无法读写的,这时候如果遇到中断的话,是无法进入中断处理函数的,但是如果代码放在RAM中,就没有影响了。

为了将代码放入RAM中运行,需要使用链接脚本控制代码段位置,使用MDK的ARMCC编译器就需要sct分散加载文件。创建一个sct文件main.sct,在RW_IRAM1存储器中添加一个.ramcode段,如下所示:

; *************************************************************

; *** Scatter-Loading Description File generated by uVision ***

; *************************************************************

LR_IROM1 0x08000000 0x00010000  {    ; load region size_region

  ER_IROM1 0x08000000 0x00010000  {  ; load address = execution address

   *.o (RESET, +First)

   *(InRoot$$Sections)

    .ANY (+RO)

   .ANY (+XO)

  }

  RW_IRAM1 0x20000000 0x00005000  {  ; RW data

   *.o(.ramcode)

   .ANY (+RW +ZI)

  }

}

然后再MDK的Options的Linker选项卡中使用我们自定义的sct文件:

【嵌入式】MDK使用sct文件将代码段放入RAM中执行_stm32_02

 最后将我们需要放在RAM中的代码使用attribute关键字放入ramcode段中:

__attribute__((section(".ramcode"))) void DMA1_Channel4_IRQHandler()
{
    DMA_ClearFlag(DMA1_FLAG_TC4);
    int i;
    for(i=0;i<sizeof(SPI2_RX_DMA_Buff);i++)
        printf("%c",SPI2_RX_DMA_Buff[i]);
    printf("\r\n");
}

编译之后查看map文件中DMA1_Channel4_IRQHandler的信息:

DMA1_Channel4_IRQHandler                 0x20000001   Thumb Code   684  main.o(.ramcode)

可以看到DMA1_Channel4_IRQHandler函数的位置位0x20000001(代码的地址最后一位置1表示为thumb代码)。然后找到Execution Region RW_IRAM1:

Execution Region RW_IRAM1 (Exec base: 0x20000000, Load base: 0x08003ab0, Size: 0x00003ec0, Max: 0x00005000, ABSOLUTE)

    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x20000000   0x08003ab0   0x000003a0   Code   RO          137    .ramcode            main.o

可以看到ramcode段的Exec Addr为0x20000000,Load Addr为0x08003ab0,即这段代码存放在Flash的0x08003ab0,需加载到0x20000000处运行。加载过程同bss段清零和data段复制类似,在main函数调用之前就会被执行(MDK的ARMCC会自动生成这部分代码,gcc编译器需要自己写)。

实验发现,放在RAM中执行代码相较于Flash,确实有速度提升(没有做定量分析实验)!但是注意代码放在RAM中比较占用RAM空间,并且在Flash中还是会存放代码的,只是在运行时拷贝到RAM中去。