硬汉嵌入式论坛

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

[SD/SDIO] 研究了下STM32H7的ThreadX FileX的SDIO底层驱动实现,为了解决DMA4字节对齐问,全部搞成了单扇区操作,读写性能起不来

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2020-12-29 17:03:58 | 显示全部楼层 |阅读模式

为了解决SDIO自带的IDMA的4字节对齐问题,搞成了512字节(一个扇区)大小为单位进行操作,没有是multiblock操作,这样的话,读写性能上不去

  1. /**************************************************************************/
  2. /*                                                                        */
  3. /*       Partial Copyright (c) Microsoft Corporation. All rights reserved.*/
  4. /*                                                                        */
  5. /*       This software is licensed under the Microsoft Software License   */
  6. /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
  7. /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
  8. /*       and in the root directory of this software.                      */
  9. /*      Partial Copyright (c) STMicroelctronics 2020. All rights reserved */
  10. /**************************************************************************/


  11. /* Include necessary system files.  */
  12. #include "fx_stm32_sd_driver.h"


  13. ALIGN_32BYTES (UCHAR scratch[DEFAULT_SECTOR_SIZE]);

  14. UINT  _fx_partition_offset_calculate(void  *partition_sector, UINT partition, ULONG *partition_start, ULONG *partition_size);

  15. static UINT sd_read_data(FX_MEDIA *media_ptr, ULONG sector, UINT num_sectors, UINT use_scratch_buffer);
  16. static UINT sd_write_data(FX_MEDIA *media_ptr, ULONG sector, UINT num_sectors, UINT use_scratch_buffer);

  17. static TX_SEMAPHORE transfer_semaphore;

  18. static uint8_t is_initialized = 0;


  19. static int32_t check_sd_status(uint32_t instance)
  20. {
  21.     uint32_t start = tx_time_get();

  22.     while (tx_time_get() - start < DEFAULT_TIMEOUT)
  23.     {
  24.       if (BSP_SD_GetCardState(instance) == SD_TRANSFER_OK)
  25.       {
  26.         return BSP_ERROR_NONE;
  27.       }
  28.     }

  29.     return BSP_ERROR_BUSY;
  30. }

  31. /**
  32.   * @brief This function is the entry point to the STM32 SDIO disk driver.     */
  33. /*        It relies on the STM32 peripheral library from ST.
  34.   * @param None
  35.   * @retval None
  36.   */
  37. VOID  fx_stm32_sd_driver(FX_MEDIA *media_ptr)
  38. {
  39.     int32_t status;
  40.     ULONG       partition_start;
  41.     ULONG       partition_size;

  42. #if (FX_DRIVER_CALLS_BSP_SD_INIT == 0)
  43.     is_initialized = 1; /* the SD  was initialized by the application*/
  44. #endif
  45. TX_INTERRUPT_SAVE_AREA
  46.    /* before performing any operation, check the status of the SDMMC */
  47.     if (is_initialized == 1)
  48.     {
  49.       if (check_sd_status(SD_INSTANCE) != BSP_ERROR_NONE)
  50.       {
  51.           media_ptr->fx_media_driver_status =  FX_IO_ERROR;
  52.           return;
  53.       }
  54.     }

  55.     /* Process the driver request specified in the media control block.  */
  56.     switch(media_ptr->fx_media_driver_request)
  57.     {
  58.         case FX_DRIVER_INIT:
  59.         {
  60. #if (FX_DRIVER_CALLS_BSP_SD_INIT == 1)
  61.             /* Initialize the SD instance */
  62.             if (is_initialized == 0)
  63.             {
  64.                 status = BSP_SD_Init(SD_INSTANCE);

  65.                 if (status == BSP_ERROR_NONE)
  66.                 {
  67.                     is_initialized = 1;
  68. #endif
  69.                     /* create a binary semaphore to check the DMA transfer status */
  70.                     if (tx_semaphore_create(&transfer_semaphore, "sdmmc dma transfer semaphore", 0) != TX_SUCCESS)
  71.                     {
  72.                         media_ptr->fx_media_driver_status =  FX_IO_ERROR;
  73.                     }
  74.                     else
  75.                     {
  76.                         media_ptr->fx_media_driver_status =  FX_SUCCESS;
  77.                     }
  78. #if (FX_DRIVER_CALLS_BSP_SD_INIT == 1)
  79.                 }
  80.                 else
  81.                 {
  82.                     media_ptr->fx_media_driver_status =  FX_IO_ERROR;
  83.                 }
  84.             }
  85. #endif
  86.             break;
  87.         }

  88.         case FX_DRIVER_UNINIT:
  89.         {
  90.             tx_semaphore_delete(&transfer_semaphore);

  91. #if (FX_DRIVER_CALLS_BSP_SD_INIT == 1)
  92.             BSP_SD_DeInit(SD_INSTANCE);
  93.             is_initialized = 0;
  94. #endif
  95.             /* Successful driver request.  */
  96.            media_ptr->fx_media_driver_status = FX_SUCCESS;
  97.            break;
  98.         }

  99.         case FX_DRIVER_READ:
  100.         {
  101.             media_ptr->fx_media_driver_status = FX_IO_ERROR;
  102.             TX_DISABLE /* disable interrupts */
  103.            if ((ULONG)(media_ptr->fx_media_driver_buffer) & 0x3)
  104.            {
  105.               if (sd_read_data(media_ptr, media_ptr->fx_media_driver_logical_sector + media_ptr->fx_media_hidden_sectors,
  106.                                 media_ptr->fx_media_driver_sectors, 1) == FX_SUCCESS)
  107.               {
  108.                   media_ptr->fx_media_driver_status = FX_SUCCESS;
  109.               }
  110.            }
  111.            else
  112.            {
  113.                if (sd_read_data(media_ptr, media_ptr->fx_media_driver_logical_sector + media_ptr->fx_media_hidden_sectors,
  114.                        media_ptr->fx_media_driver_sectors, 0) == FX_SUCCESS)
  115.                {
  116.                    media_ptr->fx_media_driver_status = FX_SUCCESS;
  117.                }
  118.            }
  119.             TX_RESTORE /* restore interrupts */

  120.             break;
  121.         }

  122.         case FX_DRIVER_WRITE:
  123.         {
  124.             media_ptr->fx_media_driver_status = FX_IO_ERROR;
  125.             TX_DISABLE /* disable interrupts */

  126.          /* the buffer is unaligned use a scratch buffer for the write operation */
  127.          if ((ULONG)(media_ptr->fx_media_driver_buffer) & 0x3)
  128.          {
  129.               if (sd_write_data(media_ptr, media_ptr->fx_media_driver_logical_sector + media_ptr->fx_media_hidden_sectors,
  130.                    media_ptr->fx_media_driver_sectors, 1) == FX_SUCCESS)
  131.               {
  132.                   media_ptr->fx_media_driver_status = FX_SUCCESS;
  133.               }
  134.            }
  135.            else
  136.            {
  137.                if (sd_write_data(media_ptr, media_ptr->fx_media_driver_logical_sector + media_ptr->fx_media_hidden_sectors,
  138.                        media_ptr->fx_media_driver_sectors, 0) == FX_SUCCESS)
  139.                {
  140.                    media_ptr->fx_media_driver_status = FX_SUCCESS;
  141.                }
  142.            }
  143.             TX_RESTORE /* restore interrupts */

  144.             break;
  145.         }

  146.         case FX_DRIVER_FLUSH:
  147.         {
  148.             /* Return driver success.  */
  149.            media_ptr->fx_media_driver_status =  FX_SUCCESS;
  150.             break;
  151.         }

  152.         case FX_DRIVER_ABORT:
  153.         {
  154.             /* Return driver success.  */
  155.            media_ptr->fx_media_driver_status =  FX_SUCCESS;
  156.             break;
  157.         }

  158.         case FX_DRIVER_BOOT_READ:
  159.         {
  160. #if (ENABLE_CACHE_MAINTENANCE == 1)
  161.             SCB_InvalidateDCache_by_Addr((uint32_t*)media_ptr->fx_media_driver_buffer, media_ptr->fx_media_driver_sectors * DEFAULT_SECTOR_SIZE);
  162. #endif
  163.             /* the boot sector is the sector 0 */

  164.             status = BSP_SD_ReadBlocks_DMA(SD_INSTANCE,(uint32_t*)media_ptr->fx_media_driver_buffer, 0, 1);

  165.             if (status != BSP_ERROR_NONE)
  166.             {
  167.                 media_ptr->fx_media_driver_status =  FX_IO_ERROR;
  168.                 break;
  169.             }

  170.             if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) != TX_SUCCESS)
  171.             {
  172.                 media_ptr->fx_media_driver_status =  FX_IO_ERROR;
  173.                 break;
  174.             }

  175.             /* Check if the sector 0 is the actual boot sector, otherwise calculate the offset into it.
  176.             Please note that this should belong to higher level of MW to do this check and it is here
  177.             as a temporary work solution */

  178.             partition_start =  0;

  179.             status =  _fx_partition_offset_calculate(media_ptr -> fx_media_driver_buffer, 0,
  180.                                                                 &partition_start, &partition_size);

  181.             /* Check partition read error.  */
  182.             if (status)
  183.             {
  184.                 /* Unsuccessful driver request.  */
  185.                 media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
  186.                 return;
  187.             }

  188.             /* Now determine if there is a partition...   */
  189.             if (partition_start)
  190.             {

  191.                 if (check_sd_status(SD_INSTANCE) != BSP_ERROR_NONE)
  192.                 {
  193.                     media_ptr->fx_media_driver_status =  FX_IO_ERROR;
  194.                     return;
  195.                 }

  196.                 /*Invalidate cache before DMA read */
  197. #if (ENABLE_CACHE_MAINTENANCE == 1)
  198.             SCB_InvalidateDCache_by_Addr((uint32_t*)media_ptr->fx_media_driver_buffer, media_ptr->fx_media_driver_sectors * DEFAULT_SECTOR_SIZE);
  199. #endif

  200.                 /* Yes, now lets read the actual boot record.  */
  201.                 status = BSP_SD_ReadBlocks_DMA(SD_INSTANCE, (uint32_t*)media_ptr -> fx_media_driver_buffer, partition_start , 1);

  202.                 /* Check status of SDIO Read.  */
  203.                 if (status != BSP_ERROR_NONE)
  204.                 {

  205.                     /* Unsuccessful driver request.  */
  206.                     media_ptr -> fx_media_driver_status =  FX_IO_ERROR;
  207.                     return;
  208.                 }

  209.                 /* Wait for Rx Transfer completion */
  210.                 if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) != TX_SUCCESS)
  211.                 {
  212.                     media_ptr->fx_media_driver_status =  FX_IO_ERROR;
  213.                     break;
  214.                 }
  215.             }

  216.             /* Successful driver request.  */
  217.             media_ptr -> fx_media_driver_status =  FX_SUCCESS;
  218.             break;
  219.         }

  220.         case FX_DRIVER_BOOT_WRITE:
  221.         {
  222. #if (ENABLE_CACHE_MAINTENANCE == 1)
  223.             SCB_CleanDCache_by_Addr((uint32_t*)media_ptr->fx_media_driver_buffer, media_ptr->fx_media_driver_sectors * DEFAULT_SECTOR_SIZE);
  224. #endif
  225.             status = BSP_SD_WriteBlocks_DMA(SD_INSTANCE,(uint32_t*)media_ptr->fx_media_driver_buffer, 0, 1);
  226.             if (status == BSP_ERROR_NONE)
  227.             {
  228.                 if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
  229.                 {
  230.                     media_ptr->fx_media_driver_status =  FX_SUCCESS;
  231.                 }
  232.                 else
  233.                 {
  234.                     media_ptr->fx_media_driver_status =  FX_IO_ERROR;
  235.                 }
  236.             }
  237.             break;
  238.         }

  239.         default:
  240.         {
  241.            media_ptr->fx_media_driver_status =  FX_IO_ERROR;
  242.             break;
  243.         }
  244.     }
  245. }

  246. /**
  247.   * @brief BSP Tx Transfer completed callbacks
  248.   * @param Instance the SD instance
  249.   * @retval None
  250.   */
  251. void BSP_SD_WriteCpltCallback(uint32_t Instance)
  252. {
  253.     tx_semaphore_put(&transfer_semaphore);
  254. }

  255. /**
  256.   * @brief BSP Rx Transfer completed callbacks
  257.   * @param Instance the sd instance
  258.   * @retval None
  259.   */
  260. void BSP_SD_ReadCpltCallback(uint32_t Instance)
  261. {
  262.     tx_semaphore_put(&transfer_semaphore);
  263. }

  264. /**
  265.   * @brief Read buffer using BSP SD API taking into account the scratch buffer
  266.   * @param FX_MEDIA *media_ptr a pointer the main FileX structure
  267.   * @param ULONG start_sector first sector to start reading from
  268.   * @param UINT num_sectors number of sectors to be read
  269.   * @param UINT use_scratch_buffer to enable scratch buffer usage or not.
  270.   * @retval FX_SUCCESS on success FX_BUFFER_ERROR otherwise
  271.   */

  272. static UINT sd_read_data(FX_MEDIA *media_ptr, ULONG start_sector, UINT num_sectors, UINT use_scratch_buffer)
  273. {
  274.     INT i = 0;
  275.     UINT status;
  276.     if (use_scratch_buffer)
  277.     {
  278.         memset(scratch, '\0', DEFAULT_SECTOR_SIZE);
  279.         for (i = 0; i < num_sectors; i++)
  280.         {
  281.             status = BSP_SD_ReadBlocks_DMA(SD_INSTANCE, (uint32_t*)scratch, start_sector++, 1);

  282.             if (status != BSP_ERROR_NONE)
  283.             {
  284.                 status = FX_IO_ERROR;
  285.                 break;
  286.             }

  287.             if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) != TX_SUCCESS)
  288.             {
  289.                 status = FX_BUFFER_ERROR;
  290.                 break;
  291.             }
  292.             else
  293.             {
  294. #if (ENABLE_CACHE_MAINTENANCE == 1)
  295.                 SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, DEFAULT_SECTOR_SIZE);
  296. #endif

  297.                 _fx_utility_memory_copy(scratch, media_ptr->fx_media_driver_buffer, DEFAULT_SECTOR_SIZE);
  298.                 media_ptr->fx_media_driver_buffer += DEFAULT_SECTOR_SIZE;
  299.             }
  300.         }

  301.         if (i == num_sectors)
  302.         {
  303.             status = FX_SUCCESS;
  304.         }
  305.     }
  306.     else
  307.     {
  308.         status = BSP_SD_ReadBlocks_DMA(SD_INSTANCE, (uint32_t*)media_ptr->fx_media_driver_buffer, start_sector, num_sectors);

  309.         if (status == BSP_ERROR_NONE)
  310.         {
  311.             if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
  312.             {
  313. #if (ENABLE_CACHE_MAINTENANCE == 1)
  314.                 SCB_InvalidateDCache_by_Addr((uint32_t*)media_ptr->fx_media_driver_buffer, num_sectors * DEFAULT_SECTOR_SIZE);
  315. #endif
  316.                 status = FX_SUCCESS;
  317.             }
  318.             else
  319.             {
  320.                 status =  FX_BUFFER_ERROR;
  321.             }
  322.         }
  323.     }

  324.     return status;
  325. }

  326. /**
  327.   * @brief write buffer using BSP SD API taking into account the scratch buffer
  328.   * @param FX_MEDIA *media_ptr a pointer the main FileX structure
  329.   * @param ULONG start_sector first sector to start writing from
  330.   * @param UINT num_sectors number of sectors to be written
  331.   * @param UINT use_scratch_buffer to enable scratch buffer usage or not.
  332.   * @retval FX_SUCCESS on success FX_BUFFER_ERROR otherwise
  333.   */

  334. static UINT sd_write_data(FX_MEDIA *media_ptr, ULONG start_sector, UINT num_sectors, UINT use_scratch_buffer)
  335. {
  336.     INT i = 0;
  337.     UINT status;

  338.     if (use_scratch_buffer)
  339.     {
  340.         for (i = 0; i < num_sectors; i++)
  341.         {
  342.             _fx_utility_memory_copy(media_ptr->fx_media_driver_buffer, scratch, DEFAULT_SECTOR_SIZE);
  343.             media_ptr->fx_media_driver_buffer += DEFAULT_SECTOR_SIZE;

  344. #if (ENABLE_CACHE_MAINTENANCE == 1)
  345.             /* Clean the DCache to make the SD DMA see the actual content of the scratch buffer */
  346.             SCB_CleanDCache_by_Addr((uint32_t*)scratch, DEFAULT_SECTOR_SIZE);
  347. #endif
  348.             status = BSP_SD_WriteBlocks_DMA(SD_INSTANCE, (uint32_t*)scratch, (uint32_t)start_sector++, 1);

  349.             if (status != BSP_ERROR_NONE)
  350.             {
  351.                 status = FX_IO_ERROR;
  352.                 break;
  353.             }

  354.             if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) != TX_SUCCESS)
  355.             {
  356.                 status = FX_BUFFER_ERROR;
  357.                 break;
  358.             }
  359.         }

  360.         if (i == num_sectors)
  361.         {
  362.             status = FX_SUCCESS;
  363.         }
  364.     }
  365.     else
  366.     {
  367.         SCB_CleanDCache_by_Addr((uint32_t*)media_ptr->fx_media_driver_buffer, num_sectors * DEFAULT_SECTOR_SIZE);
  368.         status = BSP_SD_WriteBlocks_DMA(SD_INSTANCE, (uint32_t*)media_ptr->fx_media_driver_buffer, start_sector, num_sectors);

  369.         if (status == BSP_ERROR_NONE)
  370.         {
  371.             if(tx_semaphore_get(&transfer_semaphore, DEFAULT_TIMEOUT) == TX_SUCCESS)
  372.             {
  373.                 status = FX_SUCCESS;
  374.             }
  375.             else
  376.             {
  377.                 status = FX_IO_ERROR;
  378.             }
  379.         }
  380.     }

  381.     return status;
  382. }
