硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1068|回复: 18
收起左侧

[ThreadX全家桶] FileX+USBX Msc双边同步问题

  [复制链接]

2

主题

3

回帖

9

积分

新手上路

积分
9
发表于 2025-8-20 09:50:20 | 显示全部楼层 |阅读模式
目前使用的存储介质是SD卡,进行fx_media_format格式化之后,可以被PC正常识别,写入读取都是正常的。
但是存在本地和PC端不同步的问题,比如在本地创建或写入文件,创建或写入后立即调用了fx_media_flush,本地已经生效,PC端也不会立即刷新出文件,需要重新枚举才能正常显示。
同样通过PC端写入文件,需要重新fx_media_open本地才能看到PC端上次写入的文件。

造成这样的现象,貌似是两边在维护不同的FAT表。请问有什么好的解决方法吗?

下面是我的格式化代码,以及MSC相关操作代码。

[C] 纯文本查看 复制代码
    HAL_SD_CardInfoTypeDef cardInfo;
    HAL_SD_GetCardInfo(&hsd1, &cardInfo);

    fxStatus = fx_media_format(&sdioDisk,                   //Disk Handle
                                fx_stm32_sd_driver,         //Disk Driver
                                (VOID *)FX_NULL,            //Unused
                                (UCHAR *)fxSDMediaMemory,   //Disk Buffer
                                sizeof(fxSDMediaMemory),    //Disk Buffer Size
                                FX_SD_VOLUME_NAME,          //Volume Name
                                1,                          //Num of FATs
                                32,                         //Directory Entries
                                0,                          //Hidden Sectors
                                ((cardInfo.BlockNbr * cardInfo.BlockSize) / FX_STM32_SD_DEFAULT_SECTOR_SIZE),//Total Sectors
                                FX_STM32_SD_DEFAULT_SECTOR_SIZE,//Bytes per Sector
                                128,                        //Sectors per Cluster
                                1,                          //Heads
                                1);                         //Sectors per Track


[C] 纯文本查看 复制代码
/**
  * @brief  USBD_STORAGE_Read
  *         This function is invoked to read from media.
  * @param  storage_instance : Pointer to the storage class instance.
  * @param  lun: Logical unit number is the command is directed to.
  * @param  data_pointer: Address of the buffer to be used for reading or writing.
  * @param  number_blocks: number of sectors to read/write.
  * @param  lba: Logical block address is the sector address to read.
  * @param  media_status: should be filled out exactly like the media status
  *                       callback return value.
  * @retval status
  */
UINT USBD_STORAGE_Read(VOID *storage_instance, ULONG lun, UCHAR *data_pointer,
                       ULONG number_blocks, ULONG lba, ULONG *media_status)
{
  UINT status = UX_SUCCESS;

  /* USER CODE BEGIN USBD_STORAGE_Read */
    UINT fxStatus = FX_SUCCESS;
    while (number_blocks--) {
        fxStatus = fx_media_read(sdioDisk, lba, data_pointer);
        if (fxStatus != FX_SUCCESS) {
            status = UX_ERROR;
            break;
        }
        data_pointer += sdioDisk->fx_media_bytes_per_sector;
        lba++;
    }
  /* USER CODE END USBD_STORAGE_Read */

  return status;
}

/**
  * @brief  USBD_STORAGE_Write
  *         This function is invoked to write in media.
  * @param  storage_instance : Pointer to the storage class instance.
  * @param  lun: Logical unit number is the command is directed to.
  * @param  data_pointer: Address of the buffer to be used for reading or writing.
  * @param  number_blocks: number of sectors to read/write.
  * @param  lba: Logical block address is the sector address to read.
  * @param  media_status: should be filled out exactly like the media status
  *                       callback return value.
  * @retval status
  */
UINT USBD_STORAGE_Write(VOID *storage_instance, ULONG lun, UCHAR *data_pointer,
                        ULONG number_blocks, ULONG lba, ULONG *media_status)
{
  UINT status = UX_SUCCESS;

  /* USER CODE BEGIN USBD_STORAGE_Write */
    UINT fxStatus = FX_SUCCESS;
    while (number_blocks--) {
        fxStatus = fx_media_write(sdioDisk, lba, data_pointer);
        if (fxStatus != FX_SUCCESS && lba != 0) {
            status = UX_ERROR;
            break;
        }
        data_pointer += sdioDisk->fx_media_bytes_per_sector;
        lba++;
    }
  /* USER CODE END USBD_STORAGE_Write */

  return status;
}

评分

参与人数 1金币 +10 收起 理由
OldGerman + 10 使用了楼主的方法进行双边同步,复合设备仅.

查看全部评分

回复

使用道具 举报

2

主题

