大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦i.MXRT官方SDK里关于串行Flash相关的驱动与例程资源

  经常有同事以及 i.MXRT 客户咨询痞子衡,咱们恩智浦官方 SDK 里有哪些串行 Flash 相关的示例,每一次痞子衡都是按照询问需求将 SDK 里相应资源路径发给对方。看来那句俗话说得也不尽然对,酒香也怕巷子深,今天痞子衡就给大家全面梳理一下 SDK 里和串行 Flash 相关的全部资源。

  • Note 1: 本文内容主要以 SDK_2_15_100_EVKB-IMXRT1050 软件包里的资源为例
  • Note 2: 本文共分为上下两篇,本篇是上篇,主要介绍 drives 和 components

一、Flash相关驱动概览

  首先直接开门见山,痞子衡把 SDK 里和 Flash 有关系的驱动全部罗列如下,分布在 device driver、components、middleware、azure-rtos 里。 这四个目录下的驱动关系简单概括如下:

1. device driver 就是芯片底层外设的 HAL 级驱动,代码里直接操作外设寄存器。
2. components 是基于 device driver 而设计的面向某个外围器件/具体小功能的驱动,代码里直接调用 devcie driver 里的 API。
3. middleware 则是面向某类具体功能的更大型的软件库,代码里一般调用 components 里的 API,强调与芯片外设底层隔离,主打平台无关的通用性。
4. azure-rtos 本身是硬件无关的 RTOS,但是其也同时包含了一些类似 middleware 功能实现,这些 middlware 会调用 components 里的 API。

二、Flash驱动解释及例程

2.1 drivers

2.1.1 flexspi

  fsl_flexspi 驱动是芯片外设 FlexSPI 的 HAL 级驱动,其是操作 FlexSPI 寄存器以实现 1-8bit SPI 类主设备方式数据收发,其 API 本身和 Flash 芯片操作并没有直接的联系,这从如下主要 API 原型可以看出来:

void FLEXSPI_Init(FLEXSPI_Type *base, const flexspi_config_t *config);
void FLEXSPI_SetFlashConfig(FLEXSPI_Type *base, flexspi_device_config_t *config, flexspi_port_t port);
void FLEXSPI_UpdateLUT(FLEXSPI_Type *base, uint32_t index, const uint32_t *cmd, uint32_t count);
status_t FLEXSPI_WriteBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size);
status_t FLEXSPI_ReadBlocking(FLEXSPI_Type *base, uint8_t *buffer, size_t size);
status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer);
status_t FLEXSPI_TransferNonBlocking(FLEXSPI_Type *base, flexspi_handle_t *handle, flexspi_transfer_t *xfer);

  如下配套例程调用 fsl_flexspi 驱动里 API 实现了官方 RT1050-EVKB 板卡上的 hyperflash (S26KS512S) 和四线 nor flash (IS25WP064A) 的读写功能验证。

例程路径: \SDK_2_15_100_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\flexspi
- Hyper Flash 驱动: \driver_examples\flexspi\hyper_flash\polling_transfer\flexspi_hyper_flash_ops.c
- Nor Flash 驱动: \driver_examples\flexspi\nor\polling_transfer\flexspi_nor_flash_ops.c

  其中例程里的 flexspi_xxx_flash_ops.c 源文件设计其实有那么一点 components 的味道,从 API 命名来看其实现了面向 Flash 的读写擦功能,但是 API 里的代码实现比较简洁,没有过度设计,对于不同厂商/类型的 Flash 支持,主要依赖用户定义的 LUT 表里的命令序列。

void flexspi_nor/hyper_flash_init(FLEXSPI_Type *base);
status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src);
status_t flexspi_nor_flash_read(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src, uint32_t length);
2.1.2 lpspi

  fsl_lpspi 驱动是芯片外设 LPSPI 的 HAL 级驱动,其是操作 LPSPI 寄存器以实现 1bit(4bit) SPI 主/从设备方式数据收发,API 本身和 Flash 芯片也没有直接的联系。

