很多人刚接触RT,会发现一些和传统MCU有差异的新概念,此处做出罗列。
问题1. TCM、OCRAM的区别?
Reply: 两者的区别主要包括两个点:
1. 速度上TCM等同于内核主频,OCRAM速度只是1/4。
2. TCM只能被CPU内核访问,但不能被其它的Master访问,例如DMA、USB、SDHC和Ethernet等。但是OCRAM可以被所有的Master访问。(在一些特殊情况下,入内和进入sleeping/power down状态下,TCM也支持AHBS被其他master访问)。
 
问题2. 堆栈可以放置的位置?
Reply:堆栈可以放在SDRAM, DTCM和OCRAM;在hello world代码中分别放在这3种地址内。
 
问题3. IAR ICF链接配置文件的DATA、DATA2、DATA3?
Reply:分别对应DTCM、OCRAM和SEMC区域,而text和interrupt对应ITCM、Flexspi和NandFlash等的存储区域。

1.png

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
问题4. ITCM、DTCM、OCRAM的区域分配一定要连续吗?
Reply:不是一定要连续的,具体的配置取决于IOMUXC_GPR_GPR17寄存器的配置。需要注意的一个电视OCRAM至少要有32K,因为首先最小的颗粒是32K,其次ROM Bootloader会用到OCRAM,但是ITCM和DTCM是可以配置为0K的。

2.png

 
 
 
 
 
问题5. ITCM、DTCM、SEMC、Flexspi这么多介质,用户代码如何存放?
Reply:首先,对于代码来说,至关重要的放在ITCM, 第二重要的放在外部SEMC;其次,对于数据来说,只被内核访问的放在DTCM,如果需要被其他的USB,DMA等master访问的RAM区间,只能使用OCRAM。
 
问题6. I.MX RT的代码通常存放在外部的Flash,那是在什么时候从Flash拷贝到内部RAM或者SDRAM呢?是ROM bootloader做的吗?
Reply:是由用户程序拷贝的,对应IAR的函数就是__iar_program_start,这个函数包含在IAR的lib库中。之所以会有这个问题,是因为在SDRAM场合下,在拷贝前需要对SDRAM进行初始化,然后把数据搬运过去,所以IAR有一个.mac文件进行SDRAM初始化,那去掉debugger呢?所以有机会在SystemInit先把SDRAM初始化好。
 
问题7. Boot流程?
Reply:POR后(一定要是Power On复位),启动片上ROM,根据BOOT_MODE引脚和e-Fuse决定从哪个外部器件启动,BOOT_MODE引脚的优先级更高。
ROM代码会从DCD中读取配置信息来对外设进行初始化,例如用于初始化SEMC,为后续SDRAM数据的读写做准备。(DCD存放在image里面)
 
 
 
 
问题8. Boot的选项和差异?
Reply:第一种是根据内部fuse的设置,第二种就是串口下载,第三种是internal Boot,第一种和第三种的区别在于,前者的配置可以被外部引脚override,后者的启动仅根据内部fuse来决定。
3.png
 
 
 
 
 
问题9. Boot Image要包含的内容?
Reply:IVT、Boot Data、DCD、user code、CSF和KeyBlob。

4.png

5.PNG

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
const ivt image_vector_table = {
  IVT_HEADER,                         /* IVT Header */  
  IMAGE_ENTRY_ADDRESS,             /* Image Entry Function */  中断向量表的起始地址,位于IVT/DCD/BOOT_DATA之后的区域 0x60002000
  IVT_RSVD,                           /* Reserved = 0 */
  (uint32_t)DCD_ADDRESS,              /* Address where DCD information is stored */ DCD 区域, 用于SDRAM初始化 0x60001030
  (uint32_t)BOOT_DATA_ADDRESS, /* Address where BOOT Data Structure is stored */BOOT_DATA指向最初所有代码首地址(0x60000000)0X6000 1020
 
  (uint32_t)&image_vector_table,      /* Pointer to IVT Self (absolute address */ 指向IVT自己 0x60001000
  (uint32_t)CSF_ADDRESS,              /* Address where CSF file is stored */ 指向加密区域,未指定
  IVT_RSVD                            /* Reserved = 0 */
};
define symbol m_interrupts_start       = 0x60002000;
define symbol m_interrupts_end         = 0x600023FF;
 
