分散加载
MXRT1052/1064芯片的RAM空间分为四种类型:ITCM,DTCM,OCRAM以及外部SDRAM,其中前面三个属于芯片内部RAM,RT1052有512KB,RT1064为1MB,支持用户静态分配,SDRAM属于外置RAM,最大支持到1.5G扩展空间。ITCM和DTCM是直接挂在芯片内核总线,速度可以达到与内核同频的600M,OCRAM挂在Sys AXI 64位总线,速度只能到达133M,外部SDRAM速度则可达到166M,而同时RT1050/1064内又有各32K的指令cache和数据cache,用于提高代码在外部Nor Flash中XIP执行的效率。从速度的角度看,将所有的用户代码分配ITCM/DTCM,能够发挥到最大性能,从存储空间大小的角度看,代码存放在SDRAM或者外部Flash最简单,而从USB/DMA使用的角度来看,RAM空间分配在OCRAM空间最为方便。所以这些不同RAM类型速度/大小的差异和cache的存在,就决定了要想让IMXRT性能发挥到最大,就需要用户根据客户实际应用手动修改内部RAM空间中ITCM/DTCM/OCRAM的大小分配,并定位关键代码和数据到指定RAM空间中运行。
1.如何将关键代码和数据到指定RAM中运行?
① IAR中首先找到使用的对应分散加载文件,用记事本打开;

② 确定自己的内存分配,如下是默认的一种分配方式。

/* 中断向量表 */
define symbol m_interrupts_start       = 0x70002000;
define symbol m_interrupts_end         = 0x700023FF;// 代码存放位置
define symbol m_text_start             = 0x70002400;
define symbol m_text_end               = 0x703FFFFF;// DTCRAM 128K
define symbol dtcram_start             = 0x20000000;
define symbol dtcram_end               = 0x2001FFFF;// OCRAM 768K
define symbol ocram_start              = 0x20200000;
define symbol ocram_end                = 0x202BFFFF;// itcram 128K 注意不要从0x00000000开始
define symbol itcram_start             = 0x00000004;
define symbol itcram_end               = 0x0001FFFF;/* FLASH配置和ivt等信息 */
define exported symbol m_boot_hdr_conf_start = 0x70000000;
define symbol m_boot_hdr_ivt_start           = 0x70001000;
define symbol m_boot_hdr_boot_data_start     = 0x70001020;
define symbol m_boot_hdr_dcd_data_start      = 0x70001030;

③ 规定堆栈区域大小,根据自己的实际情况分配,堆一般是用malloc函数动态分配内存区域,栈是程序的局部变量存储空间,可以适当分配大一点。

// 栈大小 局部变量
if (isdefinedsymbol(__stack_size__)) {define symbol __size_cstack__        = __stack_size__;
} else {define symbol __size_cstack__        = 0x4000;
}// 堆大小 动态分配malloc分配的空间
if (isdefinedsymbol(__heap_size__)) {define symbol __size_heap__          = __heap_size__;
} else {define symbol __size_heap__          = 0x8000;
}// RAM中的中断向量表 这里没有使用
define exported symbol __VECTOR_TABLE  = m_interrupts_start;
define exported symbol __VECTOR_RAM    = m_interrupts_start;
define exported symbol __RAM_VECTOR_TABLE_SIZE = 0x0;
define memory mem with size = 4G;

④ 定义一些储存区域和地址块

// 定义存储地址区域(region)
define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end]| mem:[from m_text_start to m_text_end];define region DTCRAM_region = mem:[from dtcram_start to dtcram_end - __size_cstack__];
define region ITCRAM_region = mem:[from itcram_start to itcram_end];
define region OCRAM_region  = mem:[from ocram_start  to ocram_end];// 栈段 栈最好分配在DTCRAM中
define region CSTACK_region = mem:[from dtcram_end - __size_cstack__+1 to dtcram_end];// 定义地址块
define block CSTACK    with alignment = 8, size = __size_cstack__   { };
define block HEAP      with alignment = 8, size = __size_heap__     { };
define block RW        { readwrite };
define block ZI        { zi };
define block NCACHE_VAR  { section NonCacheable , section NonCacheable.init };
define block ITCRAM    with alignment = 8{ section ITCRAMAccess};
define block DTCRAM    with alignment = 8{ section DTCRAMAccess};
define block OTCRAM    with alignment = 8{ section OTCRAMAccess};

⑤ 添加IAR自动初始化区域

