/* * Copyright 2020 NXP * All rights reserved. * * * SPDX-License-Identifier: BSD-3-Clause */ /*!********************************************************************************* ************************************************************************************* * Include ************************************************************************************* ********************************************************************************** */ #include "fsl_common.h" #include "fsl_flexspi.h" #include "fsl_adapter_flexspi_hyper_flash_config.h" #include "fsl_adapter_flash.h" /***************************************************************************** ***************************************************************************** * Private macros ***************************************************************************** *****************************************************************************/ #define HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA 0 #define HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEDATA 1 #define HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS 2 #define HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE 4 #define HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR 6 #define HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM 10 #define HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP 12 #define CUSTOM_LUT_LENGTH 64 #ifndef CACHE_MAINTAIN #define CACHE_MAINTAIN 0x01U #endif #ifndef EXAMPLE_BOOT_FLEXSPI #define EXAMPLE_BOOT_FLEXSPI FLEXSPI #endif #ifndef FLASH_ADAPTER_SIZE #define FLASH_ADAPTER_SIZE 0x10000U /* 64*1024 Kbyte */ #endif #define FLASH_PAGE_SIZE 512U #define SECTOR_SIZE 0x40000U /* 4K */ #ifdef APP_FLEXSPI_AMBA_BASE #define FLEXSPI_AMBA_BASE APP_FLEXSPI_AMBA_BASE #elif defined(FlexSPI1_AMBA_BASE) #define FLEXSPI_AMBA_BASE FlexSPI1_AMBA_BASE #elif defined(FlexSPI_AMBA_BASE) #define FLEXSPI_AMBA_BASE FlexSPI_AMBA_BASE #else #error Unsupported flash case #endif /* Weak function. */ #if defined(__GNUC__) #define __WEAK_FUNC __attribute__((weak)) #elif defined(__ICCARM__) #define __WEAK_FUNC __weak #elif defined(__CC_ARM) || defined(__ARMCC_VERSION) #define __WEAK_FUNC __attribute__((weak)) #endif /*!********************************************************************************* ************************************************************************************* * Private type definitions ************************************************************************************* ********************************************************************************** */ /*!********************************************************************************* ************************************************************************************* * Private prototypes ************************************************************************************* ********************************************************************************** */ /*!********************************************************************************* ************************************************************************************* * Public memory declarations ************************************************************************************* ********************************************************************************** */ static FLEXSPI_Type *s_flexspiBase[] = FLEXSPI_BASE_PTRS; flexspi_device_config_t s_deviceconfig = { .flexspiRootClk = 42000000, /* 42MHZ SPI serial clock */ .isSck2Enabled = false, .flashSize = FLASH_ADAPTER_SIZE, .CSIntervalUnit = kFLEXSPI_CsIntervalUnit1SckCycle, .CSInterval = 2, .CSHoldTime = 0, .CSSetupTime = 3, .dataValidTime = 1, .columnspace = 3, .enableWordAddress = true, .AWRSeqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEDATA, .AWRSeqNumber = 1, .ARDSeqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA, .ARDSeqNumber = 1, .AHBWriteWaitUnit = kFLEXSPI_AhbWriteWaitUnit2AhbCycle, .AHBWriteWaitInterval = 20, }; const uint32_t customLUT[CUSTOM_LUT_LENGTH] = { /* Read Data */ [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xA0, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA + 1] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04), /* Write Data */ [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEDATA] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEDATA + 1] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x02), /* Read Status */ [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS + 1] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), // ADDR 0x555 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS + 3] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x70), // DATA 0x70 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS + 4] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xA0, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS + 5] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DUMMY_RWDS_DDR, kFLEXSPI_8PAD, 0x0B), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS + 6] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_DDR, kFLEXSPI_8PAD, 0x04, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0), /* Write Enable */ [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE + 1] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), // ADDR 0x555 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE + 3] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), // DATA 0xAA [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE + 4] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE + 5] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE + 6] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x02), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE + 7] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55), /* Erase Sector */ [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 1] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), // ADDR 0x555 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 3] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x80), // DATA 0x80 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 4] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 5] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 6] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 7] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), // ADDR 0x555 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 8] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 9] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 10] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x02), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 11] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 12] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 13] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR + 14] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x30, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x00), /* program page with word program command sequence */ [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 1] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), // ADDR 0x555 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 3] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xA0), // DATA 0xA0 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 4] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x20, kFLEXSPI_Command_RADDR_DDR, kFLEXSPI_8PAD, 0x18), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 5] = FLEXSPI_LUT_SEQ( kFLEXSPI_Command_CADDR_DDR, kFLEXSPI_8PAD, 0x10, kFLEXSPI_Command_WRITE_DDR, kFLEXSPI_8PAD, 0x80), /* Erase chip */ [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 3] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x80), // 1 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 4] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 5] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 6] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 7] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), // 2 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 8] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 9] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 10] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x02), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 11] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x55), // 3 [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 12] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 13] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0xAA), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 14] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x05), [4 * HYPERFLASH_CMD_LUT_SEQ_IDX_ERASECHIP + 15] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x00, kFLEXSPI_Command_DDR, kFLEXSPI_8PAD, 0x10), }; /***************************************************************************** ***************************************************************************** * Private functions ***************************************************************************** *****************************************************************************/ __WEAK_FUNC void flexspi_clock_update(flexspi_clock_t clockSelect, FLEXSPI_Type *base); __WEAK_FUNC uint32_t flexspi_get_frequency(void); __WEAK_FUNC void flexspi_clock_init(void); __WEAK_FUNC void flexspi_clock_update(flexspi_clock_t clockSelect, FLEXSPI_Type *base){}; __WEAK_FUNC uint32_t flexspi_get_frequency(void) { return 0; } __WEAK_FUNC void flexspi_clock_init(void) { } void flexspi_delay(void) { for (uint32_t i = 0; i < SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY / 1000000; i++) { __asm("nop"); } } static status_t flexspi_nor_write_enable(FLEXSPI_Type *base, uint32_t baseAddr) { flexspi_transfer_t flashXfer; status_t status; /* Write enable */ /* Write neable */ flashXfer.deviceAddress = baseAddr; flashXfer.port = kFLEXSPI_PortA1; flashXfer.cmdType = kFLEXSPI_Command; flashXfer.SeqNumber = 2; flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEENABLE; status = FLEXSPI_TransferBlocking(base, &flashXfer); return status; } status_t flexspi_nor_hyperbus_read(FLEXSPI_Type *base, uint32_t addr, uint32_t *buffer, uint32_t bytes) { flexspi_transfer_t flashXfer; status_t status; #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) bool ICacheEnableFlag = false; /* Disable I cache. */ if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) { SCB_DisableICache(); ICacheEnableFlag = true; } #endif /* __ICACHE_PRESENT */ #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) bool DCacheEnableFlag = false; /* Disable D cache. */ if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) { SCB_DisableDCache(); DCacheEnableFlag = true; } #endif /* __DCACHE_PRESENT */ flashXfer.deviceAddress = addr * 2; flashXfer.port = kFLEXSPI_PortA1; flashXfer.cmdType = kFLEXSPI_Read; flashXfer.SeqNumber = 1; flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_READDATA; flashXfer.data = buffer; flashXfer.dataSize = bytes; status = FLEXSPI_TransferBlocking(base, &flashXfer); #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) if (DCacheEnableFlag) { /* Enable D cache. */ SCB_EnableDCache(); } #endif /* __DCACHE_PRESENT */ #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) if (ICacheEnableFlag) { /* Enable I cache. */ SCB_EnableICache(); } #endif /* __ICACHE_PRESENT */ if (status != kStatus_Success) { return status; } return status; } status_t flexspi_nor_hyperbus_write(FLEXSPI_Type *base, uint32_t addr, uint32_t *buffer, uint32_t bytes) { flexspi_transfer_t flashXfer; status_t status; #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) bool ICacheEnableFlag = false; /* Disable I cache. */ if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) { SCB_DisableICache(); ICacheEnableFlag = true; } #endif /* __ICACHE_PRESENT */ #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) bool DCacheEnableFlag = false; /* Disable D cache. */ if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) { SCB_DisableDCache(); DCacheEnableFlag = true; } #endif /* __DCACHE_PRESENT */ flashXfer.deviceAddress = addr * 2; flashXfer.port = kFLEXSPI_PortA1; flashXfer.cmdType = kFLEXSPI_Write; flashXfer.SeqNumber = 1; flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_WRITEDATA; flashXfer.data = buffer; flashXfer.dataSize = bytes; status = FLEXSPI_TransferBlocking(base, &flashXfer); #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) if (DCacheEnableFlag) { /* Enable D cache. */ SCB_EnableDCache(); } #endif /* __DCACHE_PRESENT */ #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) if (ICacheEnableFlag) { /* Enable I cache. */ SCB_EnableICache(); } #endif /* __ICACHE_PRESENT */ if (status != kStatus_Success) { return status; } return status; } static status_t flexspi_nor_wait_bus_busy(FLEXSPI_Type *base) { /* Wait status ready. */ bool isBusy; uint32_t readValue; status_t status; flexspi_transfer_t flashXfer; flashXfer.deviceAddress = 0; flashXfer.port = kFLEXSPI_PortA1; flashXfer.cmdType = kFLEXSPI_Read; flashXfer.SeqNumber = 2; flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_READSTATUS; flashXfer.data = &readValue; flashXfer.dataSize = 2; do { status = FLEXSPI_TransferBlocking(base, &flashXfer); if (status != kStatus_Success) { return status; } if (readValue & 0x8000) { isBusy = false; } else { isBusy = true; } if (readValue & 0x3200) { status = kStatus_Fail; break; } } while (isBusy); return status; } status_t flexspi_nor_hyperflash_cfi(FLEXSPI_Type *base) { /* * Read ID-CFI Parameters */ // CFI Entry status_t status; uint32_t buffer[2]; uint8_t data[4] = {0x00, 0x98}; status = flexspi_nor_hyperbus_write(base, 0x555, (uint32_t *)data, 2); if (status != kStatus_Success) { return status; } // ID-CFI Read // Read Query Unique ASCII String status = flexspi_nor_hyperbus_read(base, 0x10, &buffer[0], sizeof(buffer)); if (status != kStatus_Success) { return status; } buffer[1] &= 0xFFFF; // Check that the data read out is unicode "QRY" in big-endian order if ((buffer[0] != 0x52005100) || (buffer[1] != 0x5900)) { status = kStatus_Fail; return status; } // ASO Exit 0xF000 data[1] = 0xF0; status = flexspi_nor_hyperbus_write(base, 0x0, (uint32_t *)data, 2); if (status != kStatus_Success) { return status; } /* Do software reset. */ FLEXSPI_SoftwareReset(base); return status; } /*!********************************************************************************* ************************************************************************************* * Public functions ************************************************************************************* ********************************************************************************** */ /*! * @brief Initializes the global flash properties structure members. * * This function initializes the Flash module for the other Flash APIs. * * * @retval #kStatus_HAL_Flash_Success API was executed successfully. * @retval #kStatus_HAL_Flash_InvalidArgument An invalid argument is provided. * @retval #kStatus_HAL_Flash_ExecuteInRamFunctionNotReady Execute-in-RAM function is not available. * @retval #kStatus_HAL_Flash_PartitionStatusUpdateFailure Failed to update the partition status. */ hal_flash_status_t HAL_FlashInit(void) { FLEXSPI_Type *base; flexspi_config_t config; uint32_t key; #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) bool ICacheEnableFlag = false; /* Disable I cache. */ if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) { SCB_DisableICache(); ICacheEnableFlag = true; } #endif /* __ICACHE_PRESENT */ #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) bool DCacheEnableFlag = false; /* Disable D cache. */ if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) { SCB_DisableDCache(); DCacheEnableFlag = true; } #endif /* __DCACHE_PRESENT */ key = DisableGlobalIRQ(); base = NULL; for (uint8_t i = 0; i < (sizeof(s_flexspiBase) / sizeof(FLEXSPI_Type *)); i++) { if (NULL != s_flexspiBase[i]) { base = s_flexspiBase[i]; break; } } if (NULL == base) { return kStatus_HAL_Flash_Fail; } #if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1) if (EXAMPLE_BOOT_FLEXSPI == base) { /* Wait for bus to be idle before changing flash configuration. */ while (false == FLEXSPI_GetBusIdleStatus(base)) { } } #endif flexspi_clock_init(); /*Get FLEXSPI default settings and configure the flexspi. */ FLEXSPI_GetDefaultConfig(&config); /*Set AHB buffer size for reading data through AHB bus. */ config.ahbConfig.enableAHBPrefetch = true; /*Allow AHB read start address do not follow the alignment requirement. */ config.ahbConfig.enableReadAddressOpt = true; config.ahbConfig.enableAHBBufferable = true; config.ahbConfig.enableAHBCachable = true; /* enable diff clock and DQS */ config.enableSckBDiffOpt = true; config.rxSampleClock = kFLEXSPI_ReadSampleClkExternalInputFromDqsPad; #if !(defined(FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) && FSL_FEATURE_FLEXSPI_HAS_NO_MCR0_COMBINATIONEN) config.enableCombination = true; #endif FLEXSPI_Init(base, &config); /* Set flexspi root clock. */ s_deviceconfig.flexspiRootClk = flexspi_get_frequency(); /* Configure flash settings according to serial flash feature. */ FLEXSPI_SetFlashConfig(base, &s_deviceconfig, kFLEXSPI_PortA1); /* Update LUT table. */ FLEXSPI_UpdateLUT(base, 0, customLUT, CUSTOM_LUT_LENGTH); /* Do software reset. */ FLEXSPI_SoftwareReset(base); EnableGlobalIRQ(key); #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) if (DCacheEnableFlag) { /* Enable D cache. */ SCB_EnableDCache(); } #endif /* __DCACHE_PRESENT */ #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) if (ICacheEnableFlag) { /* Enable I cache. */ SCB_EnableICache(); } #endif /* __ICACHE_PRESENT */ flexspi_nor_hyperflash_cfi(base); return kStatus_HAL_Flash_Success; } /*! * \brief Verify erase data in Flash * * @param start The address of the Flash location * @param lengthInBytes The number of bytes to be checked * @param margin Flash margin value * @retval #kStatus_HAL_Flash_Success API was executed successfully. */ hal_flash_status_t HAL_FlashVerifyErase(uint32_t start, uint32_t lengthInBytes, hal_flash_margin_value_t margin) { hal_flash_status_t state; uint32_t address; uint32_t value; (void)margin; if (start < FLEXSPI_AMBA_BASE) { return kStatus_HAL_Flash_Fail; } address = start; while (address < (start + lengthInBytes)) { value = 0U; if ((address + sizeof(uint32_t)) < (start + lengthInBytes)) { state = HAL_FlashRead(address, sizeof(uint32_t), (uint8_t *)&value); if (0xffffffffUL != value) { return kStatus_HAL_Flash_Fail; } address += sizeof(uint32_t); } else { state = HAL_FlashRead(address, 1, (uint8_t *)&value); if (0xffU != value) { return kStatus_HAL_Flash_Fail; } address++; } if (kStatus_HAL_Flash_Success != state) { return kStatus_HAL_Flash_Fail; } } return kStatus_HAL_Flash_Success; } /*! * \brief Write alligned data to FLASH * * @param dest The address of the Flash location * @param size The number of bytes to be programed * @param pData Pointer to the data to be programmed to Flash * * @retval #kStatus_HAL_Flash_Success API was executed successfully. * */ hal_flash_status_t HAL_FlashProgram(uint32_t dest, uint32_t size, uint8_t *pData) { FLEXSPI_Type *base; uint32_t address; uint32_t writeLength; status_t status = (status_t)kStatus_HAL_Flash_Error; flexspi_transfer_t flashXfer; uint32_t key; flexspi_clock_t frequency; #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) bool ICacheEnableFlag = false; /* Disable I cache. */ if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) { SCB_DisableICache(); ICacheEnableFlag = true; } #endif /* __ICACHE_PRESENT */ #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) bool DCacheEnableFlag = false; /* Disable D cache. */ if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) { SCB_DisableDCache(); DCacheEnableFlag = true; } #endif /* __DCACHE_PRESENT */ if (dest < FLEXSPI_AMBA_BASE) { return kStatus_HAL_Flash_Fail; } dest = dest - FLEXSPI_AMBA_BASE; base = NULL; for (uint8_t i = 0; i < (sizeof(s_flexspiBase) / sizeof(FLEXSPI_Type *)); i++) { if (NULL != s_flexspiBase[i]) { base = s_flexspiBase[i]; break; } } if (NULL == base) { return kStatus_HAL_Flash_Fail; } address = dest; while (address < (dest + size)) { if (0U != (address & ((FLASH_PAGE_SIZE - 1U)))) { writeLength = address - (address & (~(FLASH_PAGE_SIZE - 1U))); writeLength = FLASH_PAGE_SIZE - writeLength; if ((dest + size - address) < writeLength) { writeLength = (dest + size - address); } } else { writeLength = dest + size - address; } if (writeLength > FLASH_PAGE_SIZE) { writeLength = FLASH_PAGE_SIZE; } key = DisableGlobalIRQ(); /* Write enable */ if (address == 0x3dc0000) { // memcpy(&s_hyperflash_program_buffer[0], pData, size); } __DSB(); // DCACHE_CleanByRange(&s_hyperflash_program_buffer[0], size); /* Speed down flexspi clock, beacuse 50 MHz timings are only relevant when a burst write is used to load data * during a HyperFlash Word Program command. */ frequency = kHAL_Flash_Flexspi_Clock_Low42M; flexspi_clock_update(frequency, base); /* Get current flexspi root clock. */ s_deviceconfig.flexspiRootClk = flexspi_get_frequency(); /* Update DLL value depending on flexspi root clock. */ FLEXSPI_UpdateDllValue(base, &s_deviceconfig, kFLEXSPI_PortA1); /* Do software reset. */ FLEXSPI_SoftwareReset(base); status = flexspi_nor_write_enable(base, address); if (status != kStatus_Success) { EnableGlobalIRQ(key); break; } flashXfer.deviceAddress = address; flashXfer.port = kFLEXSPI_PortA1; flashXfer.cmdType = kFLEXSPI_Write; flashXfer.SeqNumber = 2; flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_PAGEPROGRAM; flashXfer.data = (uint32_t *)((void *)(&pData[address - dest])); flashXfer.dataSize = writeLength; status = FLEXSPI_TransferBlocking(base, &flashXfer); if (status != kStatus_Success) { EnableGlobalIRQ(key); break; } status = flexspi_nor_wait_bus_busy(base); if (status != kStatus_Success) { EnableGlobalIRQ(key); break; } address += writeLength; /* Speed up flexspi clock for a high read performance. */ frequency = kHAL_Flash_Flexspi_Clock_High166M; flexspi_clock_update(frequency, base); /* Get current flexspi root clock. */ s_deviceconfig.flexspiRootClk = flexspi_get_frequency(); /* Update DLL value depending on flexspi root clock. */ FLEXSPI_UpdateDllValue(base, &s_deviceconfig, kFLEXSPI_PortA1); FLEXSPI_SoftwareReset(base); /*SDK_DelayAtLeastUs(2U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);*/ flexspi_delay(); EnableGlobalIRQ(key); } __DSB(); #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) if (DCacheEnableFlag) { /* Enable D cache. */ SCB_EnableDCache(); } #endif /* __DCACHE_PRESENT */ #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) if (ICacheEnableFlag) { /* Enable I cache. */ SCB_EnableICache(); } #endif /* __ICACHE_PRESENT */ return (hal_flash_status_t)status; } /*! * \brief Write data to FLASH * * @param dest The address of the Flash location * @param size The number of bytes to be programed * @param pData Pointer to the data to be programmed to Flash * * @retval #kStatus_HAL_Flash_Success API was executed successfully. * */ hal_flash_status_t HAL_FlashProgramUnaligned(uint32_t dest, uint32_t size, uint8_t *pData) { return HAL_FlashProgram(dest, size, pData); } /*! * \brief Erase to 0xFF one or more FLASH sectors. * * @param dest The start address of the first sector to be erased * @param size The amount of flash to be erased (multiple of sector size) * * @retval #kStatus_HAL_Flash_Success API was executed successfully. * */ hal_flash_status_t HAL_FlashEraseSector(uint32_t dest, uint32_t size) { FLEXSPI_Type *base; uint32_t address; status_t status = (status_t)kStatus_HAL_Flash_Error; flexspi_transfer_t flashXfer; uint32_t key; if (dest < FLEXSPI_AMBA_BASE) { return kStatus_HAL_Flash_Fail; } #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) bool ICacheEnableFlag = false; /* Disable I cache. */ if (SCB_CCR_IC_Msk == (SCB_CCR_IC_Msk & SCB->CCR)) { SCB_DisableICache(); ICacheEnableFlag = true; } #endif /* __ICACHE_PRESENT */ dest = dest - FLEXSPI_AMBA_BASE; base = NULL; for (uint8_t i = 0; i < (sizeof(s_flexspiBase) / sizeof(FLEXSPI_Type *)); i++) { if (NULL != s_flexspiBase[i]) { base = s_flexspiBase[i]; break; } } if (NULL == base) { return kStatus_HAL_Flash_Fail; } address = dest; while (address < (dest + size)) { /* Write enable */ status = flexspi_nor_write_enable(base, address); if (status != kStatus_Success) { break; } flashXfer.deviceAddress = address; flashXfer.port = kFLEXSPI_PortA1; flashXfer.cmdType = kFLEXSPI_Command; flashXfer.SeqNumber = 4; flashXfer.seqIndex = HYPERFLASH_CMD_LUT_SEQ_IDX_ERASESECTOR; key = DisableGlobalIRQ(); status = FLEXSPI_TransferBlocking(base, &flashXfer); if (status != kStatus_Success) { EnableGlobalIRQ(key); break; } status = flexspi_nor_wait_bus_busy(base); address += SECTOR_SIZE; /* Do software reset. */ FLEXSPI_SoftwareReset(base); /*SDK_DelayAtLeastUs(2U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);*/ flexspi_delay(); EnableGlobalIRQ(key); } if (status != kStatus_Success) { key = DisableGlobalIRQ(); /* Do software reset. */ FLEXSPI_SoftwareReset(base); /*SDK_DelayAtLeastUs(2U, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);*/ flexspi_delay(); EnableGlobalIRQ(key); } #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) if (ICacheEnableFlag) { /* Enable I cache. */ SCB_EnableICache(); } #endif /* __ICACHE_PRESENT */ return (hal_flash_status_t)status; } /*! * \brief Read data from FLASH * * * @param scr The address of the Flash location to be read * @param size The number of bytes to be read * @param pData Pointer to the data to be read from Flash * * @retval #kStatus_HAL_Flash_Success API was executed successfully. * */ hal_flash_status_t HAL_FlashRead(uint32_t src, uint32_t size, uint8_t *pData) { #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) bool DCacheEnableFlag = false; /* Disable D cache. */ if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) { SCB_DisableDCache(); DCacheEnableFlag = true; } #endif /* __DCACHE_PRESENT */ #if defined(CACHE_MAINTAIN) && CACHE_MAINTAIN #endif (void)memcpy(pData, (uint8_t *)src, size); #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) if (DCacheEnableFlag) { /* Enable D cache. */ SCB_EnableDCache(); } #endif /* __DCACHE_PRESENT */ return kStatus_HAL_Flash_Success; } /*! * @brief Returns the desired hal flash property. * * @param Property The desired property from the list of properties in * enum hal_flash_property_tag_t * @param value A pointer to the value returned for the desired flash property. * * @retval #kStatus_HAL_Flash_Success API was executed successfully. * @retval #kStatus_HAL_Flash_InvalidArgument An invalid argument is provided. * @retval #kStatus_HAL_Flash_Success Flash currently not support. */ hal_flash_status_t HAL_FlashGetProperty(hal_flash_property_tag_t property, uint32_t *value) { return kStatus_HAL_Flash_Success; } /*! * @brief Set the desired hal flash property. * * @param Property The desired property from the list of properties in * enum hal_flash_property_tag_t * @param value The value would be set to the desired flash property. * * @retval #kStatus_HAL_Flash_Success API was executed successfully. * @retval #kStatus_HAL_Flash_InvalidArgument An invalid argument is provided. * @retval #kStatus_HAL_Flash_Success Flash currently not support. */ hal_flash_status_t HAL_FlashSetProperty(hal_flash_property_tag_t property, uint32_t value) { return kStatus_HAL_Flash_Success; } /*! * @brief Returns the security state via the pointer passed into the function. * * This function retrieves the current flash security status, including the * security enabling state and the backdoor key enabling state. * * @param state A pointer to the value returned for the current security status * * @retval #kStatus_HAL_Flash_Success API was executed successfully. * @retval #kStatus_HAL_Flash_InvalidArgument An invalid argument is provided. * @retval #kStatus_HAL_Flash_Success Flash currently not support. */ hal_flash_status_t HAL_FlashGetSecurityState(hal_flash_security_state_t *state) { return kStatus_HAL_Flash_Success; }