大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT下FlexSPI driver实现Flash编程时对于中断支持问题

  前段时间有客户在官方社区反映 i.MXRT1170 下使用官方 SDK 里 FlexSPI 驱动去擦写 Flash 时不能很好地支持全局中断。客户项目里用了两块 NOR Flash,分别挂在不同的 FlexSPI 上,一块 Flash 用于存储 XIP 代码(FlexSPI1),另一块 Flash 用于存储项目资源数据(FlexSPI2),显然这样的设计原理上是没有问题的,那为什么使能了中断会出问题呢?今天痞子衡来分析下这个问题:

  • Note: 客户测试的 SDK 版本为 2.12.1,对应的 FlexSPI driver 版本为 2.3.6

一、为什么擦写Flash时经常需要关全局中断?

  在具体分析客户问题之前,我们先来聊聊嵌入式应用里应对 NOR Flash 的擦写为何大部分情况下都是要关闭全局中断(这里假设执行代码空间与擦写操作空间在同一个 Flash 上,当然是在不同区域),这其实跟如下两个特性有关:

1.1 RWW特性(Read-While-Write)

  RWW 特性的意思是在 Flash 执行擦写命令进入 Busy 状态期间(Flash 内部状态寄存器 WIP 位变状态 1)还能否继续响应非操作区域的读访问。如果 SR[WIP] = 1 时还能够支持读访问,则该 Flash 支持 RWW,反之则不支持 RWW。

  绝大部分 Flash 都是不支持 RWW 特性的,这就是为什么 Flash 擦写操作代码本身是需要重定向到 RAM 里去执行(尤其是回读 SR[WIP] 状态的代码)。对于支持 RWW 特性的 Flash,一般是以 Block 为单位,Flash 擦写操作代码放在 BlockX 里执行,则可以操作 BlockX 以外的其它 Block 区域,且不需要做代码重定向。

  现在你应该知道对于不支持 RWW 的 Flash 为什么擦写时需要关闭全局中断了,因为无法保证中断响应相关代码全都重定向到 RAM 里了,所以干脆在 Flash 擦写期间不响应任何中断。

1.2 SCLK Stop特性

  SCLK Stop 特性的意思是在 Flash 执行写入命令接受主设备传输过来的 Page 数据期间,如果总线上 SCLK 停止(一般情况是 FlexSPI 这一端的 TXFIFO 为空或者触发空条件),则 Flash 能否也暂停接受当前 Page 数据直到 SCLK 继续输出从而继续处理剩下的 Page 数据。

  绝大部分 Flash 是不支持 SCLK Stop 特性的,因此在 MCU 端如果传输 Page 数据,需要一次性连续传输完成,一旦中途被打断,则两次不连续的 Page 数据传输可能无法得到想要的 Page 写入结果。这也是为何 Flash 写入期间我们需要关闭中断。

二、FlexSPI外设写操作设计

  关于 i.MXRT 上的 FlexSPI 外设基本情况,痞子衡有两篇旧文 《FlexSPI支持在Flash XIP原理》《FlexSPI支持AHB方式写入Flash》,大家先读一下有个初步了解。这里痞子衡想重点说一下 FlexSPI 关于 IPG 方式写操作的设计,下图为 FlexSPI 外设的模块框图,痞子衡用绿色线标出了 IPG 方式写入的通路,这里大家可以看出其中 IP_TX_FIFO 模块起了重要的数据缓冲作用,驱动里往 FLEXSPI->TFDRx 寄存器写入的 Page 数据会先被装载进 IP_TX_FIFO 里,然后再传输出去。

  不同 i.MXRT 型号上 IP_TX_FIFO 大小不一样,目前有三种大小: 128/256/1024 Bytes。对于 QuadSPI/OctalSPI NOR Flash 来说,Page 大小一般是 256 Bytes;对于 HyperBus Flash,Page 大小一般是 512 Bytes。所以在 i.MXRT10xx 上 IP_TX_FIFO 是不足以缓冲整个 Page 的,i.MXRT117x 上可以缓冲 QuadSPI/OctalSPI NOR 类型的 Page,i.MXRT118x/5xx/6xx 上则可以缓冲全部 NOR Flash 类型的 Page。对于 Page 数据不能全部缓冲的情况,则需要一边传输一边缓冲。

型号 FlexSPI外设 IP TX FIFO大小
i.MXRT118x 2 x dual-channel /16-bit 1024 Bytes
i.MXRT117x

i.MXRT116x
1 x dual-channel /8-bit

1 x dual-channel /16-bit
256 Bytes
i.MXRT106x

