i.MXRT下FlexSPI driver实现Flash编程时对于中断支持问题。
Note: 客户测试的 SDK 版本为 2.12.1,对应的 FlexSPI driver 版本为 2.3.6
一、为什么擦写Flash时经常需要关全局中断
在具体分析客户问题之前,我们先来聊聊嵌入式应用里应对 NOR Flash 的擦写为何大部分情况下都是要关闭全局中断(这里假设执行代码空间与擦写操作空间在同一个 Flash 上,当然是在不同区域),这其实跟如下两个特性有关:
1.1 RWW特性(Read-While-Write)
现在你应该知道对于不支持 RWW 的 Flash 为什么擦写时需要关闭全局中断了,因为无法保证中断响应相关代码全都重定向到 RAM 里了,所以干脆在 Flash 擦写期间不响应任何中断。
1.2 SCLK Stop特性
绝大部分 Flash 是不支持 SCLK Stop 特性的,因此在 MCU 端如果传输 Page 数据,需要一次性连续传输完成,一旦中途被打断,则两次不连续的 Page 数据传输可能无法得到想要的 Page 写入结果。这也是为何 Flash 写入期间我们需要关闭中断。
二、FlexSPI外设写操作设计
《FlexSPI支持在Flash XIP原理》、《FlexSPI支持AHB方式写入Flash》,大家先读一下有个初步了解。这里痞子衡想重点说一下 FlexSPI 关于 IPG 方式写操作的设计,下图为 FlexSPI 外设的模块框图,痞子衡用绿色线标出了 IPG 方式写入的通路,这里大家可以看出其中 IP_TX_FIFO 模块起了重要的数据缓冲作用,驱动里往 FLEXSPI->TFDRx 寄存器写入的 Page 数据会先被装载进 IP_TX_FIFO 里,然后再传输出去。
型号 | 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写操作流程
我们直接打开 fsl_flexspi.c 驱动文件,找到跟写操作相关的 FLEXSPI_TransferBlocking( 函数,在函数实现里可以发现,启动写传输时序的控制位 FLEXSPI->IPCMD[TRG] 是在 IP_TX_FIFO 填充动作 FLEXSPI_WriteBlocking( 函数之前被开启的,那这样的实现确实是不能够很好地支持中断的。
四、如何改进FlexSPI driver支持中断
当然下面代码只是一个 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主页、知乎主页、微信公众号 平台上。
痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。