3. 打开和关闭媒体

任务目标

本案例演示ThreadX FileX文件系统中媒体(Media)的打开与关闭操作。通过调用fx_media_open和fx_media_close,完成对RAM磁盘的初始化与释放,并处理打开失败时的错误分支,最后通过媒体状态字段验证操作结果。

实现原理

fx_media_open将文件系统驱动程序与媒体控制块绑定,读取引导扇区并初始化FAT表;fx_media_close则刷新缓存并释放媒体占用的资源。打开失败时返回非FX_SUCCESS状态码,此时不应继续执行文件操作。媒体控制块的fx_media_open_count字段在打开成功后递增,关闭后递减,可用于状态检查。

关键完整代码

#include "tx_api.h"
#include "fx_api.h"

/* 定义媒体控制块和RAM驱动缓冲区 */
FX_MEDIA ram_disk;
UCHAR ram_disk_memory[512 * 64];   /* 64个扇区,每扇区512字节 */
UCHAR ram_disk_sector_cache[512];  /* 单扇区缓存 */

/* RAM磁盘驱动程序(最小实现,仅支持读写扇区) */
VOID _fx_ram_driver(FX_MEDIA *media_ptr)
{
    UCHAR *source_ptr, *destination_ptr;
    ULONG destination_sector;

    /* 处理读写请求 */
    if (media_ptr->fx_media_driver_request == FX_DRIVER_READ)
    {
        source_ptr = ram_disk_memory + (media_ptr->fx_media_driver_logical_sector * 512);
        destination_ptr = media_ptr->fx_media_driver_buffer;
        destination_sector = media_ptr->fx_media_driver_logical_sector;
        /* 复制扇区数据到缓存 */
        destination_ptr = media_ptr->fx_media_driver_buffer;
        for (int i = 0; i < 512; i++)
        {
            *destination_ptr++ = *source_ptr++;
        }
        media_ptr->fx_media_driver_status = FX_SUCCESS;
    }
    else if (media_ptr->fx_media_driver_request == FX_DRIVER_WRITE)
    {
        source_ptr = media_ptr->fx_media_driver_buffer;
        destination_ptr = ram_disk_memory + (media_ptr->fx_media_driver_logical_sector * 512);
        for (int i = 0; i < 512; i++)
        {
            *destination_ptr++ = *source_ptr++;
        }
        media_ptr->fx_media_driver_status = FX_SUCCESS;
    }
    else if (media_ptr->fx_media_driver_request == FX_DRIVER_INIT)
    {
        /* 初始化时清零媒体内存 */
        memset(ram_disk_memory, 0, sizeof(ram_disk_memory));
        media_ptr->fx_media_driver_status = FX_SUCCESS;
    }
    else if (media_ptr->fx_media_driver_request == FX_DRIVER_UNINIT)
    {
        media_ptr->fx_media_driver_status = FX_SUCCESS;
    }
    else if (media_ptr->fx_media_driver_request == FX_DRIVER_ABORT)
    {
        media_ptr->fx_media_driver_status = FX_SUCCESS;
    }
    else
    {
        media_ptr->fx_media_driver_status = FX_UNSUPPORTED;
    }
}

/* 应用入口函数 */
VOID media_open_close_demo(ULONG arg)
{
    UINT status;

    /* 第一次打开:应成功 */
    status = fx_media_open(&ram_disk, "RAM_DISK", _fx_ram_driver,
                           FX_TRUE, ram_disk_sector_cache, sizeof(ram_disk_sector_cache));
    if (status != FX_SUCCESS)
    {
        /* 打开失败处理 */
        printf("媒体打开失败,错误码:0x%x\n", status);
        return;
    }

    /* 检查打开计数 */
    printf("媒体打开成功,打开计数:%lu\n", ram_disk.fx_media_open_count);

    /* 关闭媒体 */
    status = fx_media_close(&ram_disk);
    if (status != FX_SUCCESS)
    {
        printf("媒体关闭失败,错误码:0x%x\n", status);
        return;
    }

    /* 验证关闭后状态 */
    printf("媒体关闭成功,打开计数:%lu\n", ram_disk.fx_media_open_count);

    /* 第二次打开:模拟失败场景(使用无效的媒体指针) */
    status = fx_media_open(FX_NULL, "BAD_DISK", _fx_ram_driver,
                           FX_TRUE, ram_disk_sector_cache, sizeof(ram_disk_sector_cache));
    if (status != FX_SUCCESS)
    {
        printf("预期失败已捕获,错误码:0x%x\n", status);
    }
}

/* ThreadX入口 */
VOID tx_application_define(VOID *first_unused_memory)
{
    /* 创建演示线程 */
    tx_thread_create(&demo_thread, "Demo", media_open_close_demo, 0,
                     stack_ptr, 2048, 1, 1, TX_NO_TIME_SLICE);
}

编译与运行

  1. 将以上代码与ThreadX库、FileX库一同编译链接;
  2. 确保fx_api.h和tx_api.h头文件路径已包含;
  3. 在嵌入式平台或模拟器中运行,观察串口输出。

验证方法

  • 成功路径:第一次fx_media_open返回FX_SUCCESS,且打印的打开计数为1;
  • 关闭验证:fx_media_close返回FX_SUCCESS,关闭后打开计数恢复为0;
  • 失败路径:传入FX_NULL媒体指针时,fx_media_open返回非成功状态码(预期为FX_PTR_ERROR),程序捕获并打印错误码。

若串口依次输出“媒体打开成功,打开计数:1”、“媒体关闭成功,打开计数:0”和“预期失败已捕获”,则说明媒体打开/关闭及错误处理逻辑均正确。