硬汉嵌入式论坛

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

[ThreadX全家桶] 备份SD卡使用ThreadX USBX模拟盘,底层是SDIO查询,SDIO DMA和FileX API三种方式

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107265
QQ
发表于 2021-10-7 10:47:21 | 显示全部楼层 |阅读模式
SDIO查询方式在STM32F4上很难用,而H7上很好用。

  1. /* USER CODE BEGIN Header */
  2. /**
  3.   ******************************************************************************
  4.   * @file    ux_device_msc.c
  5.   * @author  MCD Application Team
  6.   * @brief   USBX Device applicative file
  7.   ******************************************************************************
  8.   * @attention
  9.   *
  10.   * <h2><center>&#169; Copyright (c) 2020 STMicroelectronics.
  11.   * All rights reserved.</center></h2>
  12.   *
  13.   * This software component is licensed by ST under Ultimate Liberty license
  14.   * SLA0044, the "License"; You may not use this file except in compliance with
  15.   * the License. You may obtain a copy of the License at:
  16.   *                             www.st.com/SLA0044
  17.   *
  18.   ******************************************************************************
  19.   */
  20. /* USER CODE END Header */
  21. //#include "fx_stm32_sd_driver.h"
  22. /* Includes ------------------------------------------------------------------*/
  23. #include "ux_device_msc.h"
  24. //#include "fx_stm32_sd_driver.h"
  25. /* Private includes ----------------------------------------------------------*/
  26. /* USER CODE BEGIN Includes */
  27. //#include "main.h"
  28. #include "tx_api.h"
  29. //#include "app_usbx_device.h"
  30. /* USER CODE END Includes */

  31. /* Private typedef -----------------------------------------------------------*/
  32. /* USER CODE BEGIN PTD */

  33. /* USER CODE END PTD */

  34. /* Private define ------------------------------------------------------------*/
  35. /* USER CODE BEGIN PD */
  36. /* USER CODE END PD */

  37. /* Private macro -------------------------------------------------------------*/
  38. /* USER CODE BEGIN PM */

  39. /* USER CODE END PM */

  40. /* Private variables ---------------------------------------------------------*/
  41. /* USER CODE BEGIN PV */

  42. /* USER CODE END PV */

  43. /* Private function prototypes -----------------------------------------------*/
  44. /* USER CODE BEGIN PFP */
  45. static int32_t check_sd_status(uint32_t instance);
  46. /* USER CODE END PFP */

  47. #define BSP_ERROR_NONE                    0
  48. #define BSP_ERROR_BUSY                   -3

  49. #include "bsp.h"
  50. #include "tx_api.h"
  51. #include "fx_api.h"


  52. #define DEFAULT_TIMEOUT                        (500 * TX_TIMER_TICKS_PER_SECOND)


  53. extern TX_SEMAPHORE transfer_semaphore;

  54. /* Private user code ---------------------------------------------------------*/
  55. /* USER CODE BEGIN 0 */
  56. /**
  57.   * @brief  Function implementing app_usb_device_thread_media_status.
  58.   * @param arg: Not used
  59.   * @retval status
  60.   */
  61. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
  62. {

  63.   /* The ATA drive never fails. This is just for app_usb_device only !!!! */
  64.   return (UX_SUCCESS);
  65. }

  66. /**
  67.   * @brief  Function implementing app_usb_device_thread_media_read.
  68.   * @param  storage : Not used
  69.   * @param  lun: Logical unit number
  70.   * @param  lba: Logical block address
  71.   * @param  number_blocks: Blocks number
  72.   * @param  data_pointer: Data
  73.   * @param  media_status: Not used
  74.   * @retval Status (0 : OK / -1 : Error)
  75.   */
  76. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,
  77.                                        UCHAR *data_pointer,
  78.                                        ULONG number_blocks,
  79.                                        ULONG lba, ULONG *media_status)
  80. {
  81. #if 0
  82.     UINT status = 0U;

  83.     BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                                                       
  84.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);
  85.     status = check_sd_status(0);   
  86.     return (status);

  87. #else
  88.         UINT status;
  89.     if(check_sd_status(0) != BSP_ERROR_NONE)
  90.     {
  91.     }
  92.        
  93.     status = BSP_SD_ReadBlocks_DMA((uint32_t*)data_pointer, lba, number_blocks);

  94.     if (status == BSP_ERROR_NONE)
  95.     {
  96.         if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
  97.         {
  98.             status = FX_SUCCESS;
  99.         }
  100.         else
  101.         {
  102.             status =  FX_BUFFER_ERROR;
  103.         }
  104.     }

  105.     return status;
  106. #endif
  107. }

  108. /**
  109.   * @brief  Function implementing app_usb_device_thread_media_write.
  110.   * @param  storage : Not used
  111.   * @param  lun: Logical unit number
  112.   * @param  lba: Logical block address
  113.   * @param  number_blocks: Blocks number
  114.   * @param  data_pointer: Data
  115.   * @param  media_status: Not used
  116.   * @retval Status (0 : OK / -1 : Error)
  117.   */
  118. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,
  119.                                         UCHAR *data_pointer,
  120.                                         ULONG number_blocks,
  121.                                         ULONG lba, ULONG *media_status)
  122. {
  123. #if 0
  124.     UINT status = 0U;

  125.     BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);
  126.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);
  127.     status = check_sd_status(0);
  128.    
  129.     return (status);

  130. #else
  131.         UINT status;
  132.        
  133.     if(check_sd_status(0) != BSP_ERROR_NONE)
  134.     {
  135.     }

  136.     status = BSP_SD_ReadBlocks_DMA((uint32_t*)data_pointer, lba, number_blocks);

  137.     if (status == BSP_ERROR_NONE)
  138.     {
  139.         if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
  140.         {
  141.             status = FX_SUCCESS;
  142.         }
  143.         else
  144.         {
  145.             status =  FX_BUFFER_ERROR;
  146.         }
  147.     }

  148. #endif

  149.     return status;
  150. }

  151. /**
  152.   * @brief check SD card Transfer Status
  153.   * @param Instance
  154.   * @retval BSP_ERROR_NONE, BSP_ERROR_BUSY
  155.   */
  156. static int32_t check_sd_status(uint32_t Instance)
  157. {
  158.   uint32_t start = tx_time_get();

  159.   while (tx_time_get() - start < 500)
  160.   {
  161.     if (BSP_SD_GetCardState() == SD_TRANSFER_OK)
  162.     {
  163.       return BSP_ERROR_NONE;
  164.     }
  165.   }

  166.   return BSP_ERROR_BUSY;
  167. }


  168. #if 0

  169. extern FX_MEDIA     sdio_disk;
  170. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
  171. {

  172.     /* The ATA drive never fails. This is just for demo only !!!! */
  173.     return(UX_SUCCESS);
  174. }


  175. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun, UCHAR * data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
  176. {

  177. UINT    status =  0;

  178.     while(number_blocks--)
  179.     {
  180.         status =  fx_media_read(&sdio_disk,lba,data_pointer);
  181.         data_pointer+=512;
  182.         lba++;
  183.     }
  184.         
  185.     return(status);
  186. }


  187. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun, UCHAR * data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status)
  188. {

  189. UINT    status =  0;


  190.     while(number_blocks--)
  191.     {
  192.         status =  fx_media_write(&sdio_disk,lba,data_pointer);
  193.         data_pointer+=512;
  194.         lba++;
  195.     }        
  196.     return(status);
  197. }

  198. #endif

  199. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码