3

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2025-8-21 21:55:00 | 显示全部楼层
弃用MSC了,改为PIMA MTP,由设备端统一管理文件系统,可以完美兼容
回复

使用道具 举报

2

主题

3

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2025-8-21 21:56:01 | 显示全部楼层
弃用MSC了,使用PIMA MTP类,由下位机管理文件系统,可以完美兼容
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
120428
QQ
发表于 2025-8-22 12:09:03 来自手机 | 显示全部楼层
是的mtp是非常好的方案
回复

使用道具 举报

14

主题

50

回帖

92

积分

初级会员

积分
92
发表于 2025-10-21 18:04:07 | 显示全部楼层
mtp有demo吗,官方的demo怎么把默认目录下的文件罗列出来,没用文件夹的层次信息。
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
120428
QQ
发表于 2025-10-22 12:26:57 | 显示全部楼层
walk 发表于 2025-10-21 18:04
mtp有demo吗,官方的demo怎么把默认目录下的文件罗列出来,没用文件夹的层次信息。

我们自己没做过,只有官方的那个Demo
回复

使用道具 举报

14

主题

50

回帖

92

积分

初级会员

积分
92
发表于 2025-10-22 16:52:54 | 显示全部楼层
Msc 模式使用官网
回复

使用道具 举报

14

主题

50

回帖

92

积分

初级会员

积分
92
发表于 2025-10-22 17:28:25 | 显示全部楼层
Msc 模式使用官网demo:
UINT USBD_STORAGE_Read(VOID *storage_instance, ULONG lun, UCHAR *data_pointer,
                       ULONG number_blocks, ULONG lba, ULONG *media_status)
{
  HAL_MMC_ReadBlocks_DMA(&hmmc2, data_pointer, lba, number_blocks);
   FX_STM32_MMC_READ_CPLT_NOTIFY() ;
}

UINT USBD_STORAGE_Write(VOID *storage_instance, ULONG lun, UCHAR *data_pointer,
                        ULONG number_blocks, ULONG lba, ULONG *media_status)
{
HAL_MMC_WriteBlocks_DMA(&hmmc2, data_pointer, lba, number_blocks);
FX_STM32_MMC_WRITE_CPLT_NOTIFY() ;
}

文件从U盘拷贝出来没用问题,拖文件进去,小文件可以,稍微大点的就不行,不能显示进度,一直在99%,大文件就不知道当前什么状态。。。
回复

使用道具 举报

14

主题

50

回帖

92

积分

初级会员