void LPSPI_MasterInit(LPSPI_Type *base, const lpspi_master_config_t *masterConfig, uint32_t srcClock_Hz);
void LPSPI_SlaveInit(LPSPI_Type *base, const lpspi_slave_config_t *slaveConfig);
status_t LPSPI_MasterTransferBlocking(LPSPI_Type *base, lpspi_transfer_t *transfer);
status_t LPSPI_MasterTransferNonBlocking(LPSPI_Type *base, lpspi_master_handle_t *handle, lpspi_transfer_t *transfer);
status_t LPSPI_SlaveTransferNonBlocking(LPSPI_Type *base, lpspi_slave_handle_t *handle, lpspi_transfer_t *transfer);

  该驱动的配套例程是单纯的 SPI 总线传输,并没有针对 Flash,这里就不展开了,但是它会在 components/flash 里被用到,后文会提及。

2.1.3 romapi

  fsl_romapi 驱动是芯片固化 BootROM 所导出的通用 Flash API,在 BootROM 里集成了基于 FlexSPI 外设驱动而写成的通用 Flash 驱动,这个 Flash 驱动设计差不多是 components 级别,具体源代码原则上不可见,但其实我们可以在 middleware/mcu_bootloader 里大概知道。

例程路径: \SDK_2_15_100_EVKB-IMXRT1050\boards\evkbimxrt1050\driver_examples\fsl_romapi

  该驱动的 API 比较有意思,既有面向 Flash 的写擦功能,也有偏 FlexSPI 外设 HAL 级别的接口。前者相比 flexspi 驱动配套的例程里对于 Flash 的支持就强大多了,用户完全可以仅靠 API 定义的简化参数来支持不同厂商/类型的 Flash;而后者存在的意义是为了让用户能够进一步设计面向 Flash 的功能函数。

status_t ROM_FLEXSPI_NorFlash_Init(uint32_t instance, flexspi_nor_config_t *config);
status_t ROM_FLEXSPI_NorFlash_ProgramPage(uint32_t instance, flexspi_nor_config_t *config, uint32_t dstAddr, const uint32_t *src);
status_t ROM_FLEXSPI_NorFlash_EraseSector(uint32_t instance, flexspi_nor_config_t *config, uint32_t address);
status_t ROM_FLEXSPI_NorFlash_CommandXfer(uint32_t instance, flexspi_xfer_t *xfer);
status_t ROM_FLEXSPI_NorFlash_UpdateLut(uint32_t instance, uint32_t seqIndex, const uint32_t *lutBase, uint32_t seqNumber);

  总结一下,使用 fsl_romapi 例程相比 fsl_flexspi 例程去操作 Flash,好处是省代码空间且不需要考虑 Read-While-Write 限制(仅对驱动本身执行而言,无需代码重定向,但是全局中断问题仍要考虑),坏处是源代码是个黑盒子,出问题不容易定位。

2.2 components

2.2.1 mx25r_flash

  mx25r_flash 组件其实是为 LPC54114 板卡上的旺宏宽电压四线 NOR Flash MX25R 系列而设计的,其在 \SDK_2_xxx_LPCXpresso54114\boards\lpcxpresso54114\driver_examples\spi\polling_flash 例程里有被调用,而在 i.MXRT 系列 SDK 里并没有相关例程使用它(不要疑问为啥会出现在软件包里,多就是好)。这个组件设计得挺有意思,其代码实现完全与芯片具体外设隔离,外设接口传输函数是通过 callback 形式传入的,充满了代码抽象(面向对象)的味道,有兴趣可以查看源码。

