Files
2026-03-22 15:24:40 +08:00

359 lines
10 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 自然写智能点阵笔嵌入式固件软件 V1.0
* main.c - 主函数入口与RTOS任务创建
*
* 功能说明:
* 1. 系统硬件初始化(GPIO/SPI/I2C/ADC/DMA
* 2. FreeRTOS内核启动与任务创建
* 3. 各功能模块初始化协调
* 4. 看门狗定时器配置
* 5. 系统错误处理与故障恢复
*
* 硬件平台:ARM Cortex-M4F MCU
* RTOSFreeRTOS 10.x
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "timers.h"
#include "event_groups.h"
/* 硬件抽象层头文件 */
#include "hal_gpio.h"
#include "hal_spi.h"
#include "hal_i2c.h"
#include "hal_adc.h"
#include "hal_dma.h"
#include "hal_wdt.h"
#include "hal_flash.h"
#include "hal_rtc.h"
/* 功能模块头文件 */
#include "camera_driver.h"
#include "pressure_sensor.h"
#include "led_driver.h"
#include "ble_gatt_server.h"
#include "dot_decoder.h"
#include "power_manager.h"
#include "offline_storage.h"
/* ========== 任务优先级定义 ========== */
/* 图像采集任务(最高优先级,需要精确的100Hz定时) */
#define TASK_IMAGE_CAPTURE_PRIORITY (configMAX_PRIORITIES - 1)
/* 坐标计算任务 */
#define TASK_COORDINATE_PRIORITY (configMAX_PRIORITIES - 2)
/* BLE发送任务 */
#define TASK_BLE_SEND_PRIORITY (configMAX_PRIORITIES - 3)
/* 电源监测任务(较低优先级) */
#define TASK_POWER_MONITOR_PRIORITY (tskIDLE_PRIORITY + 2)
/* 看门狗喂狗任务 */
#define TASK_WATCHDOG_PRIORITY (tskIDLE_PRIORITY + 1)
/* ========== 任务栈大小定义(单位:字) ========== */
#define TASK_IMAGE_CAPTURE_STACK_SIZE 512
#define TASK_COORDINATE_STACK_SIZE 1024
#define TASK_BLE_SEND_STACK_SIZE 512
#define TASK_POWER_MONITOR_STACK_SIZE 256
#define TASK_WATCHDOG_STACK_SIZE 128
/* ========== 全局队列与信号量 ========== */
/* 图像数据队列(采集任务 → 坐标计算任务) */
QueueHandle_t g_image_data_queue;
/* 坐标数据队列(坐标计算 → BLE发送) */
QueueHandle_t g_coordinate_queue;
/* BLE连接状态事件组 */
EventGroupHandle_t g_ble_event_group;
/* 系统状态互斥锁 */
SemaphoreHandle_t g_system_mutex;
/* ========== 事件位定义 ========== */
#define EVT_BLE_CONNECTED (1 << 0)
#define EVT_BLE_DISCONNECTED (1 << 1)
#define EVT_PEN_DOWN (1 << 2)
#define EVT_PEN_UP (1 << 3)
#define EVT_LOW_BATTERY (1 << 4)
#define EVT_CHARGING (1 << 5)
#define EVT_OTA_START (1 << 6)
/* ========== 全局系统状态 ========== */
typedef struct {
bool pen_is_down; /* 笔尖是否接触纸面 */
bool ble_connected; /* BLE是否已连接 */
bool is_charging; /* 是否正在充电 */
uint8_t battery_percent; /* 电量百分比 */
uint32_t total_strokes; /* 累计笔画数 */
uint32_t uptime_seconds; /* 运行时长 */
uint8_t error_flags; /* 错误标志位 */
} SystemState;
static SystemState g_system_state;
/* ========== 任务句柄 ========== */
static TaskHandle_t g_task_image_capture;
static TaskHandle_t g_task_coordinate;
static TaskHandle_t g_task_ble_send;
static TaskHandle_t g_task_power_monitor;
static TaskHandle_t g_task_watchdog;
/* ========== 函数前向声明 ========== */
static void hardware_init(void);
static void create_rtos_objects(void);
static void create_tasks(void);
static void watchdog_task(void *pvParameters);
/* 外部任务函数(各功能模块中实现) */
extern void image_capture_task(void *pvParameters);
extern void coordinate_task(void *pvParameters);
extern void ble_send_task(void *pvParameters);
extern void power_monitor_task(void *pvParameters);
/* ========== 主函数 ========== */
/**
* 系统入口点
* 完成硬件初始化后启动FreeRTOS调度器
*/
int main(void) {
/* 步骤1:系统时钟配置(PLL → 168MHz */
SystemClock_Config();
/* 步骤2:基础硬件初始化 */
hardware_init();
/* 步骤3:LED指示启动中(蓝色闪烁) */
led_set_mode(LED_MODE_BLINK_BLUE);
/* 步骤4:初始化全局状态 */
memset(&g_system_state, 0, sizeof(g_system_state));
/* 步骤5:创建RTOS同步对象 */
create_rtos_objects();
/* 步骤6:创建功能任务 */
create_tasks();
/* 步骤7:启动看门狗定时器(超时8秒) */
hal_wdt_init(8000);
hal_wdt_start();
/* 步骤8:启动FreeRTOS调度器(不应返回) */
vTaskStartScheduler();
/* 如果到达这里说明调度器启动失败 */
led_set_mode(LED_MODE_SOLID_RED);
while (1) {
/* 系统错误,死循环 */
}
return 0;
}
/* ========== 硬件初始化 ========== */
/**
* 初始化所有硬件外设
*/
static void hardware_init(void) {
/* GPIO初始化(笔尖接触检测引脚、充电检测引脚) */
hal_gpio_init();
/* SPI初始化(连接CMOS图像传感器,主模式 8MHz) */
hal_spi_init(SPI_PORT_1, SPI_MODE_MASTER, 8000000);
/* I2C初始化(连接压力传感器和IMU) */
hal_i2c_init(I2C_PORT_1, 400000); /* 400kHz快速模式 */
/* ADC初始化(电池电压检测,12位分辨率) */
hal_adc_init(ADC_CHANNEL_BATTERY, ADC_RESOLUTION_12BIT);
/* DMA初始化(SPI图像数据DMA传输) */
hal_dma_init(DMA_CHANNEL_SPI_RX);
/* Flash初始化(离线缓存存储) */
hal_flash_init();
/* RTC初始化(时间戳生成) */
hal_rtc_init();
/* 摄像头传感器初始化 */
camera_driver_init();
/* 压力传感器校准 */
pressure_sensor_init();
pressure_sensor_calibrate();
/* LED驱动初始化 */
led_driver_init();
/* BLE协议栈初始化 */
ble_gatt_server_init();
/* 点阵码解码器初始化 */
dot_decoder_init();
/* 电源管理初始化 */
power_manager_init();
/* 离线存储初始化 */
offline_storage_init();
}
/* ========== RTOS对象创建 ========== */
/**
* 创建队列、信号量、事件组等RTOS同步对象
*/
static void create_rtos_objects(void) {
/*
* 图像数据队列:采集任务以100Hz频率产生数据
* 队列深度10帧,每帧包含图像元数据(不含原始像素)
*/
g_image_data_queue = xQueueCreate(10, sizeof(ImageFrameMetadata));
configASSERT(g_image_data_queue != NULL);
/*
* 坐标数据队列:坐标计算结果 → BLE发送
* 队列深度20,容纳突发计算结果
*/
g_coordinate_queue = xQueueCreate(20, sizeof(CoordinatePacket));
configASSERT(g_coordinate_queue != NULL);
/* BLE事件组 */
g_ble_event_group = xEventGroupCreate();
configASSERT(g_ble_event_group != NULL);
/* 系统状态互斥锁 */
g_system_mutex = xSemaphoreCreateMutex();
configASSERT(g_system_mutex != NULL);
}
/* ========== 任务创建 ========== */
/**
* 创建所有FreeRTOS任务
*/
static void create_tasks(void) {
BaseType_t ret;
/* 图像采集任务(100Hz定时采集CMOS图像) */
ret = xTaskCreate(image_capture_task, "ImgCap",
TASK_IMAGE_CAPTURE_STACK_SIZE, NULL,
TASK_IMAGE_CAPTURE_PRIORITY, &g_task_image_capture);
configASSERT(ret == pdPASS);
/* 坐标计算任务(点阵码解码+坐标计算) */
ret = xTaskCreate(coordinate_task, "CoordCalc",
TASK_COORDINATE_STACK_SIZE, NULL,
TASK_COORDINATE_PRIORITY, &g_task_coordinate);
configASSERT(ret == pdPASS);
/* BLE发送任务(坐标数据打包+BLE通知发送) */
ret = xTaskCreate(ble_send_task, "BLESend",
TASK_BLE_SEND_STACK_SIZE, NULL,
TASK_BLE_SEND_PRIORITY, &g_task_ble_send);
configASSERT(ret == pdPASS);
/* 电源监测任务(电池电压/充电状态/低功耗管理) */
ret = xTaskCreate(power_monitor_task, "PwrMon",
TASK_POWER_MONITOR_STACK_SIZE, NULL,
TASK_POWER_MONITOR_PRIORITY, &g_task_power_monitor);
configASSERT(ret == pdPASS);
/* 看门狗喂狗任务 */
ret = xTaskCreate(watchdog_task, "WDT",
TASK_WATCHDOG_STACK_SIZE, NULL,
TASK_WATCHDOG_PRIORITY, &g_task_watchdog);
configASSERT(ret == pdPASS);
}
/* ========== 看门狗任务 ========== */
/**
* 看门狗喂狗任务
* 周期性喂狗,防止系统死锁导致的假死
* 如果各功能任务异常停止,看门狗将触发系统复位
*/
static void watchdog_task(void *pvParameters) {
(void)pvParameters;
TickType_t last_wake_time = xTaskGetTickCount();
while (1) {
/* 每2秒喂一次狗(看门狗超时8秒,留足余量) */
hal_wdt_feed();
/* 更新运行时长 */
if (xSemaphoreTake(g_system_mutex, pdMS_TO_TICKS(100)) == pdTRUE) {
g_system_state.uptime_seconds += 2;
xSemaphoreGive(g_system_mutex);
}
/* 检查各任务是否正常运行 */
if (eTaskGetState(g_task_image_capture) == eSuspended &&
g_system_state.pen_is_down) {
/* 图像采集任务异常挂起但笔在书写,尝试恢复 */
vTaskResume(g_task_image_capture);
}
vTaskDelayUntil(&last_wake_time, pdMS_TO_TICKS(2000));
}
}
/* ========== FreeRTOS回调函数 ========== */
/**
* 栈溢出钩子函数
* 任何任务发生栈溢出时被调用
*/
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
/* 记录错误信息到Flash */
g_system_state.error_flags |= 0x01;
/* LED红色快闪指示严重错误 */
led_set_mode(LED_MODE_FAST_BLINK_RED);
/* 触发系统复位 */
hal_system_reset();
}
/**
* Malloc失败钩子函数
*/
void vApplicationMallocFailedHook(void) {
g_system_state.error_flags |= 0x02;
led_set_mode(LED_MODE_FAST_BLINK_RED);
hal_system_reset();
}
/**
* 空闲任务钩子函数
* 在CPU空闲时进入低功耗模式以节省电量
*/
void vApplicationIdleHook(void) {
/* 如果笔没有在书写且BLE空闲,进入轻度睡眠 */
if (!g_system_state.pen_is_down && !g_system_state.ble_connected) {
power_enter_light_sleep();
}
}