联博api:痞子衡嵌入式:行使i.MXRT1xxx系列ROM提供的FlexSPI driver API可轻松IAP

admin 2周前 (09-07) 科技 49 2

  人人好,我是痞子衡,是正经搞手艺的痞子。今天痞子衡给人人先容的是i.MXRT系列ROM中的FlexSPI驱动API实现IAP

  痞子衡的手艺交流群里经常有群友提问: i.MXRT中的FlexSPI驱动API到底怎么用啊?这个问题已经泛起过好几回了,原本痞子衡不计划专门为这个写文章的,由于这部门内容在芯片手册System Boot章节里的最后一节ROM APIs里实在先容得异常详细了,然则既然照样有不少同伙在问这个,看起来手册里的内容藏得有点深,这么好的器械被潜匿太惋惜了,那么今天痞子衡就跟人人再认真聊一聊。

一、ROM API简介

1.1、API发生靠山

  i.MXRT系列都是Flashless(没有内置NVM)的芯片,以是BootROM必不可少。BootROM是个很特殊的器械,本质上它是一个完整的C代码写成的系统级App,这个系统级App专门用于从外部存储器中加载用户级App执行。简朴地说,BootROM就是PC机里的BIOS。

  BootROM代码是存放在专门的ROM区域的(前面讲i.MXRT系列没有内置NVM,实在不够准确,实在是有内部ROM空间的,只不外这个ROM区域用户无法下载程序使用,因此等效于没有NVM),ROM顾名思义Readonly,以是BootROM代码只能随着芯片一起Tapeout,代码无法更改(实在也有ROM patch机制,以后再先容)。

  ROM空间实在挺大的,从64KB到512KB不等,因芯片启动功效庞大水平而异。下图是i.MXRT1050系列的BootROM所占空间,ROM起始地址是0x200000(起始地址在i.MXRT上都一样),ROM巨细为96KB(这是尺度启动功效所要的代码长度。在i.MXRT1010上是64KB - 精简启动功效,在i.MXRT1170上是256KB - 庞大启动功效)。

  BootROM代码实在并没有占满所有ROM空间,总有些剩余空间(由于工艺缘故原由,ROM空间都是8/16KB倍数),这部门空间浪费了着实惋惜。若是我们能把SDK里的一些常用模块驱动(好比WDOG)顺便放进去供用户挪用,既充分行使ROM空间,也为用户节约Flash空间,岂不是一石二鸟。此外,BootROM功效代码中也有一些现成模块驱动(好比种种启动装备存储器驱动接口)可以一并导出,这即是API由来。

1.2、API设计实现

  有了API想法,现在就是设计实现了。实在i.MXRT ROM API设计并不是重头最先的,在这个MCU系列被主推之前,Kinetis系列也曾当红过,Kinetis中也内置了ROM,而且提供了ROM API,痞子衡之前为此写过一篇文章 《飞思卡尔Kinetis系列MCU启动那些事(11)- KBOOT特征(ROM API)》。 i.MXRT ROM API设计思绪完全复用了Kinetis ROM API的设计。

  API说到底就是一个个功效函数的连系,我们知道工程代码都是由链接器自动分配的,因此每个函数现实链接地址是无法预期的(在链接文件里给每个函数分配牢固地址链接这种方式不在思量范围,当函数数目众多时,这种方式太贫苦),业界上一个对照通用的做法是界说成员是函数指针的结构体,i.MXRT ROM API就是接纳的业界通用方式,下面bootloader_api_entry_t即是i.MXRT1060中API原型,g_bootloaderTree就是实例:

typedef struct
{
    const uint32_t version;
    const char *copyrIGht;
    void (*ruNBootloader)(void *arg);
    const hab_rvt_t *habDriver;

    //!< FlexSPI NOR Flash API
    const flexspi_nor_driver_interface_t *flexSpiNorDriver;

    const nand_ecc_driver_interface_t *nandEccDriver;
    const clock_driver_interface_t *clockDriver;
    const rtwdog_driver_interface_t *rtwdoGDriver;
    const wdog_driver_interface_t *wdogDriver;
    const stdlib_driver_interface_t *stdlibDriver;
} bootloader_api_entry_t;

