/***********************************************************************/ /* This file is part of the ARM Toolchain package */ /* Copyright (c) 2010 Keil - An ARM Company. All rights reserved. */ /***********************************************************************/ /* */ /* FlashDev.C: Flash Programming Functions adapted */ /* for New Device 256kB Flash */ /* */ /***********************************************************************/ #include "FlashOS.H" // FlashOS Structures #include "fsl_romapi.h" #define FLEXSPI_NOR_INSTANCE 0 #define SECTOR_SIZE (4096) #define BASE_ADDRESS (0x60000000) /* Init this global variable to workaround of the issue to running this flash algo in Segger */ flexspi_nor_config_t config = {1}; /* * Initialize Flash Programming Functions * Parameter: adr: Device Base Address * clk: Clock Frequency (Hz) * fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify) * Return Value: 0 - OK, 1 - Failed */ /*${macro:start}*/ #define FlexSpiInstance 0U #define EXAMPLE_FLEXSPI_AMBA_BASE FlexSPI_AMBA_BASE #define FLASH_SIZE 0x400000UL /* 4Mb */ #define FLASH_PAGE_SIZE 256UL /* 256Bytes */ #define FLASH_SECTOR_SIZE 0x1000UL /* 4KBytes */ #define FLASH_BLOCK_SIZE 0x10000UL /* 64KBytes */ /*${macro:end}*/ void flexspi_nor_get_config(flexspi_nor_config_t *config) { config->memConfig.tag = FLEXSPI_CFG_BLK_TAG; config->memConfig.version = FLEXSPI_CFG_BLK_VERSION; config->memConfig.readSampleClkSrc = kFLEXSPIReadSampleClk_LoopbackFromDqsPad; config->memConfig.serialClkFreq = kFLEXSPISerialClk_133MHz; /* Serial Flash Frequencey.See System Boot Chapter for more details */ config->memConfig.sflashA1Size = FLASH_SIZE; config->memConfig.csHoldTime = 3U; /* Data hold time, default value: 3 */ config->memConfig.csSetupTime = 3U; /* Date setup time, default value: 3 */ config->memConfig.deviceType = kFLEXSPIDeviceType_SerialNOR; /* Flash device type default type: Serial NOR */ config->memConfig.deviceModeType = kDeviceConfigCmdType_Generic; config->memConfig.columnAddressWidth = 0U; config->memConfig.deviceModeCfgEnable = 0U; config->memConfig.waitTimeCfgCommands = 0U; config->memConfig.configCmdEnable = 0U; /* Always enable Safe configuration Frequency */ config->memConfig.controllerMiscOption = FSL_ROM_FLEXSPI_BITMASK(kFLEXSPIMiscOffset_SafeConfigFreqEnable); config->memConfig.sflashPadType = kSerialFlash_4Pads; /* Pad Type: 1 - Single, 2 - Dual, 4 - Quad, 8 - Octal */ config->pageSize = FLASH_PAGE_SIZE; config->sectorSize = FLASH_SECTOR_SIZE; config->blockSize = FLASH_BLOCK_SIZE; config->ipcmdSerialClkFreq = kFLEXSPISerialClk_30MHz; /* Clock frequency for IP command */ /* Fast Read Quad I/O */ config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READ + 0U] = FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xebU, RADDR_SDR, FLEXSPI_4PAD, 0x18U); config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READ + 1U] = FSL_ROM_FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06U, READ_SDR, FLEXSPI_4PAD, 0x4U); /* Read Status */ config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_READSTATUS] = FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05U, READ_SDR, FLEXSPI_1PAD, 0x1U); /* Write Enable */ config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_WRITEENABLE] = FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06U, STOP, FLEXSPI_1PAD, 0x0U); /* Page Program - quad mode */ config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 0U] = FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x32U, RADDR_SDR, FLEXSPI_1PAD, 0x18U); config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM + 1U] = FSL_ROM_FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_4PAD, 0x04U, STOP, FLEXSPI_1PAD, 0x0U); /* Sector Erase */ config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] = FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20U, RADDR_SDR, FLEXSPI_1PAD, 0x18U); /* Block Erase */ config->memConfig.lookupTable[4U * NOR_CMD_LUT_SEQ_IDX_ERASEBLOCK] = FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8U, RADDR_SDR, FLEXSPI_1PAD, 0x18U); } int Init(unsigned long adr, unsigned long clk, unsigned long fnc) { status_t status; WDOG1->WMCR &= ~WDOG_WMCR_PDE_MASK; WDOG2->WMCR &= ~WDOG_WMCR_PDE_MASK; /* Watchdog disable */ if (WDOG1->WCR & WDOG_WCR_WDE_MASK) { WDOG1->WCR &= ~WDOG_WCR_WDE_MASK; } if (WDOG2->WCR & WDOG_WCR_WDE_MASK) { WDOG2->WCR &= ~WDOG_WCR_WDE_MASK; } RTWDOG->CNT = 0xD928C520U; /* 0xD928C520U is the update key */ RTWDOG->TOVAL = 0xFFFF; RTWDOG->CS = (uint32_t)((RTWDOG->CS) & ~RTWDOG_CS_EN_MASK) | RTWDOG_CS_UPDATE_MASK; IOMUXC->SW_MUX_CTL_PAD[86] = IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(1) | IOMUXC_SW_MUX_CTL_PAD_SION(1); if (SCB_CCR_DC_Msk == (SCB_CCR_DC_Msk & SCB->CCR)) { SCB_DisableDCache(); } memset(&config, 0U, sizeof(flexspi_nor_config_t)); flexspi_nor_get_config(&config); status = ROM_FLEXSPI_NorFlash_Init(FLEXSPI_NOR_INSTANCE, &config); } /* * De-Initialize Flash Programming Functions * Parameter: fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify) * Return Value: 0 - OK, 1 - Failed */ int UnInit(unsigned long fnc) { /* Add your Code */ return (0); // Finished without Errors } /* * Erase complete Flash Memory * Return Value: 0 - OK, 1 - Failed */ int EraseChip(void) { status_t status; status = ROM_FLEXSPI_NorFlash_Erase(FLEXSPI_NOR_INSTANCE, &config, 0, FLASH_SIZE); // Erase all if (status != kStatus_Success) { return (1); } else { return (0); // Finished without Errors } } /* * Erase Sector in Flash Memory * Parameter: adr: Sector Address * Return Value: 0 - OK, 1 - Failed */ int EraseSector(unsigned long adr) { status_t status; adr = adr - BASE_ADDRESS; status = ROM_FLEXSPI_NorFlash_Erase(FLEXSPI_NOR_INSTANCE, &config, adr, SECTOR_SIZE); // Erase 1 sector if (status != kStatus_Success) { return (1); } else { return (0); } } /* * Program Page in Flash Memory * Parameter: adr: Page Start Address * sz: Page Size * buf: Page Data * Return Value: 0 - OK, 1 - Failed */ int ProgramPage(unsigned long adr, unsigned long sz, unsigned char *buf) { status_t status; adr = adr - BASE_ADDRESS; // Program data to destination status = ROM_FLEXSPI_NorFlash_ProgramPage(FLEXSPI_NOR_INSTANCE, &config, adr, (uint32_t *)buf); // program 1 page if (status != kStatus_Success) { return (1); } else { return (0); } }