硬汉嵌入式论坛

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

[USB] 求问USB MSC的读写函数如何才能不阻塞?

[复制链接]

2

主题

4

回帖

10

积分

新手上路

积分
10
发表于 2025-2-25 10:16:57 | 显示全部楼层 |阅读模式
大佬们,如下2个函数,如何才能在这俩函数里,不用读取完成就返回,等读取完成后再返回?
这样就不会阻塞在这里,非得等读写完了才能干别的事?
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
        if(r_sector_dma(buf,blk_addr,blk_len) == HAL_OK) //阻塞
        {
                return (USBD_OK);  
        }
        else
        {
                return(USBD_FAIL);
        }
}

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
        if(w_sector_dma(buf,blk_addr,blk_len) == HAL_OK) //阻塞
        {
                return (USBD_OK);
        }
        else
        {
                return(USBD_FAIL);
        }
}

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-2-25 10:43:05 | 显示全部楼层
这种的就让它死等就行了,适合在OS下使用,这个任务死等,不影响其它高优先级任务抢占执行。还可以里面加个osDelay释放CPU权限,让低优先级任务也得到执行。

【深入探讨】DMA到底能不能起到加速程序执行的作用,DMA死等操作是否合理,多个DMA数据流同时刷是否处理过来
https://forum.anfulai.cn/forum.p ... 9765&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

6

主题

306

回帖

324

积分

高级会员

积分
324
发表于 2025-2-25 10:50:30 | 显示全部楼层
你得上OS,然后os_thread_yeid()让出CPU控制权,这期间可以干其它的事
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-2-25 11:59:54 | 显示全部楼层
eric2013 发表于 2025-2-25 10:43
这种的就让它死等就行了,适合在OS下使用,这个任务死等,不影响其它高优先级任务抢占执行。还可以里面加个 ...

硬汉哥,主要是这个函数是在USB的中断里执行的,而USB的中断比FREE RTOS的任务切换中断优先级高,所以RTOS无法打断这个USB的中断,现在是必须要等USB的这个中断里读取完数据后返回,USB中断结束后,才能继续,这SDMMC的DMA就白用了,因为还得死等
回复

使用道具 举报

1

主题

12

回帖

15

积分

新手上路

积分
15
发表于 2025-2-25 14:12:07 | 显示全部楼层
lswhome 发表于 2025-2-25 11:59
硬汉哥,主要是这个函数是在USB的中断里执行的,而USB的中断比FREE RTOS的任务切换中断优先级高,所以RTO ...

STM32H7 的SDMMC是有DMA传输完成中断的。你可以使用dma进行数据读取和写入。在dma完成中断中获取或更新你的数据。
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-2-25 16:48:54 | 显示全部楼层

好吧,看起来是ST的库没有处理仔细,下面注释这行是库里原始的代码,判断<0,则出错,但是read回调返回的数值都是>=0的,这导致下面的
SCSI_SenseCode函数无法执行

if (((USBD_StorageTypeDef *)pdev->pUserData)->Read(lun, hmsc->bot_data,hmsc->scsi_blk_addr,(len / hmsc->scsi_blk_size)) < 0)

修改为如下,读取的时候,返回失败,然后sdmmc去读取,存入缓冲区,下次MSC再读取的时候,就把缓冲区的数据返回给host
if (((USBD_StorageTypeDef *)pdev->pUserData)->Read(lun, hmsc->bot_data,hmsc->scsi_blk_addr,(len / hmsc->scsi_blk_size)) != USBD_OK)
  {
    SCSI_SenseCode(pdev, lun, NOT_READY, 0x04);
    return -1;
  }

实测host会反复请求同一个扇区,直到达到重试次数后不再请求,这样第一次请求某扇区时,我返回USB_FAIL,并启动EMMC+DMA去读,CPU此时可以去干别的事(USB中断也完成了--因为已经返回了设备繁忙的标志),等读取完毕,DMA中断,表示数据读取完成,当HOST再次请求同一个扇区的时候,将先前读取的数据返回,并返回USBD_OK,理论上即可实现不阻塞读写数据,但这样可能会损失一点点读写性能,问题不大。。剩下的我再写个代码测试我这想法是否可行就可以了。

返回USBD_FAIL后,日志记录HOST会反复请求同一个扇区:

00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1
00> USBD_read:p=0x24000010,sec=0,num=1


回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117530
QQ
发表于 2025-2-26 09:08:08 | 显示全部楼层
lswhome 发表于 2025-2-25 16:48
好吧,看起来是ST的库没有处理仔细,下面注释这行是库里原始的代码,判断=0的,这导致下面的
SCSI_Sense ...

这个用的是ST USB库吗,这个库我记得还有个RTOS下实用的方案,中断里面发消息,放在中断外面执行了,也可以参考。
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-2-26 09:08:19 | 显示全部楼层
lswhome 发表于 2025-2-25 16:48
好吧,看起来是ST的库没有处理仔细,下面注释这行是库里原始的代码,判断=0的,这导致下面的
SCSI_Sense ...

好吧,今天测试,发现这样并不行,HOST偶尔请求的还是别的扇区的数据,导致数据错误。。放弃
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-12 18:47 , Processed in 0.042289 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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