// 初始化sections
initialize by copy { readwrite, section .textrw};
initialize by copy { section ITCRAMAccess, section DTCRAMAccess,section OCRAMAccess};
do not initialize  { section .noinit };
//IAR的ICF文件中宏导出给程序使用
place at address mem: m_interrupts_start    { readonly section .intvec };
place at address mem:m_boot_hdr_conf_start  { section .boot_hdr.conf };
place at address mem:m_boot_hdr_ivt_start   { section .boot_hdr.ivt };
place at address mem:m_boot_hdr_boot_data_start { readonly section .boot_hdr.boot_data };
place at address mem:m_boot_hdr_dcd_data_start  { readonly section .boot_hdr.dcd_data };keep{ section .boot_hdr.conf, section .boot_hdr.ivt, section .boot_hdr.boot_data, section .boot_hdr.dcd_data };

⑥ 将步骤4中定义的储存区域和地址块关联起来

// 把一系列sections和blocks放置在某个region中。sections和blocks将按任意顺序放置。
place in TEXT_region                        { readonly };                 //代码存放区域
place in DTCRAM_region                      { block RW };                 //RW段存放区域(全局或静态不为0变量)
place in DTCRAM_region                      { block ZI };                 //ZI段存放区域(全局或静态为0变量)
place in OCRAM_region                       { last block HEAP };          //malloc 动态申请内存区域
place in DTCRAM_region                      { block NCACHE_VAR };         //NCACHE区域 需要配合MPU使用
place in CSTACK_region                      { block CSTACK };             //站区域 局部变量place in ITCRAM_region                      { block ITCRAM };             //ITCRAM区域
place in DTCRAM_region                      { block DTCRAM };             //DTCRAM区域
place in OCRAM_region                       { block OCRAM };              //OCRAM区域

⑦ 我们上面在步骤4中定义了地址块ITCRAMAccess、 DTCRAMAccess、OCRAMAccess,如何在IAR中将变量放到对应地址块呢?
⑧ 打开fsl_common.h,仿照官方AT_NONCACHEABLE_SECTION宏定义添加如下宏定义。

#if (defined(__ICCARM__))
#define AT_ITCRAM_SECTION(func) func @"ITCRAMAccess"
#define AT_DTCRAM_SECTION(func) func @"DTCRAMAccess"
#define AT_OCRAM_SECTION(func)  func @"OCRAMAccess"
#elif(defined(__ARMCC_VERSION))
#define AT_ITCRAM_SECTION(func) __attribute__((section("ITCRAMAccess"))) func
#define AT_DTCRAM_SECTION(func) __attribute__((section("DTCRAMAccess"))) func
#define AT_OCRAM_SECTION(func)  __attribute__((section("OCRAMAccess")))  func
#elif(defined(__GNUC__))
#define AT_ITCRAM_SECTION(func) __attribute__((section("ITCRAMAccess"))) func
#define AT_DTCRAM_SECTION(func) __attribute__((section("DTCRAMAccess"))) func
#define AT_OCRAM_SECTION(func)  __attribute__((section("OCRAMAccess")))  func
#endif


⑨ 打开BOARD_ConfigMPU(); 函数修改MPU配置,验证对应的数据分配到了指定位置。

使用宏定义修饰函数或者变量,将函数和变量存放到指定位置。

AT_ITCRAM_SECTION(void delayms(uint16_t ms))
{volatile uint32_t i = 0;while(ms--) {for (i = 0; i < 30000; ++i){__asm("NOP"); /* delay */}}
} AT_DTCRAM_SECTION(uint8_t dcrambuf[100][1024]);
AT_OCRAM_SECTION(uint8_t orambuf[100][1024]);

⑩ MDK中类似IAR,打开分散加载文件,在里面添加块ITCRAMAccess、 DTCRAMAccess、OCRAMAccess。通过步骤8中的宏定义可以将关键代码和变量存放到指定位置。