i.MXRT1042
2 x dual-channel /8-bit 128 Bytes
i.MXRT105x 1 x dual-channel /8-bit 128 Bytes
i.MXRT1024 2 x dual-channel /8-bit 128 Bytes
i.MXRT1021

i.MXRT1015
1 x dual-channel /8-bit 128 Bytes
i.MXRT1011 1 x dual-channel /8-bit 128 Bytes
i.MXRT6xx 1 x dual-channel /8-bit 1024 Bytes
i.MXRT5xx 2 x dual-channel /8-bit 1024 Bytes

  在具体装载数据进 IP_TX_FIFO 时,主要涉及如下三个 FLEXSPI 寄存器,IP_TX_FIFO 一次只能被填入 watermark level 大小的数据,想要把全部 Page 数据填进 IP_TX_FIFO,需要分多次装载。只要 FLEXSPI->INTR[IPTXWE] 标志为 0, 即代表 IP_TX_FIFO 剩余空间大于等于 watermark level,那么就可以继续装载。

FLEXSPI->IPTXFCR[TXWMRK]  -- 设置一次装载进 IP_TX_FIFO 的数据长度(即 watermark level),8 Bytes为单位
FLEXSPI->TFDRx -- 按 watermark level 长度填入 IP_TX_FIFO 装载数据
FLEXSPI->INTR[IPTXWE] -- 触发 IP_TX_FIFO 的一次装载

三、客户问题及FlexSPI driver写操作流程

  前面铺垫了这么多,终于来到客户遇到的 FlexSPI 驱动对于中断不支持的问题了。因为客户使用了两片 Flash,所以不存在 RWW 限制问题,那剩下的原因就跟 SCLK Stop 特性有关,即 IP_TX_FIFO 并没有缓冲全部的 Page,导致 Page 传输过程被中断打断了,然后 IP_TX_FIFO 因为缓冲数据全部发完而使 FlexSPI 模块进入了 SCLK Stop 状态。

  我们直接打开 fsl_flexspi.c 驱动文件,找到跟写操作相关的 FLEXSPI_TransferBlocking() 函数,在函数实现里可以发现,启动写传输时序的控制位 FLEXSPI->IPCMD[TRG] 是在 IP_TX_FIFO 填充动作 FLEXSPI_WriteBlocking() 函数之前被开启的,那这样的实现确实是不能够很好地支持中断的。

四、如何改进FlexSPI driver支持中断?

  知道了原因所在,改起来也很简单。如果是 QuadSPI/OctalSPI NOR Flash 类型(Page=256 Bytes),在 i.MXRT117x 上,其 IP_TX_FIFO 大小为 256 Bytes,能够缓冲全部的 Page 大小,则可以先调用 FLEXSPI_WriteBlocking() 装载全部的 Page 数据,然后再开启 FLEXSPI->IPCMD[TRG] 去触发写传输时序,这时候就不怕被中断打断了,如下代码所示。

  当然下面代码只是一个 workaround 式的实现示例,不是一个完整的解决方案,毕竟 FlexSPI 驱动要适配全部 i.MXRT 型号以及全部类型的 NOR Flash,此外还适用 NAND 型 Flash(Page 一般是 2KB),这时候需要根据情况拆分调用多次 FLEXSPI_WriteBlocking() 函数(不管怎样要保证启动写传输时序前,把 IP_TX_FIFO 先装满)。

status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer)
{
// 代码略去 /* Start Transfer. */
if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config))
{
result = FLEXSPI_WriteBlocking(base, xfer->data, xfer->dataSize);
base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
}
else if (xfer->cmdType == kFLEXSPI_Read)
{
base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
result = FLEXSPI_ReadBlocking(base, xfer->data, xfer->dataSize);
}
else
{
base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK;
} // 代码略去
}

  至此,i.MXRT下FlexSPI driver实现Flash编程时对于中断支持问题痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

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

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