积分
92
发表于 2025-10-22 23:52:16 | 显示全部楼层
补充,拖大文件到U盘,一下就显示99%,等一段时间,能正常把文件拷贝到U盘中,缺陷是不能显示进度,有研究过的支个招!!!
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
120428
QQ
发表于 2025-10-23 11:14:47 | 显示全部楼层
walk 发表于 2025-10-22 17:28
Msc 模式使用官网demo:
UINT USBD_STORAGE_Read(VOID *storage_instance, ULONG lun, UCHAR *data_pointe ...

接口函数是非DMA方式试试
回复

使用道具 举报

14

主题

50

回帖

92

积分

初级会员

积分
92
发表于 2025-10-23 16:31:24 | 显示全部楼层
eric2013 发表于 2025-10-23 11:14
接口函数是非DMA方式试试

使用fx_media_write和fx_media_read还是一样
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
120428
QQ
发表于 2025-10-24 10:06:30 | 显示全部楼层
walk 发表于 2025-10-23 16:31
使用fx_media_write和fx_media_read还是一样

那不太清楚了,主要是没研究过这个功能。
回复

使用道具 举报

14

主题

50

回帖

92

积分

初级会员

积分
92
发表于 2025-10-24 10:24:49 | 显示全部楼层
网上这方面基本没用资料
回复

使用道具 举报

1

主题

26

回帖

34

积分

新手上路

积分
34
QQ
发表于 2025-12-4 20:49:08 | 显示全部楼层
楼主非常感谢你提到PIMA,其实手机和电脑传文件就在用这个协议,但是我之前一直以为是MSC哈哈
我目前卡壳儿的情况和楼主非常相似,ThreadX USBX整了一个MSC和CDC ACM的复合设备,电脑可以读写SD卡,通过虚拟串口发送一个FileX 读写测速SD卡的命令,安富莱的测速例程也能跑完,但是这之后电脑就不能打开SD卡的任何文件了(点击后一直转圈),又过了一会儿windows就把USBX整个设备都卸载了,尝试了FileX读写测速期间仅取消注册USBX 复合设备中的MSC线程,测速完毕后重新注册线程,但情况依然,表现为电脑右键U盘弹出,U盘仍然在电脑上,感觉觉得复合设备是不能热卸载和热重载其中的一个设备类的,wiki搜索了一下PIMA确实相比MSC优势很大,那么就换PIMA MTP开整
MTP概述(维基百科).png
回复

使用道具 举报

14

主题

50

回帖

92

积分

初级会员

积分
92
发表于 2025-12-4 22:36:16 | 显示全部楼层
OldGerman 发表于 2025-12-4 20:49
楼主非常感谢你提到PIMA,其实手机和电脑传文件就在用这个协议,但是我之前一直以为是MSC哈哈
我目前卡 ...

我也折腾很久,传大文件没有实时进度,果断放弃USBX,转向使用CherryUSB
PIMA MTP也折腾过,主要问题是只能浏览一个文件夹的文件;子文件夹、兄弟文件夹、父文件夹里面的文件不知道怎么处理,文件多的话,占用内存是不是很大?
回复

使用道具 举报

1

主题

26

回帖

34

积分

新手上路

积分
34
QQ
发表于 2025-12-5 23:48:59 | 显示全部楼层
walk 发表于 2025-12-4 22:36
我也折腾很久,传大文件没有实时进度,果断放弃USBX,转向使用CherryUSB
PIMA MTP也折腾过,主要问题是 ...

谢谢回复,占用内存这个问题我没有测试过就不打算继续折腾MTP了

今天早上折腾了一下PIMA MTP,发现在这种协议下,windows双击播放或查看手机内部的视频或者图片,实际播放的视频文件或查看的图片文件名后面会多一个[1]后缀,打开其所在路径是在一个Cache文件夹下,这说明电脑通过PIMA访问手机的文件都需要先拷贝整个文件的副本到电脑里,然后才打开这个文件副本
问了一下AI老师:MTP协议无法像访问本地硬盘一样直接读取手机文件,必须先将数据从手机传输到电脑内存或临时存储,不支持流式传输,实测了一下确实,不支持重名文件,而且拷贝文件时不能显示读写速度。。。

所以我果断放弃PIMA,又用回来MSC,今晚还是最终使用楼主的方式凑活用:电脑重新单独枚举复合设备中的MSC+本地重新fx_media_open来解决双边同步问题
回复

使用道具 举报

1万

主题

7万

回帖

12万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
120428
QQ
发表于 2025-12-6 10:41:37 | 显示全部楼层
OldGerman 发表于 2025-12-5 23:48
谢谢回复,占用内存这个问题我没有测试过就不打算继续折腾MTP了

今天早上折腾了一下PIMA MTP,发现 ...

这几天有个新思路,开个虚拟磁盘,让USB访问这个虚拟磁盘,然后虚拟虚拟磁盘的通过消息同步操作存储器,这样就互不影响了。USB也可以畅通无阻使用。
回复

使用道具 举报

1

主题

26

回帖

34

积分

新手上路

积分
34
QQ
发表于 2025-12-6 11:27:15 来自手机 | 显示全部楼层
eric2013 发表于 2025-12-6 10:41
这几天有个新思路,开个虚拟磁盘,让USB访问这个虚拟磁盘,然后虚拟虚拟磁盘的通过消息同步操作存储器, ...

感谢硬汉哥回复,这个虚拟磁盘思路确实很巧妙,但又考虑了一下这么做应该会有个新问题:

USBX MSC的读写函数我看到例程调用SDMMC_Write / Read 是直接访问物理地址的块级操作(512字节/块),改为虚拟磁盘读写时换成了对虚拟磁盘的物理地址读写操作。当主机向虚拟磁盘写大文件时,文件会被拆成多个块写入,这期间如果监控读写API的参数只能看到某些物理块被改写,但不知道它们属于哪个文件、文件是否传输完成,需要等待主机更新完文件系统的元数据(如FAT表、目录项)后,通过FileX才能识别出虚拟磁盘上的新文件,这时才可以发消息队列通知FileX将其拷贝到SD卡吧?

对于传输大文件得等它全部拷贝到虚拟磁盘中,如果用RAM开辟虚拟磁盘,空间可能就不够暂存,硬汉哥如何解决?
回复

使用道具 举报

2

主题

3

回帖

9

积分

新手上路

积分
9
 楼主| 发表于 2025-12-6 17:57:05 | 显示全部楼层
walk 发表于 2025-12-4 22:36
我也折腾很久,传大文件没有实时进度,果断放弃USBX,转向使用CherryUSB
PIMA MTP也折腾过,主要问题是 ...

传文件是可以实时显示进度的,Msc使用的是media_write函数,缺点是FileX的media_write一次只能写入单个block,所以导致速度比较慢,大概只有350KB左右。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-1-10 08:21 , Processed in 0.066346 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表