/* FLASH配置和ivt等信息 */
#define m_flash_config_start           0x70000000
#define m_flash_config_size            0x00001000#define m_ivt_start                    0x70001000
#define m_ivt_size                     0x00001000/* 中断向量表 */
#define m_interrupts_start             0x70002000
#define m_interrupts_size              0x00000400// 代码存放位置
#define m_text_start                   0x70002400
#define m_text_size                    0x003FDC00// DTCRAM 128K
#define dtcram_start                   0x20000000
#define dtcram_size                    0x00020000// OCRAM 768K
#define ocram_start                    0x20200000
#define ocram_size                     0x000C0000// itcram 128K 注意从0x00000004开始
#define itcram_start                   0x00000004
#define itcram_size                    0x00020000                  // 栈大小 局部变量
#if (defined(__stack_size__))#define Stack_Size                   __stack_size__
#else#define Stack_Size                   0x4000
#endif// 堆大小 动态分配malloc分配的空间
#if (defined(__heap_size__))#define Heap_Size                    __heap_size__
#else#define Heap_Size                    0x8000
#endif#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
LR_m_text m_flash_config_start m_text_start+m_text_size-m_flash_config_start {   ; load region size_regionRW_m_config_text m_flash_config_start FIXED m_flash_config_size { ; load address = execution address* (.boot_hdr.conf, +FIRST)}RW_m_ivt_text m_ivt_start FIXED m_ivt_size { ; load address = execution address* (.boot_hdr.ivt, +FIRST)* (.boot_hdr.boot_data)* (.boot_hdr.dcd_data)}
#else
LR_m_text m_interrupts_start m_text_start+m_text_size-m_interrupts_start {   ; load region size_region
#endif/* 中断向量表存放位置 */VECTOR_ROM m_interrupts_start FIXED m_interrupts_size { ; load address = execution address* (RESET,+FIRST)}/* 代码段存放位置 */TEXT_region m_text_start FIXED m_text_size { ; load address = execution address* (InRoot$$Sections).ANY (+RO)}/* DTCRAM段 */DTCRAM_region dtcram_start dtcram_size-Stack_Size{ ; RW data.ANY (+RW).ANY (+ZI)* (DTCRAMAccess)* (NonCacheable.init)* (NonCacheable)}/* ITCRAM段 */ITCRAM_region itcram_start itcram_size{ ; RW data* (ITCRAMAccess)}/* OCRAM段 */OCRAM_region ocram_start ocram_size{ ; * (OCRAMAccess)}/* 堆区域  */ARM_LIB_HEAP +0 EMPTY Heap_Size {    ; Heap region growing up}/* 栈区域 栈是向下生长的 */ARM_LIB_STACK dtcram_start+dtcram_size EMPTY -Stack_Size { ; Stack region growing down}
}

动态修改FlexRAM,修改TCRAM大小

RT1052片内的512KB RAM,可以自由分配为ITCRAM、DTCRAM和OCRAM(OCRAM最少32KB)。RT1064相比RT1052,多了512KB的OCRAM,另外的512KB RAM和RT1052一样,可以自由分配为ITCRAM、DTCRAM和OCRAM。
IMXRT的片内RAM可以根据用户需求动态分配,512KB的RAM分成16个BANK,每个BANK 由32位寄存器IOMUXC_GPR->GPR17(0x400AC044)中的两位来确定类型。
• 00b—bank is not used.
• 01b—bank is configured for OCRAM.
• 10b—bank is configured for DTCM.
• 11b—bank is configured for ITCM.
注意ITCRAM、DTCRAM应该为2的幂(32、64、128、256、512)

下图就是一个简单的例子,配置DTCRAM 128K、ITCRAM 256K、OCRAM 128K。

配置完IOMUXC_GPR->GPR17(0x400AC044)寄存器,确定每个BANK的类型后,修改寄存器IOMUXC_GPR->GPR14(0x400AC038)确定对应TCM的空间大小,并设置IOMUXC_GPR->GPR16(0x400AC040)开启动态分配的内存空间。
下面是一个DTCRAM 256K、ITCRAM 128K、OCRAM 128K的分配例子。

/* RT1052/1064 内部SRAM一共分为16个blank 每个blank 都可以选择类型 * A bank size of 512 kB / 16 = 32 kB* IOMUXC_GPR_GPR17寄存器一共32位, 每两位控制一个blank的类型* 00b—bank is not used.* 01b—bank is configured for OCRAM.* 10b—bank is configured for DTCM.* 11b—bank is configured for ITCM.*/
IOMUXC_GPR->GPR17 = IOMUXC_GPR_GPR17_FLEXRAM_BANK_CFG(0x55AAAAFF); /*! CM7_CFGITCMSZ*  0b0000..0 KB (No ITCM)*  0b0011..4 KB*  0b0100..8 KB*  0b0101..16 KB*  0b0110..32 KB*  0b0111..64 KB*  0b1000..128 KB*  0b1001..256 KB*  0b1010..512 KB*/IOMUXC_GPR->GPR14 &= ~IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_MASK;IOMUXC_GPR->GPR14 |= IOMUXC_GPR_GPR14_CM7_CFGITCMSZ(8);IOMUXC_GPR->GPR16 |= IOMUXC_GPR_GPR16_INIT_ITCM_EN(1);/*! CM7_CFGDTCMSZ*  0b0000..0 KB (No DTCM)*  0b0011..4 KB*  0b0100..8 KB*  0b0101..16 KB*  0b0110..32 KB*  0b0111..64 KB*  0b1000..128 KB*  0b1001..256 KB*  0b1010..512 KB*/IOMUXC_GPR->GPR14 &= ~IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ_MASK;IOMUXC_GPR->GPR14 |= IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ(9);IOMUXC_GPR->GPR16 |= IOMUXC_GPR_GPR16_INIT_DTCM_EN(1);/* 使能配置 */IOMUXC_GPR->GPR16 &= ~IOMUXC_GPR_GPR16_FLEXRAM_BANK_CFG_SEL_MASK;IOMUXC_GPR->GPR16 |=  IOMUXC_GPR_GPR16_FLEXRAM_BANK_CFG_SEL(1);

动态内存分配最好在堆栈初始化之前,因此我们需要将上面的代码转换为对应的RAM汇编代码,放在复位中断服务函数堆栈初始化前面,打开启动文件startup_MIMXRT10XX.s文件,找到Reset_Handler的汇编函数,添加对应汇编代码。

FLEXRAM_BANK_CFG    EQU 0x55AAAAFF
ITCRAM_SIZE         EQU 0x8;128KB 0: 0KB    6: 32KB  7: 64KB  8: 128KB  9: 256KB  10: 512KB
DTCRAM_SIZE         EQU 0x9;256KB 0: 0KB    6: 32KB  7: 64KB  8: 128KB  9: 256KB  10: 512KBReset_HandlerCPSID   I               ; Mask interrupts;IOMUXC_GPR->GPR17 = IOMUXC_GPR_GPR17_FLEXRAM_BANK_CFG(0x55AAAAFF); LDR R0, = 0x400AC044          ; 将IOMUXC_GPR->GPR17的地址放到 寄存器R0中LDR R1, = FLEXRAM_BANK_CFG    ; 将BANK划分结果放到 寄存器R1中STR R1, [R0]                  ; 将R1 存放到IOMUXC_GPR->GPR17中;IOMUXC_GPR->GPR14 &= ~IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_MASK;;IOMUXC_GPR->GPR14 &= ~IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ_MASK;LDR R0, = 0x400AC038          ; 将IOMUXC_GPR->GPR14的地址放到 寄存器R0中LDR R2, [R0]LDR R3, = 0x00FFFFAND R1,  R2, R3               ; R1 = IOMUXC_GPR->GPR14 &= ~IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_MASK中STR R1, [R0]                  ; 将R1 存放到IOMUXC_GPR->GPR14中;IOMUXC_GPR->GPR14 |= IOMUXC_GPR_GPR14_CM7_CFGITCMSZ(ITCRAM_SIZE);;IOMUXC_GPR->GPR14 |= IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ(DTCRAM_SIZE);LDR R1, = ITCRAM_SIZEMOV  R2, R1,LSL#16LDR R1, = DTCRAM_SIZEMOV  R3, R1,LSL#20ORR R1, R2, R3LDR R2, [R0]ORR R1, R1, R2STR R1, [R0]  ;IOMUXC_GPR->GPR16 |= IOMUXC_GPR_GPR16_INIT_ITCM_EN(1);;IOMUXC_GPR->GPR16 |= IOMUXC_GPR_GPR16_INIT_DTCM_EN(1);;IOMUXC_GPR->GPR16 |=  IOMUXC_GPR_GPR16_FLEXRAM_BANK_CFG_SEL(1);LDR R0, = 0x400AC040LDR R1, [R0]ORR R1, R1, #0x7STR R1, [R0]  LDR     R0, =0xE000ED08LDR     R1, =__vector_tableSTR     R1, [R0]LDR     R2, [R1]MSR     MSP, R2LDR     R0, =SystemInitBLX     R0CPSIE   I               ; Unmask interruptsLDR     R0, =__iar_program_startBX      R0

最后修改分散加载文件中地址空间分配、修改MPU配置

IMXRT 分散加载文件 修改OCRAM,DTCM、ITCM大小相关推荐

  1. 从MDK分散加载文件学习STM32启动流程

    一直在用ARM的Cortex-M系列做产品开发,也陆陆续续学习了ARM的启动流程.汇编启动文件,但是总感觉没有连贯的把全部知识串起来,不知道某些汇编语句为什么要这么写,没法按照自己的情况进行修改.今天 ...

  2. keil的sct文件_keil .sct分散加载文件及其应用(重点必看)

    (3)分散加载文件语法 load_region_name  start_address | "+"offset  [attributes] [max_size] { executi ...

  3. keil STM32中sct 分散加载文件学习

    sct 分散加载文件简介 MDK 生成一个以工程名命名的后缀为 *.sct 的分散加载文件 (Linker Control File,scatter loading),链接器根据该文件的配置分配各个节 ...

  4. 浅析keil的scf分散加载文件-基于STM32的例程

    浅析keil的scf分散加载文件-基于STM32的例程 关于分散加载文件 分散加载文件.sct 关于分散加载文件 keil编译器在链接的时候,是根据分散加载(.scf后缀的文件)来确定程序的加载域和运 ...

  5. Scatterfile分散加载文件和 mem.scf

     今天仔细学习周立功的模板的过程中,发现了几个.scf文件,自己不知道这是什么东西,所以学习了下: (一) 这是一位网友写的关于mem_a.scf,mem_b.scf,mem_c.scf文件的见解 ...

  6. 小猫爪:嵌入式小知识06-KEIL scf分散加载文件解析-链接代码至RAM

    小猫爪:嵌入式小知识06-KEIL scf分散加载文件解析-链接代码至RAM 1 前言 2 执行域和加载域 2 相关语法解析 3 实例解说 4 链接代码至RAM运行 4.1 链接单个section至R ...

  7. 【转载】ADS分散加载文件使用总结(lpc23xx)

    有如下分散加载文件: ROM_LOAD 0x00000000              ;// Origination Point of Code (Code in Flash) {     ROM_ ...

  8. [STM32] 分散加载文件 之一 (初探)

    转载自: http://bbs.21ic.com/icview-2579020-1-1.html 本帖最后由 千岁寒 于 2018-11-5 13:00 编辑 1.什么是分散加载            ...

  9. keil的sct文件_(转)KEIL下分散加载文件 **.sct文件

    在keil中编译的程序通过了,但是debug的时候会出现一些错误: *** error 65: access violation at 0x4C000018 : no 'write' permissi ...

最新文章

  1. Linux之特殊权限(SUID/SGID/SBIT)
  2. innerHTMl和确认提示的使用
  3. android studio 引入arr的问题
  4. 机器学习(二十九)——Temporal-Difference Learning
  5. 51nod1600-Simple KMP【SAM,树链剖分】
  6. day21 面向对象之继承和组合
  7. 【探索测试篇】探索无界,BUG无限,让程序猿头疼的测试技术
  8. Deep Learning基础--Softmax求导过程
  9. 《原神》月入16亿,米哈游为何仍然被嫌弃?
  10. Linux 下的任务管理 —— ps、top
  11. beyond compare代码比对工具
  12. 计算机原理中的cps,信息物理融合系统(cps)原理pdf
  13. 关于每次请求都要执行两个,即经过重写FilterInvocationSecurityMetadataSource的getAttributes()方法
  14. 适合儿童学习的编程语言一览
  15. TreeSet的两种排序方式
  16. sk_buff 剖析
  17. APICloud进行窗口和页面操作
  18. macOS 神器 Workflow ,让效率翻倍!
  19. avl二叉树 java_平衡二叉树之AVL树(Adelson-Velsky and Landis Tree)简介及Java实现
  20. 【嘉然live2d】来给WP网站添加一个live2

热门文章

  1. 更改Firefox为中文界面(Ubuntu系统)
  2. flv播放器以及调用代码
  3. ExtJs与JavaScript的call方法
  4. Fibonacci 数列
  5. JDK,JRE,JVM区别与联系
  6. srv.sys蓝屏解决补丁_电脑蓝屏重启怎么解决?
  7. (八)整合spring cloud云服务架构 - commonservice-eureka 项目构建过程
  8. 介绍一款facebook信息收集工具FBI
  9. haproxy调度web案例
  10. [CareerCup] 11.1 Merge Arrays 合并数组