STM32L4,用CUBEMX生成代码,用了FREERTOS,DMA,FATFS,SDIO,FATFS用了信号量,有一个BUG,好多年了,新的库都还没改,忍不住了,所以发出来。sd_diskio.c代码附后,更改了的地方,或者需要更改的地方红色注释。 /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file sd_diskio.c * @brief SD Disk I/O driver ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2021 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under Ultimate Liberty license * SLA0044, the "License"; You may not use this file except in compliance with * the License. You may obtain a copy of the License at: * www.st.com/SLA0044 * ****************************************************************************** */ /* USER CODE END Header */ /* Note: code generation based on sd_diskio_dma_rtos_template_bspv1.c v2.1.4 as FreeRTOS is enabled. */ /* USER CODE BEGIN firstSection */ /* can be used to modify / undefine following code or add new definitions */ /* USER CODE END firstSection*/ /* Includes ------------------------------------------------------------------*/ #include "ff_gen_drv.h" #include "sd_diskio.h" #include <string.h> #include <stdio.h> /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define QUEUE_SIZE (uint32_t) 10 #define READ_CPLT_MSG (uint32_t) 1 #define WRITE_CPLT_MSG (uint32_t) 2 /* ================================================================== enable the defines below to send custom rtos messages when an error or an abort occurs. Notice: depending on the HAL/SD driver the HAL_SD_ErrorCallback() may not be available. See BSP_SD_ErrorCallback() and BSP_SD_AbortCallback() below ================================================================== #define RW_ERROR_MSG (uint32_t) 3 #define RW_ABORT_MSG (uint32_t) 4 */ /* * the following Timeout is useful to give the control back to the applications * in case of errors in either BSP_SD_ReadCpltCallback() or BSP_SD_WriteCpltCallback() * the value by default is as defined in the BSP platform driver otherwise 30 secs */ #define SD_TIMEOUT 30 * 1000 #define SD_DEFAULT_BLOCK_SIZE 512 /* * Depending on the use case, the SD card initialization could be done at the * application level: if it is the case define the flag below to disable * the BSP_SD_Init() call in the SD_Initialize() and add a call to * BSP_SD_Init() elsewhere in the application. */ /* USER CODE BEGIN disableSDInit */ /* #define DISABLE_SD_INIT */ #ifndef __CC_ARM #define __CC_ARM//这个要增加使能//因为涉及到地址没四字节对齐,所以要判断转储下 #endif #if defined (__GNUC__) /* GNU Compiler */ #define ALIGN_32BYTES(buf) buf __attribute__ ((aligned (32))) #elif defined (__ICCARM__) /* IAR Compiler */ #define ALIGN_32BYTES(buf) _Pragma("data_alignment=32") buf #elif defined (__CC_ARM) /* ARM Compiler */ #define ALIGN_32BYTES(buf) __align(32) buf #endif /* USER CODE END disableSDInit */ /* * when using cacheable memory region, it may be needed to maintain the cache * validity. Enable the define below to activate a cache maintenance at each * read and write operation. * Notice: This is applicable only for cortex M7 based platform. */ /* USER CODE BEGIN enableSDDmaCacheMaintenance */ /* #define ENABLE_SD_DMA_CACHE_MAINTENANCE 1 */ /* USER CODE END enableSDDmaCacheMaintenance */ /* * Some DMA requires 4-Byte aligned address buffer to correctly read/write data, * in FatFs some accesses aren't thus we need a 4-byte aligned scratch buffer to correctly * transfer data */ /* USER CODE BEGIN enableScratchBuffer */ #define ENABLE_SCRATCH_BUFFER //这个要使能 /* USER CODE END enableScratchBuffer */ /* Private variables ---------------------------------------------------------*/ #if defined(ENABLE_SCRATCH_BUFFER) #if defined (ENABLE_SD_DMA_CACHE_MAINTENANCE) ALIGN_32BYTES(static uint8_t scratch[BLOCKSIZE]); // 32-Byte aligned for cache maintenance #else __ALIGN_BEGIN static uint8_t scratch[BLOCKSIZE] __ALIGN_END; #endif #endif /* Disk status */ static volatile DSTATUS Stat = STA_NOINIT; #if (osCMSIS <= 0x20000U) static osMessageQId SDQueueID = NULL; #else static osMessageQueueId_t SDQueueID = NULL; #endif /* Private function prototypes -----------------------------------------------*/ static DSTATUS SD_CheckStatus(BYTE lun); DSTATUS SD_initialize (BYTE); DSTATUS SD_status (BYTE); DRESULT SD_read (BYTE, BYTE*, DWORD, UINT); #if _USE_WRITE == 1 DRESULT SD_write (BYTE, const BYTE*, DWORD, UINT); #endif /* _USE_WRITE == 1 */ #if _USE_IOCTL == 1 DRESULT SD_ioctl (BYTE, BYTE, void*); #endif /* _USE_IOCTL == 1 */ const Diskio_drvTypeDef SD_Driver = { SD_initialize, SD_status, SD_read, #if _USE_WRITE == 1 SD_write, #endif /* _USE_WRITE == 1 */ #if _USE_IOCTL == 1 SD_ioctl, #endif /* _USE_IOCTL == 1 */ }; /* USER CODE BEGIN beforeFunctionSection */ /* can be used to modify / undefine following code or add new code */ /* USER CODE END beforeFunctionSection */ /* Private functions ---------------------------------------------------------*/ static int SD_CheckStatusWithTimeout(uint32_t timeout) { uint32_t timer; /* block until SDIO peripheral is ready again or a timeout occur */ #if (osCMSIS <= 0x20000U) timer = osKernelSysTick(); while( osKernelSysTick() - timer < timeout) #else timer = osKernelGetTickCount(); while( osKernelGetTickCount() - timer < timeout) #endif { if (BSP_SD_GetCardState() == SD_TRANSFER_OK) { return 0; } } return -1; } static DSTATUS SD_CheckStatus(BYTE lun) { Stat = STA_NOINIT; if(BSP_SD_GetCardState() == SD_TRANSFER_OK) { Stat &= ~STA_NOINIT; } return Stat; } /** * @brief Initializes a Drive * @param lun : not used * @retval DSTATUS: Operation status */ DSTATUS SD_initialize(BYTE lun) { Stat = STA_NOINIT; /* * check that the kernel has been started before continuing * as the osMessage API will fail otherwise */ #if (osCMSIS <= 0x20000U) if(osKernelRunning()) #else if(osKernelGetState() == osKernelRunning) #endif { #if !defined(DISABLE_SD_INIT) if(BSP_SD_Init() == MSD_OK) { Stat = SD_CheckStatus(lun); } #else Stat = SD_CheckStatus(lun); #endif /* * if the SD is correctly initialized, create the operation queue * if not already created */ if (Stat != STA_NOINIT) { if (SDQueueID == NULL) { #if (osCMSIS <= 0x20000U) osMessageQDef(SD_Queue, QUEUE_SIZE, uint16_t); SDQueueID = osMessageCreate (osMessageQ(SD_Queue), NULL); #else SDQueueID = osMessageQueueNew(QUEUE_SIZE, 2, NULL); #endif } if (SDQueueID == NULL) { Stat |= STA_NOINIT; } } } return Stat; } /** * @brief Gets Disk Status * @param lun : not used * @retval DSTATUS: Operation status */ DSTATUS SD_status(BYTE lun) { return SD_CheckStatus(lun); } /* USER CODE BEGIN beforeReadSection */ /* can be used to modify previous code / undefine following code / add new code */ /* USER CODE END beforeReadSection */ /** * @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) { uint8_t ret;//这里增加个定义,如果生成的文件里没有的话 DRESULT res = RES_ERROR; uint32_t timer; #if (osCMSIS < 0x20000U) osEvent event; #else uint16_t event; osStatus_t status; #endif #if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) uint32_t alignedAddr; #endif /* * ensure the SDCard is ready for a new operation */ if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0) { return res; } #if defined(ENABLE_SCRATCH_BUFFER) if (!((uint32_t)buff & 0x3)) { #endif /* Fast path cause destination buffer is correctly aligned */ ret = BSP_SD_ReadBlocks_DMA((uint32_t*)buff, (uint32_t)(sector), count); if (ret == MSD_OK) { #if (osCMSIS < 0x20000U) /* wait for a message from the queue or a timeout */ event = osMessageGet(SDQueueID, SD_TIMEOUT); if (event.status == osEventMessage) { if (event.value.v == READ_CPLT_MSG) { timer = osKernelSysTick(); /* block until SDIO IP is ready or a timeout occur */ while(osKernelSysTick() - timer <SD_TIMEOUT) #else status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT); if ((status == osOK) && (event == READ_CPLT_MSG)) { timer = osKernelGetTickCount(); /* block until SDIO IP is ready or a timeout occur */ while(osKernelGetTickCount() - timer <SD_TIMEOUT) #endif { if (BSP_SD_GetCardState() == SD_TRANSFER_OK) { res = RES_OK; #if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) /* 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; } } #if (osCMSIS < 0x20000U) } } #else } #endif } #if defined(ENABLE_SCRATCH_BUFFER) } else { /* Slow path, fetch each sector a part and memcpy to destination buffer */ 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 until the read is successful or a timeout occurs */ #if (osCMSIS < 0x20000U) /* wait for a message from the queue or a timeout */ event = osMessageGet(SDQueueID, SD_TIMEOUT); if (event.status == osEventMessage) { if (event.value.v == READ_CPLT_MSG) { timer = osKernelSysTick(); /* block until SDIO IP is ready or a timeout occur */ while(osKernelSysTick() - timer <SD_TIMEOUT) #else status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT); if ((status == osOK) && (event == READ_CPLT_MSG)) { timer = osKernelGetTickCount(); /* block until SDIO IP is ready or a timeout occur */ ret = MSD_ERROR; while(osKernelGetTickCount() - timer < SD_TIMEOUT) #endif { ret = BSP_SD_GetCardState(); if (ret == MSD_OK) { break; } } if (ret != MSD_OK) { break; } #if (osCMSIS < 0x20000U) } } #else } #endif #if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) /* * * invalidate the scratch buffer before the next read to get the actual data instead of the cached one */ SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE); #endif memcpy(buff, scratch, BLOCKSIZE); buff += BLOCKSIZE; } else { break; } } if ((i == count) && (ret == MSD_OK )) res = RES_OK; } #endif return res; } /* USER CODE BEGIN beforeWriteSection */ /* can be used to modify previous code / undefine following code / add new code */ /* USER CODE END beforeWriteSection */ /** * @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 timer; #if (osCMSIS < 0x20000U) osEvent event; #else uint16_t event; osStatus_t status; #endif #if defined(ENABLE_SCRATCH_BUFFER) int32_t ret; #endif /* * ensure the SDCard is ready for a new operation */ if (SD_CheckStatusWithTimeout(SD_TIMEOUT) < 0) { return res; } #if defined(ENABLE_SCRATCH_BUFFER) if (!((uint32_t)buff & 0x3)) { #endif #if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) uint32_t alignedAddr; /* the SCB_CleanDCache_by_Addr() requires a 32-Byte aligned address adjust the address and the D-Cache size to clean accordingly. */ alignedAddr = (uint32_t)buff & ~0x1F; SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)buff - alignedAddr)); #endif if(BSP_SD_WriteBlocks_DMA((uint32_t*)buff, (uint32_t) (sector), count) == MSD_OK) { #if (osCMSIS < 0x20000U) /* Get the message from the queue */ event = osMessageGet(SDQueueID, SD_TIMEOUT); if (event.status == osEventMessage) { if (event.value.v == WRITE_CPLT_MSG) { #else status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT); if ((status == osOK) && (event == WRITE_CPLT_MSG)) { #endif #if (osCMSIS < 0x20000U) timer = osKernelSysTick(); /* block until SDIO IP is ready or a timeout occur */ while(osKernelSysTick() - timer < SD_TIMEOUT) #else timer = osKernelGetTickCount(); /* block until SDIO IP is ready or a timeout occur */ while(osKernelGetTickCount() - timer < SD_TIMEOUT) #endif { if (BSP_SD_GetCardState() == SD_TRANSFER_OK) { res = RES_OK; break; } } #if (osCMSIS < 0x20000U) } } #else } #endif } #if defined(ENABLE_SCRATCH_BUFFER) }//这里增加个花括号, 和前面 if (!((uint32_t)buff & 0x3))判断下面的花括号配对 else { /* Slow path, fetch each sector a part and memcpy to destination buffer */ int i; #if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1) /* * invalidate the scratch buffer before the next write to get the actual data instead of the cached one */ SCB_InvalidateDCache_by_Addr((uint32_t*)scratch, BLOCKSIZE); #endif for (i = 0; i < count; i++) { memcpy((void *)scratch, buff, BLOCKSIZE); buff += BLOCKSIZE; ret = BSP_SD_WriteBlocks_DMA((uint32_t*)scratch, (uint32_t)sector++, 1); if (ret == MSD_OK ) { /* wait until the read is successful or a timeout occurs */ #if (osCMSIS < 0x20000U) /* wait for a message from the queue or a timeout */ event = osMessageGet(SDQueueID, SD_TIMEOUT); if (event.status == osEventMessage) { if (event.value.v == READ_CPLT_MSG)//这是写函数里面,为什么这里条件是READ,应该改成WRITE { timer = osKernelSysTick(); /* block until SDIO IP is ready or a timeout occur */ while(osKernelSysTick() - timer <SD_TIMEOUT) #else status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT); if ((status == osOK) && (event == READ_CPLT_MSG))//这是写函数里面,为什么这里条件是READ,应该改成WRITE { timer = osKernelGetTickCount(); /* block until SDIO IP is ready or a timeout occur */ ret = MSD_ERROR; while(osKernelGetTickCount() - timer < SD_TIMEOUT) #endif { ret = BSP_SD_GetCardState(); if (ret == MSD_OK) { break; } } if (ret != MSD_OK) { break; } #if (osCMSIS < 0x20000U) } } #else } #endif } else { break; } } if ((i == count) && (ret == MSD_OK )) res = RES_OK; } // }//这个花括号注释掉,估计是前面那个条件的括号错了位置。 #endif return res; } #endif /* _USE_WRITE == 1 */ /* USER CODE BEGIN beforeIoctlSection */ /* can be used to modify previous code / undefine following code / add new code */ /* USER CODE END beforeIoctlSection */ /** * @brief I/O control operation * @param lun : not used * @param cmd: Control code * @param *buff: Buffer to send/receive control data * @retval DRESULT: Operation result */ #if _USE_IOCTL == 1 DRESULT SD_ioctl(BYTE lun, BYTE cmd, void *buff) { DRESULT res = RES_ERROR; BSP_SD_CardInfo CardInfo; if (Stat & STA_NOINIT) return RES_NOTRDY; switch (cmd) { /* Make sure that no pending write process */ case CTRL_SYNC : res = RES_OK; break; /* Get number of sectors on the disk (DWORD) */ case GET_SECTOR_COUNT : BSP_SD_GetCardInfo(&CardInfo); *(DWORD*)buff = CardInfo.LogBlockNbr; res = RES_OK; break; /* Get R/W sector size (WORD) */ case GET_SECTOR_SIZE : BSP_SD_GetCardInfo(&CardInfo); *(WORD*)buff = CardInfo.LogBlockSize; res = RES_OK; break; /* Get erase block size in unit of sector (DWORD) */ case GET_BLOCK_SIZE : BSP_SD_GetCardInfo(&CardInfo); *(DWORD*)buff = CardInfo.LogBlockSize / SD_DEFAULT_BLOCK_SIZE; res = RES_OK; break; default: res = RES_PARERR; } return res; } #endif /* _USE_IOCTL == 1 */ /* USER CODE BEGIN afterIoctlSection */ /* can be used to modify previous code / undefine following code / add new code */ /* USER CODE END afterIoctlSection */ /* USER CODE BEGIN callbackSection */ /* can be used to modify / following code or add new code */ /* USER CODE END callbackSection */ /** * @brief Tx Transfer completed callbacks * @param hsd: SD handle * @retval None */ void BSP_SD_WriteCpltCallback(void) { /* * No need to add an "osKernelRunning()" check here, as the SD_initialize() * is always called before any SD_Read()/SD_Write() call */ #if (osCMSIS < 0x20000U) osMessagePut(SDQueueID, WRITE_CPLT_MSG, 0); #else const uint16_t msg = WRITE_CPLT_MSG; osMessageQueuePut(SDQueueID, (const void *)&msg, NULL, 0); #endif } /** * @brief Rx Transfer completed callbacks * @param hsd: SD handle * @retval None */ void BSP_SD_ReadCpltCallback(void) { /* * No need to add an "osKernelRunning()" check here, as the SD_initialize() * is always called before any SD_Read()/SD_Write() call */ #if (osCMSIS < 0x20000U) osMessagePut(SDQueueID, READ_CPLT_MSG, 0); #else const uint16_t msg = READ_CPLT_MSG; osMessageQueuePut(SDQueueID, (const void *)&msg, NULL, 0); #endif } /* USER CODE BEGIN ErrorAbortCallbacks */ /* void BSP_SD_AbortCallback(void) { #if (osCMSIS < 0x20000U) osMessagePut(SDQueueID, RW_ABORT_MSG, 0); #else const uint16_t msg = RW_ABORT_MSG; osMessageQueuePut(SDQueueID, (const void *)&msg, NULL, 0); #endif } */ /* USER CODE END ErrorAbortCallbacks */ /* USER CODE BEGIN lastSection */ /* can be used to modify / undefine previous code or add new code */ /* USER CODE END lastSection */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
STM32L431在STOP2模式下能否将串口的RX配置成EXTI唤醒呢?为什么我的唤醒不了呢?并且空闲中断也不能用
STM32G431 用MCSDK5.4.8 进行PMSM永磁同步电机FOC控制,转速上升到某一值(3500rpm)无法继续上升,上不去
STM32L4R9OSPI接口测试
STM32CUBEMX使用硬件SPI和软件SPI的区别
为什么STM32CUBEMX中无法选择STM32WB09的BLE功能外设??
ST25R3916芯片手册显示 NFC-V / ISO15693,高达53 kb/s;怎么设置?
请问一下为什么cubemx配置正确,但是生成的文件无法调用HAL_UARTEx_ReceiveToIdle_DMA()函数?
STM32WBA52CEU6 BLE芯片使用STM32Cnbex生成的工程编译报错,求解决方法
STM32F405使用LL库建立SPI通讯报溢出是什么原因?
请问为什么自己加了stdio.h,sprintf还是用不了?
正准备学习CubeMx 刚好也是用L4,先mark一下
如果功能不用这么全,好像不会出这个问题。几大功能同时使用会有错误。