0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

I.MXRT FreeRTOS环境下擦写外部Flash

li1756686189 来源:嵌入式 MCU 2023-01-30 09:18 次阅读

FreeRTOS环境下,如果外部擦写 Flash,禁用指令缓存以避免在多个任务中使用来自Flash 的分支预测和应用程序同步操作 Flash的缓存预加载指令。因为代码是XIP,所以向量表也在Flash 中。所以,当发生中断时,内核将读取此中断向量表。如果同时,Flash闪存被编程写入,读取操作将失败。用户通过禁用中断来保护关键代码,以避免这种情况。

使用 "taskENTER/EXIT_CRITICAL()" 函数,最后它会调用如下图这个函数vPortRaiseBASEPRI。该函数只能禁用优先级低于configMAX_SYSCALL_INTERRUPT_priority的中断,这可以确保系统仍然可以工作。因此,需要检查所有其他外设中断的优先级,比如LCDIPv2_IRQn,LPUART,LPSPI 等等。要确保优先级低于configMAX_SYSCALL_INTERRUPT_priority,或将configMAX_SYSCALL_INTERROPT_priority配置为更高的优先级。

afeaf3aa-a028-11ed-bfe3-dac502259ad0.png

不需要逐一禁用所有IRQ。因此,如果使用上述方式还有问题,请尝试如下API

__set_PRIMASK(1);//关闭总中断

//擦,写,读 Flash//

__set_PRIMASK(0);//开启总中断

参考示例代码:

/* FreeRTOS kernel includes. */

#include "FreeRTOS.h"

#include "task.h"

#include "queue.h"

#include "timers.h"

/* Freescale includes. */

#include "fsl_device_registers.h"

#include "fsl_debug_console.h"

#include "fsl_flexspi.h"

#include "pin_mux.h"

#include "clock_config.h"

#include "board.h"

#include "app.h"

#include "fsl_common.h"

/* Task priorities. */

#define hello_task_PRIORITY (configMAX_PRIORITIES - 2)

#define flash_operation_task_PRIORITY (configMAX_PRIORITIES - 1)

static void hello_task(void *pvParameters);

static void flash_operation_task(void *pvParameters);

status_t flexspi_nor_flash_read_sector(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, size_t leng);

extern status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);

extern status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src);

extern status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId);

extern status_t flexspi_nor_enable_quad_mode(FLEXSPI_Type *base);

extern void flexspi_nor_flash_init(FLEXSPI_Type *base);

extern void flexspi_clear_buffer(FLEXSPI_Type *base);

flexspi_device_config_t deviceconfig = {

.flexspiRootClk = 12000000,

.flashSize = FLASH_SIZE,

.CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle,

.CSInterval = 2,

.CSHoldTime = 3,

.CSSetupTime = 3,

.dataValidTime = 0,

.columnspace = 0,

.enableWordAddress = 0,

.AWRSeqIndex = 0,

.AWRSeqNumber = 0,

.ARDSeqIndex = NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD,

.ARDSeqNumber = 1,

.AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle,

.AHBWriteWaitInterval = 0,

};

