硬汉嵌入式论坛

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

[SD/SDIO] 求助 SDMMC驱动

[复制链接]

9

主题

85

回帖

112

积分

初级会员

积分
112
发表于 2022-4-23 12:38:13 | 显示全部楼层 |阅读模式
硬汉哥和兄弟们好!

今天移植了硬汉哥的SD驱动,想体验下DMA的速度,bsp_sdio_sd 和 sd_diskio_dma 都成功加入我的工程,编译通过。 可是正常运行 BSP_SD_Init 之后,读盘时 BSP_SD_ReadBlocks_DMA 运行之后,SDMMC1_IRQHandler 无法被触发,因此各种回调没法运行,SD_read一直在等待 ReadStatus=1。
检查初始化,已经运行了
HAL_NVIC_SetPriority(SDMMC1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(SDMMC1_IRQn);

哪位朋友能指正下,多谢了!
回复

使用道具 举报

9

主题

85

回帖

112

积分

初级会员

积分
112
 楼主| 发表于 2022-4-23 13:17:41 | 显示全部楼层
补充下最新调试结果
跟踪到 当执行完一次 BSP_SD_ReadBlocks_DMA 且返回 return MSD_OK; 正确后, 代码停在SD_read 里面等待结果和TICK超时,如下面
while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT))
                        {
                        }
最魔幻的是,此时连SysTick_Handler 也停止运行,导致 HAL_IncTick(); 无法增加,因此稳稳的停止运行,也没有HARDFAULT,  实在是太意想不到了。

还请兄弟们指教!
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-4-23 14:11:19 | 显示全部楼层
楼主用的是SDMMC1还是SDMMC2,这个比较重要。

如果是SDMMC1,仅支持AXI SRAM空间。
回复

使用道具 举报

9

主题

85

回帖

112

积分

初级会员

积分
112
 楼主| 发表于 2022-4-23 14:26:17 | 显示全部楼层
多谢硬汉哥,我用的 SDMMC1, 您是指 SDMMC1 DMA 模式的读写 BUF 必须定义到AXI 吗? 这个我没有特别指定,只是按照之前查询模式下可以正常运行的环境来改的,且仅仅用您的 SD_read 和 SD_write 替换了DISK IO里面的函数。 我试试将读写 BUF  定义到AXI RAM 看看行不行。
再次多谢!
回复

使用道具 举报

9

主题

85

回帖

112

积分

初级会员

积分
112
 楼主| 发表于 2022-4-23 14:55:42 | 显示全部楼层
补充信息, 刚才看了, SD_read 的BUF 的确是在 0x24000000 开始的AXI RAM 里面, 这就很奇怪了。

求进一步指导,多谢!
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-4-23 17:11:30 | 显示全部楼层
szjdb 发表于 2022-4-23 14:55
补充信息, 刚才看了, SD_read 的BUF 的确是在 0x24000000 开始的AXI RAM 里面, 这就很奇怪了。

求进 ...

方便的话,分享代码到百度云,我看看。
回复

使用道具 举报

9

主题

85

回帖

112

积分

初级会员

积分
112
 楼主| 发表于 2022-4-24 10:38:21 | 显示全部楼层
多谢硬汉哥, 原工程比较复杂。 我目前移植您的V7例子27在我的硬件上, 发现功能正常,中断能够触发。 可是在我的代码里就不行,使用的都是 BSP_SD_Init,且都能够执行过去,就是SD_read /write会停。不知道是不是其他模块的初始化或中断干扰了SDMMC, 按说SDMMC的HAL库和硬件模块是相对独立的呀,怎么会被别的模块,包括TFT ADC等干扰?
另外请教下,您的V7例子27 里面 SD_read /write 里并没有对非4字节对齐BUF进行处理,包括ST的原始DMA方式的代码也没有处理,但是V3.5手册上贴出的代码有进行对齐和非对齐处理。 难道说不用对齐实际上也可以吗, 有什么局限?

多谢指教!
回复

使用道具 举报

9

主题

85

回帖

112

积分

初级会员

积分
112
 楼主| 发表于 2022-4-24 11:03:10 | 显示全部楼层
补充一个问题,我原来用的是寄存器版本的查询模式驱动SD,非ST 的HAL库, 功能是正常的。 之所以想换DMA模式是因为目前想在播放WAV文件(48k采样率))时,边播放边录音写SD卡, 尽管已经用了4096字节双缓冲WAV信号,在写SD卡时还是会干扰到播放的SAI DMA中断,所以想换DMA模式的SD驱动看看效果。 没想到还运行不起来(HAL 库的查询和DMA模式都不行), 不知道对SDMMC 的HAL 使用有没有特别要注意的地方? 另外DMA 模式相比查询模式,是否真的能节省很多时间,值不值得去更换?

