MCUXpresso_MIMXRT1021xxxxx/boards/evkmimxrt1020/rtos_examples/freertos_hello_flash_operation/freertos_hello_flash_operat...

352 lines
12 KiB
C

/*
* Copyright 2020-2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/* 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"
/*******************************************************************************
* Definitions
******************************************************************************/
/* Task priorities. */
#define hello_task_PRIORITY (configMAX_PRIORITIES - 2)
#define flash_operation_task_PRIORITY (configMAX_PRIORITIES - 1)
/*******************************************************************************
* Prototypes
******************************************************************************/
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);
/*******************************************************************************
* Code
******************************************************************************/
flexspi_device_config_t deviceconfig = {
.flexspiRootClk = 133000000,
.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,
};
const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
/* Normal read mode -SDR */
/* 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),
};
/*!
* @brief Application entry point.
*/
int main(void)
{
/* Init board hardware. */
BOARD_ConfigMPU();
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
PRINTF("Flash Operation on FreeRTOS in XIP Mode!\r\n");
if (xTaskCreate(hello_task, "Hello_task", configMINIMAL_STACK_SIZE + 100, NULL, hello_task_PRIORITY, NULL) !=
pdPASS)
{
PRINTF("Task creation failed!.\r\n");
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!.\r\n");
while (1)
;
}
vTaskStartScheduler();
for (;;)
;
}
/*!
* @brief Task responsible for printing of "Hello world." message.
*/
static void hello_task(void *pvParameters)
{
for (;;)
{
PRINTF("Hello world.\r\n");
/* 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!\r\n");
configASSERT(NULL);
}
uint8_t *nor_read_buffer = pvPortMalloc(256);
if (NULL == nor_read_buffer)
{
PRINTF("nor_read_buffer memory allocation failed!\r\n");
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\r\n", 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...\r\n");
/* 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)
/* 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 !\r\n");
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 !\r\n ");
configASSERT(NULL);
}
}
PRINTF("Sector Erase successfully !\r\n");
/* 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 cacheable 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 in multi-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 !\r\n");
configASSERT(NULL);
}
PRINTF("Page program successfully !\r\n");
/* 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:\r\n");
for (uint16_t i = 0; i < FLASH_PAGE_SIZE; i++)
{
PRINTF("%d, ", nor_read_buffer[i]);
}
PRINTF("\r\nFlash operation done, suspend this task now.\r\n");
/* Suspend itself */
vTaskSuspend(NULL);
}