// Bootloader API Tree
const bootloader_api_entry_t g_bootloaderTree = {
    .copyright = "Copyright 2018 NXP",
    .version = MAKE_VERSION(1, 0, 0),
    .runBootloader = run_bootloader,
    .habDriver = &hab_rvt,

    .flexSpiNorDriver = &g_flexspiNorDriverInterface,

    .nandEccDriver = &g_nandEccDriverInterface,
    .clockDriver = &g_clockDriverInterface,
    .rtwdogDriver = &g_rtwdogDriverInterface,
    .wdogDriver = &g_wdogDriverInterface,
    .stdlibDriver = &g_stdlibDriverInterface,
};

  从上面代码我们可以看出,bootloader_api_entry_t成员似乎并不是函数指针,是的,为了分组利便,bootloader_api_entry_t成员照样一个个结构体,它的这些结构体成员(好比flexspi_nor_driver_interface_t)才是真正包罗一个个函数指针的结构体。API从功效来分一共提供了7类:HAB、FlexSPI NOR、NAND ECC、Clock、RT-WDOG、WDOG、stdlib。

  设计到这里,我们通过g_bootloaderTree结构体常量就可以挪用所有的API函数了,最后剩下的问题就是若何在ROM里找一个确定的地方保留随机链接的g_bootloaderTree地址(只要4字节即可)。是的,照样Kinetis ROM API用的谁人巧妙的方式,下面是BootROM工程的startup文件(Keil版),BootROM将g_bootloaderTree的地址放到了中断向量表第8个向量的位置处(该向量为ARM Cortex-M未界说的系统向量),因此0x20001c处最先的4bytes便牢固是g_bootloaderTree地址。

                PRESERVE8
                THUMB

; Vector TABLe Mapped to Address 0 at Reset

                AREA    RESET, DATA, READONLY
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size
                IMPORT  |Image$$ARM_LIB_STACK$$ZI$$Limit|
                IMPORT  g_bootloaderTree

__Vectors       DCD     |Image$$ARM_LIB_STACK$$ZI$$Limit|
                DCD     Reset_Handler
                DCD     DefaultISR
                DCD     HardFault_Handler
                DCD     DefaultISR
                DCD     DefaultISR
                DCD     DefaultISR
                DCD     g_bootloaderTree
                DCD     0
                DCD     0
                DCD     0
                DCD     SVC_Handler
                DCD     DefaultISR
                DCD     0
                DCD     DefaultISR
                DCD     DefaultISR
		        ;; ...

1.3、API挪用方式

  了解了前面先容的ROM API发生靠山与设计实现,它的挪用方式就异常简朴了,以WDOG API挪用为例,只需要如下简朴3句代码:

// 找到API根结构体
#define g_bootloaderTree (*(bootloader_api_entry_t **)0x0020001c)
// 界说WDOG模块设置变量
wdog_config_t config;
// 挪用API中WDOG_Init()
g_bootloaderTree->wdogDriver->WDOG_Init(WDOG1, config);

1.4、支持API的i.MXRT型号

  停止现在,i.MXRT1xxx系列一共出了7款型号,但并不是每个型号都开放了ROM API,最早降生的三款型号(105x、1021、1015)就并没有开放API(不是没有API,而是没有严酷测试),其余型号都支持API。

RT芯片型号 是否支持ROM API
i.MXRT117x 支持
i.MXRT1064 支持
i.MXRT106x 支持
i.MXRT105x 未开放
i.MXRT1021 未开放
i.MXRT1015 未开放
i.MXRT1011 支持

