/* * 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); }