constuint32_tcustomLUT[CUSTOM_LUT_LENGTH]={

/* Normal read mode -SDR */

[4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x03, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

[4 * NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 1] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

/* Fast read mode - SDR */

[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0B, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST + 1] = FLEXSPI_LUT_SEQ(

kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_1PAD, 0x08, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

/* Fast read quad mode - SDR */

[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xEB, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x18),

[4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD + 1] = FLEXSPI_LUT_SEQ(

kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD, 0x06, kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x04),

/* Read extend parameters */

[4 * NOR_CMD_LUT_SEQ_IDX_READSTATUS] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x81, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

/* Write Enable */

[4 * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x06, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

/* Erase Sector */

[4 * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xD7, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

/* Page Program - single mode */

[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x02, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_SINGLE + 1] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

/* Page Program - quad mode */

[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),

[4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD + 1] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

/* Read ID */

[4 * NOR_CMD_LUT_SEQ_IDX_READID] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x9F, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

/* Enable Quad mode */

[4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04),

/* Enter QPI mode */

[4 * NOR_CMD_LUT_SEQ_IDX_ENTERQPI] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x35, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

/* Exit QPI mode */

[4 * NOR_CMD_LUT_SEQ_IDX_EXITQPI] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_4PAD, 0xF5, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

/* Read status register */

[4 * NOR_CMD_LUT_SEQ_IDX_READSTATUSREG] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x05, kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),

/* Erase whole chip */

[4 * NOR_CMD_LUT_SEQ_IDX_ERASECHIP] =

FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0xC7, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),

};

int main(void)

{

/* Init board hardware. */

BOARD_ConfigMPU();

BOARD_InitPins();

BOARD_BootClockRUN();

BOARD_InitDebugConsole();

PRINTF("Flash Operation on FreeRTOS in XIP Mode! ");

if (xTaskCreate(hello_task, "Hello_task", configMINIMAL_STACK_SIZE + 100, NULL, hello_task_PRIORITY, NULL) !=

pdPASS)

{

PRINTF("Task creation failed!. ");

while (1)

;

}

if (xTaskCreate(flash_operation_task, "flash_operation_task", configMINIMAL_STACK_SIZE + 800, NULL,

flash_operation_task_PRIORITY, NULL) != pdPASS)

{

PRINTF("Task creation failed!. ");

while (1)

;

}

vTaskStartScheduler();

for (;;)

;

}

static void hello_task(void *pvParameters)

{

for (;;)

{

PRINTF("Hello world. ");

/* delay 2s */

vTaskDelay(2 * configTICK_RATE_HZ);

}

}

static void flash_operation_task(void *pvParameters)

{

status_t status;

uint8_t vendorID = 0;

/*Programe Buffer must be 4 and 4's multiplier bytes alignment */

uint8_t *nor_program_buffer = pvPortMalloc(256);

if (NULL == nor_program_buffer)

{

PRINTF("nor_program_buffer memory allocation failed! ");

configASSERT(NULL);

}

uint8_t *nor_read_buffer = pvPortMalloc(256);

if (NULL == nor_read_buffer)

{

PRINTF("nor_read_buffer memory allocation failed! ");

configASSERT(NULL);

}

taskENTER_CRITICAL();

flexspi_nor_flash_init(EXAMPLE_FLEXSPI);

taskEXIT_CRITICAL();

/* Get vendor ID. */

status = flexspi_nor_get_vendor_id(EXAMPLE_FLEXSPI, &vendorID);

if (status != kStatus_Success)

{

PRINTF("Get Vendor ID Failure!");

configASSERT(NULL);

}

PRINTF("Flash Vendor ID: 0x%x ", vendorID);

/* Disable I cache to avoid cache pre-fatch instruction with branch prediction from flash and application operate flash synchronously in multi-tasks. */

#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)

volatile bool ICacheEnableFlag = false;

/* Disable I cache. */

if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR))

{

SCB_DisableICache();

ICacheEnableFlag = true;

}

#endif /* __ICACHE_PRESENT */

/* Enter quad mode. */

taskENTER_CRITICAL();

status = flexspi_nor_enable_quad_mode(EXAMPLE_FLEXSPI);

taskEXIT_CRITICAL();

#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)

if (ICacheEnableFlag)

{

/* Enable I cache. */

SCB_EnableICache();

ICacheEnableFlag = false;

}

#endif /* __ICACHE_PRESENT */

if (status != kStatus_Success)

{

configASSERT(NULL);

}

/* Erase sectors. */

PRINTF("Erasing Serial NOR over FlexSPI... ");

/* Disable I cache to avoid cache pre-fatch instruction with branch prediction from flash and application operae flash synchronously inmulti-tasks.*/

#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)

/* Disable I cache. */

if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR))

{

SCB_DisableICache();

ICacheEnableFlag = true;

}

#endif /* __ICACHE_PRESENT */

taskENTER_CRITICAL();

status = flexspi_nor_flash_erase_sector(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE);

taskEXIT_CRITICAL();

#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)

if (ICacheEnableFlag)

{

/* Enable I cache. */

SCB_EnableICache();

ICacheEnableFlag = false;

}

#endif /* __ICACHE_PRESENT */

if (status != kStatus_Success)

{

PRINTF("Erase sector failure ! ");

configASSERT(NULL);

}

/* Invalidate the D cache before reading data from QSPI Flash */

#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN

DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE, FLASH_PAGE_SIZE);

#endif

memcpy(nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE), FLASH_PAGE_SIZE);

for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++)

{

if (0xFF != nor_read_buffer[i])

{

PRINTF("Erase data - read out data value incorrect ! ");

configASSERT(NULL);

}

}

PRINTF("Sector Erase successfully ! ");

/* Program Sector */

for (uint16_t i = 0U; i < FLASH_PAGE_SIZE; i++)

{

nor_program_buffer[i] = i;

}

/* Clean program buffer to maker sure program data is valid before program execution for SDRAM target, because heap is cacheabe in SDRAM target.*/

#if defined(USE_SDRAM) && USE_SDRAM

#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN

DCACHE_CleanByRange((uint32_t)nor_program_buffer, FLASH_PAGE_SIZE);

#endif

#endif

/* Disable I cache to avoid cache pre-fatch instruction with branch prediction from flash andapplication operate flash synchronously inmulti-tasks.*/

#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)

/* Disable I cache. */

if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR))

{

SCB_DisableICache();

ICacheEnableFlag = true;

}

#endif /* __ICACHE_PRESENT */

taskENTER_CRITICAL();

status = flexspi_nor_flash_page_program(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE, (void *)nor_program_buffer);

taskEXIT_CRITICAL();

#if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)

if (ICacheEnableFlag)

{

/* Enable I cache. */

SCB_EnableICache();

ICacheEnableFlag = false;

}

#endif /* __ICACHE_PRESENT */

if (status != kStatus_Success)

{

PRINTF("Page program failure ! ");

configASSERT(NULL);

}

PRINTF("Page program successfully ! ");

/* clean the D cache before reading data from QSPI Flash */

#if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN

DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE, FLASH_PAGE_SIZE);

#endif