define symbol m_text_start             = 0x60002400;
define symbol m_text_end               = 0x63FFFFFF;
 
define symbol m_data_start             = 0x20000000;
define symbol m_data_end               = 0x2001FFFF;
define symbol m_data2_start            = 0x20200000;
define symbol m_data2_end              = 0x2023FFFF;
 
 
define exported symbol m_boot_hdr_conf_start = 0x60000000;
define symbol m_boot_hdr_ivt_start           = 0x60001000;
define symbol m_boot_hdr_boot_data_start     = 0x60001020;
define symbol m_boot_hdr_dcd_data_start      = 0x60001030;
 
问题10. Boot Image要包含的内容?
Reply:ICF文件的定义中有很多的名词,需要了解其含义。
DATA_region表示DTCM区域,DATA2_region表示OCRAM区域, DATA2_region表示SDRAM区域,
Stack堆栈存放位置取决于用户配置,从后面开始;
m_ncache_start至于为何是0x81E00000?原因在于此处和代码是对应的,在代码的初始化函数void BOARD_ConfigMPU(void)有设置,所以non cache的位置不是固定的。
MPU->RBAR = ARM_MPU_RBAR(8, 0x81E00000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, ARM_MPU_REGION_SIZE_2MB);
 
define symbol m_interrupts_start       = 0x00000000;
define symbol m_interrupts_end         = 0x000003FF;
define symbol m_text_start             = 0x00000400;
define symbol m_text_end               = 0x0001FFFF;
 
define symbol m_data_start             = 0x20000000;
define symbol m_data_end               = 0x2001FFFF;
 
define symbol m_data2_start            = 0x20200000;
define symbol m_data2_end              = 0x2023FFFF;
 
define symbol m_data3_start            = 0x80000000;
define symbol m_data3_end              = 0x81DFFFFF;
 
define symbol m_ncache_start           = 0x81E00000;
define symbol m_ncache_end             = 0x81FFFFFF;
 
 
/* Sizes */
 
if (isdefinedsymbol(__stack_size__)) {
  define symbol __size_cstack__        = __stack_size__;
} else {
  define symbol __size_cstack__        = 0x0400;
}
 
if (isdefinedsymbol(__heap_size__)) {
  define symbol __size_heap__          = __heap_size__;
} else {
  define symbol __size_heap__          = 0x0400;
}
 
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;
define region TEXT_region = mem:[from m_interrupts_start to m_interrupts_end]
                          | mem:[from m_text_start to m_text_end];
 
 
define region DATA_region = mem:[from m_data_start to m_data_end];
define region DATA2_region = mem:[from m_data2_start to m_data2_end];
define region DATA3_region  = mem:[from m_data3_start to m_data3_end-__size_cstack__];
define region CSTACK_region = mem:[from m_data3_end-__size_cstack__+1 to m_data3_end];
define region NCACHE_region = mem:[from m_ncache_start to m_ncache_end];
 
 
define block CSTACK    with alignment = 8, size = __size_cstack__   { };
define block HEAP      with alignment = 8, size = __size_heap__     { };
define block RW        { first readwrite, section m_usb_dma_init_data };
define block ZI         with alignment = 32  { first zi, section m_usb_dma_noninit_data };
define block NCACHE_VAR with size = 0x200000 , alignment = 0x100000  { section NonCacheable , section NonCacheable.init };
 
initialize by copy { readwrite, section .textrw };
do not initialize  { section .noinit };
 
place at address mem: m_interrupts_start    { readonly section .intvec };
 
place in TEXT_region                        { readonly };
place in DATA3_region                       { block RW };
place in DATA3_region                       { block ZI };
place in DATA3_region                       { last block HEAP };
place in CSTACK_region                      { block CSTACK };
place in NCACHE_region                      { block NCACHE_VAR };