痞子衡嵌入式:飛思卡爾i.MX RT系列MCU啟動那些事(9)- 從Parallel NOR啟動

痞子衡發表於2018-06-15

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是飛思卡爾i.MX RT系列MCU的Parallel NOR啟動

  上一篇講i.MXRT從Raw NAND啟動的文章 從Raw NAND啟動 一經放出,深入廣大網友喜愛,短時間內閱讀量飆升,這讓痞子衡深入鼓舞,所以趁熱打鐵繼續把從Parallel NOR啟動也順便一起講了,為什麼說是順便呢?因為Parallel NOR與Raw NAND都是並行介面,屬於同一門派,且這兩種外存裝置在i.MXRT內部是通過同一IP(SEMC)實現底層介面通訊的,所以瞭解了Raw NAND啟動,再來看Parallel NOR啟動會覺得簡單很多。話不多說,開講。

一、支援的Parallel NOR

  依舊開門見山,i.MXRT支援載入啟動的主要是相容CFI/JESD68標準且內建EPSCD命令集(這個命令集是目前的主流,最新的NOR產品都是使用這個命令集)的ADM SLC Parallel NOR,至於資料線寬度,x8,x16都支援;關於時鐘模式,i.MXRT105x/i.MXRT102x僅支援Asynchronous,i.MXRT106x既支援Asynchronous也支援Synchronous。關於Parallel NOR基本知識請先看一下痞子衡的另一篇文章 通用NOR介面標準(CFI-JESD68)及SLC Parallel NOR簡介
  Parallel NOR廠商非常多,對應Parallel NOR晶片型號也很多,如果你在選型時不確定到底該為i.MXRT選擇哪一款Parallel NOR時,可選用下面三款晶片,痞子衡均實測過:

Micron MT28EW128ABA1LPC-0SIT    (x8/x16 bits, 32B Page/128KB Block/128Mb Device,   Non-ADM, Asynchronous)
Winbond W29GL128CH9T            (x8/x16 bits, 64B Page/128KB Sector/128Mb Device,  Non-ADM, Asynchronous)
Spansion S29GL128S90TFI020      (x16 bits,    512B Page/128KB Sector/128Mb Device, Non-ADM, Asynchronous)

Note: ADM即地址線與資料線複用,為了減少pin腳,有些Parallel NOR晶片會將低bit地址線與資料線複用,但目前市面上主流Parallel NOR晶片還是Non-ADM(即地址與資料是不復用的)居多,i.MXRT雖不能直接連線Non-ADM NOR晶片,但在i.MXRT與Non-ADM NOR晶片之間使用一片74系列鎖存器橋接一下便能正常工作。

二、Parallel NOR硬體連線

  確定了Parallel NOR晶片選型後,底下便進入Parallel NOR硬體電路設計及與i.MXRT的訊號連線環節:

  i.MXRT對於Parallel NOR的底層介面支援是通過內部SEMC這個IP實現的,SEMC最多能支援五種裝置(SDRAM, NAND, NOR, SRAM, 8080 Display),但SEMC介面訊號是複用的,所以同一時刻僅能支援一種裝置。下表是SEMC介面複用表,關於NOR介面訊號,需要特別說一下的是CE#訊號和地址線寬度,從表中我們可以看到NOR的CE4#訊號有6個,即有6種配置選擇,但i.MXRT BootROM固定選擇的是SEMC_CSX[0],至於地址線寬度,SEMC本身最大可支援28bits地址寬度,但是i.MXRT BootROM裡最大隻支援24bits地址寬度(即A0-A23,最大128Mb),這2點在設計NOR硬體連線時需要特別注意。

Note: 對於小容量Paralle NOR晶片(比如512KB,地址線A0-A18),i.MXRT當然也可以支援,SEMC未用的地址線(此處為A19-A23)可不用管。

