Files
stm32f407ve_black/BSP/Src/bsp_module.c
2026-01-23 14:35:51 +08:00

795 lines
22 KiB
C

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : bsp_module.c
* @brief : Board support package module management source file
******************************************************************************
*/
/* USER CODE END Header */
#include "bsp_module.h"
#include <string.h>
/**
* @brief Module manager instance
*/
static bsp_module_manager_t bsp_module_manager;
/**
* @brief Initialize BSP module manager
* @retval HAL status code
*/
hal_ret_t bsp_module_manager_init(void) {
/* Clear module manager */
memset(&bsp_module_manager, 0, sizeof(bsp_module_manager));
/* Initialize module arrays */
for (uint8_t i = 0; i < BSP_MODULE_TYPE_MAX; i++) {
bsp_module_manager.modules[i] = NULL;
}
bsp_module_manager.module_list = NULL;
bsp_module_manager.module_count = 0;
return HAL_RET_OK;
}
/**
* @brief Register a BSP module
* @param module: Pointer to module structure
* @retval HAL status code
*/
hal_ret_t bsp_module_register(bsp_module_t* module) {
if (module == NULL) {
return HAL_RET_INVALID_PARAM;
}
if (module->config.type >= BSP_MODULE_TYPE_MAX) {
return HAL_INVALID_PARAM;
}
/* Check if module already exists */
if (bsp_module_get(module->config.type, module->config.instance) != NULL) {
return HAL_RESOURCE_LOCKED;
}
/* Initialize module state */
module->state = BSP_MODULE_STATE_UNINIT;
module->next = NULL;
module->prev = NULL;
/* Add module to the linked list */
if (bsp_module_manager.module_list == NULL) {
bsp_module_manager.module_list = module;
} else {
/* Insert module at the end of the list */
bsp_module_t* current = bsp_module_manager.module_list;
while (current->next != NULL) {
current = current->next;
}
current->next = module;
module->prev = current;
}
/* Add module to the type-specific list */
if (bsp_module_manager.modules[module->config.type] == NULL) {
bsp_module_manager.modules[module->config.type] = module;
} else {
/* Insert module at the end of the type-specific list */
bsp_module_t* current = bsp_module_manager.modules[module->config.type];
while (current->next != NULL && current->config.type == module->config.type) {
current = current->next;
}
if (current->config.type == module->config.type) {
current->next = module;
module->prev = current;
} else {
/* Insert between current->prev and current */
if (current->prev != NULL) {
current->prev->next = module;
} else {
bsp_module_manager.modules[module->config.type] = module;
}
module->prev = current->prev;
module->next = current;
current->prev = module;
}
}
bsp_module_manager.module_count++;
return HAL_OK;
}
/**
* @brief Unregister a BSP module
* @param module: Pointer to module structure
* @retval HAL status code
*/
hal_ret_t bsp_module_unregister(bsp_module_t* module) {
if (module == NULL) {
return HAL_INVALID_PARAM;
}
/* Deinitialize module if it's initialized */
if (module->state != BSP_MODULE_STATE_UNINIT) {
if (module->ops.deinit != NULL) {
module->ops.deinit();
}
module->state = BSP_MODULE_STATE_UNINIT;
}
/* Remove module from linked list */
if (module->prev != NULL) {
module->prev->next = module->next;
} else {
/* Module is first in the list */
bsp_module_manager.module_list = module->next;
}
if (module->next != NULL) {
module->next->prev = module->prev;
}
/* Remove module from type-specific list */
if (bsp_module_manager.modules[module->config.type] == module) {
bsp_module_manager.modules[module->config.type] = module->next;
}
/* Reset module pointers */
module->next = NULL;
module->prev = NULL;
bsp_module_manager.module_count--;
return HAL_OK;
}
/**
* @brief Get a specific BSP module
* @param type: Module type
* @param instance: Module instance
* @retval Pointer to module structure, or NULL if not found
*/
bsp_module_t* bsp_module_get(bsp_module_type_t type, uint8_t instance) {
if (type >= BSP_MODULE_TYPE_MAX) {
return NULL;
}
bsp_module_t* current = bsp_module_manager.modules[type];
while (current != NULL && current->config.type == type) {
if (current->config.instance == instance) {
return current;
}
current = current->next;
}
return NULL;
}
/**
* @brief Get all modules of a specific type
* @param type: Module type
* @retval Pointer to module list, or NULL if no modules found
*/
bsp_module_t* bsp_module_get_by_type(bsp_module_type_t type) {
if (type >= BSP_MODULE_TYPE_MAX) {
return NULL;
}
return bsp_module_manager.modules[type];
}
/**
* @brief Get module by name
* @param name: Module name
* @retval Pointer to module structure, or NULL if not found
*/
bsp_module_t* bsp_module_get_by_name(const char* name) {
if (name == NULL) {
return NULL;
}
bsp_module_t* current = bsp_module_manager.module_list;
while (current != NULL) {
if (current->config.name != NULL && strcmp(current->config.name, name) == 0) {
return current;
}
current = current->next;
}
return NULL;
}
/**
* @brief Check if all dependencies of a module are satisfied
* @param module: Pointer to module structure
* @retval HAL status code
*/
hal_ret_t bsp_module_check_dependencies(const bsp_module_t* module) {
if (module == NULL) {
return HAL_INVALID_PARAM;
}
/* Check if dependencies are satisfied */
if (module->config.dependencies == 0) {
/* No dependencies */
return HAL_OK;
}
/* Check each dependency bit */
for (uint8_t i = 0; i < BSP_MODULE_TYPE_MAX; i++) {
if (module->config.dependencies & (1 << i)) {
/* Check if dependency module exists and is initialized */
bsp_module_t* dep_module = bsp_module_manager.modules[i];
if (dep_module == NULL) {
return HAL_RET_ERROR;
}
/* Check if at least one instance is initialized */
bsp_module_t* current = dep_module;
uint8_t dep_found = 0;
while (current != NULL && current->config.type == i) {
if (current->state >= BSP_MODULE_STATE_INIT) {
dep_found = 1;
break;
}
current = current->next;
}
if (!dep_found) {
return HAL_ERROR;
}
}
}
return HAL_OK;
}
/**
* @brief Initialize a specific BSP module
* @param type: Module type
* @param instance: Module instance
* @retval HAL status code
*/
hal_ret_t bsp_module_init(bsp_module_type_t type, uint8_t instance) {
/* Get module */
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
return HAL_ERROR;
}
/* Check if module is already initialized */
if (module->state != BSP_MODULE_STATE_UNINIT) {
return HAL_OK;
}
/* Check dependencies */
hal_ret_t status = bsp_module_check_dependencies(module);
if (status != HAL_OK) {
module->state = BSP_MODULE_STATE_ERROR;
return status;
}
/* Initialize module */
if (module->ops.init != NULL) {
status = module->ops.init(module->config.config_data);
if (status != HAL_OK) {
module->state = BSP_MODULE_STATE_ERROR;
return status;
}
}
module->state = BSP_MODULE_STATE_INIT;
return HAL_OK;
}
/**
* @brief Deinitialize a specific BSP module
* @param type: Module type
* @param instance: Module instance
* @retval HAL status code
*/
hal_ret_t bsp_module_deinit(bsp_module_type_t type, uint8_t instance) {
/* Get module */
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
return HAL_ERROR;
}
/* Check if module is already uninitialized */
if (module->state == BSP_MODULE_STATE_UNINIT) {
return HAL_OK;
}
/* Stop module if it's running */
if (module->state == BSP_MODULE_STATE_RUNNING && module->ops.stop != NULL) {
module->ops.stop();
}
/* Deinitialize module */
if (module->ops.deinit != NULL) {
hal_ret_t status = module->ops.deinit();
if (status != HAL_OK) {
module->state = BSP_MODULE_STATE_ERROR;
return status;
}
}
module->state = BSP_MODULE_STATE_UNINIT;
return HAL_OK;
}
/**
* @brief Configure a specific BSP module
* @param type: Module type
* @param instance: Module instance
* @param config: Module configuration data
* @param size: Module configuration size
* @retval HAL status code
*/
hal_ret_t bsp_module_configure(bsp_module_type_t type, uint8_t instance, void* config, size_t size) {
/* Get module */
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
return HAL_ERROR;
}
/* Check if module is initialized */
if (module->state < BSP_MODULE_STATE_INIT) {
return HAL_ERROR;
}
/* Configure module */
if (module->ops.configure != NULL) {
hal_ret_t status = module->ops.configure(config);
if (status != HAL_OK) {
module->state = BSP_MODULE_STATE_ERROR;
return status;
}
}
module->state = BSP_MODULE_STATE_CONFIGURED;
return HAL_OK;
}
/**
* @brief Start a specific BSP module
* @param type: Module type
* @param instance: Module instance
* @retval HAL status code
*/
hal_ret_t bsp_module_start(bsp_module_type_t type, uint8_t instance) {
/* Get module */
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
return HAL_ERROR;
}
/* Check if module is configured */
if (module->state < BSP_MODULE_STATE_CONFIGURED) {
return HAL_ERROR;
}
/* Start module */
if (module->ops.start != NULL) {
hal_ret_t status = module->ops.start();
if (status != HAL_OK) {
module->state = BSP_MODULE_STATE_ERROR;
return status;
}
}
module->state = BSP_MODULE_STATE_RUNNING;
return HAL_OK;
}
/**
* @brief Stop a specific BSP module
* @param type: Module type
* @param instance: Module instance
* @retval HAL status code
*/
hal_ret_t bsp_module_stop(bsp_module_type_t type, uint8_t instance) {
/* Get module */
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
return HAL_ERROR;
}
/* Check if module is running */
if (module->state != BSP_MODULE_STATE_RUNNING) {
return HAL_OK;
}
/* Stop module */
if (module->ops.stop != NULL) {
hal_ret_t status = module->ops.stop();
if (status != HAL_OK) {
module->state = BSP_MODULE_STATE_ERROR;
return status;
}
}
module->state = BSP_MODULE_STATE_CONFIGURED;
return HAL_OK;
}
/**
* @brief Reset a specific BSP module
* @param type: Module type
* @param instance: Module instance
* @retval HAL status code
*/
hal_ret_t bsp_module_reset(bsp_module_type_t type, uint8_t instance) {
/* Get module */
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
return HAL_ERROR;
}
/* Stop module if it's running */
hal_ret_t status = bsp_module_stop(type, instance);
if (status != HAL_OK) {
return status;
}
/* Deinitialize module */
status = bsp_module_deinit(type, instance);
if (status != HAL_OK) {
return status;
}
/* Reinitialize module */
status = bsp_module_init(type, instance);
if (status != HAL_OK) {
return status;
}
/* Configure module */
if (module->config.config_data != NULL) {
status = bsp_module_configure(type, instance, module->config.config_data, module->config.config_size);
if (status != HAL_OK) {
return status;
}
}
/* Start module */
status = bsp_module_start(type, instance);
if (status != HAL_OK) {
return status;
}
return HAL_OK;
}
/**
* @brief Get state of a specific BSP module
* @param type: Module type
* @param instance: Module instance
* @param state: Pointer to store module state
* @retval HAL status code
*/
hal_ret_t bsp_module_get_state(bsp_module_type_t type, uint8_t instance, bsp_module_state_t* state) {
if (state == NULL) {
return HAL_INVALID_PARAM;
}
/* Get module */
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
*state = BSP_MODULE_STATE_UNINIT;
return HAL_ERROR;
}
*state = module->state;
return HAL_OK;
}
/**
* @brief Control a specific BSP module
* @param type: Module type
* @param instance: Module instance
* @param cmd: Control command
* @param param: Control parameter
* @retval HAL status code
*/
hal_ret_t bsp_module_control(bsp_module_type_t type, uint8_t instance, uint32_t cmd, void* param) {
/* Get module */
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
return HAL_ERROR;
}
/* Check if module is initialized */
if (module->state < BSP_MODULE_STATE_INIT) {
return HAL_ERROR;
}
/* Control module */
if (module->ops.control != NULL) {
return module->ops.control(cmd, param);
}
return HAL_RET_NOT_SUPPORTED;
}
/**
* @brief Initialize all registered BSP modules in priority order
* @retval HAL status code
*/
hal_ret_t bsp_module_init_all(void) {
hal_ret_t status = HAL_RET_OK;
/* Initialize modules by priority */
for (uint8_t priority = BSP_MODULE_PRIORITY_HIGHEST; priority <= BSP_MODULE_PRIORITY_LOWEST; priority++) {
bsp_module_t* current = bsp_module_manager.module_list;
while (current != NULL) {
if (current->config.priority == priority) {
status = bsp_module_init(current->config.type, current->config.instance);
if (status != HAL_OK) {
return status;
}
}
current = current->next;
}
}
return status;
}
/**
* @brief Deinitialize all registered BSP modules in reverse priority order
* @retval HAL status code
*/
hal_ret_t bsp_module_deinit_all(void) {
hal_status_t status = HAL_OK;
/* Deinitialize modules by reverse priority */
for (int8_t priority = BSP_MODULE_PRIORITY_LOWEST; priority >= BSP_MODULE_PRIORITY_HIGHEST; priority--) {
bsp_module_t* current = bsp_module_manager.module_list;
while (current != NULL) {
if (current->config.priority == priority) {
status = bsp_module_deinit(current->config.type, current->config.instance);
if (status != HAL_OK) {
return status;
}
}
current = current->next;
}
}
return status;
}
/**
* @brief Start all registered BSP modules in priority order
* @retval HAL status code
*/
hal_ret_t bsp_module_start_all(void) {
hal_status_t status = HAL_OK;
/* Start modules by priority */
for (uint8_t priority = BSP_MODULE_PRIORITY_HIGHEST; priority <= BSP_MODULE_PRIORITY_LOWEST; priority++) {
bsp_module_t* current = bsp_module_manager.module_list;
while (current != NULL) {
if (current->config.priority == priority && current->state >= BSP_MODULE_STATE_CONFIGURED) {
status = bsp_module_start(current->config.type, current->config.instance);
if (status != HAL_OK) {
return status;
}
}
current = current->next;
}
}
return status;
}
/**
* @brief Stop all registered BSP modules in reverse priority order
* @retval HAL status code
*/
hal_ret_t bsp_module_stop_all(void) {
hal_status_t status = HAL_OK;
/* Stop modules by reverse priority */
for (int8_t priority = BSP_MODULE_PRIORITY_LOWEST; priority >= BSP_MODULE_PRIORITY_HIGHEST; priority--) {
bsp_module_t* current = bsp_module_manager.module_list;
while (current != NULL) {
if (current->config.priority == priority && current->state == BSP_MODULE_STATE_RUNNING) {
status = bsp_module_stop(current->config.type, current->config.instance);
if (status != HAL_OK) {
return status;
}
}
current = current->next;
}
}
return status;
}
/**
* @brief Get total number of registered modules
* @retval Number of registered modules
*/
uint32_t bsp_module_get_count(void) {
return bsp_module_manager.module_count;
}
/**
* @brief Get module manager instance
* @retval Pointer to module manager structure
*/
bsp_module_manager_t* bsp_module_get_manager(void) {
return &bsp_module_manager;
}
/**
* @brief Register a module event callback
* @param type: Module type
* @param instance: Module instance
* @param callback: Event callback function
* @retval HAL status code
*/
hal_ret_t bsp_module_register_event_callback(bsp_module_type_t type, uint8_t instance, bsp_module_event_callback_t callback) {
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
return HAL_ERROR;
}
module->event_callback = callback;
return HAL_OK;
}
/**
* @brief Trigger a module event
* @param module: Pointer to module structure
* @param event: Event to trigger
* @param data: Event data
* @retval HAL status code
*/
hal_ret_t bsp_module_trigger_event(const bsp_module_t* module, uint32_t event, void* data) {
if (module == NULL) {
return HAL_INVALID_PARAM;
}
// Check if module has an event callback registered
if (module->event_callback != NULL) {
return module->event_callback(module, event, data);
}
return HAL_OK;
}
/**
* @brief Find modules by priority range
* @param min_priority: Minimum priority
* @param max_priority: Maximum priority
* @param count: Pointer to store number of modules found
* @retval Pointer to array of module pointers, or NULL if no modules found
*/
bsp_module_t** bsp_module_find_by_priority_range(bsp_module_priority_t min_priority, bsp_module_priority_t max_priority, uint32_t* count) {
if (count == NULL) {
return NULL;
}
// First pass: count matching modules
uint32_t module_count = 0;
bsp_module_t* current = bsp_module_manager.module_list;
while (current != NULL) {
if (current->config.priority >= min_priority && current->config.priority <= max_priority) {
module_count++;
}
current = current->next;
}
if (module_count == 0) {
*count = 0;
return NULL;
}
// Second pass: allocate and fill array
bsp_module_t** modules = (bsp_module_t**)malloc(module_count * sizeof(bsp_module_t*));
if (modules == NULL) {
*count = 0;
return NULL;
}
uint32_t index = 0;
current = bsp_module_manager.module_list;
while (current != NULL && index < module_count) {
if (current->config.priority >= min_priority && current->config.priority <= max_priority) {
modules[index++] = current;
}
current = current->next;
}
*count = module_count;
return modules;
}
/**
* @brief Set module enable/disable state
* @param type: Module type
* @param instance: Module instance
* @param enable: Enable flag
* @retval HAL status code
*/
hal_ret_t bsp_module_set_enable(bsp_module_type_t type, uint8_t instance, uint8_t enable) {
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
return HAL_ERROR;
}
module->config.enable = enable;
return HAL_OK;
}
/**
* @brief Check if module is enabled
* @param type: Module type
* @param instance: Module instance
* @param enable: Pointer to store enable state
* @retval HAL status code
*/
hal_ret_t bsp_module_is_enabled(bsp_module_type_t type, uint8_t instance, uint8_t* enable) {
if (enable == NULL) {
return HAL_INVALID_PARAM;
}
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
*enable = 0;
return HAL_ERROR;
}
*enable = module->config.enable;
return HAL_OK;
}
/**
* @brief Set module priority
* @param type: Module type
* @param instance: Module instance
* @param priority: New priority
* @retval HAL status code
*/
hal_ret_t bsp_module_set_priority(bsp_module_type_t type, uint8_t instance, bsp_module_priority_t priority) {
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
return HAL_ERROR;
}
module->config.priority = priority;
return HAL_OK;
}
/**
* @brief Get module priority
* @param type: Module type
* @param instance: Module instance
* @param priority: Pointer to store priority
* @retval HAL status code
*/
hal_ret_t bsp_module_get_priority(bsp_module_type_t type, uint8_t instance, bsp_module_priority_t* priority) {
if (priority == NULL) {
return HAL_INVALID_PARAM;
}
bsp_module_t* module = bsp_module_get(type, instance);
if (module == NULL) {
*priority = BSP_MODULE_PRIORITY_MEDIUM;
return HAL_ERROR;
}
*priority = module->config.priority;
return HAL_OK;
}