mx25r_err_t mx25r_init(struct mx25r_instance *instance, transfer_cb_t callback, void *callback_prv);
mx25r_err_t mx25r_cmd_read(struct mx25r_instance *instance, uint32_t address, uint8_t *buffer, uint32_t size);
mx25r_err_t mx25r_cmd_write(struct mx25r_instance *instance, uint32_t address_256_align, uint8_t *buffer, uint32_t size_256_max);
mx25r_err_t mx25r_cmd_sector_erase(struct mx25r_instance *instance, uint32_t address);
2.2.2 internal_flash

  internal_flash 组件从名字上看像是为片内 Flash 而设计的,但是 i.MXRT 系列并无片内 Flash(RT1024/1064 只是 SIP 了串行 NOR Flash,本质上还是片外)。大家不要被这个名字骗了,这个组件最早确实是用于恩智浦 Kinetis/LPC 系列片内 Flash 的,但是在 i.MX RT 上因为配套 EVK 上有支持 XIP 的外置 NOR Flash,所以这个组件也沿用给这些外置 NOR Flash 了,因此其是基于 flexspi 驱动的组件。

  在 \components\internal_flash\fsl_adapter_flash.h 文件里一共定义了 10 个 API 接口,其中如下 4 个是必须要实现的,其余 6 个可以不用实现(跟 Kinetis/LPC 片内 Flash 特性紧相关)。因为 RT1050-EVKB 默认连接的 hyperflash,所以该组件也仅为其做了相应实现 \components\internal_flash\hyper_flash。这个组件代码实现跟 flexspi 驱动配套例程里对于 Flash 的支持差不多。

hal_flash_status_t HAL_FlashInit(void);
hal_flash_status_t HAL_FlashProgram(uint32_t dest, uint32_t size, uint8_t *pData);
hal_flash_status_t HAL_FlashEraseSector(uint32_t dest, uint32_t size);
hal_flash_status_t HAL_FlashRead(uint32_t src, uint32_t size, uint8_t *pData);

  internal_flash 组件设计的意义在于 SDK 其它例程中如果有 IAP 操作或者存储运行参数需求,均可以调用这个统一接口来实现,当然客户应用有相应需求,也一样可以使用。

2.2.3 flash

  flash 组件里一共有三个: nornandmflash,咱们一个个来说:

2.2.3.1 nor

  先来介绍 nor 组件,从如下 API 命名来看,肯定是面向 NOR Flash 的读写擦功能,接口设计上对于底层外设采用了轻度抽象的方法,形参不涉及具体外设,但是函数实现里不同外设需要不同的实现,这也是为什么我们能看到 \nor\flexspi 和 \nor\lpspi 两个文件夹里的源代码。虽然底层外设不同,但是它们要操作的均是相同的串行 NOR Flash。

status_t Nor_Flash_Init(nor_config_t *config, nor_handle_t *handle);
status_t Nor_Flash_Read(nor_handle_t *handle, uint32_t address, uint8_t *buffer, uint32_t length);
status_t Nor_Flash_Page_Program(nor_handle_t *handle, uint32_t address, uint8_t *buffer);
status_t Nor_Flash_Erase_Sector(nor_handle_t *handle, uint32_t address);
status_t Nor_Flash_Is_Busy(nor_handle_t *handle, bool *isBusy);

  \nor\flexspi 里的代码实现跟 romapi 驱动实现有点像,其会从 Flash 里读取 SFDP 表进行解析从而自动获取所需操作命令,不依赖用户填充 LUT 命令。

例程路径: \SDK_2_15_000_EVKB-IMXRT1050\boards\evkbimxrt1050\component_examples\flash_component\flexspi_nor

  \nor\lpspi 里的代码实现则比较简单,因为 LPSPI 外设本身主要支持 1bit SPI 传输,所以其也仅实现了一线方式对 Flash 进行读写擦,这部分命令是通用的,也无需用户填充 LUT。

