MCUXpresso_MIMXRT1052xxxxB/boards/evkbimxrt1050/azure_rtos_examples/filex_levelx_mflash/lx_mflash_driver.c
Yilin Sun c2668b7ca0
Update SDK to v2.13.0
Signed-off-by: Yilin Sun <imi415@imi.moe>
2023-01-26 09:35:56 +08:00

247 lines
6.1 KiB
C

/*
* Copyright 2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_debug_console.h"
#include "mflash_drv.h"
#include "fx_levelx_driver.h"
#include "lx_api.h"
#define LX_NOR_DISK_SIZE (g_disk_infor.disk_size)
#define LX_NOR_DISK_FLASH_OFF (g_disk_infor.disk_flash_offset)
#define LX_NOR_BLOCK_SIZE (g_disk_infor.levelx_block_size)
#define LX_NOR_SECTOR_SIZE_BYTES (LX_NOR_SECTOR_SIZE * sizeof(ULONG))
#define FLASH_ERASED_UINT32 (0xFFFFFFFFUL)
static ULONG _lx_nor_sector_buffer[LX_NOR_SECTOR_SIZE];
static bool is_mflash_driver_ready = false;
extern fx_levelx_disk_infor_t g_disk_infor;
static UINT _lx_mflash_read(ULONG *offset, ULONG *data, ULONG words)
{
status_t ret;
assert(data != NULL);
ret = (status_t)mflash_drv_read((uint32_t)offset,
(uint32_t *)data,
words * sizeof(ULONG));
if (ret != kStatus_Success)
{
PRINTF("ERR: mflash_drv_read(0x%x)\r\n", offset);
return LX_ERROR;
}
return LX_SUCCESS;
}
static UINT _lx_mflash_write(ULONG *offset, ULONG *data, ULONG words)
{
int8_t wbuf[MFLASH_PAGE_SIZE];
uint32_t start_offset;
uint32_t page_offset;
uint32_t size;
uint8_t *buffer;
status_t ret;
assert(data != NULL);
assert(words == 1 || words == LX_NOR_SECTOR_SIZE);
size = words * sizeof(ULONG);
if (words == 1)
{
/*
* mflash_drv_page_program() programs one page at a time,
* so set unchanged data to 0x0ff
*/
memset(wbuf, 0x0ff, MFLASH_PAGE_SIZE);
page_offset = (uint32_t)offset % MFLASH_PAGE_SIZE;
memcpy(&wbuf[page_offset], data, size);
start_offset = (uint32_t)offset / MFLASH_PAGE_SIZE * MFLASH_PAGE_SIZE;
ret = (status_t)mflash_drv_page_program(start_offset, (uint32_t *)wbuf);
if (ret != kStatus_Success)
{
PRINTF("ERR: mflash_drv_page_program(0x%x)\r\n", start_offset);
return LX_ERROR;
}
}
else
{
/* words = LX_NOR_SECTOR_SIZE */
buffer = (uint8_t *)data;
start_offset = (uint32_t)offset;
for (int index = 0; index < size / MFLASH_PAGE_SIZE; index++)
{
ret = (status_t)mflash_drv_page_program(start_offset, (uint32_t *)buffer);
if (ret != kStatus_Success)
{
PRINTF("ERR: mflash_drv_page_program(0x%x)\r\n", start_offset);
return LX_ERROR;
}
start_offset += MFLASH_PAGE_SIZE;
buffer += MFLASH_PAGE_SIZE;
}
}
return LX_SUCCESS;
}
static UINT _lx_mflash_block_erase(ULONG block, ULONG erase_count)
{
uint32_t sector_offset;
status_t ret;
int index;
int count;
LX_PARAMETER_NOT_USED(erase_count);
sector_offset = LX_NOR_DISK_FLASH_OFF + LX_NOR_BLOCK_SIZE * block;
count = LX_NOR_BLOCK_SIZE / MFLASH_SECTOR_SIZE;
for (index = 0; index < count; index++)
{
ret = mflash_drv_sector_erase(sector_offset);
if (ret != kStatus_Success)
{
return LX_ERROR;
}
sector_offset += MFLASH_SECTOR_SIZE;
}
return LX_SUCCESS;
}
static UINT _lx_mflash_block_erased_verify(ULONG block)
{
uint32_t *buffer = (uint32_t *)_lx_nor_sector_buffer;
uint32_t offset;
status_t ret;
int index;
int count;
int i;
offset = LX_NOR_DISK_FLASH_OFF + LX_NOR_BLOCK_SIZE * block;
count = LX_NOR_BLOCK_SIZE / LX_NOR_SECTOR_SIZE_BYTES;
for (index = 0; index < count; index++)
{
ret = (status_t)mflash_drv_read(offset, buffer, LX_NOR_SECTOR_SIZE_BYTES);
if (ret != kStatus_Success)
{
PRINTF("ERR: mflash_drv_read(0x%x)\r\n", offset);
return ret;
}
for (i = 0; i < LX_NOR_BLOCK_SIZE / sizeof(uint32_t); i++)
{
if (buffer[i] != FLASH_ERASED_UINT32)
return LX_ERROR;
}
offset += LX_NOR_SECTOR_SIZE_BYTES;
}
return LX_SUCCESS;
}
static UINT _lx_mflash_system_error(UINT error_code)
{
PRINTF("ERR: levelx system error (%d)\r\n", error_code);
return LX_SUCCESS;
}
UINT _lx_mflash_initialize(LX_NOR_FLASH *nor_flash)
{
status_t ret;
assert(nor_flash != NULL);
if (is_mflash_driver_ready == false) {
ret = mflash_drv_init();
if (ret != kStatus_Success)
{
PRINTF("ERR: mflash_drv_init() error\r\n");
return LX_ERROR;
}
is_mflash_driver_ready = true;
}
nor_flash->lx_nor_flash_words_per_block =
(ULONG) (LX_NOR_BLOCK_SIZE / sizeof(ULONG));
nor_flash->lx_nor_flash_total_blocks =
(ULONG) (LX_NOR_DISK_SIZE / LX_NOR_BLOCK_SIZE);
nor_flash->lx_nor_flash_base_address =
(ULONG *)LX_NOR_DISK_FLASH_OFF;
nor_flash->lx_nor_flash_driver_read = _lx_mflash_read;
nor_flash->lx_nor_flash_driver_write = _lx_mflash_write;
nor_flash->lx_nor_flash_driver_block_erase =
_lx_mflash_block_erase;
nor_flash->lx_nor_flash_driver_block_erased_verify =
_lx_mflash_block_erased_verify;
nor_flash->lx_nor_flash_driver_system_error =
_lx_mflash_system_error;
nor_flash->lx_nor_flash_sector_buffer =
_lx_nor_sector_buffer;
return LX_SUCCESS;
}
status_t erase_flash_disk(uint32_t offset, uint32_t disk_size)
{
UINT ret;
int block;
LX_PARAMETER_NOT_USED(offset);
LX_PARAMETER_NOT_USED(disk_size);
assert(LX_NOR_DISK_SIZE != 0);
assert(LX_NOR_DISK_FLASH_OFF != 0);
if (is_mflash_driver_ready == false) {
ret = mflash_drv_init();
if (ret != kStatus_Success)
{
PRINTF("ERR: mflash_drv_init() error\r\n");
return LX_ERROR;
}
is_mflash_driver_ready = true;
}
for (block = 0; block < LX_NOR_DISK_SIZE / LX_NOR_BLOCK_SIZE; block++)
{
PRINTF(".");
ret = _lx_mflash_block_erase(block, 1);
if (ret != LX_SUCCESS)
{
return kStatus_Fail;
}
}
PRINTF("\r\n");
return kStatus_Success;
}