二、API之FlexSPI驱动

  前面铺垫了太多ROM API设计细节,到这里才算进入正题,本文实在主要是要跟人人聊若何行使API里的FlexSPI NOR驱动实现IAP。痞子衡在前面铺垫那么多的缘故原由实在主要是想告诉人人,API里的每个驱动都是经由完善测试的,尤其是这个FlexSPI NOR驱动,更是经由了千锤百炼,无论是易用性、运行稳定性照样Flash型号的支持度上都是压倒一切的。

  对于JESD216尺度下的串行SPI接口Flash驱动,人人知道更多的可能是RT-Thread手艺总监朱天龙大神的开源 SFUD 项目,但痞子衡告诉你,i.MXRT ROM API里的这个串行Flash驱动也毫不逊色(连续维护与优化了近6年,历经多款MCU的ROM,是真正的产品级),只是不如开源项目那么着名,不外它的源代码也是开源在SDK里的(\SDK\middleware\mcu-boot\src\drivers\flexspi_nor),BSD-3-Clause许可证。

2.1 FlexSPI驱动原型

  flexspi_nor_driver_interface_t即是FlexSPI NOR驱动的原型,寻常的读写擦功效自然不在话下,除此以外,API内里另有一个异常厉害的xfer()函数,这个函数可以用来实现其他定制化的Flash操作函数,有兴趣的同伙可以进一步去研究。

typedef struct
{
    uint32_t version;
    status_t (*init)(uint32_t instance, flexspi_nor_config_t *config);
    status_t (*program)(uint32_t instance, flexspi_nor_config_t *config, uint32_t dst_addr, const uint32_t *src);
    status_t (*erase_all)(uint32_t instance, flexspi_nor_config_t *config);
    status_t (*erase)(uint32_t instance, flexspi_nor_config_t *config, uint32_t start, uint32_t lengthInBytes);
    status_t (*read)(uint32_t instance, flexspi_nor_config_t *config, uint32_t *dst, uint32_t addr, uint32_t lengthInBytes);
    void (*clear_cache)(uint32_t instance);
    status_t (*xfer)(uint32_t instance, flexspi_xfer_t *xfer);
    status_t (*update_lut)(uint32_t instance, uint32_t seqIndex, const uint32_t *lutBase, uint32_t seqNumber);
    status_t (*get_config)(uint32_t instance, flexspi_nor_config_t *config, serial_nor_config_option_t *option);
} flexspi_nor_driver_interface_t;

2.2 FlexSPI驱动使用示例

  FlexSPI驱动使用基本三步走,先挪用get_config()获取完整FlexSPI模块设置,然后挪用init()函数去初始化FlexSPI以及接见Flash获取SFDP表信息,最后就是挪用Flash操作函数(好比erase())。

// 找到API根结构体
#define g_bootloaderTree (*(bootloader_api_entry_t **)0x0020001c)

// 界说FlexSPI, Flash设置变量
flexspi_nor_config_t config;
serial_nor_config_option_t option;
option.option0.U = 0xC0000008; // QuadSPI NOR, Frequency: 133MHz
uint32_t instance = 0;

// 挪用API中get_config()函数
g_bootloaderTree->flexSpiNorDriver->get_config(instance, &config, &option);
// 挪用API中init()函数
g_bootloaderTree->flexSpiNorDriver->init(instance, &config);
// 挪用API中erase()函数
g_bootloaderTree->flexSpiNorDriver->erase(instance, &config, 0x40000, 0x1000);

2.3 FlexSPI驱动特点

  由于FlexSPI NOR驱动API来自于BootROM,因此其在使用上有一些小小的限制,也算是其特点吧。FlexSPI驱动API里并没有提供Flash毗邻的Pinmux设置,其Pinmux设置已经写死在init()函数中,就是ROM支持启动的FlexSPI PORTA上的那些pin(片选是SS0)。

  在上面的使用示例代码中,你会看到option.option0.U = 0xC0000008代码,这算是FlexSPI驱动最大的特点了,这是一个简化的option设置word(其原型可在芯片手册里找到),通过这个简化的option,用户可以轻松设置来接见差别厂商的Flash,下面是常用的Flash模式设置值。

