Files
ESPC3-wireless/app/config/board_config.c

253 lines
8.5 KiB
C
Raw Normal View History

2024-03-28 12:19:52 +08:00
#include "board_config.h"
#include "config/version.h"
2024-03-28 12:19:52 +08:00
#include "driver/uart.h"
#include "hal/spi_types.h"
#include "utils/crc.h"
#include "esp_partition.h"
#include "spi_flash_mmap.h"
2024-03-28 12:19:52 +08:00
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_ERR
2024-03-28 12:19:52 +08:00
#define SYS_LOG_DOMAIN "CFG"
#define CONS_ABORT()
#include "sys_log.h"
2025-04-10 10:57:28 +08:00
#include "board_config/_default_config.h"
2024-03-28 12:19:52 +08:00
typedef struct
{
uint8_t license_code[CONFIG_LICENSE_CODE_LENGTH]; // 在烧录器设置的保存滚码的字段
uint32_t crc_32; // 从 size 成员开始到数据结束的 crc32 校验值
uint16_t size; // 整个数据结构的长度
uint16_t version; // 仅指本结构的版本代号
cfg_board_t cfg; // 板载配置数据
} __cfg_board_partition_t;
static const esp_partition_t *s_partition_hdl;
const __cfg_board_partition_t *p_cfg_board_partition;
2024-03-28 12:19:52 +08:00
const cfg_board_t *g_cfg_board = &s_cfg_board_default;
const uint8_t *g_license_code;
static void _read_partition_data(__cfg_board_partition_t *out, const cfg_board_t *cfg);
static const uint8_t *_read_legacy_license_code(void);
static uint32_t _get_data_crc(const __cfg_board_partition_t *cfg);
/**
* @brief 使 g_cfg_board
* @retval 0
* @retval 1
*/
int board_cfg_init(void)
{
s_partition_hdl = esp_partition_find_first((esp_partition_type_t)CONFIG_CFG_BOARD_PARTITION_TYPE,
(esp_partition_subtype_t)CONFIG_CFG_BOARD_PARTITION_SUBTYPE,
CONFIG_CFG_BOARD_PARTITION_NAME);
*(int *)g_sys_log_on = 1;
if (s_partition_hdl == NULL)
{
g_license_code = _read_legacy_license_code();
SYS_LOG_ERR("esp_partition_find_first() fail");
return 1;
}
const void *cfg_board_partition;
esp_partition_mmap_handle_t mmp_data_handle;
esp_err_t err = esp_partition_mmap(s_partition_hdl, 0, 0x1000, ESP_PARTITION_MMAP_DATA, &cfg_board_partition, &mmp_data_handle);
if (err != ESP_OK)
{
g_license_code = _read_legacy_license_code();
SYS_LOG_ERR("esp_partition_mmap() fail");
return 1;
}
p_cfg_board_partition = cfg_board_partition;
g_license_code = p_cfg_board_partition->license_code;
if (p_cfg_board_partition->version != BOARD_CONFIG_DATA_VER ||
p_cfg_board_partition->size != sizeof(__cfg_board_partition_t) ||
p_cfg_board_partition->crc_32 != _get_data_crc(p_cfg_board_partition))
{
SYS_LOG_WRN("no config data, using default config");
return 1;
}
else
{
g_cfg_board = &p_cfg_board_partition->cfg;
SYS_LOG_INF("config data checked valid");
/* 如果代码区中的析载数据长度大于已有的数据区配置长度,则把多出来的部分添加到数据区中 */
if (sizeof(__cfg_board_partition_t) > p_cfg_board_partition->size &&
p_cfg_board_partition->size > sizeof(__cfg_board_partition_t) - sizeof(cfg_board_t))
{
cfg_board_t new_cfg;
memcpy(&new_cfg, &s_cfg_board_default, sizeof(new_cfg)); // 复制新的默认配置
memcpy(&new_cfg, g_cfg_board, sizeof(cfg_board_t) - (sizeof(__cfg_board_partition_t) - p_cfg_board_partition->size)); // 用旧的固化数据覆已有部分
board_cfg_fresh(&new_cfg); // 固化新配置
}
return 0;
}
}
/**
* @brief
*
* @param license_code
* @return int
*/
int board_license_fresh(const uint8_t license_code[CONFIG_LICENSE_CODE_LENGTH])
{
if (p_cfg_board_partition == NULL)
{
SYS_LOG_WRN("never exec board_cfg_init()");
return -1;
}
__cfg_board_partition_t cfg_buf_partition;
memcpy(&cfg_buf_partition, p_cfg_board_partition, sizeof(cfg_buf_partition));
memcpy(&cfg_buf_partition.license_code[0], license_code, sizeof(cfg_buf_partition.license_code));
cfg_buf_partition.version = BOARD_CONFIG_DATA_VER;
cfg_buf_partition.size = sizeof(cfg_buf_partition);
esp_err_t err;
err = esp_partition_erase_range(s_partition_hdl, 0, 0x1000);
if (err != ESP_OK)
{
SYS_LOG_WRN("esp_partition_erase_range() fail. err: %d", err);
return 1;
}
err = esp_partition_write_raw(s_partition_hdl, 0, &cfg_buf_partition, sizeof(cfg_buf_partition));
if (err != ESP_OK)
{
SYS_LOG_WRN("esp_partition_read_raw() fail. err: %d", err);
return 1;
}
SYS_LOG_INF("done.");
return 0;
}
/**
* @brief
*
*
* @param cfg
* @return int
*/
int board_cfg_fresh(const cfg_board_t *cfg)
{
if (p_cfg_board_partition == NULL)
{
SYS_LOG_WRN("never exec board_cfg_init()");
return -1;
}
__cfg_board_partition_t cfg_buf_partition;
_read_partition_data(&cfg_buf_partition, cfg);
esp_err_t err;
err = esp_partition_erase_range(s_partition_hdl, 0, 0x1000);
if (err != ESP_OK)
{
SYS_LOG_WRN("esp_partition_erase_range() fail. err: %d", err);
return 1;
}
err = esp_partition_write_raw(s_partition_hdl, 0, &cfg_buf_partition, sizeof(cfg_buf_partition));
if (err != ESP_OK)
{
SYS_LOG_WRN("esp_partition_read_raw() fail. err: %d", err);
return 1;
}
g_cfg_board = &p_cfg_board_partition->cfg;
SYS_LOG_INF("done.");
return 0;
}
/**
* @brief cfg __cfg_board_partition_t bin
*
* @param cfg NULL
* @retval 0
* @retval -1
*/
int board_cfg_dump(const cfg_board_t *cfg)
{
if (p_cfg_board_partition == NULL)
{
SYS_LOG_WRN("never exec board_cfg_init()");
return -1;
}
if (cfg == NULL)
{
if (p_cfg_board_partition->size > 0x1000 ||
p_cfg_board_partition->size < CONFIG_LICENSE_CODE_LENGTH ||
p_cfg_board_partition->crc_32 != _get_data_crc(p_cfg_board_partition))
{
SYS_LOG_WRN("No internal records, currently displayed as default configuration");
}
cfg = &s_cfg_board_default;
}
__cfg_board_partition_t cfg_buf_partition;
_read_partition_data(&cfg_buf_partition, cfg);
SYS_LOG_WRN("The data in the custom partition is as follows %u bytes:\r\n", sizeof(cfg_buf_partition));
int i = 0;
int len;
const uint8_t *p = (uint8_t *)&cfg_buf_partition;
SYS_PRINT("/* license code */\r\n");
len = sizeof(cfg_buf_partition.license_code);
for (i = 0; i < len; i++)
SYS_PRINT("0x%02X,%s", *p++, i + 1 < len ? " " : "\r\n");
SYS_PRINT("/* crc, size, version */\r\n");
len = cfg_buf_partition.size - sizeof(cfg_buf_partition.license_code) - sizeof(cfg_buf_partition.cfg);
for (i = 0; i < len; i++)
SYS_PRINT("0x%02X,%s", *p++, i + 1 < len ? " " : "\r\n");
SYS_PRINT("/* board configuration (from %s area) */\r\n", cfg == &s_cfg_board_default ? "code" : "data");
len = sizeof(cfg_buf_partition.cfg);
for (i = 0; i < len; i++)
SYS_PRINT("0x%02X,%s", *p++, i + 1 < len ? " " : "\r\n");
SYS_PRINT("\r\n");
return 0;
}
static void _read_partition_data(__cfg_board_partition_t *out, const cfg_board_t *cfg)
{
memcpy(out, p_cfg_board_partition, sizeof(*out));
memcpy(&out->cfg, cfg, sizeof(out->cfg));
out->version = BOARD_CONFIG_DATA_VER;
out->size = sizeof(*out);
out->crc_32 = _get_data_crc(out);
}
/**
* @brief ()
*
* @return const uint8_t* license_code
*/
static const uint8_t *_read_legacy_license_code(void)
{
spi_flash_mmap_handle_t handle;
const uint32_t LEGACY_LICENSE_CODE_START_ADDR = 0x3E0000;
uint32_t start = LEGACY_LICENSE_CODE_START_ADDR;
uint32_t end = LEGACY_LICENSE_CODE_START_ADDR + CONFIG_LICENSE_CODE_LENGTH;
const void *license_code;
spi_flash_mmap(LEGACY_LICENSE_CODE_START_ADDR, end - start, SPI_FLASH_MMAP_DATA, &license_code, &handle);
return license_code;
}
static uint32_t _get_data_crc(const __cfg_board_partition_t *cfg)
{
int cfg_size = cfg->size - sizeof(cfg->license_code) - sizeof(cfg->crc_32);
return crc32_calc(0, &cfg->size, cfg_size);
}