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

电子说

1.2w人已加入

描述

    在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配置为更高的优先级。

程序

    不需要逐一禁用所有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 and application 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);

}

  审核编辑:汤梓红

 

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

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分