更新多个 ESP32 芯片(C2、C3、S3) 的版本配置为 SBDEMO 产品添加新的配置文件实现板卡和应用程序配置模块添加 CRC 实用函数修改系统日志以支持动态日志控制更新 Kconfig 和 sdkconfig 的默认设置以适应新产品
255 lines
8.6 KiB
C
255 lines
8.6 KiB
C
#include "board_config.h"
|
|
#include "config/version.h"
|
|
#include "driver/uart.h"
|
|
#include "hal/spi_types.h"
|
|
#include "utils/crc.h"
|
|
|
|
#include "esp_partition.h"
|
|
#include "spi_flash_mmap.h"
|
|
|
|
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_ERR
|
|
#define SYS_LOG_DOMAIN "CFG"
|
|
#define CONS_ABORT()
|
|
#include "sys_log.h"
|
|
|
|
#include "board_config/devkit_esp32c2.h"
|
|
#include "board_config/devkit_esp32c3.h"
|
|
#include "board_config/devkit_esp32s3.h"
|
|
|
|
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;
|
|
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);
|
|
}
|