痞子衡嵌入式:飛思卡爾i.MX RT系列MCU啟動那些事(9)- 從Parallel NOR啟動

  如下是典型的NOR硬體連線設計,示例NOR晶片是MT28EW128ABA1LPC-0SIT,該NOR晶片為Non-ADM,所以我們使用了一片74ALVT16373鎖存器橋接了一下,當WEIM_ADV_B訊號為高電平時,鎖存器Dx會輸出給Qx,即此時WEIM_DATA[15:0]作為地址線輸出給A[15:0],而WEIM_ADV_B訊號為低電平時,WEIM_DATA[15:0]就是資料線(即此處WEIM_ADV_B作為ADV#訊號是高有效,這在後續配置NOR eFUSE時會涉及到)。

痞子衡嵌入式:飛思卡爾i.MX RT系列MCU啟動那些事(9)- 從Parallel NOR啟動

三、Parallel NOR載入啟動過程

  確保Parallel NOR硬體相關設計無誤之後,底下便是下載更新Bootable Image進Parallel NOR以供BootROM載入啟動了,在下載Bootable image之前有必要先了解Parallel NOR的載入啟動過程:

  痞子衡在啟動系列文章的第六篇 Bootable image格式與載入(elftosb/.bd) 裡的最後已經介紹過non-XIP image載入啟動過程,但實際上那個過程主要適用於儲存在外部NAND Flash中Bootable image載入啟動,對於儲存在外部Parallel NOR的Bootable image而言有一些區別,我們知道NOR Flash是支援XIP執行的,所以從NOR啟動有兩種選擇,一種是Non-XIP,另一種是XIP。
  對於Non-XIP啟動而言,其基本流程與第六篇裡介紹的non-XIP image載入啟動過程類似,只有兩點區別,第一個區別是儲存在NOR Flash裡的Bootable image中IVT偏移地址是固定在0x1000(對於NAND Flash,偏移固定是0x400);第二個區別是BootROM載入initial image的大小為12KB(對於NAND Flash,initial image是4KB),且這個initial image的載入不需要經過OCRAM快取,BootROM是直接從NOR對應的SEMC map region去獲取的
  對於XIP啟動而言,其基本流程與non-XIP image載入啟動過程差異就比較大了,因為整個Bootable image都不需要搬運,BootROM直接從NOR對應的SEMC map region去獲取IVT,BootData,Application,而BootROM中分配給SEMC NOR的XIP空間為0x90000000 - 0x90FFFFFF,所以XIP執行的Application需要連結在這個空間裡。

痞子衡嵌入式:飛思卡爾i.MX RT系列MCU啟動那些事(9)- 從Parallel NOR啟動

  有了前面的背景知識,NOR的載入啟動過程便是上電之後,BootROM先從NOR起始地址處載入initial image資料(12KB),再根據initial image裡的IVT獲取Application起始地址,如Application地址是連結在SRAM裡,便認為這是個Non-XIP Application,然後再將Application拷貝到相應SRAM裡去啟動;如Application地址是連結在SEMC NOR XIP空間裡,則不需要拷貝,直接原地XIP執行啟動。

四、下載Application進Parallel NOR

  理解了Parallel NOR載入啟動過程,我們便可以開始使用Flashloader下載Application進Parallel NOR晶片中:

  痞子衡在啟動系列文章的第四篇 Flashloader初體驗(blhost) 和第六篇 Bootable image格式與載入(elftosb/.bd) 裡分別介紹了Flashloader的基本使用以及如何將你的Application製作成Bootable image,但那裡面製作的Bootable image主要是用於NAND啟動,而對於NOR啟動,其用於生成Bootable image的BD檔案稍有不同。
  先來看Non-XIP的情況,下面是一個Non-XIP的BD檔案示例,ivtOffset必須設0x1000,因為startAddress = 0x8000, initialLoadSize = 0x3000,所以Application只讀段應從0xb000處開始連結:

options {
    flags = 0x00;
    # Note: This is an example address, it can be any non-zero address in ITCM region
    startAddress = 0x8000;
    ivtOffset = 0x1000;
    initialLoadSize = 0x3000;
    # Note: This is required if the default entrypoint is not the Reset_Handler 
    #       Please set the entryPointAddress to Reset_Handler address 
    // entryPointAddress = 0xd531;
}

sources {
    elfFile = extern(0);
}

section (0)
{
}

  再來看XIP的情況,下面是一個XIP的BD檔案示例,ivtOffset也必須設0x1000,因為startAddress = 0x90000000, initialLoadSize = 0x3000,所以Application只讀段應從0x90003000處開始連結:

options {
    flags = 0x00;
    startAddress = 0x90000000;
    ivtOffset = 0x1000;
    initialLoadSize = 0x3000;
    # Note: This is required if the default entrypoint is not the Reset_Handler 
    #       Please set the entryPointAddress to Reset_Handler address 
    // entryPointAddress = 0x90005531;
}

sources {
    elfFile = extern(0);
}

section (0)
{
}

  假定你已經制作好Bootable image並且使用blhost工具與Flashloader建立了基本通訊,正要開始將Bootable image下載進Parallel NOR。
  與Raw NAND啟動一樣,Parallel NOR也支援configuration block,只不過configuration block對於BootROM啟動而言不是必需的,configuration block必須放在NOR Flash起始地址處,下面是其結構原型(如果你還有印象的話,你會發現它跟Raw NAND的semc_nand_config_t很像),如果想使能configuration block,你需要手動建立這256bytes資料,並且用其覆蓋bootable image的前256bytes,在本文裡暫不使能configuration block。

#define SEMC_NOR_INIT_IMG_SIZE (12u * 1024)
#define SEMC_NOR_MAX_SIZE (16U * 1024 * 1024)

#define SEMC_MEM0_BASE (0x80000000u)
#define SEMC_MEM1_BASE (0x90000000u)
#define SEMC_MEM2_BASE (0xA0000000u)
#define SEMC_MEM3_BASE (0xC0000000u)
#define SEMC_MEM_NOR_AXI_BASE SEMC_MEM1_BASE

typedef struct __semc_nor_config
{
    semc_mem_config_t memConfig; //!< [0x000-0x04f]
    uint8_t vendorType;          //!< [0x050-0x050]
    uint8_t acTimingMode;        //!< [0x051-0x051]
    uint8_t deviceCommandSet;    //!< [0x052-0x052]
    uint8_t reserved0[77];       //!< [0x053-0x09f]
    uint32_t pageSizeInBytes;    //!< [0x0a0-0x0a3]
    uint32_t blockSizeInBytes;   //!< [0x0a4-0x0a7]
    uint32_t blockCount;         //!< [0x0a8-0x0ab]
    uint32_t reserved1[21];      //!< [0x0ac-0x0ff]
} semc_nor_config_t;

  前面鋪墊了這麼多,終於來到關鍵地方了,到底怎麼樣將Bootable image資料下載進Parallel NOR中呢?當然還是靠Flashloader工具,我們只需要提供簡化的4byte配置資料即可。下面是一種Application下載更新示例(該示例適用於第二節裡介紹的NOR硬體連線):

// 在SRAM裡臨時儲存Parallel NOR配置資料
blhost -p COMx -- fill-memory 0x2000 0x4 0xD0000600 // CSX0, ADV high active, 16bits IO, safe AC timing mode

// 使用Parallel NOR配置資料去配置Parallel NOR介面
blhost -p COMx -- configure-memory 0x8 0x2000

  在上述示例裡痞子衡首先使用了fill-memory命令在0x2000地址處暫存了4byte配置資料,然後通過config-memory將這4byte資料裡的資訊配置到Flashloader的Parallel NOR介面中,實際上這2個命令成功執行後,你就可以開始使用Flashloader下載Bootable image了。那麼這4byte配置資料到底是怎麼組織的?詳見下表:

痞子衡嵌入式:飛思卡爾i.MX RT系列MCU啟動那些事(9)- 從Parallel NOR啟動

  從上表我們可以知道,其實這4byte資料提供的配置資訊主要是NOR配置,這4byte裡真正需要注意的只有兩個地方(ADV# Polarity、Data Port Size),其餘可用固定配置。
  configure-memory命令執行成功之後,底下image的下載很簡單,只需要將Bootable image從SEMC NOR起始map地址開始下載即可,具體步驟如下:

// 擦除Parallel NOR並將image下載進Parallel NOR
blhost -p COMx -- flash-erase-region 0x90000000 0x20000
blhost -p COMx -- write-memory 0x90000000 ivt_image.bin

Note: 實測發現,RT1050 Flashloader 1.1裡使用USB介面去下載Parallel NOR會報kStatus_SemcNOR_ProgramVerifyFailure錯誤,而使用UART介面下載則正常,應該是USB下載對NOR的支援有缺陷,期望在後續版本的Flashloader裡修復這個問題。

  Bootable image下載成功之後,我們可以試著用read-memory從NOR晶片裡讀回IVT,BootData,Application確認一下,Bootable image起始地址在0x90000000,那麼IVT,BootData應該在0x90001000,Application應該在0x90003000:
  Non-XIP Bootable image讀回情況如下,檢查初始PC可知其連結在SRAM空間
痞子衡嵌入式:飛思卡爾i.MX RT系列MCU啟動那些事(9)- 從Parallel NOR啟動

  XIP Bootable image讀回情況如下,檢查初始PC可知其連結在SEMC NOR map空間

痞子衡嵌入式:飛思卡爾i.MX RT系列MCU啟動那些事(9)- 從Parallel NOR啟動

Note: 如果Application是XIP在SEMC NOR空間,其時鐘初始化程式碼不能覆蓋BootROM裡對於SEMC的相關配置,否則XIP可能會失敗。

  至此,Application的下載工作便結束了。

五、進入Parallel NOR啟動模式

  Application已經被成功下載進Parallel NOR晶片之後,此時我們便可以開始設定晶片從Parallel NOR啟動:

  在進入Boot Device選擇之前,你首先需要確定BOOT_MODE[1:0]=2'b00,即晶片處於Boot From Fuses模式,並且將BT_FUSE_SEL(eFUSE偏移0x460處的32bit配置資料的bit4)燒寫為1'b1,這裡看不懂的朋友請溫習痞子衡前面的文章 Boot配置(BOOT Pin/eFUSE)
  設定好正確Boot模式後,再來選擇Boot Device,,你還需要將BOOT_CFG1[7:4](eFUSE偏移0x450處的32bit配置資料的bit7:4)燒寫成4'b0001,此時便進入了從SEMC NOR啟動模式。
  如果想確保i.MXRT晶片一定正在從Parallel NOR啟動,可在晶片上電時使用Jlink偵錯程式或者藉助Flashloader讀取晶片內部2個暫存器的值,這2個暫存器分別是SRC_SBMR1/2, 我們設的關於啟動模式的BOOT_MODE pins/BOOT_CFG pin/eFUSE偏移0x450配置值在上電時會自動載入到SRC_SBMR1/2暫存器裡,BootROM主要是根據SRC_SBMR1/2暫存器的值來判斷啟動模式的。

痞子衡嵌入式:飛思卡爾i.MX RT系列MCU啟動那些事(9)- 從Parallel NOR啟動

  PS: BOOT_MODE[1:0]也可以設為2'b10,即晶片處於Internal Boot模式,此時需要確保BT_FUSE_SEL(eFUSE偏移0x460處的32bit配置資料的bit4)為1'b0和BOOT_CFG1[7:4]這四個pin的輸入狀態設為4'b0001。

六、配置eFUSE啟動Parallel NOR

  設定好晶片啟動模式是從Parallel NOR啟動之後,我們還需要最後關注一下與Parallel NOR相關的具體特性配置:

  你應該記得我們在使用Flashloader下載Application的時候提供過4bytes的NOR配置資料,這4bytes的NOR配置資料是為了讓Flashloader能夠正確初始化Parallel NOR介面去訪問NOR晶片(主要是寫Bootable image),同樣BootROM上電也需要初始化Parallel NOR介面去訪問NOR晶片(主要是讀Bootable image),所以BootROM也需要類似這4bytes NOR配置資料,而BootROM的NOR配置便放在如下的eFUSE區域裡:

痞子衡嵌入式:飛思卡爾i.MX RT系列MCU啟動那些事(9)- 從Parallel NOR啟動

痞子衡嵌入式:飛思卡爾i.MX RT系列MCU啟動那些事(9)- 從Parallel NOR啟動

  上述所有步驟全部完成之後,復位晶片你就應該能看到你放在Parallel NOR裡的Application已經正常地啟動了。

  至此,飛思卡爾i.MX RT系列MCU的Parallel NOR啟動痞子衡便介紹完畢了,掌聲在哪裡~~~

相關文章