复制代码


回复

使用道具 举报

14

主题

99

回帖

141

积分

初级会员

积分
141
发表于 2020-12-29 21:28:18 | 显示全部楼层
读写速度和FATFS相比呢?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
 楼主| 发表于 2020-12-30 08:57:59 | 显示全部楼层
LR215 发表于 2020-12-29 21:28
读写速度和FATFS相比呢?

底层驱动不同,没法做比较。
回复

使用道具 举报

3

主题

1231

回帖

1240

积分

至尊会员

积分
1240
发表于 2020-12-30 10:50:17 | 显示全部楼层
硬汉大哥这里有想法? 毕竟对方的代码是安全认证过的,也许考虑的功能安全的层面比较多。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
 楼主| 发表于 2020-12-30 11:44:40 | 显示全部楼层
morning_enr6U 发表于 2020-12-30 10:50
硬汉大哥这里有想法? 毕竟对方的代码是安全认证过的,也许考虑的功能安全的层面比较多。

当前提供的这个是最简单的实现方式,性能也是最低的。

稳定性好点
回复

使用道具 举报

610

主题

3062

回帖

4912

积分

至尊会员

积分
4912
发表于 2021-1-3 14:12:45 | 显示全部楼层
传说 稳定压倒一切,估计就是这个道理吧
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
 楼主| 发表于 2021-1-4 10:28:26 | 显示全部楼层
hpdell 发表于 2021-1-3 14:12
传说 稳定压倒一切,估计就是这个道理吧

他们先发布一个稳定易用的版本也是合理的。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-15 21:12 , Processed in 0.271597 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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