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。

相关推荐
scan19 小时前
单片机串口接收状态机STM32
stm32·单片机·串口·51·串口接收
Qingniu0110 小时前
【青牛科技】应用方案 | RTC实时时钟芯片D8563和D1302
科技·单片机·嵌入式硬件·实时音视频·安防·工控·储能
Mortal_hhh11 小时前
VScode的C/C++点击转到定义,不是跳转定义而是跳转声明怎么办?(内附详细做法)
ide·vscode·stm32·编辑器
深圳市青牛科技实业有限公司11 小时前
【青牛科技】应用方案|D2587A高压大电流DC-DC
人工智能·科技·单片机·嵌入式硬件·机器人·安防监控
Mr.谢尔比12 小时前
电赛入门之软件stm32keil+cubemx
stm32·单片机·嵌入式硬件·mcu·信息与通信·信号处理
LightningJie12 小时前
STM32中ARR(自动重装寄存器)为什么要减1
stm32·单片机·嵌入式硬件
鹿屿二向箔12 小时前
STM32外设之SPI的介绍
stm32
西瓜籽@13 小时前
STM32——毕设基于单片机的多功能节能窗控制系统
stm32·单片机·课程设计
远翔调光芯片^1382879887215 小时前
远翔升压恒流芯片FP7209X与FP7209M什么区别?做以下应用市场摄影补光灯、便携灯、智能家居(调光)市场、太阳能、车灯、洗墙灯、舞台灯必看!
科技·单片机·智能家居·能源
极客小张16 小时前
基于STM32的智能充电桩:集成RTOS、MQTT与SQLite的先进管理系统设计思路
stm32·单片机·嵌入式硬件·mqtt·sqlite·毕业设计·智能充电桩