- 新增完整的CMSIS解决方案配置,包含AC6/GCC/IAR/CLANG编译器支持 - 添加项目配置文件,定义了设备层、系统层、应用层的模块结构 - 配置ARM::CMSIS和GigaDevice::GD32E50x_DFP软件包依赖 - 创建多层代码架构:应用入口(main)、系统层(sys)、设备层(device) - 实现任务管理系统,包含任务调度器和任务执行器分离设计 - 集成ADC、CANFD、定时器、串口、温度采样等核心功能模块 - 添加详细的README文档说明项目结构和代码组织方式 - 配置AC6链接脚本和运行时环境文件 - 设置Git忽略规则以排除编译产物和临时文件
179 lines
4.3 KiB
Plaintext
179 lines
4.3 KiB
Plaintext
/**
|
|
* @file task_runner.cpp
|
|
* @brief 任务执行器初始化与待执行任务分发实现。
|
|
*/
|
|
|
|
#include "main.h"
|
|
#include "device/adc.h"
|
|
#include "device/canfd.h"
|
|
#include "device/temp_sensor.h"
|
|
#include "sys/task_manager.h"
|
|
#include "sys/task_runner.h"
|
|
|
|
namespace {
|
|
/** @brief 应用运行时上下文,保存各任务间共享的最新数据。 */
|
|
struct AppRuntime {
|
|
temp_sensor_data_t sample{};
|
|
uint16_t last_vref_raw = 0U;
|
|
uint16_t last_temp_raw = 0U;
|
|
uint32_t last_rx_id = 0U;
|
|
uint8_t last_rx_len = 0U;
|
|
uint8_t last_rx_data[64] = {0};
|
|
};
|
|
|
|
AppRuntime g_app{};
|
|
|
|
/**
|
|
* @brief 采样内部参考电压原始值。
|
|
*/
|
|
inline void task_adc_vref_sample()
|
|
{
|
|
g_app.last_vref_raw = adc_read_vref_raw();
|
|
}
|
|
|
|
/**
|
|
* @brief 采样内部温度通道原始值。
|
|
*/
|
|
inline void task_adc_temp_sample()
|
|
{
|
|
g_app.last_temp_raw = adc_read_temp_raw();
|
|
}
|
|
|
|
/**
|
|
* @brief 根据采样原始值换算 VDDA 与芯片温度。
|
|
*/
|
|
inline void task_adc_process()
|
|
{
|
|
g_app.sample.vref_raw = g_app.last_vref_raw;
|
|
g_app.sample.temp_raw = g_app.last_temp_raw;
|
|
g_app.sample.vdda = adc_calculate_vdda(g_app.sample.vref_raw);
|
|
g_app.sample.temperature = adc_calculate_temperature(g_app.sample.temp_raw, g_app.sample.vdda);
|
|
}
|
|
|
|
/**
|
|
* @brief 轮询 CANFD 接收 FIFO。
|
|
*/
|
|
inline void task_can_rx_poll()
|
|
{
|
|
canfd_poll();
|
|
}
|
|
|
|
/**
|
|
* @brief 解析并消费已接收的 CANFD 帧。
|
|
*/
|
|
inline void task_can_rx_parse()
|
|
{
|
|
if(canfd_has_rx_frame() != 0U) {
|
|
canfd_consume_rx_frame(&g_app.last_rx_id, g_app.last_rx_data, &g_app.last_rx_len);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 准备 CANFD 状态发送帧。
|
|
*/
|
|
inline void task_can_tx_prepare()
|
|
{
|
|
const canfd_status_payload_t status {
|
|
g_app.sample.temp_raw,
|
|
g_app.sample.vref_raw,
|
|
g_app.sample.vdda,
|
|
g_app.sample.temperature,
|
|
};
|
|
canfd_prepare_status(&status);
|
|
}
|
|
|
|
/**
|
|
* @brief 发送已准备好的 CANFD 帧。
|
|
*/
|
|
inline void task_can_tx_send()
|
|
{
|
|
canfd_send_prepared();
|
|
}
|
|
|
|
/**
|
|
* @brief 状态灯维护任务(当前为预留占位)。
|
|
*/
|
|
inline void task_status_led()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @brief 系统心跳维护任务(当前为预留占位)。
|
|
*/
|
|
inline void task_heartbeat()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @brief 诊断信息打印任务,输出当前所有运行时数据。
|
|
*/
|
|
inline void task_diagnostic_print()
|
|
{
|
|
const canfd_diag_t *diag = canfd_get_diag();
|
|
|
|
printf("temp_raw=%u, vref_raw=%u, vdda=%.3f V, temp=%.2f C, rx_id=0x%08lX, rx_len=%u, can_tx=%lu, can_rx=%lu, can_err=%lu\r\n",
|
|
g_app.sample.temp_raw,
|
|
g_app.sample.vref_raw,
|
|
g_app.sample.vdda,
|
|
g_app.sample.temperature,
|
|
static_cast<unsigned long>(g_app.last_rx_id),
|
|
static_cast<unsigned int>(g_app.last_rx_len),
|
|
static_cast<unsigned long>(diag->tx_count),
|
|
static_cast<unsigned long>(diag->rx_count),
|
|
static_cast<unsigned long>(diag->error_count));
|
|
}
|
|
} // namespace
|
|
|
|
/**
|
|
* @brief 初始化任务执行器运行时上下文。
|
|
* @note 执行一次初始采样,填充运行时数据起点。
|
|
*/
|
|
void task_runner_init(void)
|
|
{
|
|
adc_collect_sample(&g_app.sample);
|
|
g_app.last_vref_raw = g_app.sample.vref_raw;
|
|
g_app.last_temp_raw = g_app.sample.temp_raw;
|
|
}
|
|
|
|
/**
|
|
* @brief 执行当前所有已置位的待处理任务。
|
|
* @note 若当前没有待执行任务,直接返回。
|
|
*/
|
|
void task_runner_run_pending(void)
|
|
{
|
|
const uint32_t pending = task_manager_take_pending();
|
|
if(pending == 0U) {
|
|
return;
|
|
}
|
|
|
|
if((pending & (1UL << TASK_ADC_VREF_SAMPLE)) != 0U) {
|
|
task_adc_vref_sample();
|
|
}
|
|
if((pending & (1UL << TASK_ADC_TEMP_SAMPLE)) != 0U) {
|
|
task_adc_temp_sample();
|
|
}
|
|
if((pending & (1UL << TASK_ADC_PROCESS)) != 0U) {
|
|
task_adc_process();
|
|
}
|
|
if((pending & (1UL << TASK_CAN_RX_POLL)) != 0U) {
|
|
task_can_rx_poll();
|
|
}
|
|
if((pending & (1UL << TASK_CAN_RX_PARSE)) != 0U) {
|
|
task_can_rx_parse();
|
|
}
|
|
if((pending & (1UL << TASK_CAN_TX_PREPARE)) != 0U) {
|
|
task_can_tx_prepare();
|
|
}
|
|
if((pending & (1UL << TASK_CAN_TX_SEND)) != 0U) {
|
|
task_can_tx_send();
|
|
}
|
|
if((pending & (1UL << TASK_STATUS_LED)) != 0U) {
|
|
task_status_led();
|
|
}
|
|
if((pending & (1UL << TASK_HEARTBEAT)) != 0U) {
|
|
task_heartbeat();
|
|
}
|
|
if((pending & (1UL << TASK_DIAGNOSTIC_PRINT)) != 0U) {
|
|
task_diagnostic_print();
|
|
}
|
|
} |