/* * Copyright 2020 NXP * All rights reserved. * * * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_flexspi.h" #include "app.h" #include "fsl_debug_console.h" #include "fsl_flexspi_edma.h" #include "fsl_edma.h" #if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT #include "fsl_dmamux.h" #endif #include "pin_mux.h" #include "clock_config.h" #include "board.h" #include "fsl_common.h" /******************************************************************************* * Definitions ******************************************************************************/ /******************************************************************************* * Prototypes ******************************************************************************/ extern status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address); status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src); status_t flexspi_nor_read_data(FLEXSPI_Type *base, uint32_t startAddress, uint32_t *buffer, uint32_t length); 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); /******************************************************************************* * Variables ******************************************************************************/ /*Default flexspi+dma driver uses 32-bit data width configuration for transfer, this requires data buffer address should be aligned to 32-bit. */ AT_NONCACHEABLE_SECTION_ALIGN(static uint8_t s_nor_program_buffer[256], 4); static uint8_t s_nor_read_buffer[256]; edma_handle_t dmaTxHandle; edma_handle_t dmaRxHandle; /******************************************************************************* * Code ******************************************************************************/ /* For write DMA handler depanding on FLEXSPI_TX_DMA_CHANNEL. */ extern void DMA0_DMA16_DriverIRQHandler(void); /* For read DMA handler depanding on FLEXSPI_RX_DMA_CHANNEL. */ extern void DMA1_DMA17_DriverIRQHandler(void); 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 Main function */ int main(void) { uint32_t i = 0; status_t status; uint8_t vendorID = 0; edma_config_t userConfig; BOARD_ConfigMPU(); BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); #if defined(ENABLE_RAM_VECTOR_TABLE) /* For write DMA handler depanding on FLEXSPI_TX_DMA_CHANNEL. */ InstallIRQHandler(DMA0_DMA16_IRQn, (uint32_t)DMA0_DMA16_DriverIRQHandler); /* For read DMA handler depanding on FLEXSPI_RX_DMA_CHANNEL. */ InstallIRQHandler(DMA1_DMA17_IRQn, (uint32_t)DMA1_DMA17_DriverIRQHandler); #endif PRINTF("\r\nFLEXSPI edma example started!\r\n"); #if defined(FSL_FEATURE_SOC_DMAMUX_COUNT) && FSL_FEATURE_SOC_DMAMUX_COUNT /* DMAMUX init */ DMAMUX_Init(EXAMPLE_FLEXSPI_DMA_MUX); DMAMUX_SetSource(EXAMPLE_FLEXSPI_DMA_MUX, FLEXSPI_TX_DMA_CHANNEL, FLEXSPI_TX_DMA_REQUEST_SOURCE); DMAMUX_EnableChannel(EXAMPLE_FLEXSPI_DMA_MUX, FLEXSPI_TX_DMA_CHANNEL); DMAMUX_SetSource(EXAMPLE_FLEXSPI_DMA_MUX, FLEXSPI_RX_DMA_CHANNEL, FLEXSPI_RX_DMA_REQUEST_SOURCE); DMAMUX_EnableChannel(EXAMPLE_FLEXSPI_DMA_MUX, FLEXSPI_RX_DMA_CHANNEL); #endif /* EDMA init */ /* * userConfig.enableRoundRobinArbitration = false; * userConfig.enableHaltOnError = true; * userConfig.enableContinuousLinkMode = false; * userConfig.enableDebugMode = false; */ EDMA_GetDefaultConfig(&userConfig); EDMA_Init(EXAMPLE_FLEXSPI_DMA, &userConfig); /* Create the EDMA channel handles */ EDMA_CreateHandle(&dmaTxHandle, EXAMPLE_FLEXSPI_DMA, FLEXSPI_TX_DMA_CHANNEL); EDMA_CreateHandle(&dmaRxHandle, EXAMPLE_FLEXSPI_DMA, FLEXSPI_RX_DMA_CHANNEL); #if defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && FSL_FEATURE_EDMA_HAS_CHANNEL_MUX EDMA_SetChannelMux(EXAMPLE_FLEXSPI_DMA, FLEXSPI_TX_DMA_CHANNEL, FLEXSPI_TX_DMA_REQUEST_SOURCE); EDMA_SetChannelMux(EXAMPLE_FLEXSPI_DMA, FLEXSPI_RX_DMA_CHANNEL, FLEXSPI_RX_DMA_REQUEST_SOURCE); #endif /* FLEXSPI init */ flexspi_nor_flash_init(EXAMPLE_FLEXSPI); /* Enter quad mode. */ status = flexspi_nor_enable_quad_mode(EXAMPLE_FLEXSPI); if (status != kStatus_Success) { return status; } /* Get vendor ID. */ status = flexspi_nor_get_vendor_id(EXAMPLE_FLEXSPI, &vendorID); if (status != kStatus_Success) { return status; } PRINTF("Vendor ID: 0x%x\r\n", vendorID); /* 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) 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 */ status = flexspi_nor_flash_erase_sector(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE); #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"); return -1; } #if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE, FLASH_PAGE_SIZE); #endif memset(s_nor_program_buffer, 0xFFU, sizeof(s_nor_program_buffer)); memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE), sizeof(s_nor_read_buffer)); if (memcmp(s_nor_program_buffer, s_nor_read_buffer, sizeof(s_nor_program_buffer))) { PRINTF("Erase data - read out data value incorrect !\r\n "); return -1; } else { PRINTF("Erase data - successfully. \r\n"); } for (i = 0; i < FLASH_PAGE_SIZE; i++) { s_nor_program_buffer[i] = i; } #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 */ status = flexspi_nor_flash_page_program(EXAMPLE_FLEXSPI, EXAMPLE_SECTOR * SECTOR_SIZE, (void *)s_nor_program_buffer); #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"); return -1; } #if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN DCACHE_InvalidateByRange(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE, FLASH_PAGE_SIZE); #endif memcpy(s_nor_read_buffer, (void *)(EXAMPLE_FLEXSPI_AMBA_BASE + EXAMPLE_SECTOR * SECTOR_SIZE), sizeof(s_nor_read_buffer)); if (memcmp(s_nor_read_buffer, s_nor_program_buffer, sizeof(s_nor_program_buffer)) != 0) { PRINTF("Program data - read out data value incorrect !\r\n "); return -1; } else { PRINTF("Program data - successfully. \r\n"); } while (1) { } }