痞子衡嵌入式:探讨i.MXRT下FlexSPI driver实现Flash编程时对于中断支持问题的更多相关文章

  1. 痞子衡嵌入式:i.MXRT中FlexSPI外设对AHB Burst Read特性的支持

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是FlexSPI外设对AHB Burst Read特性的支持. 痞子衡之前写过一篇关于FlexSPI LUT的文章 <从头开始认识i ...

  2. 痞子衡嵌入式:i.MXRT中FlexSPI外设不常用的读选通采样时钟源 - loopbackFromSckPad

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT中FlexSPI外设不常用的读选通采样时钟源 - loopbackFromSckPad. 最近碰到一个客户,他们在 i.MX ...

  3. 痞子衡嵌入式:i.MXRT全系列下FlexSPI外设AHB Master ID定义与AHB RX Buffer指定的异同

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT全系列下FlexSPI外设AHB Master ID定义与AHB RX Buffer指定的异同. 因为 i.MXRT 全系列 ...

  4. 痞子衡嵌入式:i.MXRT连接特殊Octal Flash时(OPI DTR模式下反转字节序)下载与启动注意事项(以MX25UM51245为例)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是OPI DTR模式下反转字节序的Octal Flash在i.MXRT下载与启动注意事项. 在恩智浦官方参考设计板 MIMXRT595-E ...

  5. 痞子衡嵌入式:i.MXRT中不支持DQS的FlexSPI引脚组连接Flash下载与启动注意事项

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT中不支持DQS的FlexSPI引脚组连接Flash下载与启动注意事项. 最近痞子衡在支持一个印度客户,这个客户项目主芯片选择 ...

  6. 痞子衡嵌入式:MCUXpresso IDE下在线调试时使用不同复位策略的现象总结

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是MCUXpresso IDE下在线调试时使用不同复位策略的现象总结. 本篇实际上是<IAR在线调试时设不同复位类型可能会导致i.M ...

  7. 痞子衡嵌入式:MCUXpresso IDE下使用J-Link下载算法在Flash调试注意事项(i.MXRT500为例)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下使用J-Link下载算法在Flash调试注意事项. 痞子衡前段时间写过一篇小文<为i.MXRT设计更 ...

  8. 痞子衡嵌入式:MCUXpresso IDE下将应用程序RW段分散链接的几种方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下将应用程序RW段分散链接的几种方法. 早期的 MCU 芯片,一般都会嵌入内部 Flash 和 RAM,并且 ...

  9. 痞子衡嵌入式:MCUXpresso IDE下添加C++源文件进SDK工程编译的方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下添加C++源文件进SDK工程编译的方法. 最近有客户反映在MCUXpresso IDE下的SDK工程里添加 ...

  10. 痞子衡嵌入式:MCUXpresso IDE下SDK工程导入与workspace管理机制

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下SDK工程导入与workspace管理机制. MCUXpresso IDE是恩智浦软件团队倾注很大心血研发 ...

随机推荐

  1. JavaFx 使用字体图标记录

    原文:JavaFx 使用字体图标记录 - Stars-One的杂货小窝 之前其实也是研究过关于字体图标的使用,还整了个库Tornadofx学习笔记(4)--IconTextFx开源库,整合5000+个 ...

  2. 快速上手Mybatis项目

    快速上手Mybatis项目 思路流程:搭建环境-->导入Mybatis--->编写代码--->测试 1.搭建实验数据库 CREATE DATABASE `mybatis`; USE ...

  3. 在js中正则表达式验证小时分钟,将输入的字符串转换为对应的小时和分钟

    文章目录 1.预备知识 2.在js中的代码片段 3.测试结果 1.预备知识 splict()方法 Date()的相关方法 setHours()的用法 2.在js中的代码片段 //验证小时和分钟 var ...

  4. 二十一、Pod的存储之Secret

    Pod 的存储之Secret 一.Secret 存在意义 ​Secret 解决了密码.token.密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中.Secret 可以 ...

  5. JVM学习笔记——垃圾回收篇

    JVM学习笔记--垃圾回收篇 在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的垃圾回收部分 我们会分为以下几部分进行介绍: 判断垃圾回收对象 垃圾回收算法 分代垃圾回收 垃圾回收器 ...

  6. 解决 net core 3.x 跨域问题

    跨域:指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制. 以下几种情况是造成跨域的原因: 域名相同,端口不同 域名相同,协议不同(即,一个 ...

  7. 通过jmeter,造50个单位的并发用户数据(用户从上至下每50个单位依次排序)

    单位数据:loginfoll.csv         #50个单位的信息(agencyCode,passwd,agencyname,rgcode) 用户数据:50个单位,每个单位200个用户(用户名为 ...

  8. Java8中那些方便又实用的Map函数

    原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介 java8之后,常用的Map接口中添加了一些非常实用的函数,可以大大简化一些特定场景的代码编写,提升代码可读性,一 ...

  9. 【云原生 · Kubernetes】部署kube-apiserver集群

    个人名片: 因为云计算成为了监控工程师‍ 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying 部署kube-apiserver集群 10.1 创建kube-apiserver 证书 10 ...

  10. C温故补缺(五):main函数的参数

    main()的参数 main()函数的参数,用于在外部执行时传入参数,类似windows的bat脚本或linux的sh脚本.在bat脚本中传入参数,用%接收.sh脚本的参数用$接收. c语言编译成可执 ...