还请不吝赐教!
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-4-24 11:12:48 | 显示全部楼层
szjdb 发表于 2022-4-24 10:38
多谢硬汉哥, 原工程比较复杂。 我目前移植您的V7例子27在我的硬件上, 发现功能正常,中断能够触发。 可是 ...

这个帖子里面的fatfs,flashfs,filex都是做了对齐处理的。

系统的谈下STM32H7的SD卡驱动兼容性问题,现在兼容性很强,主流厂家16GB以上容量全部通过(2022-03-15)
https://www.armbbs.cn/forum.php? ... 7689&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-4-24 11:13:42 | 显示全部楼层
szjdb 发表于 2022-4-24 11:03
补充一个问题,我原来用的是寄存器版本的查询模式驱动SD,非ST 的HAL库, 功能是正常的。 之所以想换DMA模 ...

这个DMA是SDIO自动的IDMA,不占用通用DMA资源,非常值得一试。
回复

使用道具 举报

9

主题

85

回帖

112

积分

初级会员

积分
112
 楼主| 发表于 2022-4-24 12:33:13 | 显示全部楼层
多谢硬汉哥! 我再找找看看为何 HAL库 SD卡的运行不起来。 其他模块用HAL库没发现问题。

我下的就是您提到的配套例程呀,怎么里面还是未做对齐处理的代码?
网盘下载教程和配套例子:
https://pan.baidu.com/s/1Lum1i0K157Dv3z9annKiYw 提取码:0eqi

多谢!
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-4-24 12:41:12 | 显示全部楼层
szjdb 发表于 2022-4-24 12:33
多谢硬汉哥! 我再找找看看为何 HAL库 SD卡的运行不起来。 其他模块用HAL库没发现问题。

我下的就是您提 ...

image.png

[C] 纯文本查看 复制代码
/**
  * @brief  Reads Sector(s)
  * @param  lun : not used
  * @param  *buff: Data buffer to store read data
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to read (1..128)
  * @retval DRESULT: Operation result
  */
DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
    DRESULT res = RES_ERROR;
    uint32_t timeout;
    ReadStatus = 0;

    if (!((uint32_t)buff & 0x3))
    {
        if(BSP_SD_ReadBlocks_DMA((uint32_t*)buff,
                                (uint32_t) (sector),
                                count) == MSD_OK)
        {
            /* Wait that the reading process is completed or a timeout occurs */
            timeout = HAL_GetTick();
            while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT))
            {
            }
            
            /* incase of a timeout return error */
            if (ReadStatus == 0)
            {
                res = RES_ERROR;
            }
            else
            {
                ReadStatus = 0;
                timeout = HAL_GetTick();

                while((HAL_GetTick() - timeout) < SD_TIMEOUT)
                {
                    if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
                    {
                        res = RES_OK;
                        
                        #if (ENABLE_SD_DMA_CACHE_MAINTENANCE_READ == 1)
                           SCB_CleanInvalidateDCache();
                        #endif
                        break;
                    }
                }
            }
        }
    }
    else
    {
        uint8_t ret;
        int i;

        for (i = 0; i < count; i++) 
        { 

            ret = BSP_SD_ReadBlocks_DMA((uint32_t*)scratch, (uint32_t)sector++, 1);

            if(ret == MSD_OK)
            {
                /* Wait that the reading process is completed or a timeout occurs */
                timeout = HAL_GetTick();
                while((ReadStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT))
                {
                    
                }
                /* incase of a timeout return error */
                if (ReadStatus == 0)
                {
                    break;
                }
                else
                {
                    ReadStatus = 0;
                    timeout = HAL_GetTick();

                    while((HAL_GetTick() - timeout) < SD_TIMEOUT)
                    {
                        if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
                        {
                            #if (ENABLE_SD_DMA_CACHE_MAINTENANCE_READ == 1)
                                SCB_CleanInvalidateDCache();
                            #endif
                            
                            memcpy(buff, scratch, BLOCKSIZE);
                            buff += BLOCKSIZE;
                            
                            break;
                        }
                    }
                }
            }
            else
            {
                break;
            }
        }
        if ((i == count) && (ret == MSD_OK))
        {
           res = RES_OK;       
        }
    }
    return res;
}

