硬汉嵌入式论坛

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

[SD/SDIO] USB模拟U盘与FatFs同时操作eMMC有冲突

[复制链接]

9

主题

57

回帖

84

积分

初级会员

积分
84
发表于 2020-8-27 10:34:30 | 显示全部楼层 |阅读模式
1、单独使用FatFs操作eMMC能够成功(IDMA也能够成功)
2、单独使用USB擦偶作eMMC也能够成功(IDMA也能够成功)
3、同时使用USB和FatFs操作会失败,读取eMMC失败
4、使用FreeRTOS信号量互斥后依然会失败
读取eMMC的代码如下:
DRESULT USER_read (
        BYTE pdrv,      /* Physical drive nmuber to identify the drive */
        BYTE *buff,     /* Data buffer to store read data */
        DWORD sector,   /* Sector address in LBA */
        UINT count      /* Number of sectors to read */
)
{
  /* USER CODE BEGIN READ */
       
    DRESULT res = RES_ERROR;
        BYTE *addr = buff;
        uint32_t addrValue = (uint32_t)addr;
        osEvent event;
        uint32_t timer;
        uint8_t IsDMASpace;
        if(addrValue > (0x24000000UL + 1024*512) || addrValue < 0x24000000UL)    /* 非 DMA地址区间 */
        {
                if(BSP_MMC_ReadBlocks_DMA((uint32_t*)scratch, (uint32_t)sector, count) == MMC_OK)
                {
                        res = RES_OK;
                        IsDMASpace = 0;
                }
                else
                {
                        res = RES_ERROR;
                }
        }
        else
        {
                if(BSP_MMC_ReadBlocks_DMA((uint32_t*)buff,(uint32_t) (sector),count) == MMC_OK)
                {
                        res = RES_OK;
                        IsDMASpace = 1;
                }
                else
                {
                        res = RES_ERROR;
                }
        }
        if(res == RES_OK)
        {
                res = RES_ERROR;
                timer = osKernelSysTick() + SD_TIMEOUT;
                while(timer > osKernelSysTick())
                {
                        event = osMessageGet(SDQueueIDRead, SD_TIMEOUT);
                        if (event.status == osEventMessage && event.value.v == READ_CPLT_MSG)
                        {
                                timer = osKernelSysTick() + SD_TIMEOUT;
                                while(timer > osKernelSysTick())
                                {
                                        if(BSP_MMC_GetCardState() == MMC_TRANSFER_OK)
                                        {
                                                res = RES_OK;
                                                if(IsDMASpace)
                                                {
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
                                                        uint32_t alignedAddr;
                                                        /*
                                                           the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address,
                                                           adjust the address and the D-Cache size to invalidate accordingly.
                                                         */
                                                        alignedAddr = (uint32_t)buff & ~0x1F;
                                                        SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)buff - alignedAddr));
#endif
                                                        break;                                       
                                                }
                                                else
                                                {
#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)  
                                                        uint32_t alignedAddr;
                                                        /*
                                                        *
                                                        * invalidate the scratch buffer before the next read to get the actual data instead of the cached one
                                                        */
                                                        alignedAddr = (uint32_t)scratch & ~0x1F;
                                                        SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)scratch - alignedAddr));
#endif
                                                        memcpy(buff, scratch, count*BLOCKSIZE);
                                                        break;                                       
                                                }


                                        }
                                }
                                break;
                        }
                }
        }
       
        return res;
  /* USER CODE END READ */
}   
FatFs操作时的互斥代码如下:
DRESULT disk_read (
        BYTE pdrv,                /* Physical drive nmuber to identify the drive */
        BYTE *buff,                /* Data buffer to store read data */
        DWORD sector,                /* Sector address in LBA */
        UINT count                /* Number of sectors to read */
)
{
  DRESULT res;
  xSemaphoreTake(MMCReadMutex, portMAX_DELAY);
  res = disk.drv[pdrv]->disk_read(disk.lun[pdrv], buff, sector, count);
  xSemaphoreGive(MMCReadMutex);
  return res;
}

USB操作eMMC的代码如下:
int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 6 */
        int8_t ret = USBD_FAIL;
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        BaseType_t status = xSemaphoreTakeFromISR(MMCReadMutex, &xHigherPriorityTaskWoken);
        if(xHigherPriorityTaskWoken==pdTRUE)
        {
                portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        }
        if(status !=pdTRUE)
                return (USBD_FAIL);
        if(USER_read(lun,buf,blk_addr,blk_len) == RES_OK)
        {
                ret = USBD_OK;
        }
        else
        {
                ret = USBD_FAIL;
        }
        xHigherPriorityTaskWoken = pdFALSE;
        xSemaphoreGiveFromISR(MMCReadMutex, &xHigherPriorityTaskWoken);
        if(xHigherPriorityTaskWoken==pdTRUE)
        {
                portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        }
  return ret;
  /* USER CODE END 6 */
}
请问有朋友做过文件系统和USB模拟U盘的互斥吗?

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106685
QQ
发表于 2020-8-27 11:37:56 | 显示全部楼层
这个暂时没有好办法,之前这个问题讨论过好多次

最现实的问题就是你在U盘枚举和USB操作期间,如果此时FatFS也在操作,你的锁机制会导致USB通信失败。
回复

使用道具 举报

9

主题

57

回帖

84

积分

初级会员

积分
84
 楼主| 发表于 2020-8-27 12:06:17 | 显示全部楼层
eric2013 发表于 2020-8-27 11:37
这个暂时没有好办法,之前这个问题讨论过好多次

最现实的问题就是你在U盘枚举和USB操作期间,如果此时Fa ...

感谢硬汉大大的回复,我现在的处理办法就是USB中断到来的时候关闭FatFs读写任务,等到拔出后再继续读写
回复

使用道具 举报

3

主题

11

回帖

20

积分

新手上路

积分
20
发表于 2023-8-3 17:14:47 | 显示全部楼层
烟花易冷~ 发表于 2020-8-27 12:06
感谢硬汉大大的回复,我现在的处理办法就是USB中断到来的时候关闭FatFs读写任务,等到拔出后再继续读写

你好,我最近也在做这个功能,目前也遇到了这个问题,请问能否分享一下中断共存方法?
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-29 17:15 , Processed in 0.284772 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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