/*************************************************************************************************/
|
/*!
|
* \file
|
*
|
* \brief PAL Flash driver.
|
*
|
* Copyright (c) 2018-2019 Arm Ltd. All Rights Reserved.
|
*
|
* Copyright (c) 2019-2020 Packetcraft, Inc.
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*/
|
/*************************************************************************************************/
|
|
#include <string.h>
|
#include "pal_flash.h"
|
#include "mk_flash.h"
|
|
/**************************************************************************************************
|
Macros
|
**************************************************************************************************/
|
// The size of flash space available to users is 8K
|
#define MK8000_USER_TOTAL_SIZE 0x2000
|
// The starting address is 0x0407E000, 126th sector
|
#define MK8000_USER_START_ADDR 0x0407E000
|
// The end address is 0x0407FFFF
|
#define MK8000_USER_END_ADDR (MK8000_USER_START_ADDR + MK8000_USER_TOTAL_SIZE - 1)
|
|
/*! Flash block size. */
|
#define PAL_FLASH_SECTOR4K 1
|
// #define PAL_FLASH_SECTOR64K 16
|
|
#define PAL_FLASH_SECTOR4K_SIZE FLASH_SECTOR_SIZE
|
// #define PAL_FLASH_SECTOR64K_SIZE 0x10000
|
|
/*! Flash Total size. */
|
#define PAL_FLASH_TOTAL_SIZE MK8000_USER_TOTAL_SIZE
|
|
/*! Flash internal cache buffer size. Note: should be at least 2. */
|
#define PAL_FLASH_CACHE_BUF_SIZE 11
|
|
/*! Flash word size. */
|
#define PAL_FLASH_WORD_SIZE 4
|
|
/*! Aligns a value to word size. */
|
#define PAL_FLASH_WORD_ALIGN(value) (((value) + (PAL_FLASH_WORD_SIZE - 1)) & ~(PAL_FLASH_WORD_SIZE - 1))
|
/*! Validates if a value is aligned to word. */
|
#define PAL_FLASH_IS_WORD_ALIGNED(value) (((uint32_t)(value) & (PAL_FLASH_WORD_SIZE - 1)) == 0)
|
|
/*! QSPI flash commands. */
|
#define QSPI_STD_CMD_WRSR 0x01
|
#define QSPI_STD_CMD_RSTEN 0x66
|
#define QSPI_STD_CMD_RST 0x99
|
|
#ifdef DEBUG
|
|
/*! \brief Parameter check. */
|
#define PAL_FLASH_PARAM_CHECK(expr) \
|
{ \
|
if (!(expr)) \
|
{ \
|
palFlashCb.state = PAL_FLASH_STATE_ERROR; \
|
return; \
|
} \
|
}
|
|
#else
|
|
/*! \brief Parameter check (disabled). */
|
#define PAL_FLASH_PARAM_CHECK(expr)
|
|
#endif
|
|
/**************************************************************************************************
|
Local Variables
|
**************************************************************************************************/
|
|
/*! flash cache buffer. */
|
static uint32_t palFlashCacheBuf[PAL_FLASH_CACHE_BUF_SIZE];
|
static enum FLASH_DEV_T MK8000_FLASH_ID = FLASH_ID0;
|
static enum FLASH_DEV_T flash_id = FLASH_MAX_NUM;
|
|
/*! \brief Control block. */
|
static struct
|
{
|
PalFlashState_t state; /*!< State. */
|
uint32_t writeAddr; /*!< Write address. */
|
} palFlashCb;
|
|
/**************************************************************************************************
|
Global Functions
|
**************************************************************************************************/
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Initialize flash.
|
*
|
* \param[in] actCback Callback function.
|
*/
|
/*************************************************************************************************/
|
void PalFlashInit(PalFlashCback_t actCback)
|
{
|
(void)palFlashCacheBuf;
|
if (DRV_OK == flash_open(MK8000_FLASH_ID, NULL))
|
{
|
flash_id = FLASH_ID0;
|
}
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief De-initialize flash.
|
*/
|
/*************************************************************************************************/
|
void PalFlashDeInit(void)
|
{
|
flash_close(flash_id);
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Reads data from flash storage.
|
*
|
* \param[in] pBuf Pointer to memory buffer where data will be stored.
|
* \param[in] size Data size in bytes to be read.
|
* \param[in] srcAddr Word aligned address from where data is read.
|
*/
|
/*************************************************************************************************/
|
void PalFlashRead(void *pBuf, uint32_t size, uint32_t srcAddr)
|
{
|
uint32_t realAddr;
|
memset(pBuf, 0xFF, size);
|
realAddr = MK8000_USER_START_ADDR + srcAddr;
|
flash_read(flash_id, realAddr, (uint8_t *)pBuf, size);
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Writes data to flash storage.
|
*
|
* \param[in] pBuf Pointer to memory buffer from where data will be written.
|
* \param[in] size Data size in bytes to be written.
|
* \param[in] dstAddr Word aligned address to write data.
|
*/
|
/*************************************************************************************************/
|
void PalFlashWrite(const uint8_t *pBuf, uint32_t size, uint32_t dstAddr)
|
{
|
#if FLASH_WRITE_EN
|
uint32_t realAddr;
|
realAddr = MK8000_USER_START_ADDR + dstAddr;
|
flash_write_nbytes(flash_id, realAddr, pBuf, size);
|
#endif
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Erase sector.
|
*
|
* \param[in] numOfSectors Number of sectors to be erased.
|
* \param[in] startAddr Word aligned address.
|
*/
|
/*************************************************************************************************/
|
void PalFlashEraseSector(uint32_t numOfSectors, uint32_t startAddr)
|
{
|
#if FLASH_WRITE_EN
|
uint32_t realAddr;
|
realAddr = MK8000_USER_START_ADDR + startAddr;
|
if (PAL_FLASH_IS_WORD_ALIGNED(realAddr) && (numOfSectors > 0) && (numOfSectors <= (PAL_FLASH_TOTAL_SIZE / PAL_FLASH_SECTOR4K_SIZE)))
|
{
|
uint32_t sector_idx = (realAddr - FLASH_BASE) / PAL_FLASH_SECTOR4K_SIZE;
|
if ((sector_idx + numOfSectors) <= (FLASH_SIZE / PAL_FLASH_SECTOR4K_SIZE))
|
{
|
for (uint32_t i = 0; i < numOfSectors; i++, sector_idx++)
|
{
|
flash_sector_erase(flash_id, sector_idx);
|
}
|
}
|
}
|
#endif
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Erase chip. It is not recommended to use since it takes up to 240s.
|
*/
|
/*************************************************************************************************/
|
void PalFlashEraseChip(void)
|
{
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Get total size of NVM storage.
|
*
|
* \return Total size.
|
*/
|
/*************************************************************************************************/
|
uint32_t PalNvmGetTotalSize(void)
|
{
|
return PAL_FLASH_TOTAL_SIZE;
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Get sector size of NVM storage.
|
*
|
* \return Sector size.
|
*/
|
/*************************************************************************************************/
|
uint32_t PalNvmGetSectorSize(void)
|
{
|
return PAL_FLASH_SECTOR4K_SIZE;
|
}
|
|
/*************************************************************************************************/
|
/*!
|
* \brief Get flash state.
|
*
|
* \return flash state.
|
*/
|
/*************************************************************************************************/
|
PalFlashState_t PalFlashGetState(void)
|
{
|
return palFlashCb.state;
|
}
|