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。

相关推荐
yutian06062 小时前
Keil MDK下载程序后MCU自动重启设置
单片机·嵌入式硬件·keil
析木不会编程5 小时前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
枯无穷肉9 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名6779 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式科普9 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣9 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp
云山工作室10 小时前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
嵌入式-老费10 小时前
基于海思soc的智能产品开发(mcu读保护的设置)
单片机·嵌入式硬件
qq_3975623112 小时前
MPU6050 , 设置内部低通滤波器,对于输出数据的影响。(简单实验)
单片机
liyinuo201712 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范