IMXRT 分散加载文件 修改OCRAM,DTCM、ITCM大小
分散加载
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大小相关推荐
- 从MDK分散加载文件学习STM32启动流程
一直在用ARM的Cortex-M系列做产品开发,也陆陆续续学习了ARM的启动流程.汇编启动文件,但是总感觉没有连贯的把全部知识串起来,不知道某些汇编语句为什么要这么写,没法按照自己的情况进行修改.今天 ...
- keil的sct文件_keil .sct分散加载文件及其应用(重点必看)
(3)分散加载文件语法 load_region_name start_address | "+"offset [attributes] [max_size] { executi ...
- keil STM32中sct 分散加载文件学习
sct 分散加载文件简介 MDK 生成一个以工程名命名的后缀为 *.sct 的分散加载文件 (Linker Control File,scatter loading),链接器根据该文件的配置分配各个节 ...
- 浅析keil的scf分散加载文件-基于STM32的例程
浅析keil的scf分散加载文件-基于STM32的例程 关于分散加载文件 分散加载文件.sct 关于分散加载文件 keil编译器在链接的时候,是根据分散加载(.scf后缀的文件)来确定程序的加载域和运 ...
- Scatterfile分散加载文件和 mem.scf
今天仔细学习周立功的模板的过程中,发现了几个.scf文件,自己不知道这是什么东西,所以学习了下: (一) 这是一位网友写的关于mem_a.scf,mem_b.scf,mem_c.scf文件的见解 ...
- 小猫爪:嵌入式小知识06-KEIL scf分散加载文件解析-链接代码至RAM
小猫爪:嵌入式小知识06-KEIL scf分散加载文件解析-链接代码至RAM 1 前言 2 执行域和加载域 2 相关语法解析 3 实例解说 4 链接代码至RAM运行 4.1 链接单个section至R ...
- 【转载】ADS分散加载文件使用总结(lpc23xx)
有如下分散加载文件: ROM_LOAD 0x00000000 ;// Origination Point of Code (Code in Flash) { ROM_ ...
- [STM32] 分散加载文件 之一 (初探)
转载自: http://bbs.21ic.com/icview-2579020-1-1.html 本帖最后由 千岁寒 于 2018-11-5 13:00 编辑 1.什么是分散加载 ...
- keil的sct文件_(转)KEIL下分散加载文件 **.sct文件
在keil中编译的程序通过了,但是debug的时候会出现一些错误: *** error 65: access violation at 0x4C000018 : no 'write' permissi ...
最新文章
- Linux之特殊权限(SUID/SGID/SBIT)
- innerHTMl和确认提示的使用
- android studio 引入arr的问题
- 机器学习(二十九)——Temporal-Difference Learning
- 51nod1600-Simple KMP【SAM,树链剖分】
- day21 面向对象之继承和组合
- 【探索测试篇】探索无界,BUG无限,让程序猿头疼的测试技术
- Deep Learning基础--Softmax求导过程
- 《原神》月入16亿,米哈游为何仍然被嫌弃?
- Linux 下的任务管理 —— ps、top
- beyond compare代码比对工具
- 计算机原理中的cps,信息物理融合系统(cps)原理pdf
- 关于每次请求都要执行两个,即经过重写FilterInvocationSecurityMetadataSource的getAttributes()方法
- 适合儿童学习的编程语言一览
- TreeSet的两种排序方式
- sk_buff 剖析
- APICloud进行窗口和页面操作
- macOS 神器 Workflow ,让效率翻倍!
- avl二叉树 java_平衡二叉树之AVL树(Adelson-Velsky and Landis Tree)简介及Java实现
- 【嘉然live2d】来给WP网站添加一个live2
热门文章
- 更改Firefox为中文界面(Ubuntu系统)
- flv播放器以及调用代码
- ExtJs与JavaScript的call方法
- Fibonacci 数列
- JDK,JRE,JVM区别与联系
- srv.sys蓝屏解决补丁_电脑蓝屏重启怎么解决?
- (八)整合spring cloud云服务架构 - commonservice-eureka 项目构建过程
- 介绍一款facebook信息收集工具FBI
- haproxy调度web案例
- [CareerCup] 11.1 Merge Arrays 合并数组