/**
  * @brief  Writes Sector(s)
  * @param  lun : not used
  * @param  *buff: Data to be written
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to write (1..128)
  * @retval DRESULT: Operation result
  */
#if _USE_WRITE == 1
DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
    DRESULT res = RES_ERROR;
    uint32_t timeout;
    WriteStatus = 0;

#if (ENABLE_SD_DMA_CACHE_MAINTENANCE_WRITE == 1)
   SCB_CleanInvalidateDCache();
#endif

    if (!((uint32_t)buff & 0x3))
    {
        if(BSP_SD_WriteBlocks_DMA((uint32_t*)buff,
                                (uint32_t)(sector),
                                count) == MSD_OK)
        {
            /* Wait that writing process is completed or a timeout occurs */
            timeout = HAL_GetTick();
            while((WriteStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT))
            {
            }
            
            /* incase of a timeout return error */
            if (WriteStatus == 0)
            {
                res = RES_ERROR;
            }
            else
            {
                WriteStatus = 0;
                timeout = HAL_GetTick();

                while((HAL_GetTick() - timeout) < SD_TIMEOUT)
                {
                    if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
                    {
                        res = RES_OK;
                        break;
                    }
                }
            }
        }
    }
    else
    {
        int i;
        uint8_t ret;
        
        for (i = 0; i < count; i++)
        {
            WriteStatus = 0;
            
            memcpy((void *)scratch, (void *)buff, BLOCKSIZE);
            buff += BLOCKSIZE;

            ret = BSP_SD_WriteBlocks_DMA((uint32_t*)scratch, (uint32_t)sector++, 1);
            if(ret == MSD_OK)
            {
                /* Wait that writing process is completed or a timeout occurs */

                timeout = HAL_GetTick();
                while((WriteStatus == 0) && ((HAL_GetTick() - timeout) < SD_TIMEOUT))
                {
                }
                
                /* incase of a timeout return error */
                if (WriteStatus == 0)
                {
                    break;
                }
                else
                {
                    WriteStatus = 0;
                    timeout = HAL_GetTick();

                    while((HAL_GetTick() - timeout) < SD_TIMEOUT)
                    {
                        if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                break;
            }
        }

        if ((i == count) && (ret == MSD_OK))
        {
            res = RES_OK;           
        }
    }

    return res;
}
#endif /* _USE_WRITE == 1 */

回复

使用道具 举报

9

主题

85

回帖

112

积分

初级会员

积分
112
 楼主| 发表于 2022-4-24 15:22:56 | 显示全部楼层
多谢硬汉哥! 我再详细查查问题。

还有个问题,您的 V7-027_SD卡的FatFS文件系统+SD卡虚拟U盘 里面 , FATFS 使用的是 BSP_SD_ReadBlocks_DMA, 而 USB 却使用 BSP_SD_ReadBlocks , 这个没有别的特殊原因吧? USB 与 SD DMA冲突?

多谢!
回复

使用道具 举报

9

主题

85

回帖

112

积分

初级会员

积分
112
 楼主| 发表于 2022-4-25 16:27:20 | 显示全部楼层
硬汉哥您好, 昨天的信息看到了吗,能否指点一下? 多谢!
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-4-25 17:18:52 | 显示全部楼层
szjdb 发表于 2022-4-24 15:22
多谢硬汉哥! 我再详细查查问题。

还有个问题,您的 V7-027_SD卡的FatFS文件系统+SD卡虚拟U盘 里面 , F ...

模拟U盘? 效果不好,不稳定,我们去掉了。
回复

使用道具 举报

9

主题

85

回帖

112

积分

初级会员

积分
112
 楼主| 发表于 2022-4-25 17:35:09 | 显示全部楼层
多谢硬汉哥!  
如何测试出不稳定的现象,求指导。  模拟U盘用处很大呀,关键功能。

多谢!
回复

使用道具 举报

1

主题

4

回帖

7

积分

新手上路

积分
7
发表于 2022-10-7 15:13:47 | 显示全部楼层
eric2013 发表于 2022-4-23 14:11
楼主用的是SDMMC1还是SDMMC2,这个比较重要。

如果是SDMMC1,仅支持AXI SRAM空间。

记录一下,通过这个解决了我的问题,我遇到的问题是遇到IDMA OVERRUN错误,如果轮询则没问题,此方法可解.

另外似乎HAL库是没有用IDMA双缓冲的,有点可惜,不知道是否还有性能提升空间.
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-16 07:51 , Processed in 0.364353 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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