• QuadSPI NOR - Quad SDR Read: option0 = 0xc0000008 (133MHz)
• QuadSPI NOR - Quad DDR Read: option0 = 0xc0100003 (60MHz)
• HyperFLASH 1V8: option0 = 0xc0233009 (166MHz)
• HyperFLASH 3V0: option0 = 0xc0333006 (100MHz)
• MXIC OPI DDR (OPI DDR enabled by default): option=0xc0433008(133MHz)
• Micron Octal DDR: option0=0xc0600006 (100MHz)
• Micron OPI DDR: option0=0xc0603008 (133MHz), SPI->OPI DDR
• Micron OPI DDR (DDR read enabled by default): option0 = 0xc0633008 (133MHz)
• Adesto OPI DDR: option0=0xc0803008(133MHz)

2.4 FlexSPI驱动用作IAP

  IAP实在就是在App中实现Flash擦写,单纯从手艺上来说并不是一个很难的器械。但i.MXRT上许多时刻App代码自己也在统一片Flash里执行(也叫XIP),而市面上许多Flash都是不支持RWW(Read-While-Write)的,这就导致一个问题,当你挪用Flash操作函数去擦写Flash时,CPU又需要继续去Flash获取指令,违反了RWW,因此你只能把Flash相关操作函数所有放在RAM中去执行(这涉及涣散加载了,对于低级嵌入式用户来说稍微有点难)。

  现在我们有了ROM API,FlexSPI驱动代码体所有都在ROM空间里,并不占用Flash空间,因此不存在RWW问题,真是自然为IAP而生,再也不用再管什么涣散加载这么贫苦的事了。

三、FlexSPI API业界应用

  最后再先容一下i.MXRT FlexSPI API在业界的应用,这个API实在并不小众,现在已被主流IDE和调试工具用作i.MXRT Flash下载算法。

3.1 用于IAR下载算法

  若是你的IAR版本够新,能够支持i.MXRT1060等型号,随便打开一个i.MXRT1060 SDK工程,在工程Option里找到Debugger,然后进入Flashloader设置,你会看到页面里有Extra parameters一栏,在下面的注释里有这个参数的示例,它就是前面2.3节里先容的option0。有了这种方式设计的Flash下载算法,你再也不用手动更新下载算法文件去支持差别的Flash了,改参数就行了。

联博api:痞子衡嵌入式:行使i.MXRT1xxx系列ROM提供的FlexSPI driver API可轻松IAP 第1张

3.2 用于J-Link下载算法

  现在最新的Jlink驱动里的下载算法也是基于ROM API的,痞子衡有一个开源项目,收集了i.MXRT所有型号的下载算法源代码工程,其中jlink算法是最全的,其他IDE算法还在陆续完善中。

https://github.com/JayHeng/imxrt-tool-flash-algo

  至此,i.MXRT系列ROM中的FlexSPI驱动API实现IAP痞子衡便先容完毕了,掌声在那里~~~

迎接订阅

文章会同时公布到我的 博客园主页、CSDN主页、微信民众号 平台上。

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机第一时间看了哦。

联博api:痞子衡嵌入式:行使i.MXRT1xxx系列ROM提供的FlexSPI driver API可轻松IAP 第2张

,

欧博APP

欢迎进入欧博APP(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务

AllBetGaming声明:该文看法仅代表作者自己,与本平台无关。转载请注明:联博api:痞子衡嵌入式:行使i.MXRT1xxx系列ROM提供的FlexSPI driver API可轻松IAP

网友评论

  • (*)

最新评论

站点信息

  • 文章总数:658
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1144
  • 评论总数:222
  • 浏览总数:10179