1092 lines
34 KiB
C
1092 lines
34 KiB
C
|
/***************************************************************************
|
||
|
*
|
||
|
* Copyright 2015-2019 BES.
|
||
|
* All rights reserved. All unpublished rights reserved.
|
||
|
*
|
||
|
* No part of this work may be used or reproduced in any form or by any
|
||
|
* means, or stored in a database or retrieval system, without prior written
|
||
|
* permission of BES.
|
||
|
*
|
||
|
* Use of this work is governed by a license granted by BES.
|
||
|
* This work contains confidential and proprietary information of
|
||
|
* BES. which is protected by copyright, trade secret,
|
||
|
* trademark and other intellectual property rights.
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
#ifdef NEW_NV_RECORD_ENABLED
|
||
|
#include <stdbool.h>
|
||
|
#include <string.h>
|
||
|
#include <assert.h>
|
||
|
#include "cmsis.h"
|
||
|
#include "nvrecord_extension.h"
|
||
|
#include "hal_trace.h"
|
||
|
#include "crc32.h"
|
||
|
#include "hal_sleep.h"
|
||
|
#include "hal_norflash.h"
|
||
|
#include "norflash_api.h"
|
||
|
#include "norflash_drv.h"
|
||
|
#include "nvrecord_bt.h"
|
||
|
#include "nvrecord_env.h"
|
||
|
#include "nvrecord_ble.h"
|
||
|
#include "nvrecord_dma_config.h"
|
||
|
#include "nvrecord_fp_account_key.h"
|
||
|
#include "customparam_section.h"
|
||
|
#include "mpu.h"
|
||
|
#include "besbt.h"
|
||
|
#include "hal_timer.h"
|
||
|
|
||
|
extern uint32_t __userdata_start[];
|
||
|
extern uint32_t __userdata_end[];
|
||
|
extern void nvrecord_rebuild_system_env(struct nvrecord_env_t* pSystemEnv);
|
||
|
extern void nvrecord_rebuild_paired_bt_dev_info(NV_RECORD_PAIRED_BT_DEV_INFO_T* pPairedBtInfo);
|
||
|
#ifdef GFPS_ENABLED
|
||
|
extern void nvrecord_rebuild_fp_account_key(NV_FP_ACCOUNT_KEY_RECORD_T* pFpAccountKey);
|
||
|
#endif
|
||
|
#ifdef NVREC_BAIDU_DATA_SECTION
|
||
|
extern void nvrecord_rebuild_dma_configuration(NV_DMA_CONFIGURATION_T* pDmaConfig);
|
||
|
#endif
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
NV_STATE_IDLE,
|
||
|
NV_STATE_MAIN_ERASING,
|
||
|
NV_STATE_MAIN_ERASED,
|
||
|
NV_STATE_MAIN_WRITTING,
|
||
|
NV_STATE_MAIN_WRITTEN,
|
||
|
NV_STATE_MAIN_DONE,
|
||
|
NV_STATE_BAK_ERASING,
|
||
|
NV_STATE_BAK_ERASED,
|
||
|
NV_STATE_BAK_WRITTING,
|
||
|
NV_STATE_BAK_WRITTEN,
|
||
|
NV_STATE_BAK_DONE,
|
||
|
}NV_STATE;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
bool is_update;
|
||
|
NV_STATE state;
|
||
|
uint32_t written_size;
|
||
|
}NV_FLUSH_STATE;
|
||
|
|
||
|
static NV_FLUSH_STATE nv_flsh_state;
|
||
|
static bool nvrec_init = false;
|
||
|
static uint32_t _user_data_main_start;
|
||
|
static uint32_t _user_data_bak_start;
|
||
|
static uint8_t _nv_burn_buf[NV_EXTENSION_PAGE_SIZE];
|
||
|
|
||
|
NV_EXTENSION_RECORD_T *nvrecord_extension_p = NULL;
|
||
|
|
||
|
/*
|
||
|
*Note: the NV_EXTENSION_MIRROR_RAM_SIZE must be power of 2
|
||
|
*/
|
||
|
#if defined(__ARM_ARCH_8M_MAIN__)
|
||
|
#define __NV_BUF_MPU_ALIGNED __ALIGNED(0x20)
|
||
|
#else
|
||
|
/*
|
||
|
* armv7 mpu require the address must be aligned to the section size and
|
||
|
* the section size must be algined to power of 2
|
||
|
*/
|
||
|
#define __NV_BUF_MPU_ALIGNED __ALIGNED(NV_EXTENSION_MIRROR_RAM_SIZE)
|
||
|
#endif
|
||
|
|
||
|
static NV_MIRROR_BUF_T local_extension_data __NV_BUF_MPU_ALIGNED
|
||
|
__attribute__((section(".sram_data"))) =
|
||
|
{
|
||
|
.nv_record = {
|
||
|
{ // header
|
||
|
NV_EXTENSION_MAGIC_NUMBER,
|
||
|
NV_EXTENSION_MAJOR_VERSION,
|
||
|
NV_EXTENSION_MINOR_VERSION,
|
||
|
NV_EXTENSION_VALID_LEN,
|
||
|
0,
|
||
|
},
|
||
|
|
||
|
{ // system info
|
||
|
},
|
||
|
|
||
|
{ // bt_pair_info
|
||
|
0
|
||
|
},
|
||
|
|
||
|
{ // ble_pair_info
|
||
|
|
||
|
},
|
||
|
|
||
|
#ifdef TWS_SYSTEM_ENABLED
|
||
|
{ // tws_info
|
||
|
|
||
|
},
|
||
|
#endif
|
||
|
|
||
|
#ifdef GFPS_ENABLED
|
||
|
{ // fp_account_key_rec
|
||
|
0
|
||
|
},
|
||
|
#endif
|
||
|
|
||
|
#ifdef NVREC_BAIDU_DATA_SECTION
|
||
|
{ // dma_config
|
||
|
BAIDU_DATA_DEF_FM_FREQ,
|
||
|
},
|
||
|
#endif
|
||
|
|
||
|
#ifdef TILE_DATAPATH
|
||
|
{
|
||
|
{0}
|
||
|
},
|
||
|
#endif
|
||
|
|
||
|
#ifdef OTA_ENABLED
|
||
|
{
|
||
|
{0,},
|
||
|
},
|
||
|
#endif
|
||
|
|
||
|
#if defined(BISTO_ENABLED)
|
||
|
{
|
||
|
true,
|
||
|
},
|
||
|
#endif
|
||
|
|
||
|
#if 1//def TX_IQ_CAL
|
||
|
{
|
||
|
BT_IQ_INVALID_MAGIC_NUM,
|
||
|
{0},
|
||
|
{0},
|
||
|
},
|
||
|
#endif
|
||
|
// TODO:
|
||
|
// If want to extend the nvrecord while keeping the history information,
|
||
|
// append the new items to the tail of NV_EXTENSION_RECORD_T and
|
||
|
// set their intial content here
|
||
|
},
|
||
|
};
|
||
|
|
||
|
STATIC_ASSERT(sizeof(local_extension_data) <= NV_EXTENSION_MIRROR_RAM_SIZE, "NV local buffer too small");
|
||
|
|
||
|
static int nv_record_extension_flush(bool is_async);
|
||
|
|
||
|
#ifdef TILE_DATAPATH
|
||
|
static void nvrecord_rebuild_tileconfig(NV_TILE_INFO_CONFIG_T *tileConfig)
|
||
|
{
|
||
|
memset((uint8_t*)tileConfig,0,sizeof(NV_TILE_INFO_CONFIG_T));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef OTA_ENABLED
|
||
|
static void nvrecord_rebuild_ota_info(NV_OTA_INFO_T *ota_info)
|
||
|
{
|
||
|
memset((uint8_t *)ota_info, 0, OTA_DEVICE_CNT * sizeof(NV_OTA_INFO_T));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if defined(BISTO_ENABLED)
|
||
|
static void nvrecord_rebuild_gsound_info(NV_GSOUND_INFO_T *gsound_info)
|
||
|
{
|
||
|
memset((uint8_t*)gsound_info,0,sizeof(NV_GSOUND_INFO_T));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#if 1//def TX_IQ_CAL
|
||
|
static void nvrecord_rebuild_btiqcalconfig(BT_IQ_CALIBRATION_CONFIG_T *btIqCalConfig)
|
||
|
{
|
||
|
memset((uint8_t*)btIqCalConfig,0,sizeof(BT_IQ_CALIBRATION_CONFIG_T));
|
||
|
btIqCalConfig->validityMagicNum = BT_IQ_INVALID_MAGIC_NUM;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static bool nv_record_data_is_valid(NV_EXTENSION_RECORD_T *nv_record)
|
||
|
{
|
||
|
bool is_valid = false;
|
||
|
|
||
|
NVRECORD_HEADER_T* pExtRecInFlash = &nv_record->header;
|
||
|
uint8_t* pData = (uint8_t*)nv_record + NV_EXTENSION_HEADER_SIZE;
|
||
|
|
||
|
TRACE(0,"nv ext magic 0x%x valid len %d", pExtRecInFlash->magicNumber,
|
||
|
pExtRecInFlash->validLen);
|
||
|
|
||
|
if ((NV_EXTENSION_MAJOR_VERSION == pExtRecInFlash->majorVersion) &&
|
||
|
(NV_EXTENSION_MAGIC_NUMBER == pExtRecInFlash->magicNumber))
|
||
|
{
|
||
|
// check whether the data length is valid
|
||
|
if (pExtRecInFlash->validLen <= NV_EXTENSION_SIZE-NV_EXTENSION_HEADER_SIZE)
|
||
|
{
|
||
|
// check crc32
|
||
|
uint32_t crc = crc32(0, pData, pExtRecInFlash->validLen);
|
||
|
TRACE(1,"generated crc32: 0x%x, header crc: 0x%x",
|
||
|
crc, pExtRecInFlash->crc32);
|
||
|
if (crc == pExtRecInFlash->crc32)
|
||
|
{
|
||
|
// correct
|
||
|
TRACE(2,"Nv extension is valid.");
|
||
|
|
||
|
TRACE(2,"Former nv ext valid len %d", pExtRecInFlash->validLen);
|
||
|
TRACE(2,"Current FW version nv ext valid len %d", NV_EXTENSION_VALID_LEN);
|
||
|
|
||
|
if (NV_EXTENSION_VALID_LEN < pExtRecInFlash->validLen)
|
||
|
{
|
||
|
TRACE(0,"Valid length of extension must be increased,"
|
||
|
"use the default value.");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(NV_EXTENSION_VALID_LEN > pExtRecInFlash->validLen)
|
||
|
{
|
||
|
TRACE(2, "NV extension is extended! (0x%x) -> (0x%x)",
|
||
|
pExtRecInFlash->validLen,NV_EXTENSION_VALID_LEN);
|
||
|
}
|
||
|
is_valid = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return is_valid;
|
||
|
|
||
|
}
|
||
|
|
||
|
static bool nv_record_items_is_valid(NV_EXTENSION_RECORD_T *nv_record)
|
||
|
{
|
||
|
nv_record = nv_record;
|
||
|
#if 0
|
||
|
NV_RECORD_PAIRED_BT_DEV_INFO_T *pbt_pair_info;
|
||
|
pbt_pair_info = &nv_record->bt_pair_info;
|
||
|
TRACE(1,"%s: pairedDevNum: %d ", __func__,pbt_pair_info->pairedDevNum);
|
||
|
for(uint8_t i = 0; i < pbt_pair_info->pairedDevNum; i++)
|
||
|
{
|
||
|
DUMP8("0x%x,", (uint8_t*)pbt_pair_info->pairedBtDevInfo[i].record.bdAddr.address,6);
|
||
|
}
|
||
|
#endif
|
||
|
// TODO: add cheking for nv_record items.
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static void nv_record_set_default(NV_EXTENSION_RECORD_T *nv_record)
|
||
|
{
|
||
|
memset((uint8_t*)nv_record, 0 ,sizeof(NV_EXTENSION_RECORD_T));
|
||
|
nvrecord_rebuild_system_env(&(nv_record->system_info));
|
||
|
nvrecord_rebuild_paired_bt_dev_info(&(nv_record->bt_pair_info));
|
||
|
nvrecord_rebuild_paired_ble_dev_info(&(nv_record->ble_pair_info));
|
||
|
#ifdef GFPS_ENABLED
|
||
|
nvrecord_rebuild_fp_account_key(&(nv_record->fp_account_key_rec));
|
||
|
#endif
|
||
|
|
||
|
#ifdef NVREC_BAIDU_DATA_SECTION
|
||
|
nvrecord_rebuild_dma_configuration(&(nv_record->dma_config));
|
||
|
#endif
|
||
|
|
||
|
#ifdef TILE_DATAPATH
|
||
|
nvrecord_rebuild_tileconfig(&nv_record->tileConfig);
|
||
|
#endif
|
||
|
|
||
|
#if defined(BISTO_ENABLED)
|
||
|
nvrecord_rebuild_gsound_info(&nv_record->gsound_info);
|
||
|
#endif
|
||
|
|
||
|
#ifdef OTA_ENABLED
|
||
|
nvrecord_rebuild_ota_info((NV_OTA_INFO_T *)&nv_record->ota_info);
|
||
|
#endif
|
||
|
|
||
|
#if 1//def TX_IQ_CAL
|
||
|
nvrecord_rebuild_btiqcalconfig(&nv_record->btIqCalConfig);
|
||
|
#endif
|
||
|
|
||
|
nv_record->header.magicNumber = NV_EXTENSION_MAGIC_NUMBER;
|
||
|
nv_record->header.majorVersion = NV_EXTENSION_MAJOR_VERSION;
|
||
|
nv_record->header.minorVersion = NV_EXTENSION_MINOR_VERSION;
|
||
|
nv_record->header.validLen = NV_EXTENSION_VALID_LEN;
|
||
|
nv_record->header.crc32 =
|
||
|
crc32(0, ((uint8_t *)nv_record + NV_EXTENSION_HEADER_SIZE),
|
||
|
NV_EXTENSION_VALID_LEN);
|
||
|
}
|
||
|
|
||
|
static void _nv_record_extension_init(void)
|
||
|
{
|
||
|
enum NORFLASH_API_RET_T result;
|
||
|
uint32_t sector_size = 0;
|
||
|
uint32_t block_size = 0;
|
||
|
uint32_t page_size = 0;
|
||
|
|
||
|
hal_norflash_get_size(HAL_NORFLASH_ID_0,
|
||
|
NULL,
|
||
|
&block_size,
|
||
|
§or_size,
|
||
|
&page_size);
|
||
|
result = norflash_api_register(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
HAL_NORFLASH_ID_0,
|
||
|
((uint32_t)__userdata_start),
|
||
|
((uint32_t)__userdata_end - (uint32_t)__userdata_start),
|
||
|
block_size,
|
||
|
sector_size,
|
||
|
page_size,
|
||
|
NV_EXTENSION_SIZE*2,
|
||
|
nv_extension_callback
|
||
|
);
|
||
|
ASSERT(result == NORFLASH_API_OK,"_nv_record_extension_init: module register failed! result = %d.",result);
|
||
|
}
|
||
|
|
||
|
uint32_t nv_record_pre_write_operation(void)
|
||
|
{
|
||
|
uint32_t lock = int_lock_global();
|
||
|
mpu_clear(MPU_ID_USER_DATA_SECTION);
|
||
|
return lock;
|
||
|
}
|
||
|
|
||
|
void nv_record_post_write_operation(uint32_t lock)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
uint32_t nv_start = (uint32_t)&local_extension_data.nv_record;
|
||
|
uint32_t len = NV_EXTENSION_MIRROR_RAM_SIZE;
|
||
|
|
||
|
ret = mpu_set(MPU_ID_USER_DATA_SECTION, nv_start, len, 0, MPU_ATTR_READ);
|
||
|
int_unlock_global(lock);
|
||
|
TRACE(2,"set mpu 0x%x len %d result %d", nv_start, len, ret);
|
||
|
}
|
||
|
|
||
|
static void nv_record_extension_init(void)
|
||
|
{
|
||
|
uint32_t lock;
|
||
|
bool main_is_valid = false;
|
||
|
bool bak_is_valid = false;
|
||
|
bool data_is_valid = false;
|
||
|
|
||
|
if(nvrec_init)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
_user_data_main_start = (uint32_t)__userdata_start;
|
||
|
_user_data_bak_start = (uint32_t)__userdata_start + NV_EXTENSION_SIZE;
|
||
|
|
||
|
lock = nv_record_pre_write_operation();
|
||
|
_nv_record_extension_init();
|
||
|
|
||
|
nv_flsh_state.is_update = false;
|
||
|
nv_flsh_state.written_size = 0;
|
||
|
nv_flsh_state.state = NV_STATE_IDLE;
|
||
|
|
||
|
nvrecord_extension_p = &local_extension_data.nv_record;
|
||
|
|
||
|
if(nvrecord_extension_p->header.magicNumber != NV_EXTENSION_MAGIC_NUMBER ||
|
||
|
nvrecord_extension_p->header.majorVersion != NV_EXTENSION_MAJOR_VERSION ||
|
||
|
nvrecord_extension_p->header.minorVersion != NV_EXTENSION_MINOR_VERSION ||
|
||
|
nvrecord_extension_p->header.validLen >= (NV_EXTENSION_SIZE - NV_EXTENSION_HEADER_SIZE))
|
||
|
{
|
||
|
ASSERT(0, "%s: local_extension_data error!(0x%x,0x%x,0x%x,0x%x)",
|
||
|
__func__,
|
||
|
nvrecord_extension_p->header.magicNumber,
|
||
|
nvrecord_extension_p->header.majorVersion,
|
||
|
nvrecord_extension_p->header.minorVersion,
|
||
|
nvrecord_extension_p->header.validLen);
|
||
|
}
|
||
|
|
||
|
// Check main sector.
|
||
|
if(nv_record_data_is_valid((NV_EXTENSION_RECORD_T*)_user_data_main_start)
|
||
|
&& nv_record_items_is_valid((NV_EXTENSION_RECORD_T*)_user_data_main_start))
|
||
|
{
|
||
|
TRACE(2,"%s,main sector is valid.",__func__);
|
||
|
main_is_valid = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE(1,"%s,main sector is invalid!",__func__);
|
||
|
main_is_valid = false;
|
||
|
}
|
||
|
|
||
|
// Check bak secotr.
|
||
|
if(nv_record_data_is_valid((NV_EXTENSION_RECORD_T*)_user_data_bak_start)
|
||
|
&& nv_record_items_is_valid((NV_EXTENSION_RECORD_T*)_user_data_main_start))
|
||
|
{
|
||
|
TRACE(2,"%s,bak sector is valid.",__func__);
|
||
|
bak_is_valid = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE(1,"%s,bak sector is invalid!",__func__);
|
||
|
bak_is_valid = false;
|
||
|
}
|
||
|
|
||
|
if(main_is_valid)
|
||
|
{
|
||
|
data_is_valid = true;
|
||
|
if(!bak_is_valid)
|
||
|
{
|
||
|
nv_flsh_state.is_update = true;
|
||
|
nv_flsh_state.state = NV_STATE_MAIN_DONE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(bak_is_valid)
|
||
|
{
|
||
|
data_is_valid = true;
|
||
|
nv_flsh_state.is_update = true;
|
||
|
nv_flsh_state.state = NV_STATE_IDLE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
data_is_valid = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(data_is_valid)
|
||
|
{
|
||
|
TRACE(2,"%s,data is valid.", __func__);
|
||
|
if(main_is_valid)
|
||
|
{
|
||
|
memcpy((uint8_t *)nvrecord_extension_p + NV_EXTENSION_HEADER_SIZE,
|
||
|
(uint8_t *)_user_data_main_start + NV_EXTENSION_HEADER_SIZE,
|
||
|
NV_EXTENSION_VALID_LEN);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy((uint8_t *)nvrecord_extension_p + NV_EXTENSION_HEADER_SIZE,
|
||
|
(uint8_t *)_user_data_bak_start + NV_EXTENSION_HEADER_SIZE,
|
||
|
NV_EXTENSION_VALID_LEN);
|
||
|
}
|
||
|
nvrecord_extension_p->header.crc32 =
|
||
|
crc32(0,
|
||
|
((uint8_t *)nvrecord_extension_p + NV_EXTENSION_HEADER_SIZE),
|
||
|
nvrecord_extension_p->header.validLen);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE(1,"%s,data invalid, rebuild... ",__func__);
|
||
|
nv_record_set_default(nvrecord_extension_p);
|
||
|
TRACE(2,"%s,rebuild crc = 0x%x. ",__func__,nvrecord_extension_p->header.crc32);
|
||
|
// need to update the content in the flash
|
||
|
nv_record_extension_update();
|
||
|
}
|
||
|
|
||
|
nvrec_init = true;
|
||
|
|
||
|
nv_record_post_write_operation(lock);
|
||
|
|
||
|
if(nv_flsh_state.is_update)
|
||
|
{
|
||
|
nv_record_extension_flush(false);
|
||
|
}
|
||
|
TRACE(2,"%s,done.", __func__);
|
||
|
}
|
||
|
|
||
|
NV_EXTENSION_RECORD_T* nv_record_get_extension_entry_ptr(void)
|
||
|
{
|
||
|
return nvrecord_extension_p;
|
||
|
}
|
||
|
|
||
|
void nv_record_extension_update(void)
|
||
|
{
|
||
|
nv_flsh_state.is_update = true;
|
||
|
}
|
||
|
|
||
|
static int nv_record_extension_flush_main(bool is_async)
|
||
|
{
|
||
|
uint32_t crc;
|
||
|
uint32_t lock;
|
||
|
enum NORFLASH_API_RET_T ret = NORFLASH_API_OK;
|
||
|
|
||
|
if(NULL == nvrecord_extension_p)
|
||
|
{
|
||
|
TRACE(1,"%s,nvrecord_extension_p is null.", __func__);
|
||
|
goto _func_end;
|
||
|
}
|
||
|
|
||
|
// TRACE(3, "%s is_async %d state %d", __func__, is_async, nv_flsh_state.state);
|
||
|
|
||
|
if(is_async)
|
||
|
{
|
||
|
if(nv_flsh_state.state == NV_STATE_IDLE
|
||
|
&& nv_flsh_state.is_update == true)
|
||
|
{
|
||
|
TRACE(3,"%s: async flush begin!", __func__);
|
||
|
}
|
||
|
|
||
|
hal_trace_pause();
|
||
|
lock = int_lock_global();
|
||
|
|
||
|
if(nv_flsh_state.state == NV_STATE_IDLE
|
||
|
|| nv_flsh_state.state == NV_STATE_MAIN_ERASING)
|
||
|
{
|
||
|
if(nv_flsh_state.state == NV_STATE_IDLE)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_MAIN_ERASING;
|
||
|
TRACE(4,"%s: NV_STATE_MAIN_ERASING", __func__);
|
||
|
}
|
||
|
|
||
|
ret = norflash_api_erase(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
(uint32_t)(__userdata_start),
|
||
|
NV_EXTENSION_SIZE,
|
||
|
true);
|
||
|
if(ret == NORFLASH_API_OK)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_MAIN_ERASED;
|
||
|
TRACE(4,"%s: NV_STATE_MAIN_ERASED", __func__);
|
||
|
TRACE(4,"%s: norflash_api_erase ok,addr = 0x%x.",__func__,_user_data_main_start);
|
||
|
}
|
||
|
else if(ret == NORFLASH_API_BUFFER_FULL)
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(0,"%s: norflash_api_erase err,ret = %d,addr = 0x%x.",__func__,ret,_user_data_main_start);
|
||
|
}
|
||
|
}
|
||
|
else if(nv_flsh_state.state == NV_STATE_MAIN_ERASED
|
||
|
|| nv_flsh_state.state == NV_STATE_MAIN_WRITTING)
|
||
|
{
|
||
|
if(nv_flsh_state.state == NV_STATE_MAIN_ERASED)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_MAIN_WRITTING;
|
||
|
TRACE(4,"%s: NV_STATE_MAIN_WRITTING", __func__);
|
||
|
}
|
||
|
uint32_t tmpLock = nv_record_pre_write_operation();
|
||
|
crc = crc32(0,(uint8_t *)nvrecord_extension_p + NV_EXTENSION_HEADER_SIZE,
|
||
|
NV_EXTENSION_VALID_LEN);
|
||
|
nvrecord_extension_p->header.crc32 = crc;
|
||
|
ASSERT(nv_record_data_is_valid(nvrecord_extension_p)
|
||
|
&& nv_record_items_is_valid(nvrecord_extension_p),
|
||
|
"%s nv_record is invalid!",__func__);
|
||
|
ret = norflash_api_write(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
(uint32_t)(__userdata_start),
|
||
|
(uint8_t *)nvrecord_extension_p,
|
||
|
NV_EXTENSION_SIZE,
|
||
|
true);
|
||
|
nv_record_post_write_operation(tmpLock);
|
||
|
if(ret == NORFLASH_API_OK)
|
||
|
{
|
||
|
nv_flsh_state.is_update = false;
|
||
|
nv_flsh_state.state = NV_STATE_MAIN_WRITTEN;
|
||
|
TRACE(4,"%s: NV_STATE_MAIN_WRITTEN", __func__);
|
||
|
TRACE(4,"%s: norflash_api_write ok,addr = 0x%x.",__func__,_user_data_main_start);
|
||
|
}
|
||
|
else if(ret == NORFLASH_API_BUFFER_FULL)
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(0,"%s: norflash_api_write err,ret = %d,addr = 0x%x.",__func__,ret,_user_data_main_start);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(norflash_api_get_used_buffer_count(NORFLASH_API_MODULE_ID_USERDATA_EXT,NORFLASH_API_ALL) == 0)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_MAIN_DONE;
|
||
|
// TRACE(1,"%s: NV_STATE_MAIN_DONE", __func__);
|
||
|
TRACE(1,"%s: async flush done.", __func__);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}
|
||
|
}
|
||
|
int_unlock_global(lock);
|
||
|
hal_trace_continue();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE(4,"%s: sync flush begin!", __func__);
|
||
|
if(nv_flsh_state.state == NV_STATE_IDLE
|
||
|
|| nv_flsh_state.state == NV_STATE_MAIN_ERASING)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
hal_trace_pause();
|
||
|
lock = int_lock_global();
|
||
|
ret = norflash_api_erase(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
(uint32_t)(__userdata_start),
|
||
|
NV_EXTENSION_SIZE,
|
||
|
true);
|
||
|
int_unlock_global(lock);
|
||
|
hal_trace_continue();
|
||
|
if(ret == NORFLASH_API_OK)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_MAIN_ERASED;
|
||
|
TRACE(4,"%s: norflash_api_erase ok,addr = 0x%x.",__func__, _user_data_main_start);
|
||
|
}
|
||
|
else if(ret == NORFLASH_API_BUFFER_FULL)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}while(norflash_api_get_free_buffer_count(NORFLASH_API_ERASING) == 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(0,"%s: norflash_api_erase err,ret = %d,addr = 0x%x.",__func__,ret,_user_data_main_start);
|
||
|
}
|
||
|
|
||
|
}while(ret == NORFLASH_API_BUFFER_FULL);
|
||
|
}
|
||
|
|
||
|
if(nv_flsh_state.state == NV_STATE_MAIN_ERASED
|
||
|
|| nv_flsh_state.state == NV_STATE_MAIN_WRITTING)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
hal_trace_pause();
|
||
|
uint32_t tmpLock = nv_record_pre_write_operation();
|
||
|
crc = crc32(0,(uint8_t *)nvrecord_extension_p + NV_EXTENSION_HEADER_SIZE,
|
||
|
NV_EXTENSION_VALID_LEN);
|
||
|
nvrecord_extension_p->header.crc32 = crc;
|
||
|
ASSERT(nv_record_data_is_valid(nvrecord_extension_p)
|
||
|
&& nv_record_items_is_valid(nvrecord_extension_p),
|
||
|
"%s nv_record is invalid!",__func__);
|
||
|
ret = norflash_api_write(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
(uint32_t)(__userdata_start),
|
||
|
(uint8_t *)nvrecord_extension_p,
|
||
|
NV_EXTENSION_SIZE,
|
||
|
true);
|
||
|
nv_record_post_write_operation(tmpLock);
|
||
|
hal_trace_continue();
|
||
|
if(ret == NORFLASH_API_OK)
|
||
|
{
|
||
|
nv_flsh_state.is_update = false;
|
||
|
nv_flsh_state.state = NV_STATE_MAIN_WRITTEN;
|
||
|
TRACE(4,"%s: norflash_api_write ok,addr = 0x%x.",__func__,_user_data_main_start);
|
||
|
}
|
||
|
else if(ret == NORFLASH_API_BUFFER_FULL)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}while(norflash_api_get_free_buffer_count(NORFLASH_API_WRITTING) == 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(0,"%s: norflash_api_write err,ret = %d,addr = 0x%x.",__func__,ret,_user_data_main_start);
|
||
|
}
|
||
|
}while(ret == NORFLASH_API_BUFFER_FULL);
|
||
|
}
|
||
|
|
||
|
do
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}while(norflash_api_get_used_buffer_count(NORFLASH_API_MODULE_ID_USERDATA_EXT,NORFLASH_API_ALL) > 0);
|
||
|
|
||
|
nv_flsh_state.state = NV_STATE_MAIN_DONE;
|
||
|
TRACE(1,"%s: sync flush done.", __func__);
|
||
|
}
|
||
|
_func_end:
|
||
|
return (ret == NORFLASH_API_OK) ? 0:1;
|
||
|
}
|
||
|
|
||
|
static int nv_record_extension_flush_bak(bool is_async)
|
||
|
{
|
||
|
uint32_t lock;
|
||
|
enum NORFLASH_API_RET_T ret = NORFLASH_API_OK;
|
||
|
uint8_t *burn_buf = (uint8_t*)_nv_burn_buf;
|
||
|
|
||
|
if(is_async)
|
||
|
{
|
||
|
hal_trace_pause();
|
||
|
lock = int_lock_global();
|
||
|
if(nv_flsh_state.state == NV_STATE_MAIN_DONE
|
||
|
|| nv_flsh_state.state == NV_STATE_BAK_ERASING)
|
||
|
{
|
||
|
if(nv_flsh_state.state == NV_STATE_MAIN_DONE)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_BAK_ERASING;
|
||
|
TRACE(3,"%s: async flush begin", __func__);
|
||
|
}
|
||
|
ret = norflash_api_erase(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
_user_data_bak_start,
|
||
|
NV_EXTENSION_SIZE,
|
||
|
true);
|
||
|
if(ret == NORFLASH_API_OK)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_BAK_ERASED;
|
||
|
TRACE(4,"%s: norflash_api_erase ok,addr = 0x%x.",
|
||
|
__func__,_user_data_bak_start);
|
||
|
// TRACE(4,"%s: NV_STATE_BAK_ERASED", __func__);
|
||
|
}
|
||
|
else if(ret == NORFLASH_API_BUFFER_FULL)
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(0,"%s: norflash_api_erase err,ret = %d,addr = 0x%x.",
|
||
|
__func__,ret,_user_data_bak_start);
|
||
|
}
|
||
|
}
|
||
|
else if(nv_flsh_state.state == NV_STATE_BAK_ERASED
|
||
|
|| nv_flsh_state.state == NV_STATE_BAK_WRITTING)
|
||
|
{
|
||
|
if(nv_flsh_state.state == NV_STATE_BAK_ERASED)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_BAK_WRITTING;
|
||
|
nv_flsh_state.written_size = 0;
|
||
|
// TRACE(4,"%s: NV_STATE_BAK_WRITTING", __func__);
|
||
|
}
|
||
|
do
|
||
|
{
|
||
|
ret = norflash_api_read(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
_user_data_main_start + nv_flsh_state.written_size,
|
||
|
burn_buf,
|
||
|
NV_EXTENSION_PAGE_SIZE
|
||
|
);
|
||
|
ASSERT(ret == NORFLASH_API_OK,"norflash_api_read failed! ret = %d, addr = 0x%x.",
|
||
|
(int32_t)ret,_user_data_main_start + nv_flsh_state.written_size);
|
||
|
|
||
|
ret = norflash_api_write(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
_user_data_bak_start + nv_flsh_state.written_size,
|
||
|
burn_buf,
|
||
|
NV_EXTENSION_PAGE_SIZE,
|
||
|
true
|
||
|
);
|
||
|
if(ret == NORFLASH_API_OK)
|
||
|
{
|
||
|
nv_flsh_state.written_size += NV_EXTENSION_PAGE_SIZE;
|
||
|
|
||
|
if(nv_flsh_state.written_size == NV_EXTENSION_SIZE)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_BAK_WRITTEN;
|
||
|
// TRACE(4,"%s: NV_STATE_BAK_WRITTEN", __func__);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if(ret == NORFLASH_API_BUFFER_FULL)
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(0,"%s: norflash_api_write err,ret = %d,addr = 0x%x.",
|
||
|
__func__,ret,_user_data_bak_start + nv_flsh_state.written_size);
|
||
|
}
|
||
|
}while(1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(norflash_api_get_used_buffer_count(NORFLASH_API_MODULE_ID_USERDATA_EXT,NORFLASH_API_ALL) == 0)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_BAK_DONE;
|
||
|
TRACE(3,"%s: async flush done.", __func__);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}
|
||
|
}
|
||
|
int_unlock_global(lock);
|
||
|
hal_trace_continue();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE(4,"%s: sync flush begin.", __func__);
|
||
|
if(nv_flsh_state.state == NV_STATE_MAIN_DONE
|
||
|
|| nv_flsh_state.state == NV_STATE_BAK_ERASING)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
hal_trace_pause();
|
||
|
lock = int_lock_global();
|
||
|
ret = norflash_api_erase(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
_user_data_bak_start,
|
||
|
NV_EXTENSION_SIZE,
|
||
|
true);
|
||
|
int_unlock_global(lock);
|
||
|
hal_trace_continue();
|
||
|
if(ret == NORFLASH_API_OK)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_BAK_ERASED;
|
||
|
TRACE(4,"%s: norflash_api_erase ok,addr = 0x%x.",
|
||
|
__func__, _user_data_bak_start);
|
||
|
}
|
||
|
else if(ret == NORFLASH_API_BUFFER_FULL)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}while(norflash_api_get_free_buffer_count(NORFLASH_API_ERASING) == 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(0,"%s: norflash_api_erase err,ret = %d,addr = 0x%x.",__func__,ret,_user_data_bak_start);
|
||
|
}
|
||
|
}while(ret == NORFLASH_API_BUFFER_FULL);
|
||
|
}
|
||
|
|
||
|
if(nv_flsh_state.state == NV_STATE_BAK_ERASED
|
||
|
|| nv_flsh_state.state == NV_STATE_BAK_WRITTING)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_BAK_WRITTING;
|
||
|
nv_flsh_state.written_size = 0;
|
||
|
|
||
|
hal_trace_pause();
|
||
|
do
|
||
|
{
|
||
|
lock = int_lock_global();
|
||
|
ret = norflash_api_read(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
_user_data_main_start + nv_flsh_state.written_size,
|
||
|
burn_buf,
|
||
|
NV_EXTENSION_PAGE_SIZE
|
||
|
);
|
||
|
ASSERT(ret == NORFLASH_API_OK,"norflash_api_read failed! ret = %d, addr = 0x%x.",
|
||
|
(int32_t)ret, _user_data_main_start + nv_flsh_state.written_size);
|
||
|
|
||
|
ret = norflash_api_write(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
_user_data_bak_start + nv_flsh_state.written_size,
|
||
|
burn_buf,
|
||
|
NV_EXTENSION_PAGE_SIZE,
|
||
|
true
|
||
|
);
|
||
|
int_unlock_global(lock);
|
||
|
if(ret == NORFLASH_API_OK)
|
||
|
{
|
||
|
nv_flsh_state.written_size += NV_EXTENSION_PAGE_SIZE;
|
||
|
if(nv_flsh_state.written_size == NV_EXTENSION_SIZE)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_BAK_WRITTEN;
|
||
|
TRACE(3,"%s: NV_STATE_BAK_WRITTEN", __func__);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if(ret == NORFLASH_API_BUFFER_FULL)
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}while(norflash_api_get_free_buffer_count(NORFLASH_API_WRITTING) == 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(0,"%s: norflash_api_write err,ret = %d,addr = 0x%x.",
|
||
|
__func__,ret,_user_data_bak_start + nv_flsh_state.written_size);
|
||
|
}
|
||
|
}while(1);
|
||
|
}
|
||
|
hal_trace_continue();
|
||
|
|
||
|
// nv_flsh_state.state == NV_STATE_BAK_WRITTEN;
|
||
|
do
|
||
|
{
|
||
|
norflash_api_flush();
|
||
|
}while(norflash_api_get_used_buffer_count(NORFLASH_API_MODULE_ID_USERDATA_EXT,NORFLASH_API_ALL) > 0);
|
||
|
|
||
|
nv_flsh_state.state = NV_STATE_BAK_DONE;
|
||
|
TRACE(1,"%s: sync flush done.", __func__);
|
||
|
}
|
||
|
|
||
|
if(nv_flsh_state.state == NV_STATE_BAK_DONE)
|
||
|
{
|
||
|
nv_flsh_state.state = NV_STATE_IDLE;
|
||
|
TRACE(1,"%s: NV_STATE_IDLE", __func__);
|
||
|
}
|
||
|
|
||
|
return (ret == NORFLASH_API_OK) ? 0:1;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int nv_record_extension_flush(bool is_async)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
// TRACE(3, "%s state %d is_update %d", __func__, nv_flsh_state.state, nv_flsh_state.is_update);
|
||
|
do{
|
||
|
if(nv_flsh_state.state == NV_STATE_IDLE
|
||
|
&& nv_flsh_state.is_update == FALSE)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if((nv_flsh_state.state == NV_STATE_IDLE
|
||
|
&& nv_flsh_state.is_update == TRUE)
|
||
|
|| nv_flsh_state.state == NV_STATE_MAIN_ERASING
|
||
|
|| nv_flsh_state.state == NV_STATE_MAIN_ERASED
|
||
|
|| nv_flsh_state.state == NV_STATE_MAIN_WRITTING
|
||
|
|| nv_flsh_state.state == NV_STATE_MAIN_WRITTEN
|
||
|
)
|
||
|
{
|
||
|
ret = nv_record_extension_flush_main(is_async);
|
||
|
if(is_async)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(nv_flsh_state.state == NV_STATE_MAIN_DONE
|
||
|
|| nv_flsh_state.state == NV_STATE_BAK_ERASING
|
||
|
|| nv_flsh_state.state == NV_STATE_BAK_ERASED
|
||
|
|| nv_flsh_state.state == NV_STATE_BAK_WRITTING
|
||
|
|| nv_flsh_state.state == NV_STATE_BAK_WRITTEN
|
||
|
|| nv_flsh_state.state == NV_STATE_BAK_DONE
|
||
|
)
|
||
|
{
|
||
|
ret = nv_record_extension_flush_bak(is_async);
|
||
|
}
|
||
|
}while(!is_async);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void nv_extension_callback(void* param)
|
||
|
{
|
||
|
NORFLASH_API_OPERA_RESULT *opera_result;
|
||
|
opera_result = (NORFLASH_API_OPERA_RESULT*)param;
|
||
|
|
||
|
TRACE(6,"%s:type = %d, addr = 0x%x,len = 0x%x,remain = %d,result = %d.",
|
||
|
__func__,
|
||
|
opera_result->type,
|
||
|
opera_result->addr,
|
||
|
opera_result->len,
|
||
|
opera_result->remain_num,
|
||
|
opera_result->result);
|
||
|
}
|
||
|
|
||
|
void nv_record_init(void)
|
||
|
{
|
||
|
nv_record_open(section_usrdata_ddbrecord);
|
||
|
|
||
|
nv_custom_parameter_section_init();
|
||
|
}
|
||
|
|
||
|
bt_status_t nv_record_open(SECTIONS_ADP_ENUM section_id)
|
||
|
{
|
||
|
nv_record_extension_init();
|
||
|
#ifdef FLASH_SUSPEND
|
||
|
hal_sleep_set_sleep_hook(HAL_SLEEP_HOOK_USER_NVRECORD,
|
||
|
nv_record_flash_flush_in_sleep);
|
||
|
#else
|
||
|
hal_sleep_set_deep_sleep_hook(HAL_DEEP_SLEEP_HOOK_USER_NVRECORD,
|
||
|
nv_record_flash_flush_in_sleep);
|
||
|
#endif
|
||
|
return BT_STS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
void nv_record_update_runtime_userdata(void)
|
||
|
{
|
||
|
nv_record_extension_update();
|
||
|
}
|
||
|
|
||
|
|
||
|
int nv_record_touch_cause_flush(void)
|
||
|
{
|
||
|
nv_record_update_runtime_userdata();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void nv_record_sector_clear(void)
|
||
|
{
|
||
|
uint32_t lock;
|
||
|
enum NORFLASH_API_RET_T ret;
|
||
|
|
||
|
lock = int_lock_global();
|
||
|
ret = norflash_api_erase(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
(uint32_t)__userdata_start,
|
||
|
NV_EXTENSION_SIZE,
|
||
|
false);
|
||
|
ASSERT(ret == NORFLASH_API_OK,
|
||
|
"%s: norflash_api_erase(0x%x) failed! ret = %d.",
|
||
|
__func__, (uint32_t)__userdata_start, (int32_t)ret);
|
||
|
|
||
|
ret = norflash_api_erase(NORFLASH_API_MODULE_ID_USERDATA_EXT,
|
||
|
(uint32_t)__userdata_start + NV_EXTENSION_SIZE,
|
||
|
NV_EXTENSION_SIZE,
|
||
|
false);
|
||
|
ASSERT(ret == NORFLASH_API_OK,
|
||
|
"%s: norflash_api_erase(0x%x) failed! ret = %d.",
|
||
|
__func__, (uint32_t)__userdata_start + NV_EXTENSION_SIZE, (int32_t)ret);
|
||
|
//pmu_reboot();
|
||
|
int_unlock_global(lock);
|
||
|
}
|
||
|
|
||
|
void nv_record_rebuild(void)
|
||
|
{
|
||
|
if(nvrecord_extension_p)
|
||
|
{
|
||
|
uint32_t nv_start;
|
||
|
TRACE(1,"%s: begin.", __func__);
|
||
|
uint32_t lock = int_lock_global();
|
||
|
mpu_clear(MPU_ID_USER_DATA_SECTION);
|
||
|
nv_record_set_default(nvrecord_extension_p);
|
||
|
nv_start = (uint32_t)&local_extension_data.nv_record;
|
||
|
mpu_set(MPU_ID_USER_DATA_SECTION, nv_start,
|
||
|
NV_EXTENSION_MIRROR_RAM_SIZE, 0, MPU_ATTR_READ);
|
||
|
nv_record_extension_update();
|
||
|
nv_record_flash_flush();
|
||
|
int_unlock_global(lock);
|
||
|
TRACE(1,"%s: done.", __func__);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE(1,"%s: begin. nvrecord_extension_p = null.", __func__);
|
||
|
uint32_t lock = int_lock_global();
|
||
|
nv_record_sector_clear();
|
||
|
nvrec_init = false;
|
||
|
nv_record_extension_init();
|
||
|
int_unlock_global(lock);
|
||
|
TRACE(1,"%s: done.", __func__);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define NV_RECORD_FLUSH_EXECUTION_INTERVAL_MS (20*60*1000)
|
||
|
static uint32_t lastFlushCheckPointInMs = 0;
|
||
|
|
||
|
static void nv_record_reset_flush_checkpoint(void)
|
||
|
{
|
||
|
lastFlushCheckPointInMs = GET_CURRENT_MS();;
|
||
|
}
|
||
|
|
||
|
static bool nv_record_is_timer_expired_to_check(void)
|
||
|
{
|
||
|
uint32_t passedTimerMs;
|
||
|
uint32_t currentTimerMs = GET_CURRENT_MS();
|
||
|
|
||
|
if (0 == lastFlushCheckPointInMs)
|
||
|
{
|
||
|
passedTimerMs = currentTimerMs;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (currentTimerMs > lastFlushCheckPointInMs)
|
||
|
{
|
||
|
passedTimerMs = currentTimerMs - lastFlushCheckPointInMs;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
passedTimerMs = 0xFFFFFFFF - lastFlushCheckPointInMs + currentTimerMs + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (passedTimerMs > NV_RECORD_FLUSH_EXECUTION_INTERVAL_MS)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void nv_record_flash_flush(void)
|
||
|
{
|
||
|
nv_record_extension_flush(false);
|
||
|
nv_record_reset_flush_checkpoint();
|
||
|
}
|
||
|
|
||
|
void nv_record_execute_async_flush(void)
|
||
|
{
|
||
|
int ret = nv_record_extension_flush(true);
|
||
|
if (0 == ret)
|
||
|
{
|
||
|
nv_record_reset_flush_checkpoint();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int nv_record_flash_flush_in_sleep(void)
|
||
|
{
|
||
|
if ((NV_STATE_IDLE == nv_flsh_state.state) &&
|
||
|
!nv_record_is_timer_expired_to_check())
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
nv_record_execute_async_flush();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif // #if defined(NEW_NV_RECORD_ENABLED)
|