回复

使用道具 举报

19

主题

125

回帖

182

积分

初级会员

积分
182
发表于 2022-4-15 00:23:38 | 显示全部楼层
AZURE RTOS和CUBEMX生成的FREERTOS一样,有通病,读写时候出错,因为开了DMA,所以这个地方老规矩

/**
  * @brief This function handles DMA2 channel4 global interrupt.
  */
void DMA2_Channel4_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Channel4_IRQn 0 */
                if((hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_READ_SINGLE_BLOCK)) ||
                         (hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_READ_MULTIPLE_BLOCK)))
                {
                        BSP_SD_DMA_Rx_IRQHandler();
                }
                else if((hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_WRITE_SINGLE_BLOCK)) ||
                                         (hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_WRITE_MULTIPLE_BLOCK)))
         {
                 BSP_SD_DMA_Tx_IRQHandler();
         }
  /* USER CODE END DMA2_Channel4_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_sdmmc1);
  /* USER CODE BEGIN DMA2_Channel4_IRQn 1 */

  /* USER CODE END DMA2_Channel4_IRQn 1 */
}
回复

使用道具 举报

19

主题

125

回帖

182

积分

初级会员

积分
182
发表于 2022-4-15 00:25:32 | 显示全部楼层
AZURE RTOS也用CUBEMX生成的,也用了DMA,也用了回调,结果一样的要在中断这里加内容。。。

/**
  * @brief This function handles DMA2 channel4 global interrupt.
  */
