Files
STM32F4-Base/Src/freertos.c
2026-07-21 20:18:28 +08:00

328 lines
9.4 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 "flashdb.h"
#include "gd5f2gq5ue.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* 存储测试统计 */
typedef struct {
uint16_t total;
uint16_t passed;
uint16_t failed;
} storage_test_stats_t;
#define STORAGE_TEST_CHECK(cond, fmt, ...) do { \
g_storage_stats.total++; \
if (cond) { \
g_storage_stats.passed++; \
DBG_INFO(" [PASS] " fmt, ##__VA_ARGS__); \
} else { \
g_storage_stats.failed++; \
DBG_ERROR(" [FAIL] " fmt, ##__VA_ARGS__); \
} \
} while (0)
#define STORAGE_TEST_REPORT(name) do { \
DBG_INFO("=== %s: %d/%d PASSED (failed=%d) ===", \
name, g_storage_stats.passed, g_storage_stats.total, g_storage_stats.failed); \
} while (0)
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
static struct fdb_kvdb s_kvdb;
static storage_test_stats_t g_storage_stats;
static uint8_t s_perf_buf[4096];
/* 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 netMsgQueue */
osMessageQueueId_t netMsgQueueHandle;
const osMessageQueueAttr_t netMsgQueue_attributes = {
.name = "netMsgQueue"
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void StartNetTask(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);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* 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 */
static FATFS fs;
static FIL fil;
static uint8_t work[FF_MAX_SS];
char read_buf[64];
const char *test_str = "Hello FatFS + dhara FTL!";
fdb_err_t fdb_ret;
memset(&g_storage_stats, 0, sizeof(g_storage_stats));
/* ==================== FTL + FatFS 文件系统测试 ==================== */
FRESULT res = f_mount(&fs, "", 1);
if (res == FR_NO_FILESYSTEM) {
MKFS_PARM opts = {FM_FAT32, 0, 0, 0, 0};
res = f_mkfs("", &opts, work, sizeof(work));
STORAGE_TEST_CHECK(res == FR_OK, "f_mkfs");
res = f_mount(&fs, "", 1);
}
STORAGE_TEST_CHECK(res == FR_OK, "f_mount");
if (res == FR_OK) {
UINT bw, br;
res = f_open(&fil, "test.txt", FA_CREATE_ALWAYS | FA_WRITE);
STORAGE_TEST_CHECK(res == FR_OK, "f_open(write)");
if (res == FR_OK) {
f_write(&fil, test_str, strlen(test_str), &bw);
STORAGE_TEST_CHECK(bw == strlen(test_str), "f_write (%u bytes)", bw);
f_close(&fil);
res = f_open(&fil, "test.txt", FA_READ);
STORAGE_TEST_CHECK(res == FR_OK, "f_open(read)");
if (res == FR_OK) {
f_read(&fil, read_buf, sizeof(read_buf) - 1, &br);
f_close(&fil);
read_buf[br] = '\0';
STORAGE_TEST_CHECK(br == strlen(test_str) && memcmp(test_str, read_buf, br) == 0,
"data verify \"%s\"", read_buf);
}
}
f_unlink("test.txt");
}
/* ==================== FlashDB KVDB 测试 ==================== */
DBG_INFO("=== Storage Test: FlashDB KVDB ===");
/* 第一次 init会触发 FAL 初始化,报告错误但成功) */
fdb_ret = fdb_kvdb_init(&s_kvdb, "kvdb1", "fdb_kvdb1", NULL, NULL);
/* 清除旧验证数据:格式化所有 sector */
fdb_kv_set_default(&s_kvdb);
/* 重新初始化干净的数据库 */
fdb_ret = fdb_kvdb_init(&s_kvdb, "kvdb1", "fdb_kvdb1", NULL, NULL);
STORAGE_TEST_CHECK(fdb_ret == FDB_NO_ERR, "fdb_kvdb_init");
if (fdb_ret == FDB_NO_ERR) {
fdb_ret = fdb_kv_set(&s_kvdb, "hello", "FlashDB KVDB!");
STORAGE_TEST_CHECK(fdb_ret == FDB_NO_ERR, "fdb_kv_set(hello)");
char *val = fdb_kv_get(&s_kvdb, "hello");
STORAGE_TEST_CHECK(val != NULL && strcmp(val, "FlashDB KVDB!") == 0,
"fdb_kv_get(hello) -> \"%s\"", val ? val : "NULL");
uint32_t blob_data = 0xDEADBEEF;
struct fdb_blob blob;
fdb_blob_make(&blob, &blob_data, sizeof(blob_data));
fdb_ret = fdb_kv_set_blob(&s_kvdb, "counter", &blob);
STORAGE_TEST_CHECK(fdb_ret == FDB_NO_ERR, "fdb_kv_set_blob(counter)");
uint32_t read_data = 0;
struct fdb_blob read_blob;
fdb_blob_make(&read_blob, &read_data, sizeof(read_data));
size_t len = fdb_kv_get_blob(&s_kvdb, "counter", &read_blob);
STORAGE_TEST_CHECK(len == sizeof(read_data) && read_data == 0xDEADBEEF,
"fdb_kv_get_blob(counter) -> 0x%08lX", (unsigned long)read_data);
fdb_kv_del(&s_kvdb, "hello");
fdb_kv_del(&s_kvdb, "counter");
}
/* ==================== FTL + FatFS 性能测试 ==================== */
DBG_INFO("=== Storage Test: Performance ===");
{
FIL pfile;
UINT pw, pr;
uint32_t t0, tw, tr;
uint32_t i;
uint32_t total_kb = 128;
uint32_t chunk = sizeof(s_perf_buf);
uint32_t count = (total_kb * 1024) / chunk;
memset(s_perf_buf, 0xA5, sizeof(s_perf_buf));
/* 写入 */
t0 = HAL_GetTick();
if (f_open(&pfile, "perf.dat", FA_CREATE_ALWAYS | FA_WRITE) == FR_OK) {
for (i = 0; i < count; i++) {
f_write(&pfile, s_perf_buf, chunk, &pw);
}
f_close(&pfile);
}
tw = HAL_GetTick() - t0;
/* 读取 */
t0 = HAL_GetTick();
if (f_open(&pfile, "perf.dat", FA_READ) == FR_OK) {
for (i = 0; i < count; i++) {
f_read(&pfile, s_perf_buf, chunk, &pr);
}
f_close(&pfile);
}
tr = HAL_GetTick() - t0;
f_unlink("perf.dat");
if (tw > 0) {
DBG_INFO(" Write: %lu KB in %lu ms = %lu KB/s",
total_kb, tw, (total_kb * 1000) / tw);
}
if (tr > 0) {
DBG_INFO(" Read: %lu KB in %lu ms = %lu KB/s",
total_kb, tr, (total_kb * 1000) / tr);
}
}
/* ==================== 汇总报告 ==================== */
STORAGE_TEST_REPORT("Storage Tests");
for (;;) {
osDelay(1000);
}
/* 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 */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/* USER CODE END Application */