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

科技资讯 投稿 16700 0 评论

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


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主页、知乎主页、微信公众号 平台上。

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

编程笔记 » 痞子衡嵌入式:探讨i.MXRT下FlexSPI driver实现Flash编程时对于中断支持问题

赞同 (58) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