- binary_tx_handler를 dr_binary_tx_safe로 전체 교체 (APP_ERROR_CHECK 제거) - data_tx_handler APP_ERROR_CHECK → DBG_PRINTF 교체 - memset/memcpy 하드코딩 크기를 define 상수로 교체 (버퍼 오버런 수정) - SERIAL_NO_LENGTH, HW_NO_LENGTH, PASSKEY_LENGTH를 main.h로 통합 - 미사용 HW 드라이버/EEPROM 코드 삭제, TWI를 i2c_manager.c로 통합 - EEPROM → FDS 전환, 코드 리뷰 현황 문서 추가 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
362 lines
9.6 KiB
C
362 lines
9.6 KiB
C
/*******************************************************************************
|
|
TEST medi50 Dec 23
|
|
******************************************************************************/
|
|
|
|
#include "sdk_config.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "app_error.h"
|
|
#include "boards.h"
|
|
#include "nrf_fstorage.h"
|
|
#include "nrf_soc.h"
|
|
#include "nrf_strerror.h"
|
|
#include "sdk_config.h"
|
|
#include "nrf_fstorage_sd.h"
|
|
#include "nrf_delay.h"
|
|
#include "ble_gap.h"
|
|
#include "fds.h"
|
|
|
|
#include "nrf_log.h"
|
|
#include "nrf_log_ctrl.h"
|
|
#include "nrf_log_default_backends.h"
|
|
|
|
#include "fstorage.h"
|
|
#include "nrf_pwr_mgmt.h"
|
|
#include "main.h"
|
|
#include "debug_print.h"
|
|
|
|
|
|
/* File ID and Key used for the configuration record. */
|
|
|
|
#define CONFIG_FILE (0x8010)
|
|
#define CONFIG_REC_KEY (0x7010)
|
|
|
|
#define CONFIG_MAGIC_NUMBER_VALUE (0x20231226)
|
|
config_data_t m_config;
|
|
|
|
extern bool go_device_power_off;
|
|
extern bool go_sleep_mode_enter;
|
|
extern bool go_NVIC_SystemReset;
|
|
|
|
/* Flag to check fds initialization. */
|
|
static bool volatile m_fds_initialized;
|
|
|
|
bool fds_flag_write = false;
|
|
/* A record containing dummy configuration data. */
|
|
static fds_record_t const m_dummy_record =
|
|
{
|
|
.file_id = CONFIG_FILE,
|
|
.key = CONFIG_REC_KEY,
|
|
.data.p_data = (void const *)&m_config,
|
|
/* The length of a record is always expressed in 4-byte units (words). */
|
|
.data.length_words = (sizeof(m_config) + 3) / sizeof(uint32_t),
|
|
};
|
|
|
|
|
|
int8_t reset_status_dflt = 99;
|
|
uint8_t static_passkey_dflt[6] = "123456";
|
|
|
|
void fds_default_value_set(void)
|
|
{
|
|
/* HW Number - empty (set via BLE command) */
|
|
memset(m_config.hw_no, 0, 12);
|
|
|
|
/* Serial Number - default from FIRMWARE_SERIAL_NO */
|
|
memset(m_config.serial_no, 0, 12);
|
|
memcpy(m_config.serial_no, "VB026030000", 11);
|
|
|
|
/* Static Passkey */
|
|
memcpy(m_config.static_passkey, static_passkey_dflt, 6);
|
|
|
|
/* Bond data delete */
|
|
m_config.bond_data_delete = 1;
|
|
|
|
/* Reset status */
|
|
m_config.reset_status = reset_status_dflt;
|
|
|
|
/* Measurement parameters */
|
|
m_config.pd_adc_cnt = 8;
|
|
m_config.pd_delay_us = 8000;
|
|
|
|
/* Device usage count */
|
|
m_config.life_cycle = 0;
|
|
}
|
|
|
|
|
|
static volatile uint8_t fds_last_evt = 0xFF;
|
|
|
|
static void fds_evt_handler( fds_evt_t const *p_evt )
|
|
{
|
|
fds_last_evt = p_evt->id;
|
|
|
|
switch( p_evt->id )
|
|
{
|
|
case FDS_EVT_INIT:
|
|
if( p_evt->result == NRF_SUCCESS )
|
|
{
|
|
m_fds_initialized = true;
|
|
}
|
|
break;
|
|
|
|
case FDS_EVT_WRITE:
|
|
{
|
|
fds_flag_write = false;
|
|
}
|
|
break;
|
|
|
|
case FDS_EVT_UPDATE:
|
|
{
|
|
fds_flag_write = false;
|
|
|
|
if(go_device_power_off == true) {
|
|
/* After flash writing completed, System Power Off */
|
|
device_power_off();
|
|
}
|
|
if(go_sleep_mode_enter == true) {
|
|
/* After flash writing completed, System go to Sleep Mode */
|
|
sleep_mode_enter();
|
|
}
|
|
if(go_NVIC_SystemReset == true) {
|
|
/* After flash writing completed, System Reset */
|
|
DBG_PRINTF("Off FDS_EVENT\r\n");
|
|
NVIC_SystemReset();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FDS_EVT_DEL_RECORD:
|
|
break;
|
|
|
|
case FDS_EVT_DEL_FILE:
|
|
break;
|
|
|
|
case FDS_EVT_GC:
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/**@brief Wait for fds to initialize. */
|
|
static void wait_for_fds_ready( void )
|
|
{
|
|
uint32_t timeout = 0;
|
|
while( !m_fds_initialized )
|
|
{
|
|
nrf_pwr_mgmt_run();
|
|
nrf_delay_ms(1);
|
|
timeout++;
|
|
if (timeout > 3000) { /* 3 second timeout */
|
|
DBG_PRINTF("[FDS] TIMEOUT!\r\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void config_load( void )
|
|
{
|
|
ret_code_t rc;
|
|
fds_record_desc_t desc = { 0 };
|
|
fds_find_token_t tok = { 0 };
|
|
uint8_t cfg_retry = 0;
|
|
|
|
cfg_load_start:
|
|
memset((char *)&desc, 0, sizeof(desc));
|
|
memset((char *)&tok, 0, sizeof(tok));
|
|
rc = fds_record_find(CONFIG_FILE, CONFIG_REC_KEY, &desc, &tok);
|
|
DBG_PRINTF("[FDS] find rc=%u\r\n", rc);
|
|
|
|
/* FDS may not be fully ready yet - retry before writing defaults */
|
|
if (rc != NRF_SUCCESS && cfg_retry < 10) {
|
|
cfg_retry++;
|
|
DBG_PRINTF("[FDS] retry %u/10\r\n", cfg_retry);
|
|
nrf_delay_ms(100);
|
|
goto cfg_load_start;
|
|
}
|
|
|
|
if( rc == NRF_SUCCESS )
|
|
{
|
|
/* A config file is in flash. Let's update it. */
|
|
fds_flash_record_t config = { 0 };
|
|
|
|
/* Open the record and read its contents. */
|
|
rc = fds_record_open(&desc, &config);
|
|
if (rc != NRF_SUCCESS) {
|
|
/* CRC error or corrupt record - delete and use defaults */
|
|
DBG_PRINTF("[FDS] open ERR=%u, deleting\r\n", rc);
|
|
(void)fds_record_delete(&desc);
|
|
fds_gc();
|
|
fds_default_value_set();
|
|
goto cfg_load_write_new;
|
|
}
|
|
|
|
/* Copy the configuration from flash into m_config. */
|
|
memcpy(&m_config, config.p_data, sizeof(config_data_t));
|
|
|
|
/* Close the record when done reading. */
|
|
rc = fds_record_close(&desc);
|
|
APP_ERROR_CHECK(rc);
|
|
|
|
DBG_PRINTF("[FDS] magic=0x%08X (expect 0x%08X)\r\n",
|
|
m_config.magic_number, CONFIG_MAGIC_NUMBER_VALUE);
|
|
|
|
if( m_config.magic_number != (uint32_t)CONFIG_MAGIC_NUMBER_VALUE )
|
|
{ // first init
|
|
DBG_PRINTF("[FDS] FORMAT! overwriting with defaults\r\n");
|
|
rc = fds_record_delete(&desc);
|
|
APP_ERROR_CHECK(rc);
|
|
m_config.magic_number = CONFIG_MAGIC_NUMBER_VALUE;
|
|
|
|
// default....
|
|
fds_default_value_set();
|
|
|
|
/* Write the updated record to flash. */
|
|
rc = fds_record_update(&desc, &m_dummy_record);
|
|
if( (rc != NRF_SUCCESS) && (rc == FDS_ERR_NO_SPACE_IN_FLASH) )
|
|
{
|
|
rc = fds_gc();
|
|
APP_ERROR_CHECK(rc);
|
|
}
|
|
else
|
|
{
|
|
APP_ERROR_CHECK(rc);
|
|
}
|
|
goto cfg_load_start;
|
|
}
|
|
DBG_PRINTF("[FDS] Loaded OK\r\n");
|
|
}
|
|
else
|
|
{
|
|
cfg_load_write_new:
|
|
DBG_PRINTF("[FDS] New - writing defaults\r\n");
|
|
/* System config not found (or corrupt); write a new one. */
|
|
m_config.magic_number = CONFIG_MAGIC_NUMBER_VALUE;
|
|
|
|
// default....
|
|
fds_default_value_set();
|
|
|
|
fds_flag_write = true;
|
|
rc = fds_record_write(&desc, &m_dummy_record);
|
|
if (rc != NRF_SUCCESS) {
|
|
DBG_PRINTF("[FDS] Write ERR=%u\r\n", rc);
|
|
fds_flag_write = false;
|
|
}
|
|
while( fds_flag_write )
|
|
{
|
|
nrf_pwr_mgmt_run();
|
|
}
|
|
if( (rc != NRF_SUCCESS) && (rc == FDS_ERR_NO_SPACE_IN_FLASH) )
|
|
{
|
|
rc = fds_gc();
|
|
APP_ERROR_CHECK(rc);
|
|
}
|
|
else
|
|
{
|
|
APP_ERROR_CHECK(rc);
|
|
}
|
|
NRF_LOG_FLUSH();
|
|
goto cfg_load_start;
|
|
}
|
|
}
|
|
|
|
|
|
void config_save( void )
|
|
{
|
|
ret_code_t rc;
|
|
fds_record_desc_t desc = { 0 };
|
|
fds_find_token_t tok = { 0 };
|
|
|
|
DBG_PRINTF("[CFG_SAVE] start\r\n");
|
|
|
|
/* Wait for any previous FDS operation to complete */
|
|
if (fds_flag_write) {
|
|
uint32_t wait_cnt = 0;
|
|
DBG_PRINTF("[CFG_SAVE] waiting for prev FDS op...\r\n");
|
|
while (fds_flag_write && wait_cnt < 3000) {
|
|
nrf_pwr_mgmt_run();
|
|
nrf_delay_ms(1);
|
|
wait_cnt++;
|
|
}
|
|
if (fds_flag_write) {
|
|
DBG_PRINTF("[CFG_SAVE] TIMEOUT! forcing flag clear\r\n");
|
|
fds_flag_write = false;
|
|
}
|
|
}
|
|
|
|
if( m_config.magic_number != (uint32_t)CONFIG_MAGIC_NUMBER_VALUE )
|
|
{
|
|
m_config.magic_number = CONFIG_MAGIC_NUMBER_VALUE;
|
|
}
|
|
|
|
memset((char *)&desc, 0, sizeof(desc));
|
|
memset((char *)&tok, 0, sizeof(tok));
|
|
rc = fds_record_find(CONFIG_FILE, CONFIG_REC_KEY, &desc, &tok);
|
|
DBG_PRINTF("[CFG_SAVE] find rc=%u\r\n", rc);
|
|
|
|
if( rc == NRF_SUCCESS )
|
|
{
|
|
fds_flag_write = true;
|
|
rc = fds_record_update(&desc, &m_dummy_record);
|
|
DBG_PRINTF("[CFG_SAVE] update rc=%u\r\n", rc);
|
|
if( rc == FDS_ERR_NO_SPACE_IN_FLASH )
|
|
{
|
|
fds_flag_write = false;
|
|
rc = fds_gc();
|
|
DBG_PRINTF("[CFG_SAVE] gc rc=%u, retry\r\n", rc);
|
|
fds_flag_write = true;
|
|
rc = fds_record_update(&desc, &m_dummy_record);
|
|
DBG_PRINTF("[CFG_SAVE] retry rc=%u\r\n", rc);
|
|
}
|
|
if( rc != NRF_SUCCESS )
|
|
{
|
|
DBG_PRINTF("[CFG_SAVE] FAIL rc=%u\r\n", rc);
|
|
fds_flag_write = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_PRINTF("[CFG_SAVE] not found, writing new\r\n");
|
|
fds_flag_write = true;
|
|
rc = fds_record_write(&desc, &m_dummy_record);
|
|
DBG_PRINTF("[CFG_SAVE] write rc=%u\r\n", rc);
|
|
if( rc != NRF_SUCCESS )
|
|
{
|
|
DBG_PRINTF("[CFG_SAVE] FAIL rc=%u\r\n", rc);
|
|
fds_flag_write = false;
|
|
}
|
|
}
|
|
|
|
DBG_PRINTF("[CFG_SAVE] done\r\n");
|
|
}
|
|
|
|
|
|
void fs_set_value(void)
|
|
{
|
|
config_load();
|
|
}
|
|
|
|
void fs_storage_init(void)
|
|
{
|
|
ret_code_t rc;
|
|
|
|
/* Register first to receive an event when initialization is complete. */
|
|
rc = fds_register(fds_evt_handler);
|
|
APP_ERROR_CHECK(rc);
|
|
|
|
rc = fds_init();
|
|
APP_ERROR_CHECK(rc);
|
|
|
|
/* Wait for fds to initialize. */
|
|
wait_for_fds_ready();
|
|
|
|
fds_stat_t stat = { 0 };
|
|
rc = fds_stat(&stat);
|
|
APP_ERROR_CHECK(rc);
|
|
|
|
DBG_PRINTF("[FDS] OK\r\n");
|
|
}
|