2022-08-23 15:00:33 +00:00
|
|
|
/*
|
2022-12-02 11:44:05 +00:00
|
|
|
* Copyright 2020-2022 NXP
|
2022-08-23 15:00:33 +00:00
|
|
|
* 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)
|
|
|
|
{
|
2022-12-02 11:44:05 +00:00
|
|
|
PRINTF("nor_program_buffer memory allocation failed!\r\n");
|
2022-08-23 15:00:33 +00:00
|
|
|
configASSERT(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t *nor_read_buffer = pvPortMalloc(256);
|
|
|
|
if (NULL == nor_read_buffer)
|
|
|
|
{
|
2022-12-02 11:44:05 +00:00
|
|
|
PRINTF("nor_read_buffer memory allocation failed!\r\n");
|
2022-08-23 15:00:33 +00:00
|
|
|
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);
|
|
|
|
}
|