mcu_hi3321_watch/tjd/driver/nandflash/flash_api.c
2025-05-26 20:15:20 +08:00

526 lines
16 KiB
C

/*----------------------------------------------------------------------------
* Copyright (c) Fenda Technologies Co., Ltd. 2020. All rights reserved.
*
* Description: flash_api.c
*
* Author: saimen
*
* Create: 2020-09-25
*--------------------------------------------------------------------------*/
//lib
#include "stdlib.h"
#include <string.h>
//os
//sdk
//drv
//#include "flash_port_mspi.h"
#include "flash_port_sdio.h"
#include "flash_drv_kas041s1.h"
#include "flash_api.h"
//user
#define ENABLE_STATIC_PRINT false
extern uint32_t flash_port_print(const char *pcFmt, ...);
#define static_print_remind(...) flash_port_print(__VA_ARGS__)
#if ENABLE_STATIC_PRINT
#define static_print_info(...) flash_port_print(__VA_ARGS__)
#else
#define static_print_info(...)
#endif
#define FLASH_MX25U51245G_CHIP_ID 0xC2253A
#define FLASH_DS35M_CHIP_ID 0xF1
#define FLASH_EMMC_KOWIN4G_CHIP_ID 0X30343153
typedef struct {
uint32_t type; /* nor,nand,emmc */
uint32_t count;
uint32_t chip_id;
uint32_t total_size;
uint32_t erase_unit_size;
uint32_t read_unit_size;
uint32_t write_unit_size;
uint32_t spare_unit_size;
uint32_t fs_memory_base;
uint32_t fs_memory_size;
uint32_t fs_unit_base;
uint32_t (*get_chip_id) (void);
uint32_t (*get_expect_id) (void);
uint32_t (*get_total_size) (void);
uint32_t (*get_read_unit_size) (void);
uint32_t (*get_write_unit_size) (void);
uint32_t (*get_erase_unit_size) (void);
uint32_t (*get_spare_unit_size) (void);
int (*deinit) (void);
int (*open) (void);
int (*close) (void);
int (*get_status) (void);
int (*enter_low_power) (void);
int (*exit_low_power) (void);
int (*erase_chip) (void);
int (*erase) (uint32_t ui32_addr);
int (*read) (uint32_t ui32_addr, uint8_t *p_data, uint32_t ui32_length);
int (*write) (uint32_t ui32_addr, uint8_t *p_data, uint32_t ui32_length);
int (*read_ex) (uint32_t ui32_addr, uint8_t *p_data, uint32_t ui32_length);
//lfs
int (*lfs_erase) (uint32_t block);
int (*lfs_read) (uint32_t block, uint32_t offset, uint8_t *buffer, uint32_t size);
int (*lfs_write) (uint32_t block, uint32_t offset, uint8_t *buffer, uint32_t size);
//yaffs
int (*yaffs_erase) (uint32_t ui32_addr);
int (*yaffs_read) (uint32_t page_offset, uint16_t addr_offset, uint8_t *out_data, uint16_t len);
int (*yaffs_write) (uint32_t page_offset, uint16_t addr_offset, uint8_t *in_data, uint16_t len);
int (*yaffs_switch_ecc) (bool sw);
}flash_info;
static flash_info g_flash_info = {0};
/*-------------------------------*/
//
//共用接口
//
/*-------------------------------*/
void flash_api_create_lock(void)
{
flash_port_create_mutex();
}
void flash_api_null_function(void)
{
g_flash_info.count++;
}
int flash_api_init(void)
{
uint32_t u32_id;
uint8_t i=0;
g_flash_info.chip_id = NULL;
flash_port_mutex_lock();
for(i=0;i<3;i++)
{
#if 0
if (g_flash_info.chip_id == NULL)
{
flash_drv_mx25u512_info_init(flash_port_transfer_cb);
flash_drv_mx25u512_open();
u32_id = flash_drv_mx25u512_read_id();
if(u32_id == FLASH_MX25U51245G_CHIP_ID)
{
g_flash_info.type = FLASH_TYPE_NOR;
g_flash_info.chip_id = u32_id;
g_flash_info.get_chip_id = flash_drv_mx25u512_read_id;
g_flash_info.total_size = MX25U51245G_TOTAL_SIZE;
g_flash_info.erase_unit_size = MX25U51245G_SECTOR_SIZE;
g_flash_info.read_unit_size = MX25U51245G_PAGE_SIZE;
g_flash_info.write_unit_size = MX25U51245G_PAGE_SIZE;
g_flash_info.spare_unit_size = 0;
g_flash_info.fs_memory_base = MX25U51245G_FS_BASE_SECTOR*MX25U51245G_SECTOR_SIZE;
g_flash_info.fs_memory_size = MX25U51245G_FS_SECTORS*MX25U51245G_SECTOR_SIZE;
g_flash_info.open = flash_drv_mx25u512_open;
g_flash_info.close = flash_drv_mx25u512_close;
g_flash_info.get_status = flash_drv_mx25u512_read_status;
g_flash_info.enter_low_power = flash_drv_mx25u512_enter_power_down;
g_flash_info.exit_low_power = flash_drv_mx25u512_exit_power_down;
g_flash_info.erase_chip = flash_drv_mx25u512_chip_erase;
g_flash_info.erase = flash_drv_mx25u512_sector_erase;
g_flash_info.read = flash_drv_mx25u512_read_nonblocking;
g_flash_info.write = flash_drv_mx25u512_write_nonblocking;
g_flash_info.read_ex = flash_drv_mx25u512_read_nonblocking_ex;
g_flash_info.lfs_erase = flash_drv_mx25u512_sector_erase;
g_flash_info.lfs_read = flash_drv_mx25u512_read_nonblocking;
g_flash_info.lfs_write = flash_drv_mx25u512_write_nonblocking;
g_flash_info.yaffs_erase = NULL;
g_flash_info.yaffs_read = NULL;
g_flash_info.yaffs_write = NULL;
g_flash_info.yaffs_switch_ecc =NULL;
break;
}
else
{
flash_drv_mx25u512_close();
}
static_print_remind("flash_drv_mx25u512_read_id: 0X%X\r\n",u32_id);
}
if (g_flash_info.chip_id == NULL)
{
Ds35m_Init();
Ds35m_ReadId(&u16_id);
if(u16_id == FLASH_DS35M_CHIP_ID)
{
g_flash_info.chip_id = (uint32_t)(u16_id);
g_flash_info.type = FLASH_TYPE_NAND;
break;
}
else
{
Ds35m_Deinit();
}
static_print_remind("Ds35m_ReadId:0X%X\r\n",u16_id);
}
#endif
if (g_flash_info.chip_id == NULL)
{
flash_drv_kas041s1_open();
u32_id = flash_drv_kas041s1_get_chip_id();
if(u32_id == FLASH_EMMC_KOWIN4G_CHIP_ID)
{
g_flash_info.type = FLASH_TYPE_EMMC;
g_flash_info.chip_id = u32_id;
g_flash_info.get_chip_id = flash_drv_kas041s1_get_chip_id;
g_flash_info.total_size = EMMC_KAS041S1_TOTAL_SIZE;
g_flash_info.erase_unit_size = EMMC_KAS041S1_ERASE_UNIT_SIZE;
g_flash_info.read_unit_size = EMMC_KAS041S1_READ_UNIT_SIZE;
g_flash_info.write_unit_size = EMMC_KAS041S1_WRITE_UNIT_SIZE;
g_flash_info.spare_unit_size = 0;
g_flash_info.fs_memory_base = EMMC_KAS041S1_FS_MEMORY_BASE;
g_flash_info.fs_memory_size = EMMC_KAS041S1_FS_MEMORY_SIZE;
g_flash_info.fs_unit_base = (EMMC_KAS041S1_FS_MEMORY_BASE/EMMC_KAS041S1_ERASE_UNIT_SIZE);
g_flash_info.open = flash_drv_kas041s1_open;
g_flash_info.close = flash_drv_kas041s1_close;
g_flash_info.get_status = flash_drv_kas041s1_get_status;
g_flash_info.enter_low_power = flash_drv_kas041s1_enter_low_power;
g_flash_info.exit_low_power = flash_drv_kas041s1_exit_low_power;
g_flash_info.erase_chip = flash_drv_kas041s1_erase_chip;
g_flash_info.erase = flash_drv_kas041s1_erase;
g_flash_info.read = flash_drv_kas041s1_read;
g_flash_info.write = flash_drv_kas041s1_write;
g_flash_info.read_ex = flash_drv_kas041s1_read_ex;
g_flash_info.lfs_erase = flash_drv_kas041s1_lfs_erase;
g_flash_info.lfs_read = flash_drv_kas041s1_lfs_read;
g_flash_info.lfs_write = flash_drv_kas041s1_lfs_write;
g_flash_info.yaffs_erase = NULL;
g_flash_info.yaffs_read = NULL;
g_flash_info.yaffs_write = NULL;
g_flash_info.yaffs_switch_ecc =NULL;
break;
}
else
{
flash_drv_kas041s1_close();
}
static_print_remind("emmc_read_id: 0X%X\r\n",u32_id);
}
}
flash_port_mutex_unlock();
static_print_remind("flash_id: 0X%X\r\n",g_flash_info.chip_id);
return g_flash_info.chip_id;
}
int flash_api_deinit(void)
{
flash_port_mutex_lock();
if(g_flash_info.deinit)
{
g_flash_info.deinit();
}
flash_port_mutex_unlock();
return true;
}
int flash_api_open(void)
{
flash_port_mutex_lock();
if(g_flash_info.open)
{
g_flash_info.open();
}
flash_port_mutex_unlock();
return 0;
}
int flash_api_close(void)
{
flash_port_mutex_lock();
if(g_flash_info.close)
{
g_flash_info.close();
}
flash_port_mutex_unlock();
return 0;
}
uint32_t flash_api_get_status(void)
{
if(g_flash_info.get_status)
{
return g_flash_info.get_status();
}
return false;
}
int flash_api_enter_low_power(void)
{
flash_port_mutex_lock();
if(g_flash_info.enter_low_power)
{
g_flash_info.enter_low_power();
}
flash_port_mutex_unlock();
return true;
}
int flash_api_exit_low_power(void)
{
flash_port_mutex_lock();
if(g_flash_info.exit_low_power)
{
g_flash_info.exit_low_power();
}
flash_port_mutex_unlock();
return true;
}
uint32_t flash_api_get_chip_id(void)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.get_chip_id)
{
u32_ret = g_flash_info.get_chip_id();
}
flash_port_mutex_unlock();
return u32_ret;
}
uint32_t flash_api_get_expect_id(void)
{
return g_flash_info.chip_id;
}
uint32_t flash_api_get_type(void)
{
return g_flash_info.type;
}
uint32_t flash_api_get_total_size(void)
{
return g_flash_info.total_size;
}
uint32_t flash_api_get_read_unit_size(void)
{
return g_flash_info.read_unit_size;
}
uint32_t flash_api_get_write_unit_size(void)
{
return g_flash_info.write_unit_size;
}
uint32_t flash_api_get_erase_unit_size(void)
{
return g_flash_info.erase_unit_size;
}
uint32_t flash_api_get_spare_unit_size(void)
{
return g_flash_info.spare_unit_size;
}
int flash_api_erase_chip(void)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.erase_chip)
{
u32_ret = g_flash_info.erase_chip();
}
flash_port_mutex_unlock();
return u32_ret;
}
int flash_api_erase(uint32_t ui32_addr)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.erase)
{
u32_ret = g_flash_info.erase(ui32_addr);
}
flash_port_mutex_unlock();
return u32_ret;
}
int flash_api_read_ex(uint32_t ui32_addr, void *p_data, uint32_t ui32_length)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.read_ex)
{
u32_ret = g_flash_info.read_ex(ui32_addr, p_data, ui32_length);
}
flash_port_mutex_unlock();
return u32_ret;
}
int flash_api_read(uint32_t ui32_addr, void *p_data, uint32_t ui32_length)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.read)
{
u32_ret = g_flash_info.read(ui32_addr, p_data, ui32_length);
}
flash_port_mutex_unlock();
return u32_ret;
}
int flash_api_write(uint32_t ui32_addr, void *p_data, uint32_t ui32_length)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.write)
{
u32_ret = g_flash_info.write(ui32_addr, p_data, ui32_length);
}
flash_port_mutex_unlock();
return u32_ret;
}
uint32_t flash_api_get_fs_memory_base(void)
{
return g_flash_info.fs_memory_base;
}
uint32_t flash_api_get_fs_memory_size(void)
{
return g_flash_info.fs_memory_size;
}
/*-------------------------------*/
//
//api lfs
//
/*-------------------------------*/
int flash_api_lfs_erase(void *c, uint32_t block)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.lfs_erase)
{
u32_ret = g_flash_info.lfs_erase((block+g_flash_info.fs_unit_base)*g_flash_info.erase_unit_size);
}
flash_port_mutex_unlock();
return u32_ret;
}
int flash_api_lfs_read(void *c, uint32_t block, uint32_t offset, void *buffer, uint32_t size)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.lfs_read)
{
u32_ret = g_flash_info.lfs_read((block+g_flash_info.fs_unit_base), offset, buffer, size);
}
flash_port_mutex_unlock();
return u32_ret;
}
int flash_api_lfs_write(void *c, uint32_t block, uint32_t offset, void *buffer, uint32_t size)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.lfs_write)
{
u32_ret = g_flash_info.lfs_write((block+g_flash_info.fs_unit_base), offset, buffer, size);
}
flash_port_mutex_unlock();
return u32_ret;
}
/*-------------------------------*/
//
//api yaffs
//
/*-------------------------------*/
int flash_api_yaffs_erase(uint32_t ui32_addr)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.yaffs_erase)
{
u32_ret = g_flash_info.yaffs_erase(ui32_addr+g_flash_info.fs_unit_base);
}
flash_port_mutex_unlock();
return u32_ret;
}
int flash_api_yaffs_read(uint32_t page_offset, uint16_t addr_offset, uint8_t *buffer, uint16_t len)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.yaffs_read)
{
u32_ret = g_flash_info.yaffs_read(page_offset+g_flash_info.fs_unit_base, addr_offset, buffer, len);
}
flash_port_mutex_unlock();
return u32_ret;
}
int flash_api_yaffs_write(uint32_t page_offset, uint16_t addr_offset, uint8_t *buffer, uint16_t len)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.yaffs_write)
{
u32_ret = g_flash_info.yaffs_write(page_offset+g_flash_info.fs_unit_base, addr_offset, buffer, len);
}
flash_port_mutex_unlock();
return u32_ret;
}
int flash_api_yaffs_switch_ecc(bool sw)
{
uint32_t u32_ret = 0;
flash_port_mutex_lock();
if(g_flash_info.yaffs_switch_ecc)
{
u32_ret = g_flash_info.yaffs_switch_ecc(sw);
}
flash_port_mutex_unlock();
return u32_ret;
}
//api test
void flash_api_test (void)
{
#if 1
#define BLK_NUM 2
#define BUF_LEN 512*BLK_NUM
uint8_t buffer_wr[BUF_LEN] __attribute__((aligned(8)));
uint8_t buffer_rd[BUF_LEN] __attribute__((aligned(8)));
uint32_t u32_addr = 0x0;
#endif
for (int i = 0; i < BUF_LEN; i++)
{
buffer_wr[i] = i % 256;
}
for(uint8_t i=0;i<2;i++)
{
flash_port_delay_ms(100);
static_print_remind("FLASH CHIP ID = 0x%x \r\n",flash_api_get_chip_id());
static_print_remind("\r\n flash_api_write \r\n");
flash_api_write(u32_addr, (uint8_t *)buffer_wr, BUF_LEN);
memset((void *)buffer_rd, 0x0, BUF_LEN);
flash_api_read(u32_addr, (uint8_t *)buffer_rd, BUF_LEN);
static_print_remind("%02x %02x %02x %02x\r\n",buffer_rd[0],buffer_rd[1],buffer_rd[2],buffer_rd[3]);
static_print_remind("%02x %02x %02x %02x\r\n",buffer_rd[4],buffer_rd[5],buffer_rd[6],buffer_rd[7]);
static_print_remind("\r\n flash_api_erase \r\n");
flash_api_erase(u32_addr);
memset((void *)buffer_rd, 0x0, BUF_LEN);
flash_api_read(u32_addr, (uint8_t *)buffer_rd, BUF_LEN);
static_print_remind("%02x %02x %02x %02x\r\n",buffer_rd[0],buffer_rd[1],buffer_rd[2],buffer_rd[3]);
static_print_remind("%02x %02x %02x %02x\r\n",buffer_rd[4],buffer_rd[5],buffer_rd[6],buffer_rd[7]);
static_print_remind("============================================================\r\n");
}
}