Initial import of NFC GNSS SDK project
This commit is contained in:
@@ -0,0 +1,780 @@
|
||||
/*==========================================================================================================
|
||||
Copyright (c) 2021, Quectel Wireless Solutions Co., Ltd. All rights reserved.
|
||||
Quectel Wireless Solutions Proprietary and Confidential.
|
||||
===========================================================================================================*/
|
||||
|
||||
/*==========================================================================================================
|
||||
|
||||
EDIT HISTORY FOR MODULE
|
||||
|
||||
This section contains comments describing changes made to the module.
|
||||
Notice that changes are listed in reverse chronological order.
|
||||
|
||||
WHEN WHO WHAT, WHERE, WHY
|
||||
------------ ------- -------------------------------------------------------------------------------
|
||||
10/04/2022 Sharon.li 此文件是操作内部Nor Flash的(QSPI)的接口INTERNAL_NORFLASH
|
||||
===========================================================================================================*/
|
||||
#include "loadTable.h"
|
||||
#include "quec_debug.h"
|
||||
#include <string.h>
|
||||
#include "loadTable.h"
|
||||
#include "quec_flash.h"
|
||||
#include "UART.h"
|
||||
#include "qspi_nor.h"
|
||||
#include <lfs_cache.h>
|
||||
#include "Flash_wk.h"
|
||||
|
||||
#define quec_flash_printf(msg, ...) custom_log("Flash_LOG", msg, ##__VA_ARGS__)
|
||||
|
||||
|
||||
#ifdef QUEC_LIMIT_FLASH_ERASE //分区擦除保护功能,用于实现当前分区是否可以被擦除
|
||||
typedef struct
|
||||
{
|
||||
UINT32 start_addr; //addr not 0x80000000
|
||||
UINT32 end_addr;
|
||||
}QUEC_PART_ADDR_S;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char name[16];//分区名称
|
||||
char erase_flag;//分区是否能被擦除 1,可以被擦除;0,不能被擦除
|
||||
QUEC_PART_ADDR_S AddrInfo;//分区的结束地址和起始地址
|
||||
}QUEC_PART_ADDR_TYPE_S;
|
||||
|
||||
QUEC_PART_ADDR_TYPE_S QUEC_PART_ADDR_TYPE_AERA[]={
|
||||
{"nvm",1,NULL},
|
||||
{"quec_cfg",1,NULL},
|
||||
{"fota_param",1,NULL},
|
||||
{"factory_a",1,NULL},
|
||||
{"factory_b",1,NULL},
|
||||
{"erase_rd",1,NULL},
|
||||
{"bootloader",NULL},
|
||||
{"ptable",0,NULL},
|
||||
{"fwcerts",0,NULL},
|
||||
{"rd",0,NULL},
|
||||
{"cp",0,NULL},
|
||||
{"dsp",0,NULL},
|
||||
{"rfbin",0,NULL},
|
||||
{"customer_app",1,NULL},
|
||||
{"reserved",0,NULL},
|
||||
{"logo",0,NULL},
|
||||
};
|
||||
#define QFTEST_PARTITION_COUNT_MAX (sizeof(QUEC_PART_ADDR_TYPE_AERA)/sizeof(QUEC_PART_ADDR_TYPE_AERA[0]))
|
||||
UINT32 G_QftestEraseCount[QFTEST_PARTITION_COUNT_MAX] = {0};
|
||||
|
||||
//初始化分区信息
|
||||
UINT32 CHECK_FLASH_AREA_ADDR_CONFIG(void)
|
||||
{
|
||||
int len = QFTEST_PARTITION_COUNT_MAX;
|
||||
_ptentry *pnt;
|
||||
int i;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
pnt=ptable_find_entry(QUEC_PART_ADDR_TYPE_AERA[i].name);
|
||||
if(pnt==NULL)
|
||||
{
|
||||
uart_printf("Egan_check flash not found name=%s\r\n",QUEC_PART_ADDR_TYPE_AERA[i].name);
|
||||
continue;
|
||||
}
|
||||
QUEC_PART_ADDR_TYPE_AERA[i].AddrInfo.start_addr=pnt->start;
|
||||
QUEC_PART_ADDR_TYPE_AERA[i].AddrInfo.end_addr=pnt->start + pnt->size;
|
||||
// uart_printf("Egan_flash_name=%s flash_addr=0x%x flash_end=0x%x \r\n",QUEC_PART_ADDR_TYPE_AERA[i].name,QUEC_PART_ADDR_TYPE_AERA[i].AddrInfo.start_addr,QUEC_PART_ADDR_TYPE_AERA[i].AddrInfo.end_addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//检查指定的Flash地址和大小是否可以被擦除
|
||||
//flash_addr:要擦除Flash地址
|
||||
//flash_size:擦除的大小
|
||||
//rw_flag:是否记录此次擦除,0,不记录;1,记录
|
||||
UINT32 FLASH_LIMIT_ALLOW_AREA(UINT32 flash_addr,UINT32 flash_size,BOOL rw_flag)
|
||||
{
|
||||
int len = QFTEST_PARTITION_COUNT_MAX;
|
||||
int i;
|
||||
QUEC_PART_ADDR_TYPE_S *ptr=QUEC_PART_ADDR_TYPE_AERA;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
if((flash_addr>=ptr[i].AddrInfo.start_addr)&&((flash_addr + flash_size) <= ptr[i].AddrInfo.end_addr))
|
||||
{
|
||||
if((ptr[i].erase_flag==1)&&(flash_size!=NULL))
|
||||
{
|
||||
if(rw_flag)
|
||||
G_QftestEraseCount[i]++;
|
||||
break;
|
||||
}
|
||||
else{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*****************************************************************
|
||||
* Function: QUEC_PART_ADDR_TYPE_AERA_GET_CNT
|
||||
*
|
||||
* Description:
|
||||
* 获取数组QUEC_PART_ADDR_TYPE_AERA的下标值
|
||||
* Parameters:
|
||||
* name [in] partition name
|
||||
*
|
||||
* Return:
|
||||
* -1 failure
|
||||
*****************************************************************/
|
||||
|
||||
int QUEC_PART_ADDR_TYPE_AERA_GET_CNT(const char *name)
|
||||
{
|
||||
int len = QFTEST_PARTITION_COUNT_MAX;
|
||||
int i;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
if(!strcmp(name, QUEC_PART_ADDR_TYPE_AERA[i].name))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define CHIP_SECTOR_SIZE 0x1000 //erase 4k each times
|
||||
UINT16 g_FlashBlkEraseCnt[1024]; //4M for nvm erea
|
||||
UINT16 g_FlashBlkEraseTotal = 0;
|
||||
|
||||
extern UINT32 nvm_flash_start_addr;
|
||||
|
||||
#ifdef QUEC_FS_WEAR_BALANCE_VERIFY //QuecOpen 记录文件系统均衡的次数
|
||||
UINT32 customer_fs_flash_start_addr = 0;
|
||||
UINT32 gFsRWBkTotalCnt = 0; //存储文件系统擦写的总次数
|
||||
UINT32 *gFsPerBkRWCnt = NULL; //存储每块block的擦写次数
|
||||
UINT32 gFsTotalBkCnt = 0; //存储文件系统block的数量
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//检查指定的Flash地址是否在某个分区内
|
||||
//0:Flash地址不在指定的分区内;1:Flash地址在指定的分区内部
|
||||
UINT32 CHECK_FLASH_AREA(const char *name,UINT32 flash_addr,UINT32 flash_size)
|
||||
{
|
||||
_ptentry *pnt;
|
||||
pnt=ptable_find_entry(name);
|
||||
if(pnt==NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if(flash_addr>=pnt->start)
|
||||
{
|
||||
if((flash_addr+ flash_size)<= (pnt->start + pnt->size))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define CRANE_NVM_ON_FLASH_BASE_ADD (nvm_flash_start_addr&0xF0000000)
|
||||
#define CRANE_COUSTOMER_FS_ON_FLASH_BASE_ADD (customer_fs_flash_start_addr&0XF0000000)
|
||||
|
||||
|
||||
//记录flash_addr所在分区的第几个block,被擦除的次数
|
||||
UINT32 Flash_erase_count_Set(UINT32 flash_addr,UINT32 size)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
UINT32 nvm_block_id=(CRANE_NVM_ON_FLASH_BASE_ADD+flash_addr-nvm_flash_start_addr)/CHIP_SECTOR_SIZE;
|
||||
|
||||
if(g_FlashBlkEraseCnt == NULL)
|
||||
return 0;
|
||||
|
||||
if(CHECK_FLASH_AREA("nvm",flash_addr,size))
|
||||
{
|
||||
for(i=0;i*CHIP_SECTOR_SIZE<size;i++)
|
||||
{
|
||||
g_FlashBlkEraseCnt[nvm_block_id+i]++;
|
||||
g_FlashBlkEraseTotal++;
|
||||
}
|
||||
}
|
||||
#ifdef QUEC_FS_WEAR_BALANCE_VERIFY //QuecOpen 记录文件系统均衡的次数
|
||||
if(CHECK_FLASH_AREA("customer_fs",flash_addr,size))
|
||||
{
|
||||
UINT32 customer_fs_block_id=(CRANE_COUSTOMER_FS_ON_FLASH_BASE_ADD+flash_addr-customer_fs_flash_start_addr)/CHIP_SECTOR_SIZE;
|
||||
//RTI_LOG("flash_addr(0x%x),size(0x%x),customer_fs_block_id(0x%x)\r\n",flash_addr,size,customer_fs_block_id);
|
||||
if(NULL != gFsPerBkRWCnt)
|
||||
{
|
||||
for(i=0;i*CHIP_SECTOR_SIZE<size;i++)
|
||||
{
|
||||
gFsPerBkRWCnt[customer_fs_block_id+i]++;
|
||||
gFsRWBkTotalCnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void quec_norflash_get_addr(unsigned char *patition_name, unsigned int *start_addr, unsigned int *size)
|
||||
{
|
||||
unsigned int end_addr=0;
|
||||
|
||||
*start_addr=quec_get_patition_start_address((const char *)patition_name);
|
||||
end_addr=quec_get_patition_end_address((const char *)patition_name);
|
||||
*size=end_addr-*start_addr;
|
||||
}
|
||||
|
||||
|
||||
unsigned int quec_norflash_do_read(unsigned char *patition_name, unsigned int addr, unsigned int buf_addr, unsigned int size)
|
||||
{
|
||||
unsigned int ret=FLASH_RW_ERROR;
|
||||
unsigned int start_address=0;
|
||||
unsigned int end_address=0;
|
||||
unsigned int free_size=0;
|
||||
unsigned int relative_addr = 0;
|
||||
|
||||
relative_addr = addr&0x7FFFFFFF;
|
||||
start_address=quec_get_patition_start_address((const char *)patition_name);
|
||||
end_address=quec_get_patition_end_address((const char *)patition_name);
|
||||
|
||||
if(addr<start_address || addr>end_address)
|
||||
{
|
||||
uart_printf("error address param \n");
|
||||
return FLASH_RW_ERROR;
|
||||
}
|
||||
|
||||
free_size=end_address-addr;
|
||||
if(size<=free_size)
|
||||
{
|
||||
ret = spi_nor_do_read(relative_addr, buf_addr, size, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_printf("no enough free space \n");
|
||||
ret = FLASH_RW_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int quec_norflash_do_write(unsigned char *patition_name, unsigned int addr, unsigned int buf_addr, unsigned int size)
|
||||
{
|
||||
unsigned int ret=FLASH_RW_ERROR;
|
||||
unsigned int start_address=0;
|
||||
unsigned int end_address=0;
|
||||
unsigned int free_size=0;
|
||||
unsigned int relative_addr = 0;
|
||||
unsigned char buf[10] = {0};
|
||||
|
||||
relative_addr = addr&0x7FFFFFFF;
|
||||
start_address=quec_get_patition_start_address((const char *)patition_name);
|
||||
end_address=quec_get_patition_end_address((const char *)patition_name);
|
||||
|
||||
if(addr<start_address || addr>end_address)
|
||||
{
|
||||
uart_printf("error address param \n");
|
||||
return FLASH_RW_ERROR;
|
||||
}
|
||||
|
||||
free_size=end_address-addr;
|
||||
if(size<=free_size)
|
||||
{
|
||||
if(size >= 8)
|
||||
{
|
||||
ret = spi_nor_do_write(relative_addr, buf_addr, size, 0);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(buf, 0xFF, 10);
|
||||
memcpy(buf,(const void *)buf_addr, size);
|
||||
ret = spi_nor_do_write(relative_addr, (unsigned int)&buf, 8, 0);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_printf("no enough free space \n");
|
||||
ret = FLASH_RW_ERROR;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
//erase a block for internal test
|
||||
int quec_erase_block(int blk_index, unsigned int disable_protect)
|
||||
{
|
||||
int flash_err = 0;
|
||||
lfsBlockInfo * p_blk_prop = NULL;
|
||||
|
||||
p_blk_prop = GetLfsBlkInfo(0);
|
||||
|
||||
//fatal_printf("EraseFlash_4k 0x%x 0x%x\r\n", flash_addr, size);
|
||||
|
||||
if(blk_index*p_blk_prop->FlashBlockSize > quec_get_patition_end_address("all"))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return spi_nor_do_erase_4k(blk_index*p_blk_prop->FlashBlockSize,p_blk_prop->FlashBlockSize, BOOT_FLASH);
|
||||
|
||||
}
|
||||
|
||||
//擦除,实现了非4K对齐的擦除
|
||||
int quec_norflash_do_erase(unsigned char *patition_name, unsigned int addr, unsigned int size)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
unsigned int sector_size = 4*1024;//4K
|
||||
unsigned int back_recovery_size=0;
|
||||
unsigned int start_address = 0;
|
||||
unsigned int end_address = 0;
|
||||
unsigned int free_size = 0;
|
||||
unsigned int erase_size = 0;
|
||||
volatile unsigned int sector_size_num = 0;
|
||||
volatile unsigned int sector_addr_num = 0;
|
||||
unsigned int relative_addr = 0;
|
||||
unsigned char *recovery_buf1 = NULL;
|
||||
unsigned char *recovery_buf2 = NULL;
|
||||
|
||||
relative_addr = addr&0x7FFFFFFF;
|
||||
start_address = quec_get_patition_start_address((const char *)patition_name);
|
||||
end_address = quec_get_patition_end_address((const char *)patition_name);
|
||||
|
||||
if(addr<start_address || addr>end_address)
|
||||
{
|
||||
uart_printf("error address param \n");
|
||||
return FLASH_RW_ERROR;
|
||||
}
|
||||
|
||||
free_size=end_address-addr;
|
||||
if(size <= free_size)
|
||||
{
|
||||
if(relative_addr%sector_size == 0)
|
||||
{
|
||||
if((size%sector_size == 0))
|
||||
{
|
||||
ret = spi_nor_do_erase_4k(relative_addr, size, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
recovery_buf1 = malloc(sector_size);
|
||||
sector_size_num = (relative_addr+size)/sector_size;
|
||||
back_recovery_size = size%sector_size;
|
||||
|
||||
spi_nor_do_read((sector_size_num*sector_size),(unsigned int)recovery_buf1, sector_size, 0);
|
||||
|
||||
ret = spi_nor_do_erase_4k(relative_addr, (size - (size%sector_size) + sector_size), 0);
|
||||
|
||||
spi_nor_do_write((relative_addr+size),(unsigned int)(recovery_buf1+back_recovery_size), (sector_size-back_recovery_size), 0);
|
||||
|
||||
free(recovery_buf1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((relative_addr+size)%sector_size ==0)
|
||||
{
|
||||
recovery_buf1 = malloc(sector_size);
|
||||
sector_addr_num = relative_addr/sector_size;
|
||||
|
||||
spi_nor_do_read((sector_addr_num*sector_size), (unsigned int)recovery_buf1, sector_size, 0);
|
||||
|
||||
ret = spi_nor_do_erase_4k((sector_addr_num*sector_size), (size + (relative_addr%sector_size)), 0);
|
||||
|
||||
spi_nor_do_write((sector_addr_num*sector_size), (unsigned int)recovery_buf1, (relative_addr%sector_size), 0);
|
||||
|
||||
free(recovery_buf1);
|
||||
}
|
||||
else
|
||||
{
|
||||
recovery_buf1 = malloc(sector_size);
|
||||
recovery_buf2 = malloc(sector_size);
|
||||
|
||||
sector_size_num = (relative_addr+size)/sector_size;
|
||||
sector_addr_num = relative_addr/sector_size;
|
||||
back_recovery_size = (relative_addr+size)%sector_size;
|
||||
erase_size = (size + relative_addr%sector_size);
|
||||
|
||||
spi_nor_do_read((sector_addr_num*sector_size), (unsigned int)recovery_buf1, sector_size, 0);
|
||||
spi_nor_do_read((sector_size_num*sector_size), (unsigned int)recovery_buf2, sector_size, 0);
|
||||
|
||||
ret = spi_nor_do_erase_4k((sector_addr_num*sector_size), (erase_size - (erase_size%sector_size) +sector_size), 0);
|
||||
|
||||
spi_nor_do_write((sector_addr_num*sector_size), (unsigned int)recovery_buf1, (relative_addr%sector_size), 0);
|
||||
|
||||
spi_nor_do_write((relative_addr+size), (unsigned int)(recovery_buf2+back_recovery_size), (sector_size-back_recovery_size), 0);
|
||||
|
||||
free(recovery_buf1);
|
||||
free(recovery_buf2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_printf("no enough free space \n");
|
||||
ret = FLASH_RW_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern unsigned int nor_flash_id;
|
||||
//获取内部QSPI Nor Flash的id
|
||||
int quec_norflash_read_id(void)
|
||||
{
|
||||
return nor_flash_id;
|
||||
}
|
||||
|
||||
UINT32 get_quec_cfg_start_address(void)
|
||||
{
|
||||
_ptentry * QUEC_CFG_Entry= ptable_find_entry("quec_cfg");
|
||||
return QUEC_CFG_Entry->vstart;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef QUEC_NORFLASH_ERASE_OPTIMIZE //补擦的实现
|
||||
|
||||
unsigned int Quec_EraseFlashExt(unsigned int addr, unsigned int size, unsigned char flashType);
|
||||
unsigned int Quec_ReadFlashExt(unsigned int addr, unsigned int buf_addr, unsigned int size, unsigned char flashType);
|
||||
unsigned int Quec_WriteFlashExt(unsigned int addr, unsigned int buf_addr,unsigned int size, unsigned char flashType);
|
||||
|
||||
UINT32 get_erase_rd_start_address(void)
|
||||
{
|
||||
_ptentry * erase_rd_start_Entry= ptable_find_entry("erase_rd");
|
||||
if(erase_rd_start_Entry==NULL)
|
||||
return NULL;
|
||||
return erase_rd_start_Entry->start;
|
||||
}
|
||||
UINT32 get_erase_rd_bin_size(void)
|
||||
{
|
||||
_ptentry * erase_rd_begin_Entry= ptable_find_entry("erase_rd");
|
||||
if(erase_rd_begin_Entry==NULL)
|
||||
return NULL;
|
||||
return erase_rd_begin_Entry->vsize;
|
||||
}
|
||||
|
||||
extern const char USER_ERASE_RECORD_AREA[2][16]; //user 补擦区域
|
||||
char ERASE_RECORD_AREA[][16]={
|
||||
"nvm",
|
||||
};//此数组+USER_ERASE_RECORD_AREA需要与boot33同步
|
||||
|
||||
int quec_repair_erase_get_parti_name_valid(char* parti_name)
|
||||
{
|
||||
int len =sizeof(ERASE_RECORD_AREA)/sizeof(ERASE_RECORD_AREA[0]);
|
||||
_ptentry *pnt = NULL;
|
||||
int i = 0;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
pnt=ptable_find_entry(ERASE_RECORD_AREA[i]);
|
||||
//分区存在,且属于补擦区域,必须要是内部flash
|
||||
if(pnt && !strcmp(ERASE_RECORD_AREA[i], parti_name) && ((pnt->vstart & 0xF0000000) == 0x80000000))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
len =sizeof(USER_ERASE_RECORD_AREA)/sizeof(USER_ERASE_RECORD_AREA[0]);
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
pnt=ptable_find_entry(USER_ERASE_RECORD_AREA[i]);
|
||||
//分区存在,且属于补擦区域,必须要是内部flash
|
||||
if(pnt && !strcmp(USER_ERASE_RECORD_AREA[i], parti_name) && ((pnt->vstart & 0xF0000000) == 0x80000000))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
UINT32 FLASH_ERASE_RECORD_ALLOW_AREA(UINT32 flash_addr,UINT32 size)
|
||||
{
|
||||
int len =sizeof(ERASE_RECORD_AREA)/sizeof(ERASE_RECORD_AREA[0]);
|
||||
_ptentry *pnt;
|
||||
int i;
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
pnt=ptable_find_entry(ERASE_RECORD_AREA[i]);
|
||||
//补擦的分区必须是内部分区才能判断地址范围
|
||||
if(pnt && ((pnt->vstart & 0xF0000000) == 0x80000000))
|
||||
{
|
||||
if(flash_addr >= pnt->start)
|
||||
{
|
||||
if((flash_addr+size) <= (pnt->start + pnt->size))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
len =sizeof(USER_ERASE_RECORD_AREA)/sizeof(USER_ERASE_RECORD_AREA[0]);
|
||||
for(i=0;i<len;i++)
|
||||
{
|
||||
pnt=ptable_find_entry(USER_ERASE_RECORD_AREA[i]);
|
||||
//补擦的分区必须是内部分区才能判断地址范围
|
||||
if(pnt && ((pnt->vstart & 0xF0000000) == 0x80000000))
|
||||
{
|
||||
if(flash_addr >= pnt->start)
|
||||
{
|
||||
if((flash_addr+size) <= (pnt->start + pnt->size))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define NoError 0x0
|
||||
#define QUEC_RECORD_MAGIC1 (0x78E5D4C2)
|
||||
#define QUEC_RECORD_MAGIC2 (0x54F7D60E) // only record cell 0 used , for mark record area is erase successed
|
||||
#define CHIP_SECTOR_SIZE 0x1000 //erase 4k each times
|
||||
#define CHIP_BLOCK_SIZE 0x10000 //erase 4k each times
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 flag;// 0xAAA55AA55
|
||||
UINT32 reserve;
|
||||
}quec_Eraseflag_s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 RecordMagic;
|
||||
UINT32 PageId; // recored the eraseing block id ,
|
||||
UINT32 Record_type; // recored the eraseing block or page
|
||||
}quec_RecordInfo_s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
quec_RecordInfo_s ReInfo;
|
||||
quec_Eraseflag_s Eflag;
|
||||
}quec_flashErase_record_s;
|
||||
|
||||
|
||||
UINT32 g_RecordCell = 0xffffffff;
|
||||
UINT8 g_IsfirstTimeReadRecordblock = 1;
|
||||
|
||||
|
||||
void Quec_FlashEraseRecord_step1(UINT32 flash_addr,quec_Record_type_enum type)
|
||||
{
|
||||
UINT32 Retval = NoError;
|
||||
quec_flashErase_record_s *p_BlkEraseRecordCell = NULL;
|
||||
quec_RecordInfo_s *p_BlkERCellInfo = NULL;
|
||||
quec_Eraseflag_s *p_BlkERCellflag = NULL;
|
||||
quec_RecordInfo_s BlkERecordCellInfo;
|
||||
char *Record_buff = NULL;
|
||||
int i=0, flash_BlkSize = 0;
|
||||
UINT32 QUEC_RECORD_BLOCKREASE_AREA_SIZE=get_erase_rd_bin_size();
|
||||
UINT32 QUEC_RECORD_BLOCKREASE_AREA_ADD=get_erase_rd_start_address();
|
||||
//如果是AT补擦测试,把当前cell的reserve记录为0X12345678,需先正常记录,此次必须为第二次记录
|
||||
#ifdef QUEC_FLASH_TEST_REPAIR_ERASE
|
||||
if(type == QUEC_FLASH_TEST_REPAIR_ERASE)
|
||||
{
|
||||
quec_flashErase_record_s* now_record = (quec_flashErase_record_s*)(QUEC_RECORD_BLOCKREASE_AREA_ADD+g_RecordCell*(sizeof(quec_flashErase_record_s)));
|
||||
uint32_t test_reserve_fg = 0X12345678;
|
||||
Retval = Quec_WriteFlashExt((unsigned int)&now_record->Eflag.reserve, (unsigned int)&test_reserve_fg, sizeof(uint32_t), 0);
|
||||
if(NoError != Retval)
|
||||
{
|
||||
RTI_LOG("WriteFlash failed, retval=%d, g_RecordCell=%d need Record EraseblockId=%d !!!!\r\n", Retval, g_RecordCell,BlkERecordCellInfo.PageId);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if((!QUEC_RECORD_BLOCKREASE_AREA_SIZE)||(!QUEC_RECORD_BLOCKREASE_AREA_ADD))
|
||||
{
|
||||
quec_flash_printf("not found erase_rd !!!");
|
||||
return ;
|
||||
}
|
||||
flash_BlkSize=type?CHIP_SECTOR_SIZE:CHIP_BLOCK_SIZE;
|
||||
if(0 == g_IsfirstTimeReadRecordblock)
|
||||
{
|
||||
g_RecordCell++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Record_buff = malloc(QUEC_RECORD_BLOCKREASE_AREA_SIZE);
|
||||
if(NULL == Record_buff)
|
||||
{
|
||||
quec_flash_printf("malloc failed !!!!!!!!");
|
||||
return;
|
||||
}
|
||||
Retval = Quec_ReadFlashExt(QUEC_RECORD_BLOCKREASE_AREA_ADD,(unsigned int)Record_buff,QUEC_RECORD_BLOCKREASE_AREA_SIZE, 0);
|
||||
if( NoError != Retval)
|
||||
{
|
||||
|
||||
if( NULL !=Record_buff )
|
||||
{
|
||||
free(Record_buff);
|
||||
Record_buff = NULL;
|
||||
}
|
||||
quec_flash_printf("Flash read failed !!");
|
||||
return;
|
||||
}
|
||||
// check record block is erase successed
|
||||
p_BlkEraseRecordCell = (quec_flashErase_record_s*)Record_buff; // check the 0 cell which is mark for record area not erase
|
||||
p_BlkERCellInfo = (quec_RecordInfo_s*)Record_buff;
|
||||
if(QUEC_RECORD_MAGIC2 == p_BlkERCellInfo->RecordMagic && 0x00 == p_BlkERCellInfo->PageId)
|
||||
{
|
||||
// scan for 1 . because cell 0 is a flag which mark the block is not erase
|
||||
for( i=1; i*sizeof(quec_flashErase_record_s)<QUEC_RECORD_BLOCKREASE_AREA_SIZE; i++)
|
||||
{
|
||||
p_BlkEraseRecordCell = (quec_flashErase_record_s*)Record_buff+i;
|
||||
p_BlkERCellInfo = (quec_RecordInfo_s *)p_BlkEraseRecordCell;//
|
||||
p_BlkERCellflag = (quec_Eraseflag_s *)((char *)p_BlkEraseRecordCell + sizeof(p_BlkEraseRecordCell->ReInfo));
|
||||
if(( 0xffffffff == p_BlkERCellInfo->PageId ) && ( 0xffffffff == p_BlkERCellflag->flag)) // this record cell is not used
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_RecordCell = i;
|
||||
quec_flash_printf("g_RecordCall =%d\r\n",g_RecordCell);
|
||||
g_IsfirstTimeReadRecordblock = 0;
|
||||
if( NULL !=Record_buff )
|
||||
{
|
||||
free(Record_buff);
|
||||
Record_buff = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Retval = NoError;
|
||||
if( 0xffffffff != p_BlkERCellInfo->RecordMagic )
|
||||
{
|
||||
Retval = Quec_EraseFlashExt(QUEC_RECORD_BLOCKREASE_AREA_ADD, QUEC_RECORD_BLOCKREASE_AREA_SIZE, 0);
|
||||
}
|
||||
if(NoError ==Retval)
|
||||
{
|
||||
BlkERecordCellInfo.RecordMagic = QUEC_RECORD_MAGIC2;
|
||||
BlkERecordCellInfo.PageId = 0x00;
|
||||
Retval = Quec_WriteFlashExt(QUEC_RECORD_BLOCKREASE_AREA_ADD, (unsigned int)&BlkERecordCellInfo, sizeof(BlkERecordCellInfo),0);
|
||||
if(NoError !=Retval)
|
||||
{
|
||||
quec_flash_printf("[Ramos], write cell0 EraseRecord area erase flag faild !!!!!");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
quec_flash_printf("[Ramos], erase record area fail !!!!!!");
|
||||
return ;
|
||||
}
|
||||
g_RecordCell = 1; // record block erase cell form cell 1. because cell 0 used record RecordArea erase success flag
|
||||
}
|
||||
if( NULL !=Record_buff )
|
||||
{
|
||||
free(Record_buff);
|
||||
Record_buff = NULL;
|
||||
}
|
||||
}
|
||||
//quec_flashErase_record_s 20 Byte 最后一个cell不止要小于尾地址,而且范围也不能超过
|
||||
if( (g_RecordCell*sizeof(quec_flashErase_record_s) >= QUEC_RECORD_BLOCKREASE_AREA_SIZE) ||
|
||||
(g_RecordCell*sizeof(quec_flashErase_record_s)+sizeof(quec_flashErase_record_s) > QUEC_RECORD_BLOCKREASE_AREA_SIZE)
|
||||
)
|
||||
{
|
||||
Retval = Quec_EraseFlashExt(QUEC_RECORD_BLOCKREASE_AREA_ADD, QUEC_RECORD_BLOCKREASE_AREA_SIZE, 0);
|
||||
if(NoError ==Retval)
|
||||
{
|
||||
BlkERecordCellInfo.RecordMagic = QUEC_RECORD_MAGIC2;
|
||||
BlkERecordCellInfo.PageId = 0x00;
|
||||
Retval = Quec_WriteFlashExt(QUEC_RECORD_BLOCKREASE_AREA_ADD, (unsigned int)&BlkERecordCellInfo, sizeof(BlkERecordCellInfo),0);
|
||||
if(NoError !=Retval)
|
||||
{
|
||||
quec_flash_printf("[Ramos], write cell0 EraseRecord area erase flag faild !!!!!");
|
||||
return ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
quec_flash_printf("[Ramos], erase record area fail !!!!!!");
|
||||
return ;
|
||||
}
|
||||
g_RecordCell = 1; // record block erase cell form cell 1. because cell 0 used record RecordArea erase success flag
|
||||
}
|
||||
|
||||
BlkERecordCellInfo.RecordMagic = QUEC_RECORD_MAGIC1;
|
||||
BlkERecordCellInfo.PageId = flash_addr/flash_BlkSize;
|
||||
BlkERecordCellInfo.Record_type=type;
|
||||
quec_flash_printf("addr %x type %d",flash_addr,type);
|
||||
Retval = Quec_WriteFlashExt((QUEC_RECORD_BLOCKREASE_AREA_ADD+g_RecordCell*(sizeof(quec_flashErase_record_s))), (unsigned int)&(BlkERecordCellInfo), sizeof(BlkERecordCellInfo),0);
|
||||
if(NoError != Retval)
|
||||
{
|
||||
quec_flash_printf("WriteFlash failed, retval=%d, g_RecordCell=%d need Record EraseblockId=%d !!!!", Retval, g_RecordCell,BlkERecordCellInfo.PageId);
|
||||
}
|
||||
memset(&BlkERecordCellInfo,0,sizeof(BlkERecordCellInfo));
|
||||
Retval = Quec_ReadFlashExt((QUEC_RECORD_BLOCKREASE_AREA_ADD+g_RecordCell*(sizeof(quec_flashErase_record_s))), (unsigned int)&(BlkERecordCellInfo), sizeof(BlkERecordCellInfo),0);
|
||||
if(NoError != Retval)
|
||||
{
|
||||
quec_flash_printf("readFlash failed, retval=%d, g_RecordCell=%d need Record EraseblockId=%d !!!!", Retval, g_RecordCell,BlkERecordCellInfo.PageId);
|
||||
}
|
||||
uint32_t read_record_addr = BlkERecordCellInfo.PageId * (flash_BlkSize=type?CHIP_SECTOR_SIZE:CHIP_BLOCK_SIZE);
|
||||
if( (BlkERecordCellInfo.RecordMagic != QUEC_RECORD_MAGIC1) ||
|
||||
(!FLASH_ERASE_RECORD_ALLOW_AREA(read_record_addr, flash_BlkSize)) ||
|
||||
(BlkERecordCellInfo.Record_type != type))
|
||||
{
|
||||
quec_Eraseflag_s BlkERecordCellflag;
|
||||
BlkERecordCellflag.flag=0xAAAA5555;
|
||||
BlkERecordCellflag.reserve = 0xffffffff;
|
||||
|
||||
if(0xffffffff != g_RecordCell)
|
||||
{
|
||||
//quec_debug("[Ramos] write cell(%d) RecordEraseblock(%d) flag 0xAA55!!",g_RecordCell, flash_addr/flash_BlkSize);
|
||||
Retval = Quec_WriteFlashExt((QUEC_RECORD_BLOCKREASE_AREA_ADD+g_RecordCell*sizeof(quec_flashErase_record_s)+sizeof(quec_RecordInfo_s)), (unsigned int)&BlkERecordCellflag, sizeof(BlkERecordCellflag),0);
|
||||
if(NoError != Retval)
|
||||
{
|
||||
quec_flash_printf("WriteFlash failed, retval=%d, g_RecordCell=%d, need Record EraseblockId=%d !!", Retval,g_RecordCell, flash_addr/flash_BlkSize);
|
||||
}
|
||||
quec_flash_printf("magic %x addr %x type %x %x",BlkERecordCellInfo.RecordMagic,BlkERecordCellInfo.PageId * (flash_BlkSize=type?CHIP_SECTOR_SIZE:CHIP_BLOCK_SIZE),BlkERecordCellInfo.Record_type,type);
|
||||
}
|
||||
else
|
||||
{
|
||||
quec_flash_printf("g_RecordCall(0x%x) not found !! need Record EraseblockId=%d!", g_RecordCell, flash_addr/flash_BlkSize);
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void Quec_FlashEraseRecord_step2(UINT32 flash_addr,quec_Record_type_enum type)
|
||||
{
|
||||
UINT32 Retval = NoError, flash_BlkSize = 0;
|
||||
quec_Eraseflag_s BlkERecordCellflag;
|
||||
UINT32 QUEC_RECORD_BLOCKREASE_AREA_SIZE=get_erase_rd_bin_size();
|
||||
UINT32 QUEC_RECORD_BLOCKREASE_AREA_ADD=get_erase_rd_start_address();
|
||||
if((!QUEC_RECORD_BLOCKREASE_AREA_SIZE)||(!QUEC_RECORD_BLOCKREASE_AREA_ADD))
|
||||
{
|
||||
quec_flash_printf("not found erase_rd !!!");
|
||||
return ;
|
||||
}
|
||||
flash_BlkSize=type?CHIP_SECTOR_SIZE:CHIP_BLOCK_SIZE;;
|
||||
|
||||
if(0xffffffff != g_RecordCell)
|
||||
{
|
||||
Retval = Quec_ReadFlashExt((QUEC_RECORD_BLOCKREASE_AREA_ADD+g_RecordCell*sizeof(quec_flashErase_record_s)+sizeof(quec_RecordInfo_s)), (unsigned int)&BlkERecordCellflag, sizeof(BlkERecordCellflag),0);
|
||||
if(NoError != Retval)
|
||||
{
|
||||
quec_flash_printf("readFlash failed, retval=%d, g_RecordCell=%d!!!!", Retval, g_RecordCell);
|
||||
}
|
||||
if(BlkERecordCellflag.flag == 0xAAAA5555)
|
||||
{
|
||||
quec_flash_printf("flag is already write,jump it!!!");
|
||||
} else {
|
||||
BlkERecordCellflag.flag=0xAAAA5555;
|
||||
BlkERecordCellflag.reserve = 0xffffffff;
|
||||
//quec_debug("[Ramos] write cell(%d) RecordEraseblock(%d) flag 0xAA55!!",g_RecordCell, flash_addr/flash_BlkSize);
|
||||
Retval = Quec_WriteFlashExt((QUEC_RECORD_BLOCKREASE_AREA_ADD+g_RecordCell*sizeof(quec_flashErase_record_s)+sizeof(quec_RecordInfo_s)), (unsigned int)&BlkERecordCellflag, sizeof(BlkERecordCellflag),0);
|
||||
if(NoError != Retval)
|
||||
{
|
||||
quec_flash_printf("WriteFlash failed, retval=%d, g_RecordCell=%d, need Record EraseblockId=%d !!", Retval,g_RecordCell, flash_addr/flash_BlkSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
quec_flash_printf("g_RecordCall(0x%x) not found !! need Record EraseblockId=%d!", g_RecordCell, flash_addr/flash_BlkSize);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user