2.2.3.2 nand

  再来介绍 nand 组件,从如下 API 命名来看,肯定是面向 NAND Flash 的读写擦功能,接口设计上对于底层外设同样采用了轻度抽象的方法,形参不涉及具体外设,但是函数实现里不同外设需要不同的实现,这也是为什么我们能看到 \nand\flexspi 和 \nor\semc 两个文件夹里的源代码。不过 flexspi 外设和 semc 外设所支持的 NAND 不是一个产品,前者是串行 NAND,后者是并行 NAND,完全是两类不同的存储器标准。

  \nand\flexspi 里的代码实现则比较简洁,因为串行 NAND 发展不如串行 NOR 那样丰富多样,所以其使用了固定 LUT 里的预设命令序列,基本能够支持华邦等主流四线串行 NAND 产品。

status_t Nand_Flash_Init(nand_config_t *config, nand_handle_t *handle);
status_t Nand_Flash_Read_Page(nand_handle_t *handle, uint32_t pageIndex, uint8_t *buffer, uint32_t length);
status_t Nand_Flash_Page_Program(nand_handle_t *handle, uint32_t pageIndex, const uint8_t *src, uint32_t length);
status_t Nand_Flash_Erase_Block(nand_handle_t *handle, uint32_t blockIndex);
2.2.3.3 mflash

  最后要重点介绍 mflash 组件,其分为 drv 层和 file 层两种不同类型的 API,drv 层提供基于芯片外设的底层 Flash 操作(详见 \mflash\mimxrt1052 文件夹下代码),file 层则是基于 drv 层里的 API 而设计的轻量级静态文件系统,简单理解就是将 Flash 虚拟成一个由具有固定最大长度的预定义命名文件集组成的存储空间,我们可以将小数据以文件名索引的方式写入 Flash,适用于需要存储运行参数或者设备配置数据的场合。

bool mflash_is_initialized(void);
status_t mflash_init(const mflash_file_t *dir_template, bool init_drv);
status_t mflash_file_save(char *path, uint8_t *data, uint32_t size);
status_t mflash_file_mmap(char *path, uint8_t **pdata, uint32_t *psize); int32_t mflash_drv_init(void);
int32_t mflash_drv_sector_erase(uint32_t sector_addr);
int32_t mflash_drv_page_program(uint32_t page_addr, uint32_t *data);
int32_t mflash_drv_read(uint32_t addr, uint32_t *buffer, uint32_t len);
void *mflash_drv_phys2log(uint32_t addr, uint32_t len);
uint32_t mflash_drv_log2phys(void *ptr, uint32_t len);

  mflash 组件会在 middleware 以及 rtos 里被广泛使用,这个痞子衡将会在下篇里再具体介绍。

  至此,恩智浦i.MXRT官方SDK里关于串行Flash相关的驱动与例程资源痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

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

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

