1008 lines
36 KiB
C
1008 lines
36 KiB
C
/*
|
|
* 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;
|
|
}
|