前言
- 此次记录是使用threadx+filex测试sd重复挂载时,第二次就会卡死在HAL的函数中
- 使用的是stm32f407zgt6
问题现象
测试代码(主要)
串口线程
c
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-4 shchl first version
*/
#include "includes.h"
#if 1
#define APP_TASK_SERIAL_MONI_STK_SIZE 2048
#define APP_TASK_SERIAL_MONI_PRIO 10
/*
*******************************************************************************************************
* 外部引入变量
*******************************************************************************************************
*/
extern app_msg filex_msg;
extern TX_QUEUE AppFilexQueue;
/*
*******************************************************************************************************
* 变量
*******************************************************************************************************
*/
/*
*********************************************************************************************************
* 静态全局变量
*********************************************************************************************************
*/
static TX_THREAD serial_moni_thread;
static uint64_t serial_moni_task_stk[APP_TASK_SERIAL_MONI_STK_SIZE / 8];
/*
*********************************************************************************************************
* 函数声明
*********************************************************************************************************
*/
static void serial_moni_entry(ULONG input);
/*
*********************************************************************************************************
* 外部函数
*********************************************************************************************************
*/
/**
* @brief cpu 状态任务
*/
void tx_task_serial_monitor_create() {
tx_thread_create(&serial_moni_thread, /* 任务控制块地址 */
"serial_moni", /* 任务名 */
serial_moni_entry, /* 启动任务函数地址 */
0, /* 传递给任务的参数 */
&serial_moni_task_stk[0], /* 堆栈基地址 */
APP_TASK_SERIAL_MONI_STK_SIZE, /* 堆栈空间大小 */
APP_TASK_SERIAL_MONI_PRIO, /* 任务优先级*/
APP_TASK_SERIAL_MONI_PRIO, /* 任务抢占阀值 */
TX_NO_TIME_SLICE, /* 不开启时间片 */
TX_AUTO_START); /* 创建后立即启动 */
}
/*
*********************************************************************************************************
* 内部函数
*********************************************************************************************************
*/
static inline void serial_filex_handle(const char *cmd);
static void serial_moni_entry(ULONG input) {
static uint8_t buf[256];
filex_msg.msg_id = 0;
filex_msg.code = 0;
while (1) {
uint8_t *ptr = buf;
while (comGetChar(COM1, ptr)) {
ptr++;
if (ptr > buf + 256) {
break;
}
}
if (ptr != buf) {
*ptr = '\0';
if (strstr((const char *) buf, "printf")) {
app_task_info_out();
} else {
serial_filex_handle((const char *) buf);
}
}
tx_thread_sleep(10);
}
}
static inline void serial_filex_handle(const char *cmd) {
static UINT msgAddr = (UINT) &filex_msg;
#define FILEX_CMD_PRE "filex_"
#define FILEX_CMD_PRE_LEN strlen(FILEX_CMD_PRE)
if (strstr(cmd, FILEX_CMD_PRE) && strlen(cmd) > FILEX_CMD_PRE_LEN) {
char ch = *(cmd + FILEX_CMD_PRE_LEN);
if ('0' <= ch && ch < '9') {
filex_msg.code = ch -'0';
if (tx_queue_send(&AppFilexQueue, &msgAddr, 1000) == TX_SUCCESS) {
tx_log("send ok,code is [%d]\r\n", filex_msg.code);
}
filex_msg.msg_id++;
}
}
}
#endif
处理filex文件线程
c
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-5 shchl first version
*/
#include "includes.h"
#define FILEX_DEMO_STK_SIZE 4096
extern TX_QUEUE AppFilexQueue;
TX_THREAD filex_demo_thread;
static uint64_t filex_demo_stack[FILEX_DEMO_STK_SIZE / 8];
static VOID filex_demo_entry(ULONG input);
void app_task_filex_demo_create() {
_txe_thread_create(
&filex_demo_thread,
"filex_demo_thread",
filex_demo_entry,
0,
filex_demo_stack,
FILEX_DEMO_STK_SIZE,
15,
15,
TX_NO_TIME_SLICE,
TX_AUTO_START,
sizeof(TX_THREAD)
);
}
extern void app_filex_sys_mount();
extern void app_filex_create_file_test();
static VOID filex_demo_entry(ULONG input) {
app_msg *msg;
UINT stat;
UINT add;
while (1) {
stat = tx_queue_receive(&AppFilexQueue, &add, TX_WAIT_FOREVER);
msg = (app_msg *)add;
if(stat==TX_SUCCESS){
switch (msg->code) {
case 1: {
tx_log("app_filex_sys_mount func test\r\n");
app_filex_sys_mount();
break;
}
case 2:
tx_log("app_filex_create_file_test func test\r\n");
app_filex_create_file_test();
break;
default:
tx_log("not implement\r\n");
break;
}
}
}
}
filex 组件测试
c
/*
* Copyright (c) 2024-2024,shchl
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-4-5 shchl 文件系统挂载
*/
#include "includes.h"
#include "fx_stm32_sd_driver.h"
#define SD_MEDIA_MEM_SIZE 1024
static FX_MEDIA sd_media_disk;
static UCHAR sd_media_memmory[SD_MEDIA_MEM_SIZE];
/* FileX相关变量 */
static FX_FILE fx_file;
static CHAR entry_name[FX_MAX_LONG_NAME_LEN] = {0};
static volatile uint8_t mount_flag = 0;
static void app_dir_info_out(FX_MEDIA *media);
static inline UINT app_sd_mount() {
UINT stat;
if (!mount_flag) {
stat = fx_media_open(&sd_media_disk, "STM32_SDIO_DISK", fx_stm32_sd_driver, 0, sd_media_memmory,
SD_MEDIA_MEM_SIZE);
} else {
return FX_SUCCESS;
}
if (stat == FX_SUCCESS) {
mount_flag = 1;
}
return stat;
}
static inline UINT app_sd_unmount() {
mount_flag = 0;
return fx_media_close(&sd_media_disk);
}
void app_filex_sys_mount() {
UINT status;
UINT cnt;
ULONG64 available_bytes;
/* 挂载sd 媒体驱动*/
status = app_sd_mount();
if (status != FX_SUCCESS) {
tx_log("fx_media_open is err[%]\r\n", status);
return;
}
app_dir_info_out(&sd_media_disk);
/* SD卡剩余容量大小 */
status = fx_media_extended_space_available(&sd_media_disk, &available_bytes);
if (status == FX_SUCCESS) {
tx_log("SD卡剩余容量大小 -- %lldMB\r\n", available_bytes / 1024 / 1024);
}
/* 卸载SD卡 */
status = app_sd_unmount();
if (status != FX_SUCCESS) {
printf("卸载文件系统卸载失败 -- %d\r\n", status);
}
}
void app_filex_create_file_test() {
UINT status;
/* 挂载SD卡 */
status = app_sd_mount();
if (status != FX_SUCCESS) {
tx_log("挂载文件系统失败 -- %d\r\n", status);
return;
}
/* 创建文件 */
status = fx_file_create(&sd_media_disk, "armfly.txt");
/* 检测状态 */
if (status != FX_SUCCESS) {
/* 失败的话,可以考虑二次创建 */
if (status != FX_ALREADY_CREATED) {
printf("创建文件失败\r\n");
}
}
/* 打开文件 */
status = fx_file_open(&sd_media_disk, &fx_file, "armfly.txt", FX_OPEN_FOR_WRITE);
if (status != FX_SUCCESS) {
tx_log("打开文件失败\r\n");
}
/* 设置到起始位置读取 */
status = fx_file_seek(&fx_file, 0);
if (status != FX_SUCCESS) {
tx_log("设置读取位置失败\r\n");
}
#define WR_CONTENT_STR "hello filex, this is content"
#define WR_CONTENT_STR_LEN strlen(WR_CONTENT_STR)
/* 写入字符串到文件 */
status = fx_file_write(&fx_file, WR_CONTENT_STR, WR_CONTENT_STR_LEN);
#undef WR_CONTENT_STR
#undef WR_CONTENT_STR_LEN
if (status == FX_SUCCESS) {
tx_log("armfly.txt 文件写入成功\r\n");
} else {
tx_log("armfly.txt 文件写入失败 %d\r\n", status);
}
/* 关闭文件 */
status = fx_file_close(&fx_file);
/* Check the file close status. */
if (status != FX_SUCCESS) {
tx_log("关闭文件失败\r\n");
}
/* 保证文件写入全部生效 */
status = fx_media_flush(&sd_media_disk);
if (status != FX_SUCCESS) {
tx_log("flush失败\r\n");
}
/* 卸载SD卡 */
status = app_sd_unmount();
if (status != FX_SUCCESS) {
tx_log("卸载文件系统卸载失败 -- %d\r\n", status);
}
}
static void app_dir_info_out(FX_MEDIA *media) {
UINT status;
UINT attributes;
ULONG size;
UINT year;
UINT month;
UINT day;
UINT hour;
UINT minute;
UINT second;
tx_log("属性 | 文件大小 | 短文件名 | 长文件名\r\n");
for (int cnt = 0;; cnt++) {
/* 读取目录项,索引会自动下移 */
status = fx_directory_next_full_entry_find(media,
entry_name,
&attributes,
&size,
&year, &month, &day,
&hour, &minute, &second);
if (status != FX_SUCCESS || entry_name[0] == 0) {
break;
}
if (entry_name[0] == '.') {
continue;
}
/* 判断是文件还是子目录 */
if (attributes & FX_DIRECTORY) {
tx_log("目录 ");
} else {
tx_log("文件 ");
}
/* 打印文件大小, 最大4G */
tx_log(" %10d", (int) size);
tx_log(" %s\r\n", (char *) entry_name); /* 长文件名 */
}
}
通讯逻辑
解决方案
修改HAL库之SD初始化代码