痞子衡嵌入式:浅聊恩智浦i.MXRT官方SDK里关于串行Flash相关的驱动与例程资源(上篇)
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦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 组件里一共有三个: nor、nand、mflash,咱们一个个来说:
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相关的驱动与例程资源(上篇)的更多相关文章
- 痞子衡嵌入式:了解i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRTxxx系列ROM中灵活的串行NOR Flash启动硬复位引脚选择. 关于 i.MXRT 系列 BootROM 中串行 NOR ...
- 痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道. ECC 是 "Error Correc ...
- 痞子衡嵌入式:对比恩智浦全系列MCU(包含Kinetis/LPC/i.MXRT/MCX)的GPIO电平中断设计差异
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦全系列MCU(包含Kinetis, LPC, i.MXRT, MCX)的GPIO电平中断设计差异. 在痞子衡旧文 <以i.M ...
- 痞子衡嵌入式:一种i.MXRT下从App中进入ROM串行下载模式的方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT下在App中利用ROM API进ISP/SDP模式的方法. 我们知道i.MXRT系列分为两大阵营:CM33内核的i.MXRT ...
- 痞子衡嵌入式:基于恩智浦i.MXRT1060的MP4视频播放器(RT-Mp4Player)设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是基于i.MXRT1062的MP4播放器参考设计. i.MXRT1062是恩智浦i.MXRT四位数系列的中端型号,外设搭配上很均衡,辅以6 ...
- 痞子衡嵌入式:分享一个i.MXRT系列配套DRAM压力测试上位机工具(i.MXRT DRAM Tester)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦SE团队制作的i.MXRT配套DRAM压力测试上位机工具. 事情源于痞子衡的技术交流群里的提问,有群友在恩智浦官方技术公众号 [恩 ...
- 痞子衡嵌入式:轻松为i.MXRT设计更新Segger J-Link Flash下载算法文件
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是为i.MXRT设计更新Segger J-Link Flash下载算法文件. 想要在Flash中调试,基本是离不开Flash下载算法的,毕 ...
- 痞子衡嵌入式:基于恩智浦i.MXRT1010的MP3音乐播放器(RT-Mp3Player)设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是基于i.MXRT1011的MP3播放器参考设计. i.MXRT1011是恩智浦i.MXRT四位数系列的入门型号,虽然是入门级,可也是50 ...
- 痞子衡嵌入式:关于恩智浦入驻B站的一些思考
故事起源于这周五的一封公司邮件,标题是"恩智浦B站首支原创视频播放量破万",公司Marcom部门特地群发了这个邮件给全体员工,并鼓励大家积极DIY工作相关的有趣视频,为公司这个萌新 ...
- 痞子衡嵌入式:对比MbedTLS算法库纯软件实现与i.MXRT上DCP,CAAM硬件加速器实现性能差异
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MbedTLS算法库纯软件实现与i.MXRT上DCP,CAAM硬件加速器实现性能差异. 近期有 i.MXRT 客户在集成 OTA SBL ...
随机推荐
- mac本地搭建ollama
mac本地搭建ollama webUI *简介:ollama-webUI是一个开源项目,简化了安装部署过程,并能直接管理各种大型语言模型(LLM).本文将介绍如何在你的macOS上安装Ollama服务 ...
- 2D空间中比较两三角形相交与包含
在处理UV重叠.CPU的ZFighting检测时会遇到2D空间中的三角形相交问题, 网上普遍是3D空间的相交解法,因此写本文研究下,不过虽然实现了需求, 但用的方法比较暴力. 效果如图: (鼠标拖动区 ...
- 用 C 语言开发一门编程语言 — 交互式解释器
目录 文章目录 目录 前言 环境 编译型 vs 解释型 实现交互式解释器 使用 GNU Readline 函数库 前言 通过开发一门类 Lisp 的编程语言来理解编程语言的设计思想,本实践来自著名的& ...
- 5款.NET开源、免费、功能强大的图表库
LiveCharts2 LiveCharts2是一个.NET开源(MIT License).简单.灵活.交互式且功能强大的.NET图表.地图和仪表,现在几乎可以在任何地方运行如:Maui.Uno Pl ...
- Python作图三维等高面
技术背景 对于等高线,大家都是比较熟悉的,因为日常生活中遇到的山体和水面,都可以用一系列的等高线描绘出来.而等高面,顾名思义,就是在三维空间"高度一致"的曲面.当然了,在二维平面上 ...
- 一文搞懂docker容器基础:docker镜像管理,docker容器管理
目录 一.系统环境 二.docker 2.1 Docker 概述 2.2 Docker 平台 2.3 我可以使用 Docker 做什么? 2.3.1 快速.一致地交付您的应用程序 2.3.2 响应式部 ...
- linux下date命令设置时间的输出格式和修改时间
目录 一.关于linux下的时间 二.linux下使用date命令设置时间的输出格式 三.修改linux时间 3.1 在可以访问Internet情况下修改时间 3.2 在无法访问Internet情况下 ...
- navicat premium 15 下载和激活
Navicat Premium 15 下载地址 链接:https://pan.baidu.com/s/1bL-M3-hkEa4M-547giVjYQ?pwd=1107 推荐安装参考地址:https:/ ...
- LlamaFS自组织文件管理器
LlamaFS是一个自组织文件管理器.它可以基于文件内容和修改时间等属性自动重命名和组织您的文件.它能让你不把时间花在对文件的复制.粘贴.重命名.拷贝.排序等简单操作上.有幸在Github上看到Lla ...
- 使用C#开发微信公众号对接ChatGPT和DALL-E
本人是一家小公司的技术总监,工作包括写市场分析.工作汇报.产品推广文案及代码开发等.在ChatGPT推出之后本人一直在工作中使用,在头脑风暴.大纲生成.语句优化.代码生成方面很有效果.但ChatGPT ...