526 lines
16 KiB
C
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");
|
|
}
|
|
}
|