void DMA2_Channel4_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Channel4_IRQn 0 */
                if((hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_READ_SINGLE_BLOCK)) ||
                         (hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_READ_MULTIPLE_BLOCK)))
                {
                        BSP_SD_DMA_Rx_IRQHandler();
                }
                else if((hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_WRITE_SINGLE_BLOCK)) ||
                                         (hsd1.Context == (SD_CONTEXT_DMA | SD_CONTEXT_WRITE_MULTIPLE_BLOCK)))
         {
                 BSP_SD_DMA_Tx_IRQHandler();
         }
  /* USER CODE END DMA2_Channel4_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_sdmmc1);
  /* USER CODE BEGIN DMA2_Channel4_IRQn 1 */

  /* USER CODE END DMA2_Channel4_IRQn 1 */
}
回复

使用道具 举报

1

主题

21

回帖

24

积分

新手上路

积分
24
发表于 2022-10-18 10:43:07 | 显示全部楼层
请问大侠,我现在用的是SD DMA方式读写文件裸机正常,改为使用UCOSIII之后,经常运行时间不固定,多则十几个小时,少则十几分钟,读写错误。请问SD DMA这个函数这里怎么修改呢 ?程序运行时,只有一个任务读写SD卡。按道理跟裸机一样就可以啊。没有其他任务读写SD卡了。使用GD25Q128作为内部DISK也是一样,裸机正常,用了UCSOIII就不正常了。程序执行时也是只有一个任务同一时刻读写SD卡或者SPI_FLASH。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107265
QQ
 楼主| 发表于 2022-10-18 13:09:40 | 显示全部楼层
shnd 发表于 2022-10-18 10:43
请问大侠,我现在用的是SD DMA方式读写文件裸机正常,改为使用UCOSIII之后,经常运行时间不固定,多则十几 ...

你的主控芯片是那个,这个我们uCOS-III相关的SD卡Demo有好几个,应该可以参考下。
回复

使用道具 举报

1

主题

21

回帖

24

积分

新手上路

积分
24
发表于 2022-10-19 10:14:33 | 显示全部楼层
eric2013 发表于 2022-10-18 13:09
你的主控芯片是那个,这个我们uCOS-III相关的SD卡Demo有好几个,应该可以参考下。

我的主控芯片是GD32F470ZGT6,目前SD卡我改的差不多了。应该可以了。但是GD25Q128还是不行。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107265
QQ
 楼主| 发表于 2022-10-20 11:00:39 | 显示全部楼层
shnd 发表于 2022-10-19 10:14
我的主控芯片是GD32F470ZGT6,目前SD卡我改的差不多了。应该可以了。但是GD25Q128还是不行。

GD25Q128的裸机方式正常吗
回复

使用道具 举报

1

主题

21

回帖

24

积分

新手上路

积分
24
发表于 2022-10-25 16:43:46 | 显示全部楼层
现在是GD25Q128确定没问题了。SD卡我们使用了DMA方式,参考了你们的例程,裸机运行很正常,现在使用UCOSIII了,就是偶发报错,有时候几分钟,有时候十几个小时,经监控发现HAL_SD_ReadBlocks_DMA函数里面,报错行errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);这一行,监测hsd->ErrorCode = SDMMC_ERROR_TIMEOUT,超时错误。然后继续监控SDMMC_CmdReadMultiBlock()函数里面SDMMC_GetCmdResp1()这个函数超时了。  
do
  {
                        if (count-- == 0U)
                        {
                                return SDMMC_ERROR_TIMEOUT;
                        }       
    sta_reg = SDIOx->STA;
  }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
         ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));这是具体代码。
我把超时监测关掉,让程序一直等待状态寄存器,但是就陷入死循环了。
已经把所有的针对SD卡寄存器操作的函数,全部加了临界区锁定。还是偶尔会报错这个代码。
回复

使用道具 举报

1

主题

21

回帖

24

积分

新手上路

积分
24
发表于 2022-10-25 16:48:27 | 显示全部楼层
另外,使用的是4字节对齐读写缓冲区,和SD的DMA模式都设置了好几轮都不行,应该不是这里得问题,还有关于f_read()和f_lseek()函数都应该没有问题,因为针对U盘和25Q128的读写都没有问题。更换过几张SD卡,有的卡就好一点,运行十几个小时偶发报错,有的卡就不行,十几分钟甚至几分钟就报错,SD卡的SCK速度也改过,DIV降到5以下,卡都基本上不能识别了。所有应该也不是SD的时钟速度问题。
回复

使用道具 举报

1

主题

21

回帖

24

积分

新手上路

积分
24
发表于 2022-10-25 17:07:57 | 显示全部楼层
【新提醒】STM32CbueMX+FatFS+SD+FreeRTOS DMA 超时bug - 文件系统 - 硬汉嵌入式论坛 - Powered by Discuz!
https://www.armbbs.cn/forum.php? ... ;highlight=SD%2BDMA,搜索论坛发现了这个帖子。好像跟我这个问题有些类似,但是好像又不一样,老大能帮我看看吗?
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-24 00:57 , Processed in 0.330498 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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