大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是i.MXRT1050/1020/1015系列ROM中的FlexSPI驅(qū)動(dòng)API使用。 今天痞子衡去4S店給愛(ài)車(chē)做保養(yǎng)了,保養(yǎng)一次要等兩小時(shí),閑來(lái)無(wú)聊就寫(xiě)了這篇文章打發(fā)時(shí)間,正好痞子衡技術(shù)交流群里有朋友也在問(wèn)這個(gè)主題,急人所急是痞子衡的一大特質(zhì)(此處請(qǐng)?jiān)试S我裝一下)。 本篇是 《利用i.MXRT1xxx系列ROM提供的FlexSPI driver API可輕松IAP》 的續(xù)集,上篇文章基本上把ROM API原理及使用講得很透徹了,但文中賣(mài)了一個(gè)關(guān)子,即i.MXRT1xxx系列一共出了7款型號(hào),但并不是每個(gè)型號(hào)都開(kāi)放了ROM API,最早誕生的三款型號(hào)(105x、1021、1015)就并沒(méi)有開(kāi)放API(不是沒(méi)有API,而是沒(méi)有嚴(yán)格測(cè)試),隨著ROM API的優(yōu)點(diǎn)逐漸被大家意識(shí)到,客戶要求API開(kāi)放的呼聲也越來(lái)越高,因此恩智浦研發(fā)團(tuán)隊(duì)對(duì)未開(kāi)放的API做了測(cè)試,明確功能一切正常后,終于官宣了。所以今天痞子衡著重講這三款未開(kāi)放API的RT型號(hào)在API使用上跟主流RT型號(hào)(如i.MXRT1060)有什么區(qū)別。
一、ROM API簡(jiǎn)介1.1、API設(shè)計(jì)實(shí)現(xiàn)關(guān)于i.MXRT1050/1020/1015 API設(shè)計(jì)原理,這里就不予贅述了,因?yàn)楦鷌.MXRT1060中是一樣的。咱們直接看它們的API原型 bootloader_api_entry_t,細(xì)心的朋友會(huì)發(fā)現(xiàn)在原型定義上跟i.MXRT1060是有區(qū)別的,結(jié)構(gòu)體中前3個(gè)成員順序上不一樣,其實(shí)這是早期的原型定義,存在不合理的地方,顯然version放第一個(gè)才符合API標(biāo)準(zhǔn)定義,因此這在i.MXRT1060中得到了改進(jìn)。此外在后面API分組功能上也差異較大,不過(guò)我們最在意的FlexSPI NOR驅(qū)動(dòng)API在就行。 typedef struct { void (*runBootloader)(void *arg); const uint32_t version; const char * copyright; const hab_rvt_t* habDriver; //!< FlexSPI NOR Flash API const flexspi_nor_driver_interface_t* flexSpiNorDriver; const flexspi_nand_driver_interface_t* flexSpiNandDriver; const nand_ecc_driver_interface_t *nandEccDriver; const dcp_aes_driver_interface_t *dcpAesDriver; }bootloader_api_entry_t; 下面是i.MXRT1050中的g_bootloaderTree實(shí)例,其實(shí)只真正提供了HAB、FlexSPI NOR、NAND ECC三類(lèi)API: // Bootloader API Tree const bootloader_api_entry_t g_bootloaderTree = { .runBootloader = run_bootloader, .version = MAKE_VERSION(1, 1, 0), .copyright = "Copyright 2017 NXP", .habDriver = &hab_rvt, .flexSpiNorDriver = &g_flexspiNorDriverInterface, .flexSpiNandDriver = NULL, .nandEccDriver = &g_nandEccDriverInterface, }; 下面是i.MXRT1020/1015中的g_bootloaderTree實(shí)例,這里甚至只提供了FlexSPI NOR API,沒(méi)辦法,BootROM空間有限: // Bootloader API Tree const bootloader_api_entry_t g_bootloaderTree = { .runBootloader = run_bootloader, .version = MAKE_VERSION(1, 0, 0), .copyright = "Copyright 2017 NXP", .habDriver = NULL, .flexSpiNorDriver = &g_flexspiNorDriverInterface, }; 二、API之FlexSPI驅(qū)動(dòng)2.1 FlexSPI驅(qū)動(dòng)原型flexspi_nor_driver_interface_t是FlexSPI NOR驅(qū)動(dòng)的原型,原型中定義了全部的API函數(shù),但具體在每個(gè)RT型號(hào)里并不是都有實(shí)例。 下面是i.MXRT1050中的g_flexspiNorDriverInterface實(shí)例,缺少了get_config()函數(shù)實(shí)現(xiàn): const flexspi_nor_driver_interface_t g_flexspiNorDriverInterface = { .version = MAKE_VERSION(1, 4, 0), .init = flexspi_nor_flash_init, .program = flexspi_nor_flash_page_program, .erase_all = flexspi_nor_flash_erase_all, .erase = flexspi_nor_flash_erase, .read = flexspi_nor_flash_read, .clear_cache = flexspi_clear_cache, .xfer = flexspi_command_xfer, .update_lut = flexspi_update_lut, }; 下面是i.MXRT1020/1015中的g_flexspiNorDriverInterface實(shí)例,除了缺少get_config()函數(shù),還缺少erase_all()函數(shù)實(shí)現(xiàn): const flexspi_nor_driver_interface_t g_flexspiNorDriverInterface = { .version = MAKE_VERSION(1, 4, 0), .init = flexspi_nor_flash_init, .program = flexspi_nor_flash_page_program, .erase = flexspi_nor_flash_erase, .clear_cache = flexspi_clear_cache, .xfer = flexspi_command_xfer, .update_lut = flexspi_update_lut, }; 2.2 FlexSPI驅(qū)動(dòng)使用示例根據(jù)前面介紹,我們知道未開(kāi)放的API主要缺少get_config()函數(shù),其他都是一樣的,但是別小看這個(gè)get_config()函數(shù),它可是API簡(jiǎn)便易用的核心所在,現(xiàn)在沒(méi)有了這個(gè)函數(shù),我們只能根據(jù)板子上的Flash型號(hào)去手工提供512bytes的flexspi_nor_config_t變量。 // 找到API根結(jié)構(gòu)體 #define g_bootloaderTree (*(bootloader_api_entry_t **)0x0020001c) // 定義FlexSPI配置變量 flexspi_nor_config_t config; uint32_t instance = 0; // 需要初始化完整512bytes FlexSPI配置變量 config.memConfig.tag = FLEXSPI_CFG_BLK_TAG config.memConfig.version = FLEXSPI_CFG_BLK_VERSION // ... // 調(diào)用API中init()函數(shù) g_bootloaderTree->flexSpiNorDriver->init(instance, &config); // 調(diào)用API中erase()函數(shù) g_bootloaderTree->flexSpiNorDriver->erase(instance, &config, 0x40000, 0x1000); 2.3 FlexSPI配置變量初始化那么如何初始化這512bytes的flexspi_nor_config_t變量呢,這就說(shuō)來(lái)話長(zhǎng)了,痞子衡講一個(gè)最常見(jiàn)的四線QSPI Flash的配置吧。 我們知道i.MXRT1060-EVK上默認(rèn)連的是ISSI的8MB QSPI Flash,SDK XIP工程里默認(rèn)使用了它的配置,在 \SDK_2.x.x_EVK-MIMXRT1060\boards\evkmimxrt1060\xip\evkmimxrt1060_flexspi_nor_config.c中定義了常量 qspiflash_config,我們可以參考這個(gè)常量定義。 qspiflash_config適用于四線、100MHz、8MB的Flash,如果你的QSPI Flash在大小和速度上與它不同,可以做相應(yīng)調(diào)整。不過(guò)這個(gè)qspiflash_config主要是給ROM啟動(dòng)用的,而ROM啟動(dòng)僅需要讀Flash,因此這個(gè)配置中LUT僅有Read,而我們需要的API一般都要實(shí)現(xiàn)擦除和編程,因此要修改其lookupTable如下: config.memConfig.lookupTable = { // Sequence 0 - Quad Read // 0x6B - Fast read Quad Output command, 0x18 - 24 bit address [0] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x6B, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18), // 0x08 - 8 dummy clocks, 0x80 - read 128 bytes [1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD, 0x08, kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x80), // Sequence 1 - Read Status Register // 0x05 - Read status register command, 0x4 - read 4 bytes [4] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x05, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04), // Sequence 2 - Write Status Register 2 // 0x31 - Write status register 2 command, 0x1 - write 1 byte [8] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x31, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x01), // Sequence 3 - Write enable // 0x06 - Write enable command [12] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06, kFLEXSPI_Command_STOP, 0x00, 0x00), //[16] - Seq 4 empty // Sequence 5 - 4K Sector erase // 0x20 - Sector erase command, 0x18 - 24 bit address [20] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x20, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18), //[24] - Seq 6 empty //[28] - Seq 7 empty //[32] - Seq 8 empty // Sequence 9 - Page Program, 256 bytes // 0x02 - page program command, 0x18 - 24 bit address [36] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18), // 0x04 - write 4 bytes [37] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, 0x00, 0x00), //[40] - Seq 10 empty //[44] - Seq 11 empty // Sequence 12 - Read JEDEC // 0x9F - read JEDEC command, 0x04 - read 4 bytes [48] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x9F, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04), //[52-60] - Seqs 13 - 15 empty }; 至此,i.MXRT1050/1020/1015系列ROM中的FlexSPI驅(qū)動(dòng)API使用痞子衡便介紹完畢了,掌聲在哪里~~~ |
|
來(lái)自: 精品唯居 > 《待分類(lèi)》