stm32源码记录分析之sdio驱动问题(filex组件)

前言

  1. 此次记录是使用threadx+filex测试sd重复挂载时,第二次就会卡死在HAL的函数中
  2. 使用的是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初始化代码


测试结果

测试ok。

相关推荐
-Springer-1 小时前
STM32 学习 —— 个人学习笔记5(EXTI 外部中断 & 对射式红外传感器及旋转编码器计数)
笔记·stm32·学习
LS_learner1 小时前
树莓派(ARM64 架构)Ubuntu 24.04 (Noble) 系统 `apt update` 报错解决方案
嵌入式硬件
来自晴朗的明天2 小时前
16、电压跟随器(缓冲器)电路
单片机·嵌入式硬件·硬件工程
钰珠AIOT2 小时前
在同一块电路板上同时存在 0805 0603 不同的封装有什么利弊?
嵌入式硬件
代码游侠2 小时前
复习——Linux设备驱动开发笔记
linux·arm开发·驱动开发·笔记·嵌入式硬件·架构
代码游侠13 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
xuxg200515 小时前
4G 模组 AT 命令解析框架课程正式发布
stm32·嵌入式·at命令解析框架
CODECOLLECT17 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen18 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制