痞子衡嵌入式:浅聊恩智浦i.MXRT官方SDK里关于串行Flash相关的驱动与例程资源(上篇)的更多相关文章

  1. 痞子衡嵌入式:了解i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择. 关于 i.MXRT 系列 BootROM 中串行 NOR ...

  2. 痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道. ECC 是 "Error Correc ...

  3. 痞子衡嵌入式:对比恩智浦全系列MCU(包含Kinetis/LPC/i.MXRT/MCX)的GPIO电平中断设计差异

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦全系列MCU(包含Kinetis, LPC, i.MXRT, MCX)的GPIO电平中断设计差异. 在痞子衡旧文 <以i.M ...

  4. 痞子衡嵌入式:一种i.MXRT下从App中进入ROM串行下载模式的方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT下在App中利用ROM API进ISP/SDP模式的方法. 我们知道i.MXRT系列分为两大阵营:CM33内核的i.MXRT ...

  5. 痞子衡嵌入式:基于恩智浦i.MXRT1060的MP4视频播放器(RT-Mp4Player)设计

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是基于i.MXRT1062的MP4播放器参考设计. i.MXRT1062是恩智浦i.MXRT四位数系列的中端型号,外设搭配上很均衡,辅以6 ...

  6. 痞子衡嵌入式:分享一个i.MXRT系列配套DRAM压力测试上位机工具(i.MXRT DRAM Tester)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦SE团队制作的i.MXRT配套DRAM压力测试上位机工具. 事情源于痞子衡的技术交流群里的提问,有群友在恩智浦官方技术公众号 [恩 ...

  7. 痞子衡嵌入式:轻松为i.MXRT设计更新Segger J-Link Flash下载算法文件

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是为i.MXRT设计更新Segger J-Link Flash下载算法文件. 想要在Flash中调试,基本是离不开Flash下载算法的,毕 ...

  8. 痞子衡嵌入式:基于恩智浦i.MXRT1010的MP3音乐播放器(RT-Mp3Player)设计

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是基于i.MXRT1011的MP3播放器参考设计. i.MXRT1011是恩智浦i.MXRT四位数系列的入门型号,虽然是入门级,可也是50 ...

  9. 痞子衡嵌入式:关于恩智浦入驻B站的一些思考

    故事起源于这周五的一封公司邮件,标题是"恩智浦B站首支原创视频播放量破万",公司Marcom部门特地群发了这个邮件给全体员工,并鼓励大家积极DIY工作相关的有趣视频,为公司这个萌新 ...

  10. 痞子衡嵌入式:对比MbedTLS算法库纯软件实现与i.MXRT上DCP,CAAM硬件加速器实现性能差异

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MbedTLS算法库纯软件实现与i.MXRT上DCP,CAAM硬件加速器实现性能差异. 近期有 i.MXRT 客户在集成 OTA SBL ...

随机推荐

  1. 使用.NET查询日出日落时间

    在WPF中,通过资源文件实现主题切换是个常见的功能,有不少文章介绍了如何实现手动切换主题.那如何实现自动切换主题呢?通常有两种机制:一是跟随系统明暗主题切换,二是像手机操作系统那样根据日出日落时间自动 ...

  2. Nifi:Nifi中的Controller Service

    Service简介 首先Nifi中的Controller Service 和我们MVC概念中的Controller Service不是一个概念,Nifi中的Controller Service更像是和 ...

  3. 使用 Spacesniffer 找回 48G 系统存储空间的总结

    前言 Spacesniffer 是一个免费的文件扫描工具,通过使用树状图可视化布局,可以立即了解大文件夹的位置,帮助用户处理找到这些文件夹 当前系统C盘空间 清理后系统C盘空间 下载 Spacesni ...

  4. Django 的 ORM

    Django 的 ORM: 注意: 需要提前创建好数据库,Django不会自动创建数据库

  5. 在kubernetes里使用seccomp限制容器的系统调用

    目录 一.系统环境 二.前言 三.系统调用简介 四.使用seccomp限制docker容器系统调用 五.在kubernetes里使用seccomp限制容器的系统调用 5.1 配置seccomp允许po ...

  6. 利用 Helm 在各类 Kubernetes 中安装 Rainbond

    利用 Helm 安装 Rainbond 好雨科技技术团队一直致力于让用户更方便的安装 Rainbond 这款产品. 不久前,我们刚刚推出了在一个容器中部署 Rainbond 的快速安装方式,这种方式覆 ...

  7. idea mapper xml 文件报红

    在使用 idea 打开 mapper 文件,出现一下报红错误: 可以看到数据表和字段都是红色的. 解决方案 打开设置,window版本是打开Settings: 找到 Languages & F ...

  8. JavaScript语法形式2 内部式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. jquery浏览器的上卷高度 节点的创建和写入 节点的删除

    // js 的兼容语法         // let scrollT = document.documentElement.scrollTop || document.body.scrollTop; ...

  10. Vue第三方库与插件实战手册

    title: Vue第三方库与插件实战手册 date: 2024/6/8 updated: 2024/6/8 excerpt: 这篇文章介绍了如何在Vue框架中实现数据的高效验证与处理,以及如何集成E ...