Files
STM32F4-Base/Src/freertos.c
T

363 lines
12 KiB
C
Raw 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.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include "net_task.h"
#include "ch395f.h"
#include "dbg_log.h"
#include "net_socket.h"
#include "usart.h"
#include "ff.h"
#include "gd5f2gq5ue.h"
#include "lftpd.h"
#include "../test/ch395f_test_task.h"
#include "../test/ch395f_test.h" /* ENABLE_NET_LAYER_TESTS:netTask 条件创建 */
#include "time_sync.h"
#include "sys_events.h"
#include "sys_log.h"
#include "net_cfg.h"
#include "cfg_file.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* 存储测试变量(g_storage_stats / s_perf_buf)已迁至 test/storage_test_task.c */
osThreadId_t timeSyncTaskHandle;
const osThreadAttr_t timeSyncTask_attributes = {
.name = "timeSyncTask",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for netTask */
osThreadId_t netTaskHandle;
const osThreadAttr_t netTask_attributes = {
.name = "netTask",
.stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for ftpTask */
osThreadId_t ftpTaskHandle;
const osThreadAttr_t ftpTask_attributes = {
.name = "ftpTask",
.stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for testTask */
osThreadId_t testTaskHandle;
const osThreadAttr_t testTask_attributes = {
.name = "testTask",
.stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityBelowNormal,
};
/* Definitions for uiTask */
osThreadId_t uiTaskHandle;
const osThreadAttr_t uiTask_attributes = {
.name = "uiTask",
.stack_size = 4096 * 4,
.priority = (osPriority_t) osPriorityBelowNormal,
};
/* Definitions for netMsgQueue */
osMessageQueueId_t netMsgQueueHandle;
const osMessageQueueAttr_t netMsgQueue_attributes = {
.name = "netMsgQueue"
};
/* Definitions for sys_evt */
osEventFlagsId_t sys_evtHandle;
const osEventFlagsAttr_t sys_evt_attributes = {
.name = "sys_evt"
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
void ui_task_func(void *argument);
static void default_task_net_cfg_save_notify(void);
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void StartNetTask(void *argument);
void StartFtpTask(void *argument);
void start_test_task(void *argument);
void StartUiTask(void *argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* Create the queue(s) */
/* creation of netMsgQueue */
netMsgQueueHandle = osMessageQueueNew (8, sizeof(net_msg_t), &netMsgQueue_attributes);
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* creation of netTask */
netTaskHandle = osThreadNew(StartNetTask, NULL, &netTask_attributes);
/* creation of ftpTask */
ftpTaskHandle = osThreadNew(StartFtpTask, NULL, &ftpTask_attributes);
/* creation of testTask */
testTaskHandle = osThreadNew(start_test_task, NULL, &testTask_attributes);
/* creation of uiTask */
uiTaskHandle = osThreadNew(StartUiTask, NULL, &uiTask_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* netTask = 基础线程:上方生成区的实例是全构建唯一实例(P1-6:旧
* #ifdef ENABLE_NET_LAYER_TESTS 的重复创建已删除)。
* - 产品 / NET 层测试模式:正常运行 bring_up + net_poll
* - CH395F 硬件层测试模式:net_task_func 入口自挂起(testTask 独占 CH395F) */
/* 本地时间同步任务(PC 推送 TCP):依赖 netTask 处理消息队列 */
timeSyncTaskHandle = osThreadNew(time_sync_task, NULL, &timeSyncTask_attributes);
/* USER CODE END RTOS_THREADS */
/* Create the event(s) */
/* creation of sys_evt */
sys_evtHandle = osEventFlagsNew(&sys_evt_attributes);
/* USER CODE BEGIN RTOS_EVENTS */
/* add events, ... */
/* USER CODE END RTOS_EVENTS */
}
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
(void)argument;
/* 系统启动期挂载 NAND 上的 FatFS 卷,供 FTP 及其它模块访问。
* f_mount(forced=1) 会触发 disk_initialize() → nand_ftl_init()
* (dhara_map_resume)。此前默认构建从未挂载,导致 FTP 的
* LIST/STOR/RETR 全部返回 550(f_opendir 失败)。
* 若卷为空(FR_NO_FILESYSTEM,如恢复/坏块重建后清空),则首次自动
* 格式化建卷(MKFS_PARM 与存储测试一致:FM_FAT32 / 无分区表)。 */
static FATFS default_fatfs;
FRESULT fr = f_mount(&default_fatfs, "", 1);
if (fr == FR_NO_FILESYSTEM) {
DBG_INFO("[FS] no FAT volume, formatting NAND...");
static uint8_t fs_work[FF_MAX_SS];
MKFS_PARM opts = { FM_FAT32, 0, 0, 0, 0 };
fr = f_mkfs("", &opts, fs_work, sizeof(fs_work));
if (fr == FR_OK) {
fr = f_mount(&default_fatfs, "", 1);
} else {
DBG_ERROR("[FS] f_mkfs failed (fr=%d)", (int)fr);
}
}
if (fr == FR_OK) {
DBG_INFO("[FS] FATFS mounted");
/* 日志引擎挂载后处理:建 /log 目录 + 写"上电/重启"分类记录(唯一写者) */
syslog_mcu_mounted();
/* 加载网络配置进 RAM 副本(配置引擎属主 = 本任务;首启含旧档迁移;
* 文件缺失/损坏 = 工厂默认,不阻塞组网)。须在置位 STORAGE_READY 前,
* 使"存储就绪"屏障蕴含"配置已就绪",netTask 组网时配置恒有效 */
(void)net_cfg_load();
/* 广播"存储就绪"(= 卷挂载 + 配置加载完成),唤醒依赖文件系统的任务 */
if (sys_evtHandle != NULL) {
osEventFlagsSet(sys_evtHandle, SYS_EVT_STORAGE_READY);
}
} else {
DBG_ERROR("[FS] f_mount failed (fr=%d)", (int)fr);
/* 存储不可写:自检故障仅能滞留待发队列(串口已告警) */
syslog_post(SYSLOG_SELFTEST, "文件系统异常");
}
/* 注册"保存网络配置"请求通知:UI(uiTask)投递 → 置事件 → 本任务立即执行写盘
* (配置引擎属主 = 本任务;UI 保存不再直接触碰配置文件引擎,P1-3) */
net_cfg_set_save_req_cb(default_task_net_cfg_save_notify);
/* 配置 poll 周期计数(每 4 次循环 = 2s 轮询一次,与引擎文档/模拟器一致) */
uint32_t cfg_poll_cnt = 0u;
for (;;) {
/* 等待"保存网络配置"请求:有请求立即唤醒;无请求 500ms 后返回
* (取代原 osDelay(500):循环节奏不变,保存响应零空转) */
if (sys_evtHandle != NULL) {
(void)osEventFlagsWait(sys_evtHandle, SYS_EVT_CFG_SAVE, osFlagsWaitAny, 500u);
}
/* 执行待处理保存(配置引擎属主:写盘 + 成功后立即应用);无请求 = 空操作 */
net_cfg_save_run();
/* 配置文件变更轮询(2s 周期;沉降去抖在引擎内) */
if ((cfg_poll_cnt++ & 3u) == 0u) {
cfg_file_poll();
}
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);
/* 排空运行期日志(上电/重启分类与自检故障落盘) */
syslog_drain();
}
/* USER CODE END StartDefaultTask */
}
/* USER CODE BEGIN Header_StartNetTask */
/**
* @brief Function implementing the netTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartNetTask */
void StartNetTask(void *argument)
{
/* USER CODE BEGIN StartNetTask */
net_task_func(argument);
/* USER CODE END StartNetTask */
}
/* USER CODE BEGIN Header_StartFtpTask */
/**
* @brief Function implementing the ftpTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartFtpTask */
__weak void StartFtpTask(void *argument)
{
/* USER CODE BEGIN StartFtpTask */
/* 等网络 + 存储都真正就绪后再 listen,取代拍脑袋的 7s 魔法延时 */
/*
sys_evtHandle:等待哪个事件组
SYS_EVT_NET_READY | SYS_EVT_STORAGE_READY:要等哪几位(1u<<0 网络、1u<<1 存储)
osFlagsWaitAll:请求的位全部置位才唤醒(即"网络且存储都就绪")
osWaitForever:无限期等待,不设超时——任务会挂起(让出 CPU,零占用),直到生产者置位对应位才被唤醒
*/
if (sys_evtHandle != NULL) {
(void)osEventFlagsWait(sys_evtHandle,
SYS_EVT_NET_READY | SYS_EVT_STORAGE_READY,
osFlagsWaitAll, osWaitForever);
}
lftpd_t ftp;
lftpd_start("/", 21, &ftp);
/* 广播"FTP 服务就绪"(预留给依赖 FTP 的后续功能) */
if (sys_evtHandle != NULL) {
osEventFlagsSet(sys_evtHandle, SYS_EVT_FTP_READY);
}
/* USER CODE END StartFtpTask */
}
/* USER CODE BEGIN Header_start_test_task */
/**
* @brief Function implementing the testTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_start_test_task */
__weak void start_test_task(void *argument)
{
/* USER CODE BEGIN start_test_task */
/* Infinite loop */
for(;;)
{
osDelay(1);
}
/* USER CODE END start_test_task */
}
/* USER CODE BEGIN Header_StartUiTask */
/**
* @brief Function implementing the uiTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartUiTask */
void StartUiTask(void *argument)
{
/* USER CODE BEGIN StartUiTask */
ui_task_func(argument);
/* USER CODE END StartUiTask */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/*
* "保存网络配置"请求通知(注册给 net_cfg 的保存交接):
* uiTask 投递保存请求 → 置 SYS_EVT_CFG_SAVE → defaultTask 循环立即唤醒执行写盘
*/
static void default_task_net_cfg_save_notify(void)
{
if (sys_evtHandle != NULL) {
(void)osEventFlagsSet(sys_evtHandle, SYS_EVT_CFG_SAVE);
}
}
/* USER CODE END Application */