/* the below read sector API can be used in both Code in QSPI mode and Code in SRAM mode */

taskENTER_CRITICAL();

memcpy(nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE), FLASH_PAGE_SIZE);

taskEXIT_CRITICAL();

PRINTF("Read Sector Content: ");

for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++)

{

PRINTF("%d, ", nor_read_buffer[i]);

}

PRINTF(" Flash operation done, suspend this task now. ");

/* Suspend itself */

vTaskSuspend(NULL);

}

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FlaSh
    +关注

    关注

    10

    文章

    1551

    浏览量

    146699
  • 中断
    +关注

    关注

    5

    文章

    884

    浏览量

    41028
  • 程序
    +关注

    关注

    114

    文章

    3631

    浏览量

    79552
  • 函数
    +关注

    关注

    3

    文章

    3903

    浏览量

    61310
  • FreeRTOS
    +关注

    关注

    12

    文章

    473

    浏览量

    61351

原文标题:I.MXRT FreeRTOS 环境下擦写外部 Flash

文章出处:【微信号:嵌入式 MCU,微信公众号:嵌入式 MCU】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    MCUXpresso IDE使用J-Link下载算法在Flash调试注意事项

      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是MCUXpresso IDE使用J-Link下载算法在Flash调试注意事项。  痞子衡前段时间写过一篇小文《为i.MXRT
    发表于 11-04 09:02

    如何在串口波特率识别里提升i.MXRT代码的执行性能呢

    怎样去识别SBL项目里ISP串口的高波特率呢?如何在串口波特率识别里提升i.MXRT代码的执行性能呢?
    发表于 11-09 07:48

    FlashDummy Cycle设置方法的差异

    今天痞子衡给大家介绍的是同一厂商不同系列Flash型号Dummy Cycle设置方法的差异。  上一篇文章 《在i.MXRT启动头FDCB里调整Flash工作频率也需同步设Dummy
    发表于 12-13 06:29

    i.MXRT设计更新Segger J-Link Flash下载算法文件

    给大家分享的是为i.MXRT设计更新Segger J-Link Flash下载算法文件。  想要在Flash中调试,基本是离不开Flash下载算法的,毕竟要先将代码烧写进
    发表于 12-15 06:11

    i.MXRT系列FlexSPI驱动Flash页编程执行时间

      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT系列FlexSPI驱动Flash页编程执行时间。  痞子衡之前写过一篇文章 《串行NOR Flash的页编程模式对于
    发表于 12-21 07:30

    i.MXRT上使能NOR Flash的Continuous read模式在软复位后无法正常启动怎么解决?

    i.MXRT上使能NOR Flash的Continuous read模式在软复位后无法正常启动怎么解决?
    发表于 01-19 07:19

    IAR开发环境i.MXRT的串行NOR Flash下载算法设计

      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是IAR开发环境i.MXRT的串行NOR Flash下载算法设计。  在i.MX
    发表于 01-26 07:46

    i.MXRT上使能NOR Flash的Continuous read模式在软复位后无法正常启动问题的解决

    《串行NOR Flash的Continuous read模式软复位后i.MXRT无法启动问题解决方案之RESET#》,利用RESET#引脚复位功能是痞子衡找到的第一种解决方案,今天痞子衡继续给大家介...
    发表于 01-26 06:52

    FlexSPI复位方式不当会导致i.MXRT系列OTFAD加密启动失败怎么解决?

    FlexSPI复位方式不当会导致i.MXRT系列OTFAD加密启动失败怎么解决?
    发表于 02-07 08:11

    介绍i.MXRT启动头FDCB里的lookupTable

    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT启动头FDCB里的lookupTable。一个MCU内部通常有很多外设模块,这些外设模块是各MCU厂商做差异化产...
    发表于 02-17 07:47

    使用PTPD/FreeRTOS和WIP-TCP/IP堆栈在i.MXRT上实现IEEE1588v2是我教程

    使用PTPD、FreeRTOS和WIP-TCP/IP堆栈在i.MXRT上实现IEEE1588v2
    发表于 12-12 06:42

    在哪里可以找到适用于i.MXRT 1160平台的FlashLoader?

    在哪里可以找到适用于 i.MXRT 1160 平台的 FlashLoader。但是对于 i.MXRT1160 ,无法找到 FlashLoader?
    发表于 03-29 09:04

    如何将LVGL示例部署到i.MXRT 117H EVK?

    我想将 LVGL 示例部署到 i.MXRT 117H EVK,您能否提供任何指南或应用说明。谢谢。
    发表于 04-17 08:31

    J-Link工具下i.MXRT的串行NOR Flash下载算法设计

    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是 J-Link 工具下 i.MXRT 的串行 NOR Flash 下载算法设计。 一、J-Link 各版本对 i.MXRT 的支持
    的头像 发表于 12-08 10:07 792次阅读

    Flash不支持SFDP,如何下载适用i.MXRT

    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是导致串行 NOR Flashi.MXRT 下无法正常下载 / 启动的常见因素之 SFDP。 i.MXRT 系列 MCU 发布
    的头像 发表于 10-30 10:30 430次阅读