654 lines
17 KiB
C
654 lines
17 KiB
C
/* USER CODE BEGIN Header */
|
|
/**
|
|
******************************************************************************
|
|
* @file : bsp_config.c
|
|
* @brief : 板级支持包配置文件源文件
|
|
******************************************************************************
|
|
*/
|
|
/* USER CODE END Header */
|
|
|
|
#include "bsp_config.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
/**
|
|
* @brief 配置存储条目
|
|
*/
|
|
typedef struct bsp_config_storage_entry {
|
|
char section[BSP_CONFIG_MAX_SECTION_NAME_LENGTH];
|
|
char key[BSP_CONFIG_MAX_KEY_NAME_LENGTH];
|
|
char value[BSP_CONFIG_MAX_VALUE_LENGTH];
|
|
struct bsp_config_storage_entry* next;
|
|
} bsp_config_storage_entry_t;
|
|
|
|
/**
|
|
* @brief 配置存储
|
|
*/
|
|
typedef struct {
|
|
bsp_config_storage_entry_t* entries;
|
|
uint32_t entry_count;
|
|
uint8_t initialized;
|
|
} bsp_config_storage_t;
|
|
|
|
/**
|
|
* @brief 配置存储实例
|
|
*/
|
|
static bsp_config_storage_t bsp_config_storage = {
|
|
.entries = NULL,
|
|
.entry_count = 0,
|
|
.initialized = 0
|
|
};
|
|
|
|
/**
|
|
* @brief 去除字符串中的空白字符
|
|
* @param str: 要处理的字符串
|
|
* @return 处理后的字符串
|
|
*/
|
|
static char* bsp_config_trim(char* str) {
|
|
char* end;
|
|
|
|
// Trim leading whitespace
|
|
while (isspace((unsigned char)*str)) {
|
|
str++;
|
|
}
|
|
|
|
if (*str == 0) {
|
|
return str;
|
|
}
|
|
|
|
// Trim trailing whitespace
|
|
end = str + strlen(str) - 1;
|
|
while (end > str && isspace((unsigned char)*end)) {
|
|
end--;
|
|
}
|
|
|
|
// Null terminate
|
|
*(end + 1) = 0;
|
|
|
|
return str;
|
|
}
|
|
|
|
/**
|
|
* @brief 打开配置文件
|
|
* @param filename: 配置文件名称
|
|
* @param parser: 解析器上下文
|
|
* @retval HAL 状态码
|
|
*/
|
|
static hal_ret_t bsp_config_file_open(const char* filename, bsp_config_parser_t* parser) {
|
|
if (filename == NULL || parser == NULL) {
|
|
return HAL_INVALID_PARAM;
|
|
}
|
|
|
|
parser->file = fopen(filename, "r");
|
|
if (parser->file == NULL) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
memset(parser->current_section, 0, sizeof(parser->current_section));
|
|
memset(parser->buffer, 0, sizeof(parser->buffer));
|
|
parser->line_number = 0;
|
|
parser->initialized = 1;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 关闭配置文件
|
|
* @param parser: 解析器上下文
|
|
* @retval HAL 状态码
|
|
*/
|
|
static hal_ret_t bsp_config_file_close(bsp_config_parser_t* parser) {
|
|
if (parser == NULL || !parser->initialized) {
|
|
return HAL_INVALID_PARAM;
|
|
}
|
|
|
|
if (parser->file != NULL) {
|
|
fclose(parser->file);
|
|
parser->file = NULL;
|
|
}
|
|
|
|
parser->initialized = 0;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 从文件读取配置条目
|
|
* @param parser: 解析器上下文
|
|
* @param entry: 配置条目
|
|
* @retval HAL 状态码
|
|
*/
|
|
static hal_ret_t bsp_config_file_read_entry(bsp_config_parser_t* parser, bsp_config_entry_t* entry) {
|
|
if (parser == NULL || entry == NULL || !parser->initialized) {
|
|
return HAL_INVALID_PARAM;
|
|
}
|
|
|
|
if (parser->file == NULL) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
while (fgets(parser->buffer, sizeof(parser->buffer), parser->file) != NULL) {
|
|
parser->line_number++;
|
|
|
|
char* line = bsp_config_trim(parser->buffer);
|
|
size_t len = strlen(line);
|
|
|
|
// Skip empty lines and comments
|
|
if (len == 0 || line[0] == '#') {
|
|
continue;
|
|
}
|
|
|
|
// Check for section header
|
|
if (line[0] == '[' && line[len - 1] == ']') {
|
|
// Extract section name
|
|
memset(parser->current_section, 0, sizeof(parser->current_section));
|
|
strncpy(parser->current_section, line + 1, len - 2);
|
|
parser->current_section[len - 2] = '\0';
|
|
continue;
|
|
}
|
|
|
|
// Check for key-value pair
|
|
char* equals = strchr(line, '=');
|
|
if (equals != NULL) {
|
|
// Extract key and value
|
|
*equals = '\0';
|
|
char* key = bsp_config_trim(line);
|
|
char* value = bsp_config_trim(equals + 1);
|
|
|
|
entry->section = parser->current_section;
|
|
entry->key = key;
|
|
entry->value = value;
|
|
|
|
return HAL_OK;
|
|
}
|
|
}
|
|
|
|
return HAL_TIMEOUT;
|
|
}
|
|
|
|
/**
|
|
* @brief 解析整数值
|
|
* @param value: 要解析的字符串值
|
|
* @param result: 存储结果的指针
|
|
* @retval HAL 状态码
|
|
*/
|
|
static hal_ret_t bsp_config_parse_int(const char* value, int* result) {
|
|
if (value == NULL || result == NULL) {
|
|
return HAL_INVALID_PARAM;
|
|
}
|
|
|
|
char* endptr;
|
|
long val = strtol(value, &endptr, 0);
|
|
|
|
if (*endptr != '\0') {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
*result = (int)val;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 解析无符号整数值
|
|
* @param value: 要解析的字符串值
|
|
* @param result: 存储结果的指针
|
|
* @retval HAL 状态码
|
|
*/
|
|
static hal_ret_t bsp_config_parse_uint(const char* value, uint32_t* result) {
|
|
if (value == NULL || result == NULL) {
|
|
return HAL_INVALID_PARAM;
|
|
}
|
|
|
|
char* endptr;
|
|
unsigned long val = strtoul(value, &endptr, 0);
|
|
|
|
if (*endptr != '\0') {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
*result = (uint32_t)val;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 解析布尔值
|
|
* @param value: 要解析的字符串值
|
|
* @param result: 存储结果的指针
|
|
* @retval HAL 状态码
|
|
*/
|
|
static hal_ret_t bsp_config_parse_bool(const char* value, uint8_t* result) {
|
|
if (value == NULL || result == NULL) {
|
|
return HAL_INVALID_PARAM;
|
|
}
|
|
|
|
if (strcmp(value, "true") == 0 || strcmp(value, "TRUE") == 0 ||
|
|
strcmp(value, "1") == 0 || strcmp(value, "yes") == 0 ||
|
|
strcmp(value, "YES") == 0) {
|
|
*result = 1;
|
|
return HAL_OK;
|
|
} else if (strcmp(value, "false") == 0 || strcmp(value, "FALSE") == 0 ||
|
|
strcmp(value, "0") == 0 || strcmp(value, "no") == 0 ||
|
|
strcmp(value, "NO") == 0) {
|
|
*result = 0;
|
|
return HAL_OK;
|
|
}
|
|
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
/**
|
|
* @brief 解析字符串值
|
|
* @param value: 要解析的字符串值
|
|
* @param result: 存储结果的指针
|
|
* @param max_length: 结果缓冲区的最大长度
|
|
* @retval HAL 状态码
|
|
*/
|
|
static hal_ret_t bsp_config_parse_string(const char* value, char* result, size_t max_length) {
|
|
if (value == NULL || result == NULL) {
|
|
return HAL_INVALID_PARAM;
|
|
}
|
|
|
|
strncpy(result, value, max_length - 1);
|
|
result[max_length - 1] = '\0';
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 添加配置条目到存储
|
|
* @param section: 节名称
|
|
* @param key: 键名称
|
|
* @param value: 值
|
|
* @retval HAL 状态码
|
|
*/
|
|
static hal_ret_t bsp_config_storage_add(const char* section, const char* key, const char* value) {
|
|
// Check if entry already exists
|
|
bsp_config_storage_entry_t* entry = bsp_config_storage.entries;
|
|
while (entry != NULL) {
|
|
if (strcmp(entry->section, section) == 0 && strcmp(entry->key, key) == 0) {
|
|
// Update existing entry
|
|
strncpy(entry->value, value, sizeof(entry->value) - 1);
|
|
entry->value[sizeof(entry->value) - 1] = '\0';
|
|
return HAL_OK;
|
|
}
|
|
entry = entry->next;
|
|
}
|
|
|
|
// Create new entry
|
|
bsp_config_storage_entry_t* new_entry = malloc(sizeof(bsp_config_storage_entry_t));
|
|
if (new_entry == NULL) {
|
|
return HAL_OUT_OF_MEMORY;
|
|
}
|
|
|
|
strncpy(new_entry->section, section, sizeof(new_entry->section) - 1);
|
|
strncpy(new_entry->key, key, sizeof(new_entry->key) - 1);
|
|
strncpy(new_entry->value, value, sizeof(new_entry->value) - 1);
|
|
new_entry->section[sizeof(new_entry->section) - 1] = '\0';
|
|
new_entry->key[sizeof(new_entry->key) - 1] = '\0';
|
|
new_entry->value[sizeof(new_entry->value) - 1] = '\0';
|
|
new_entry->next = NULL;
|
|
|
|
// Add to list
|
|
if (bsp_config_storage.entries == NULL) {
|
|
bsp_config_storage.entries = new_entry;
|
|
} else {
|
|
entry = bsp_config_storage.entries;
|
|
while (entry->next != NULL) {
|
|
entry = entry->next;
|
|
}
|
|
entry->next = new_entry;
|
|
}
|
|
|
|
bsp_config_storage.entry_count++;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 清空配置存储
|
|
*/
|
|
static void bsp_config_storage_clear(void) {
|
|
bsp_config_storage_entry_t* entry = bsp_config_storage.entries;
|
|
while (entry != NULL) {
|
|
bsp_config_storage_entry_t* next = entry->next;
|
|
free(entry);
|
|
entry = next;
|
|
}
|
|
|
|
bsp_config_storage.entries = NULL;
|
|
bsp_config_storage.entry_count = 0;
|
|
}
|
|
|
|
/**
|
|
* @brief 初始化 BSP 配置系统
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_init(void) {
|
|
if (bsp_config_storage.initialized) {
|
|
return HAL_OK;
|
|
}
|
|
|
|
bsp_config_storage_clear();
|
|
bsp_config_storage.initialized = 1;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 反初始化 BSP 配置系统
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_deinit(void) {
|
|
if (!bsp_config_storage.initialized) {
|
|
return HAL_OK;
|
|
}
|
|
|
|
bsp_config_storage_clear();
|
|
bsp_config_storage.initialized = 0;
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 从文件加载 BSP 配置
|
|
* @param filename: 配置文件名称
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_load(const char* filename) {
|
|
if (!bsp_config_storage.initialized) {
|
|
hal_ret_t status = bsp_config_init();
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
bsp_config_parser_t parser;
|
|
hal_ret_t status = bsp_config_file_open(filename, &parser);
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
bsp_config_entry_t entry;
|
|
while ((status = bsp_config_file_read_entry(&parser, &entry)) == HAL_OK) {
|
|
status = bsp_config_storage_add(entry.section, entry.key, entry.value);
|
|
if (status != HAL_OK) {
|
|
bsp_config_file_close(&parser);
|
|
return status;
|
|
}
|
|
}
|
|
|
|
if (status != HAL_TIMEOUT) {
|
|
bsp_config_file_close(&parser);
|
|
return status;
|
|
}
|
|
|
|
status = bsp_config_file_close(&parser);
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 保存 BSP 配置到文件
|
|
* @param filename: 配置文件名称
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_save(const char* filename) {
|
|
if (!bsp_config_storage.initialized || bsp_config_storage.entry_count == 0) {
|
|
return HAL_OK;
|
|
}
|
|
|
|
FILE* file = fopen(filename, "w");
|
|
if (file == NULL) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
fprintf(file, "# BSP Configuration File\n");
|
|
fprintf(file, "# Version: %s\n\n", BSP_CONFIG_FILE_VERSION);
|
|
|
|
char current_section[BSP_CONFIG_MAX_SECTION_NAME_LENGTH] = "";
|
|
bsp_config_storage_entry_t* entry = bsp_config_storage.entries;
|
|
|
|
while (entry != NULL) {
|
|
if (strcmp(entry->section, current_section) != 0) {
|
|
// New section
|
|
strncpy(current_section, entry->section, sizeof(current_section) - 1);
|
|
fprintf(file, "[%s]\n", current_section);
|
|
}
|
|
|
|
fprintf(file, "%s=%s\n", entry->key, entry->value);
|
|
entry = entry->next;
|
|
}
|
|
|
|
fclose(file);
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 获取配置值
|
|
* @param section: 配置节名称
|
|
* @param key: 配置键名称
|
|
* @param value: 存储值的指针
|
|
* @param max_length: 值缓冲区的最大长度
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_get_value(const char* section, const char* key, char* value, size_t max_length) {
|
|
if (!bsp_config_storage.initialized || section == NULL || key == NULL || value == NULL) {
|
|
return HAL_INVALID_PARAM;
|
|
}
|
|
|
|
bsp_config_storage_entry_t* entry = bsp_config_storage.entries;
|
|
while (entry != NULL) {
|
|
if (strcmp(entry->section, section) == 0 && strcmp(entry->key, key) == 0) {
|
|
strncpy(value, entry->value, max_length - 1);
|
|
value[max_length - 1] = '\0';
|
|
return HAL_OK;
|
|
}
|
|
entry = entry->next;
|
|
}
|
|
|
|
return HAL_NOT_SUPPORTED;
|
|
}
|
|
|
|
/**
|
|
* @brief 设置配置值
|
|
* @param section: 配置节名称
|
|
* @param key: 配置键名称
|
|
* @param value: 配置值
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_set_value(const char* section, const char* key, const char* value) {
|
|
if (!bsp_config_storage.initialized || section == NULL || key == NULL || value == NULL) {
|
|
return HAL_INVALID_PARAM;
|
|
}
|
|
|
|
return bsp_config_storage_add(section, key, value);
|
|
}
|
|
|
|
/**
|
|
* @brief 获取配置值作为整数
|
|
* @param section: 配置节名称
|
|
* @param key: 配置键名称
|
|
* @param value: 存储整数值的指针
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_get_int(const char* section, const char* key, int* value) {
|
|
char str_value[BSP_CONFIG_MAX_VALUE_LENGTH];
|
|
hal_ret_t status = bsp_config_get_value(section, key, str_value, sizeof(str_value));
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
return bsp_config_parse_int(str_value, value);
|
|
}
|
|
|
|
/**
|
|
* @brief 设置配置值作为整数
|
|
* @param section: 配置节名称
|
|
* @param key: 配置键名称
|
|
* @param value: 整数值
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_set_int(const char* section, const char* key, int value) {
|
|
char str_value[BSP_CONFIG_MAX_VALUE_LENGTH];
|
|
snprintf(str_value, sizeof(str_value), "%d", value);
|
|
return bsp_config_set_value(section, key, str_value);
|
|
}
|
|
|
|
/**
|
|
* @brief 获取配置值作为无符号整数
|
|
* @param section: 配置节名称
|
|
* @param key: 配置键名称
|
|
* @param value: 存储无符号整数值的指针
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_get_uint(const char* section, const char* key, uint32_t* value) {
|
|
char str_value[BSP_CONFIG_MAX_VALUE_LENGTH];
|
|
hal_status_t status = bsp_config_get_value(section, key, str_value, sizeof(str_value));
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
return bsp_config_parse_uint(str_value, value);
|
|
}
|
|
|
|
/**
|
|
* @brief 设置配置值作为无符号整数
|
|
* @param section: 配置节名称
|
|
* @param key: 配置键名称
|
|
* @param value: 无符号整数值
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_set_uint(const char* section, const char* key, uint32_t value) {
|
|
char str_value[BSP_CONFIG_MAX_VALUE_LENGTH];
|
|
snprintf(str_value, sizeof(str_value), "%lu", (unsigned long)value);
|
|
return bsp_config_set_value(section, key, str_value);
|
|
}
|
|
|
|
/**
|
|
* @brief 获取配置值作为布尔值
|
|
* @param section: 配置节名称
|
|
* @param key: 配置键名称
|
|
* @param value: 存储布尔值的指针
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_get_bool(const char* section, const char* key, uint8_t* value) {
|
|
char str_value[BSP_CONFIG_MAX_VALUE_LENGTH];
|
|
hal_status_t status = bsp_config_get_value(section, key, str_value, sizeof(str_value));
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
return bsp_config_parse_bool(str_value, value);
|
|
}
|
|
|
|
/**
|
|
* @brief 设置配置值作为布尔值
|
|
* @param section: 配置节名称
|
|
* @param key: 配置键名称
|
|
* @param value: 布尔值
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_set_bool(const char* section, const char* key, uint8_t value) {
|
|
return bsp_config_set_value(section, key, value ? "true" : "false");
|
|
}
|
|
|
|
/**
|
|
* @brief 从配置解析 BSP 模块
|
|
* @param config: 指向要填充的 BSP 板卡配置结构体的指针
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_config_parse_modules(bsp_board_config_t* config) {
|
|
if (config == NULL) {
|
|
return HAL_INVALID_PARAM;
|
|
}
|
|
|
|
// TODO: Implement module parsing logic
|
|
// This will depend on the specific configuration file format
|
|
// and how modules are defined in the configuration
|
|
|
|
return HAL_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief 从配置文件初始化 BSP
|
|
* @param filename: 配置文件名称
|
|
* @retval HAL 状态码
|
|
*/
|
|
hal_ret_t bsp_init_from_config(const char* filename) {
|
|
// Load configuration file
|
|
hal_ret_t status = bsp_config_load(filename);
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
// Initialize HAL layer
|
|
status = hal_init();
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
// Initialize BSP module manager
|
|
status = bsp_module_manager_init();
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
// Create board configuration from file
|
|
bsp_board_config_t board_config;
|
|
memset(&board_config, 0, sizeof(board_config));
|
|
|
|
// Parse board information
|
|
char board_name[64];
|
|
status = bsp_config_get_value("board", "name", board_name, sizeof(board_name));
|
|
if (status == HAL_OK) {
|
|
board_config.name = strdup(board_name);
|
|
} else {
|
|
board_config.name = "Unknown";
|
|
}
|
|
|
|
uint32_t version = BSP_CONFIG_VERSION;
|
|
status = bsp_config_get_uint("board", "version", &version);
|
|
if (status == HAL_OK) {
|
|
board_config.version = version;
|
|
} else {
|
|
board_config.version = BSP_CONFIG_VERSION;
|
|
}
|
|
|
|
// Parse modules from configuration
|
|
status = bsp_config_parse_modules(&board_config);
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
// Initialize board
|
|
status = bsp_board_init();
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
// Initialize all modules
|
|
status = bsp_module_init_all();
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
// Configure all modules
|
|
// TODO: Implement module configuration from file
|
|
|
|
// Start all modules
|
|
status = bsp_module_start_all();
|
|
if (status != HAL_OK) {
|
|
return status;
|
|
}
|
|
|
|
return HAL_OK;
|
|
}
|