首页 > 其他分享 >痞子衡嵌入式:浅聊恩智浦i.MXRT官方SDK里关于串行Flash相关的驱动与例程资源(上篇)

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

时间:2024-07-07 23:19:59浏览次数:22  
标签:status flexspi flash 恩智浦 浅聊 例程 Flash uint32 nor


  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦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主页知乎主页微信公众号 平台上。

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

标签:status,flexspi,flash,恩智浦,浅聊,例程,Flash,uint32,nor
From: https://www.cnblogs.com/henjay724/p/18289104

相关文章

  • EKF+UKF+CKF+PF的效果对比|三维非线性滤波|MATLAB例程
    前言标题里的EKF、UKF、CKF、PF分别为:扩展卡尔曼滤波、无迹卡尔曼滤波、容积卡尔曼滤波、粒子滤波。EKF是扩展卡尔曼滤波,计算快,最常用于非线性状态方程或观测方程下的卡尔曼滤波。但是EKF应对强非线性的系统时,估计效果不如UKF。UKF是无迹卡尔曼滤波/无味卡尔曼滤波,使用U......
  • 【STM32F1例程10】UCOSII系统实验
      那么这个实验,从项目的工程结构来看,其实稍微稍微有一丢丢,有一丢丢比之前几个实验复杂,但是还是老话,既然能读到这篇文章,证明能力还是得到认可的。实验简介  那么在STM32上进行uC/OS-II系统实验是一种常见的实践,可以帮助大家了解和应用实时操作系统(RTOS)在嵌入式系统开......
  • 【《视觉十四讲》例程运行记录】——运行ch9后端优化CeresBA和g2o求解BA的实践例程
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录一、运行ch9的例程代码1.MeshLab安装2.编译例程代码前的修改3.编译例程二可能的报错:c++:internalcompilererror:已杀死(programcclplus)1.问题描述2.原因分析3.解决总结一、运行ch9......
  • NRF52840DK PCA10056 BLE Mesh Light例程记录
    1.创建项目在打开的VSCode窗口,打开nRFConnect选项卡,"Createanewapplication" 选择"Copyasample" 输入"light", 选择"BluetoothMeshlight". 选择copy后,保存的路径。 键盘"Enter"一下。 点击"AddBuildConfiguration&qu......
  • 【STM32F1例程2】GPIO外部中断输入
    1.实验说明无需连外部杜邦线,下载程序,全速运行,按右边按键看到LEDD1(PB4引脚驱动)亮暗能变化一次2.主要代码先上main.c#include"delay.h"#include"sys.h"//外部中断0配置,PA0脚产生外部中断是外部中断0voidEXTI0_Config(void){ EXTI_InitTypeDefEXTI_InitStructur......
  • 【STM32F1例程3】ADC实验
    1.实验说明 PA4口作为ADC采集口,PA4口接地或者接3.3V。下载运行程序,PA4口接地,会发现VolDta值为0,然后把PA4口接3.3V,会发现VolDta值为33002.主要程序直接上main.c#include"delay.h"#include"sys.h"//ADC配置,ADC1通道4voidADC_Config_Init(void){ ADC_InitTypeDef......
  • 《DX12龙书》-第一个例程出现的报错:error: 应用程序请求的操作依赖于已缺失或不匹配的
    《DX12龙书》|《Introductionto3DGameProgrammingwithDirectX12》|《DirectX123D游戏开发实践》个人电脑环境Window11;VisualStudio2022出现问题主要原因:书中代码的环境是:Windows10;VS2015,在不同环境上运行难免会出现一些错误。问题一:C2102&要求左值错......
  • Python-使用OpenCV(二)_第一个示例程序
    1、创建项目2、创建代码importcv2#加载图片image=cv2.imread("C:\\Users\\Administrator\\Pictures\\Screenshots\\20240311220733.png")#显示图片cv2.imshow("Image",image)#等待任意键被敲击cv2.waitKey(0)#关闭所有窗口cv2.destroyAllWindows()3、结......
  • HDevelop示例程序-optical_flow.hdev
    应用范围:安全系统提示:这里可以添加系列文章的所有文章的目录coherence_enhancing_diff.hdevoptical_flow.hdevoptical_flow_bicycle.hdevoptical_flow_hydraulic_engineering.hdevxing.hdev提示:文章目录文章目录应用范围:安全系统前言一、原示例程序二、程序解......
  • 嵌入式实时操作系统笔记3:FreeRTOS移植(STM32F407)_编写简单的FreeRTOS任务例程
    上文讲到UC/OSIII系统的移植,那篇文章是失败了的,网络上的资料真是层次不清,多有遗漏步骤,导致单片机连操作系统的初始化都卡在那,这次换个赛道,学FreeRTOS吧......今日任务如标题所示:FreeRTOS移植(STM32F407)_编写简单的FreeRTOS任务例程文章提供测试代码讲解、完整工程下载、测......