IMXRT 分散加载文件 修改OCRAM,DTCM、ITCM大小
分散加載
MXRT1052/1064芯片的RAM空間分為四種類型:ITCM,DTCM,OCRAM以及外部SDRAM,其中前面三個(gè)屬于芯片內(nèi)部RAM,RT1052有512KB,RT1064為1MB,支持用戶靜態(tài)分配,SDRAM屬于外置RAM,最大支持到1.5G擴(kuò)展空間。ITCM和DTCM是直接掛在芯片內(nèi)核總線,速度可以達(dá)到與內(nèi)核同頻的600M,OCRAM掛在Sys AXI 64位總線,速度只能到達(dá)133M,外部SDRAM速度則可達(dá)到166M,而同時(shí)RT1050/1064內(nèi)又有各32K的指令cache和數(shù)據(jù)cache,用于提高代碼在外部Nor Flash中XIP執(zhí)行的效率。從速度的角度看,將所有的用戶代碼分配ITCM/DTCM,能夠發(fā)揮到最大性能,從存儲(chǔ)空間大小的角度看,代碼存放在SDRAM或者外部Flash最簡單,而從USB/DMA使用的角度來看,RAM空間分配在OCRAM空間最為方便。所以這些不同RAM類型速度/大小的差異和cache的存在,就決定了要想讓IMXRT性能發(fā)揮到最大,就需要用戶根據(jù)客戶實(shí)際應(yīng)用手動(dòng)修改內(nèi)部RAM空間中ITCM/DTCM/OCRAM的大小分配,并定位關(guān)鍵代碼和數(shù)據(jù)到指定RAM空間中運(yùn)行。
1.如何將關(guān)鍵代碼和數(shù)據(jù)到指定RAM中運(yùn)行?
① IAR中首先找到使用的對(duì)應(yīng)分散加載文件,用記事本打開;
② 確定自己的內(nèi)存分配,如下是默認(rèn)的一種分配方式。
/* 中斷向量表 */ 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;③ 規(guī)定堆棧區(qū)域大小,根據(jù)自己的實(shí)際情況分配,堆一般是用malloc函數(shù)動(dòng)態(tài)分配內(nèi)存區(qū)域,棧是程序的局部變量存儲(chǔ)空間,可以適當(dāng)分配大一點(diǎn)。
// 棧大小 局部變量 if (isdefinedsymbol(__stack_size__)) {define symbol __size_cstack__ = __stack_size__; } else {define symbol __size_cstack__ = 0x4000; }// 堆大小 動(dòng)態(tài)分配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;④ 定義一些儲(chǔ)存區(qū)域和地址塊
// 定義存儲(chǔ)地址區(qū)域(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自動(dòng)初始化區(qū)域
// 初始化sections initialize by copy { readwrite, section .textrw}; initialize by copy { section ITCRAMAccess, section DTCRAMAccess,section OCRAMAccess}; do not initialize { section .noinit }; //IAR的ICF文件中宏導(dǎo)出給程序使用 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中定義的儲(chǔ)存區(qū)域和地址塊關(guān)聯(lián)起來
// 把一系列sections和blocks放置在某個(gè)region中。sections和blocks將按任意順序放置。 place in TEXT_region { readonly }; //代碼存放區(qū)域 place in DTCRAM_region { block RW }; //RW段存放區(qū)域(全局或靜態(tài)不為0變量) place in DTCRAM_region { block ZI }; //ZI段存放區(qū)域(全局或靜態(tài)為0變量) place in OCRAM_region { last block HEAP }; //malloc 動(dòng)態(tài)申請(qǐng)內(nèi)存區(qū)域 place in DTCRAM_region { block NCACHE_VAR }; //NCACHE區(qū)域 需要配合MPU使用 place in CSTACK_region { block CSTACK }; //站區(qū)域 局部變量place in ITCRAM_region { block ITCRAM }; //ITCRAM區(qū)域 place in DTCRAM_region { block DTCRAM }; //DTCRAM區(qū)域 place in OCRAM_region { block OCRAM }; //OCRAM區(qū)域⑦ 我們上面在步驟4中定義了地址塊ITCRAMAccess、 DTCRAMAccess、OCRAMAccess,如何在IAR中將變量放到對(duì)應(yīng)地址塊呢?
⑧ 打開fsl_common.h,仿照官方AT_NONCACHEABLE_SECTION宏定義添加如下宏定義。
⑨ 打開BOARD_ConfigMPU(); 函數(shù)修改MPU配置,驗(yàn)證對(duì)應(yīng)的數(shù)據(jù)分配到了指定位置。
使用宏定義修飾函數(shù)或者變量,將函數(shù)和變量存放到指定位置。
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中的宏定義可以將關(guān)鍵代碼和變量存放到指定位置。
動(dòng)態(tài)修改FlexRAM,修改TCRAM大小
RT1052片內(nèi)的512KB RAM,可以自由分配為ITCRAM、DTCRAM和OCRAM(OCRAM最少32KB)。RT1064相比RT1052,多了512KB的OCRAM,另外的512KB RAM和RT1052一樣,可以自由分配為ITCRAM、DTCRAM和OCRAM。
IMXRT的片內(nèi)RAM可以根據(jù)用戶需求動(dòng)態(tài)分配,512KB的RAM分成16個(gè)BANK,每個(gè)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應(yīng)該為2的冪(32、64、128、256、512)
下圖就是一個(gè)簡單的例子,配置DTCRAM 128K、ITCRAM 256K、OCRAM 128K。
配置完IOMUXC_GPR->GPR17(0x400AC044)寄存器,確定每個(gè)BANK的類型后,修改寄存器IOMUXC_GPR->GPR14(0x400AC038)確定對(duì)應(yīng)TCM的空間大小,并設(shè)置IOMUXC_GPR->GPR16(0x400AC040)開啟動(dòng)態(tài)分配的內(nèi)存空間。
下面是一個(gè)DTCRAM 256K、ITCRAM 128K、OCRAM 128K的分配例子。
動(dòng)態(tài)內(nèi)存分配最好在堆棧初始化之前,因此我們需要將上面的代碼轉(zhuǎn)換為對(duì)應(yīng)的RAM匯編代碼,放在復(fù)位中斷服務(wù)函數(shù)堆棧初始化前面,打開啟動(dòng)文件startup_MIMXRT10XX.s文件,找到Reset_Handler的匯編函數(shù),添加對(duì)應(yīng)匯編代碼。
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劃分結(jié)果放到 寄存器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配置
總結(jié)
以上是生活随笔為你收集整理的IMXRT 分散加载文件 修改OCRAM,DTCM、ITCM大小的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: systick定时器 延时计时
- 下一篇: 如何为程序分配合适的栈空间?