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宏定義添加如下宏定義。
⑨ 打開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中的宏定義可以將關鍵代碼和變量存放到指定位置。
動態修改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的分配例子。
動態內存分配最好在堆棧初始化之前,因此我們需要將上面的代碼轉換為對應的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大小的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: systick定时器 延时计时
- 下一篇: 如何为程序分配合适的栈空间?