427 lines
15 KiB
C
427 lines
15 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.
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
/*****************************header include********************************/
|
||
|
#include "cmsis.h"
|
||
|
#include "nv_section_dbg.h"
|
||
|
#include "nvrecord_gsound.h"
|
||
|
#include "factory_section.h"
|
||
|
|
||
|
#ifdef BISTO_ENABLED
|
||
|
#include "gsound_target_ota.h"
|
||
|
|
||
|
#ifdef GSOUND_HOTWORD_ENABLED
|
||
|
#include "gsound_custom_hotword_common.h"
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
/************************private macro defination***************************/
|
||
|
#define HOTWORD_MODEL_MAX_SIZE (80 * 1024) //!< should adjust this value if
|
||
|
//!< hotword model size changed and should adjust the flash section size at
|
||
|
//!< the sametime., @see HOTWORD_SECTION_SIZE in common.mk
|
||
|
|
||
|
#ifndef OTA_FLASH_LOGIC_ADDR
|
||
|
#define OTA_FLASH_LOGIC_ADDR (FLASH_NC_BASE)
|
||
|
#endif
|
||
|
|
||
|
/************************private type defination****************************/
|
||
|
|
||
|
/************************extern function declearation***********************/
|
||
|
#ifdef GSOUND_HOTWORD_ENABLED
|
||
|
extern uint32_t __hotword_model_start[];
|
||
|
extern uint32_t __hotword_model_end[];
|
||
|
#endif
|
||
|
|
||
|
/**********************private function declearation************************/
|
||
|
|
||
|
/************************private variable defination************************/
|
||
|
#ifdef GSOUND_HOTWORD_ENABLED
|
||
|
#ifdef MODEL_FILE_EMBEDED
|
||
|
const uint8_t EMBEDED_MODEL_FILE [] = {
|
||
|
#include "res/gs_hw/en_all.txt" //!< must correspond to specific model ID, @see DEFAULT_HOTWORD_MODEL_ID
|
||
|
};
|
||
|
|
||
|
/// NOTE: Add more embeded model file info here
|
||
|
|
||
|
#define DEFAULT_MODEL_START_ADDR EMBEDED_MODEL_FILE //!< map to specific flash address within the bin file
|
||
|
#else /// #ifndef MODEL_FILE_EMBEDED
|
||
|
#define DEFAULT_MODEL_START_ADDR __hotword_model_start //!< map to specific flash address out of the bin file
|
||
|
#endif /// #ifdef MODEL_FILE_EMBEDED
|
||
|
|
||
|
HOTWORD_MODEL_INFO_T defaultModel[DEFAULT_MODEL_NUM] = {
|
||
|
{DEFAULT_HOTWORD_MODEL_ID, (uint32_t)DEFAULT_MODEL_START_ADDR, HOTWORD_MODEL_MAX_SIZE},
|
||
|
/// NOTE: Add other embeded model info here
|
||
|
};
|
||
|
|
||
|
char supportedModels[GSOUND_MAX_SUPPORTED_HOTWORD_MODELS_BYTES] = {};
|
||
|
#endif /// #ifdef GSOUND_HOTWORD_ENABLED
|
||
|
|
||
|
static NV_GSOUND_INFO_T *nvrecord_gsound_p = NULL;
|
||
|
|
||
|
/****************************function defination****************************/
|
||
|
void nv_record_gsound_rec_init(void)
|
||
|
{
|
||
|
if (NULL == nvrecord_gsound_p)
|
||
|
{
|
||
|
nvrecord_gsound_p = &(nvrecord_extension_p->gsound_info);
|
||
|
}
|
||
|
|
||
|
#ifdef GSOUND_HOTWORD_ENABLED
|
||
|
/// init default supported model file(s)
|
||
|
/// add to supported model file set(if it is not in this set)
|
||
|
LOG_I("supportedModelCnt:%d", nvrecord_gsound_p->supportedModelCnt);
|
||
|
if (0 == nvrecord_gsound_p->supportedModelCnt) //!< load default info at first time bootup
|
||
|
{
|
||
|
for (uint8_t i = 0; i < DEFAULT_MODEL_NUM; i++)
|
||
|
{
|
||
|
LOG_I("hotword_model_start:0x%x",
|
||
|
defaultModel[i].startAddr);
|
||
|
|
||
|
nv_record_gsound_rec_add_new_model((void *)&defaultModel[i]);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void nv_record_gsound_rec_get_ptr(void **ptr)
|
||
|
{
|
||
|
*ptr = nvrecord_gsound_p;
|
||
|
}
|
||
|
|
||
|
void nv_record_gsound_rec_updata_enable_state(bool enable)
|
||
|
{
|
||
|
LOG_I("gsound enable state update:%d->%d", nvrecord_gsound_p->isGsoundEnabled, enable);
|
||
|
|
||
|
if (nvrecord_gsound_p->isGsoundEnabled != enable)
|
||
|
{
|
||
|
/// disable the MPU protection for write operation
|
||
|
uint32_t lock = nv_record_pre_write_operation();
|
||
|
|
||
|
/// update the enable state
|
||
|
nvrecord_gsound_p->isGsoundEnabled = enable;
|
||
|
nv_record_extension_update();
|
||
|
|
||
|
/// enable the MPU protection after the write operation
|
||
|
nv_record_post_write_operation(lock);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef GSOUND_HOTWORD_ENABLED
|
||
|
bool nv_record_gsound_rec_is_model_insert_allowed(const char *model)
|
||
|
{
|
||
|
bool ret = true;
|
||
|
uint8_t i;
|
||
|
|
||
|
if ((nvrecord_gsound_p->supportedModelCnt >= HOTWORD_MODLE_MAX_NUM) &&
|
||
|
(0xFF != nvrecord_gsound_p->supportedModelCnt))
|
||
|
{
|
||
|
for (i = 0; i < HOTWORD_MODLE_MAX_NUM; i++)
|
||
|
{
|
||
|
/// hotword model exist already
|
||
|
if (!memcmp(&nvrecord_gsound_p->modelInfo[i].modelId, model, strlen(model)))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (HOTWORD_MODLE_MAX_NUM == i)
|
||
|
{
|
||
|
ret = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
bool nv_record_gsound_rec_add_new_model(void *pInfo)
|
||
|
{
|
||
|
bool ret = true;
|
||
|
bool found = false;
|
||
|
uint32_t lock = 0;
|
||
|
|
||
|
HOTWORD_MODEL_INFO_T *info = (HOTWORD_MODEL_INFO_T *)pInfo;
|
||
|
|
||
|
if (INVALID_MODEL_NUM == nvrecord_gsound_p->supportedModelCnt)
|
||
|
{
|
||
|
lock = nv_record_pre_write_operation();
|
||
|
nvrecord_gsound_p->supportedModelCnt = 0;
|
||
|
nv_record_post_write_operation(lock);
|
||
|
}
|
||
|
|
||
|
if (info)
|
||
|
{
|
||
|
lock = nv_record_pre_write_operation();
|
||
|
info->startAddr |= OTA_FLASH_LOGIC_ADDR;
|
||
|
|
||
|
for (uint8_t i = 0; i < nvrecord_gsound_p->supportedModelCnt; i++)
|
||
|
{
|
||
|
/// hotword model exist already
|
||
|
if (!memcmp(&nvrecord_gsound_p->modelInfo[i].modelId, info->modelId, GSOUND_HOTWORD_MODEL_ID_BYTES))
|
||
|
{
|
||
|
LOG_I("info->startAddr:%x", info->startAddr);
|
||
|
|
||
|
///.update the start address
|
||
|
if (info->startAddr)
|
||
|
{
|
||
|
nvrecord_gsound_p->modelInfo[i].startAddr = info->startAddr;
|
||
|
nvrecord_gsound_p->modelInfo[i].len = info->len;
|
||
|
}
|
||
|
|
||
|
LOG_I("model already exist in user section, model_id:%s, model_addr:%x",
|
||
|
nvrecord_gsound_p->modelInfo[i].modelId,
|
||
|
nvrecord_gsound_p->modelInfo[i].startAddr);
|
||
|
found = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOG_I("current supportedModelCnt:%d", nvrecord_gsound_p->supportedModelCnt);
|
||
|
|
||
|
/// brand new model insert
|
||
|
if (!found)
|
||
|
{
|
||
|
memcpy(&nvrecord_gsound_p->modelInfo[nvrecord_gsound_p->supportedModelCnt],
|
||
|
info,
|
||
|
sizeof(HOTWORD_MODEL_INFO_T));
|
||
|
|
||
|
LOG_I("new added modelId:%s, startAddr:%x, modelFileLen:%x", info->modelId, info->startAddr, info->len);
|
||
|
nvrecord_gsound_p->supportedModelCnt++;
|
||
|
}
|
||
|
nv_record_post_write_operation(lock);
|
||
|
|
||
|
/// new model file incoming, update flash info
|
||
|
if (!found)
|
||
|
{
|
||
|
/// flush the hotword info to flash
|
||
|
nv_record_update_runtime_userdata();
|
||
|
nv_record_flash_flush();
|
||
|
}
|
||
|
|
||
|
LOG_I("current supportedModelCnt:%d", nvrecord_gsound_p->supportedModelCnt);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LOG_W("NULL pointer received in %s", __func__);
|
||
|
ret = false;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
uint32_t nv_record_gsound_rec_get_hotword_model_addr(const char *model_id, bool add_new, int32_t newModelLen)
|
||
|
{
|
||
|
uint32_t addr = 0;
|
||
|
bool found = false;
|
||
|
|
||
|
LOG_I("%s revceived model ID: %s", __func__, model_id);
|
||
|
if (nvrecord_gsound_p)
|
||
|
{
|
||
|
for (uint8_t i = 0; i < ARRAY_SIZE(nvrecord_gsound_p->modelInfo); i++)
|
||
|
{
|
||
|
if (!memcmp(nvrecord_gsound_p->modelInfo[i].modelId, model_id, 4))
|
||
|
{
|
||
|
addr = nvrecord_gsound_p->modelInfo[i].startAddr;
|
||
|
found = true;
|
||
|
LOG_I("found saved model info, index:%d", i);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if (add_new && !found)
|
||
|
{
|
||
|
addr = (uint32_t)__hotword_model_start;
|
||
|
uint32_t tempAddr;
|
||
|
uint8_t startIdx = 0;
|
||
|
#ifdef MODEL_FILE_EMBEDED
|
||
|
startIdx = DEFAULT_MODEL_NUM; //!< set offset to skip the embeded model file info
|
||
|
#endif
|
||
|
|
||
|
if (INVALID_MODEL_NUM == nvrecord_gsound_p->supportedModelCnt)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/// get the largest flash address
|
||
|
for (uint8_t i = startIdx; i < nvrecord_gsound_p->supportedModelCnt; i++)
|
||
|
{
|
||
|
tempAddr = nvrecord_gsound_p->modelInfo[i].startAddr + nvrecord_gsound_p->modelInfo[i].len;
|
||
|
if ((tempAddr & 0xFFFFFF) > (addr & 0xFFFFFF))
|
||
|
{
|
||
|
addr = tempAddr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// force 4K align the address
|
||
|
addr = F_4K_ALIGN(addr);
|
||
|
LOG_I("supportedModelCnt:%d, Largest address:0x%x", nvrecord_gsound_p->supportedModelCnt, addr);
|
||
|
|
||
|
/// check is overwrite needed
|
||
|
if ((newModelLen + addr) > (uint32_t)__hotword_model_end ||
|
||
|
(nvrecord_gsound_p->supportedModelCnt >= HOTWORD_MODLE_MAX_NUM))
|
||
|
{
|
||
|
uint8_t cleanIdx = 0; //!< model file index to clean
|
||
|
addr = nvrecord_gsound_p->modelInfo[startIdx].startAddr; //!< init anchor point
|
||
|
uint32_t cleanSize = F_4K_ALIGN(addr + nvrecord_gsound_p->modelInfo[startIdx].len) - addr; //!< flash size to clean
|
||
|
|
||
|
uint32_t lock = nv_record_pre_write_operation(); //!< disable the MPU for info update
|
||
|
uint32_t intLock = int_lock(); //!< lock the global interrupt
|
||
|
|
||
|
/// remove the first record
|
||
|
for (uint8_t i = startIdx; i < (nvrecord_gsound_p->supportedModelCnt - 1); i++)
|
||
|
{
|
||
|
nvrecord_gsound_p->modelInfo[i] = nvrecord_gsound_p->modelInfo[i + 1];
|
||
|
}
|
||
|
|
||
|
/// decrease the number of supported model
|
||
|
nvrecord_gsound_p->supportedModelCnt--;
|
||
|
|
||
|
while (cleanSize < newModelLen)
|
||
|
{
|
||
|
uint8_t headAdjacentIdx = 0xFF, tailAdjacentIdx = 0xFF;
|
||
|
uint32_t headAdjacentOffset = 0xFFFFFFFF, tailAdjacentOffset = 0xFFFFFFFF;
|
||
|
|
||
|
/// find the adjacent chunck
|
||
|
for (uint8_t i = startIdx; i < nvrecord_gsound_p->supportedModelCnt; i++)
|
||
|
{
|
||
|
if (nvrecord_gsound_p->modelInfo[i].startAddr > addr)
|
||
|
{
|
||
|
if (nvrecord_gsound_p->modelInfo[i].startAddr - addr < tailAdjacentOffset)
|
||
|
{
|
||
|
tailAdjacentOffset = nvrecord_gsound_p->modelInfo[i].startAddr - addr;
|
||
|
tailAdjacentIdx = i;
|
||
|
}
|
||
|
}
|
||
|
else if (nvrecord_gsound_p->modelInfo[i].startAddr < addr)
|
||
|
{
|
||
|
if (addr - nvrecord_gsound_p->modelInfo[i].startAddr < headAdjacentOffset)
|
||
|
{
|
||
|
headAdjacentOffset = nvrecord_gsound_p->modelInfo[i].startAddr - addr;
|
||
|
headAdjacentIdx = i;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOG_I("headAdjacentIdx:%d, tailAdjacentIdx:%d", headAdjacentIdx, tailAdjacentIdx);
|
||
|
|
||
|
/// find the smaller index, smaller index means older record
|
||
|
if (headAdjacentIdx > tailAdjacentIdx)
|
||
|
{
|
||
|
cleanSize += F_4K_ALIGN(nvrecord_gsound_p->modelInfo[tailAdjacentIdx].startAddr +
|
||
|
nvrecord_gsound_p->modelInfo[tailAdjacentIdx].len) -
|
||
|
nvrecord_gsound_p->modelInfo[tailAdjacentIdx].startAddr;
|
||
|
cleanIdx = tailAdjacentIdx;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
addr = nvrecord_gsound_p->modelInfo[headAdjacentIdx].startAddr;
|
||
|
cleanSize += F_4K_ALIGN(addr + nvrecord_gsound_p->modelInfo[headAdjacentIdx].len) - addr;
|
||
|
cleanIdx = headAdjacentIdx;
|
||
|
}
|
||
|
|
||
|
/// remove the first record
|
||
|
for (uint8_t i = cleanIdx; i < (nvrecord_gsound_p->supportedModelCnt - 1); i++)
|
||
|
{
|
||
|
nvrecord_gsound_p->modelInfo[i] = nvrecord_gsound_p->modelInfo[i + 1];
|
||
|
}
|
||
|
|
||
|
/// decrease the number of supported model
|
||
|
nvrecord_gsound_p->supportedModelCnt--;
|
||
|
}
|
||
|
|
||
|
if ((addr < (uint32_t)__hotword_model_start) ||
|
||
|
(addr > (uint32_t)__hotword_model_end))
|
||
|
{
|
||
|
LOG_I("invalid addr found:0x%x, clean all model files", addr);
|
||
|
nvrecord_gsound_p->supportedModelCnt = startIdx;
|
||
|
addr = (uint32_t)__hotword_model_start;
|
||
|
}
|
||
|
|
||
|
if (0 == nvrecord_gsound_p->supportedModelCnt)
|
||
|
{
|
||
|
/// invalid number used to identify with fist time bootup
|
||
|
nvrecord_gsound_p->supportedModelCnt = INVALID_MODEL_NUM;
|
||
|
}
|
||
|
|
||
|
int_unlock(intLock); //!< unlock the global interrupt
|
||
|
nv_record_post_write_operation(lock); //!< enable the MPU
|
||
|
|
||
|
/// flush the hotword info to flash
|
||
|
nv_record_update_runtime_userdata();
|
||
|
nv_record_flash_flush();
|
||
|
}
|
||
|
}
|
||
|
} while (0);
|
||
|
|
||
|
return addr;
|
||
|
}
|
||
|
|
||
|
int nv_record_gsound_rec_get_supported_model_id(char *models_out,
|
||
|
uint8_t *length_out)
|
||
|
{
|
||
|
int ret= 0;
|
||
|
const char* terminator = NULL;
|
||
|
|
||
|
if (INVALID_MODEL_NUM == nvrecord_gsound_p->supportedModelCnt)
|
||
|
{
|
||
|
memcpy(models_out, STRING_TERMINATOR_NULL, STRING_TERMINATOR_SIZE);
|
||
|
*length_out = STRING_TERMINATOR_SIZE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (uint8_t i = 0; i < nvrecord_gsound_p->supportedModelCnt; i++)
|
||
|
{
|
||
|
LOG_I("supported model_id:%s, model_addr:%x",
|
||
|
nvrecord_gsound_p->modelInfo[i].modelId,
|
||
|
nvrecord_gsound_p->modelInfo[i].startAddr);
|
||
|
|
||
|
memcpy((supportedModels + i * GSOUND_HOTWORD_SUPPORTED_MODEL_ID_BYTES),
|
||
|
nvrecord_gsound_p->modelInfo[i].modelId,
|
||
|
GSOUND_HOTWORD_MODEL_ID_BYTES);
|
||
|
|
||
|
if ((i + 1) == nvrecord_gsound_p->supportedModelCnt)
|
||
|
{
|
||
|
terminator = STRING_TERMINATOR_NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
terminator = SUPPORTED_HOTWORD_MODEL_DELIM;
|
||
|
}
|
||
|
memcpy(&supportedModels[(i * GSOUND_HOTWORD_SUPPORTED_MODEL_ID_BYTES) + GSOUND_HOTWORD_MODEL_ID_BYTES],
|
||
|
terminator,
|
||
|
STRING_TERMINATOR_SIZE);
|
||
|
}
|
||
|
|
||
|
if (nvrecord_gsound_p->supportedModelCnt * GSOUND_HOTWORD_SUPPORTED_MODEL_ID_BYTES <= *length_out)
|
||
|
{
|
||
|
strcpy(models_out, supportedModels);
|
||
|
*length_out = strlen(supportedModels) + STRING_TERMINATOR_SIZE;
|
||
|
LOG_I("total supported model_id(length is %d):", *length_out);
|
||
|
DUMP8("0x%02x ", models_out, *length_out);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ret = -1;
|
||
|
LOG_W("supported model id length exceeded max length");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
#endif
|