/* SD driver provided by ST, modified for use in a FreeRTOS+FAT demo. */ /** ****************************************************************************** * @file stm32f4xx_hal_sd.c * @author MCD Application Team * @version V1.3.2 * @date 26-June-2015 * @brief SD card HAL module driver. * This file provides firmware functions to manage the following * functionalities of the Secure Digital (SD) peripheral: * + Initialization and de-initialization functions * + IO operation functions * + Peripheral Control functions * + Peripheral State functions * * @verbatim * ============================================================================== ##### How to use this driver ##### #####============================================================================== #####[..] #####This driver implements a high level communication layer for read and write from/to #####this memory. The needed STM32 hardware resources (SDIO and GPIO) are performed by #####the user in HAL_SD_MspInit() function (MSP layer). #####Basically, the MSP layer configuration should be the same as we provide in the #####examples. #####You can easily tailor this configuration according to hardware resources. ##### #####[..] #####This driver is a generic layered driver for SDIO memories which uses the HAL #####SDIO driver functions to interface with SD and uSD cards devices. #####It is used as follows: ##### #####(#)Initialize the SDIO low level resources by implement the HAL_SD_MspInit() API: ##### (##) Enable the SDIO interface clock using __HAL_RCC_SDIO_CLK_ENABLE(); ##### (##) SDIO pins configuration for SD card ##### (+++) Enable the clock for the SDIO GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE(); ##### (+++) Configure these SDIO pins as alternate function pull-up using HAL_GPIO_Init() ##### and according to your pin assignment; ##### (##) DMA Configuration if you need to use DMA process (HAL_SD_ReadBlocks_DMA() ##### and HAL_SD_WriteBlocks_DMA() APIs). ##### (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE(); ##### (+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled. ##### (##) NVIC configuration if you need to use interrupt process when using DMA transfer. ##### (+++) Configure the SDIO and DMA interrupt priorities using functions ##### HAL_NVIC_SetPriority(); DMA priority is superior to SDIO's priority ##### (+++) Enable the NVIC DMA and SDIO IRQs using function HAL_NVIC_EnableIRQ() ##### (+++) SDIO interrupts are managed using the macros __HAL_SD_SDIO_ENABLE_IT() ##### and __HAL_SD_SDIO_DISABLE_IT() inside the communication process. ##### (+++) SDIO interrupts pending bits are managed using the macros __HAL_SD_SDIO_GET_IT() ##### and __HAL_SD_SDIO_CLEAR_IT() #####(#) At this stage, you can perform SD read/write/erase operations after SD card initialization ##### ##### *** SD Card Initialization and configuration *** ***================================================ ***[..] ***To initialize the SD Card, use the HAL_SD_Init() function. It Initializes ***the SD Card and put it into Standby State (Ready for data transfer). ***This function provide the following operations: *** ***(#) Apply the SD Card initialization process at 400KHz and check the SD Card *** type (Standard Capacity or High Capacity). You can change or adapt this *** frequency by adjusting the "ClockDiv" field. *** The SD Card frequency (SDIO_CK) is computed as follows: *** *** SDIO_CK = SDIOCLK / (ClockDiv + 2) *** *** In initialization mode and according to the SD Card standard, *** make sure that the SDIO_CK frequency doesn't exceed 400KHz. *** ***(#) Get the SD CID and CSD data. All these information are managed by the SDCardInfo *** structure. This structure provide also ready computed SD Card capacity *** and Block size. *** *** -@- These information are stored in SD handle structure in case of future use. *** ***(#) Configure the SD Card Data transfer frequency. By Default, the card transfer *** frequency is set to 24MHz. You can change or adapt this frequency by adjusting *** the "ClockDiv" field. *** In transfer mode and according to the SD Card standard, make sure that the *** SDIO_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch. *** To be able to use a frequency higher than 24MHz, you should use the SDIO *** peripheral in bypass mode. Refer to the corresponding reference manual *** for more details. *** ***(#) Select the corresponding SD Card according to the address read with the step 2. *** ***(#) Configure the SD Card in wide bus mode: 4-bits data. *** *** SD Card Read operation *** ***============================== ***[..] ***(+) You can read from SD card in polling mode by using function HAL_SD_ReadBlocks(). *** This function support only 512-bytes block length (the block size should be *** chosen as 512 bytes). *** You can choose either one block read operation or multiple block read operation *** by adjusting the "NumberOfBlocks" parameter. *** ***(+) You can read from SD card in DMA mode by using function HAL_SD_ReadBlocks_DMA(). *** This function support only 512-bytes block length (the block size should be *** chosen as 512 bytes). *** You can choose either one block read operation or multiple block read operation *** by adjusting the "NumberOfBlocks" parameter. *** After this, you have to call the function HAL_SD_CheckReadOperation(), to insure *** that the read transfer is done correctly in both DMA and SD sides. *** *** SD Card Write operation *** ***=============================== ***[..] ***(+) You can write to SD card in polling mode by using function HAL_SD_WriteBlocks(). *** This function support only 512-bytes block length (the block size should be *** chosen as 512 bytes). *** You can choose either one block read operation or multiple block read operation *** by adjusting the "NumberOfBlocks" parameter. *** ***(+) You can write to SD card in DMA mode by using function HAL_SD_WriteBlocks_DMA(). *** This function support only 512-bytes block length (the block size should be *** chosen as 512 byte). *** You can choose either one block read operation or multiple block read operation *** by adjusting the "NumberOfBlocks" parameter. *** After this, you have to call the function HAL_SD_CheckWriteOperation(), to insure *** that the write transfer is done correctly in both DMA and SD sides. *** *** SD card status *** ***====================== ***[..] ***(+) At any time, you can check the SD Card status and get the SD card state *** by using the HAL_SD_GetStatus() function. This function checks first if the *** SD card is still connected and then get the internal SD Card transfer state. ***(+) You can also get the SD card SD Status register by using the HAL_SD_SendSDStatus() *** function. *** *** SD HAL driver macros list *** ***================================== ***[..] ***Below the list of most used macros in SD HAL driver. *** ***(+) __HAL_SD_SDIO_ENABLE : Enable the SD device ***(+) __HAL_SD_SDIO_DISABLE : Disable the SD device ***(+) __HAL_SD_SDIO_DMA_ENABLE: Enable the SDIO DMA transfer ***(+) __HAL_SD_SDIO_DMA_DISABLE: Disable the SDIO DMA transfer ***(+) __HAL_SD_SDIO_ENABLE_IT: Enable the SD device interrupt ***(+) __HAL_SD_SDIO_DISABLE_IT: Disable the SD device interrupt ***(+) __HAL_SD_SDIO_GET_FLAG:Check whether the specified SD flag is set or not ***(+) __HAL_SD_SDIO_CLEAR_FLAG: Clear the SD's pending flags *** ***(@) You can refer to the SD HAL driver header file for more useful macros *** ***@endverbatim ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2015 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ #include "FreeRTOS.h" #include "task.h" /* This include is not necessary except for including the definition of FF_PRINTF(). */ #include "ff_headers.h" /* Includes ------------------------------------------------------------------*/ #include "stm32f4xx_hal.h" #ifdef HAL_SD_MODULE_ENABLED /** @addtogroup STM32F4xx_HAL_Driver * @{ */ /** @addtogroup SD * @{ */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /** @addtogroup SD_Private_Defines * @{ */ /** * @brief SDIO Data block size */ #define DATA_BLOCK_SIZE ( ( uint32_t ) ( 9 << 4 ) ) /** * @brief SDIO Static flags, Timeout, FIFO Address */ #define SDIO_STATIC_FLAGS \ ( ( uint32_t ) ( SDIO_FLAG_CCRCFAIL | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_CTIMEOUT | \ SDIO_FLAG_DTIMEOUT | SDIO_FLAG_TXUNDERR | SDIO_FLAG_RXOVERR | \ SDIO_FLAG_CMDREND | SDIO_FLAG_CMDSENT | SDIO_FLAG_DATAEND | \ SDIO_FLAG_DBCKEND ) ) #define SDIO_CMD0TIMEOUT ( ( uint32_t ) 0x00010000 ) /** * @brief Mask for errors Card Status R1 (OCR Register) */ #define SD_OCR_ADDR_OUT_OF_RANGE ( ( uint32_t ) 0x80000000 ) #define SD_OCR_ADDR_MISALIGNED ( ( uint32_t ) 0x40000000 ) #define SD_OCR_BLOCK_LEN_ERR ( ( uint32_t ) 0x20000000 ) #define SD_OCR_ERASE_SEQ_ERR ( ( uint32_t ) 0x10000000 ) #define SD_OCR_BAD_ERASE_PARAM ( ( uint32_t ) 0x08000000 ) #define SD_OCR_WRITE_PROT_VIOLATION ( ( uint32_t ) 0x04000000 ) #define SD_OCR_LOCK_UNLOCK_FAILED ( ( uint32_t ) 0x01000000 ) #define SD_OCR_COM_CRC_FAILED ( ( uint32_t ) 0x00800000 ) #define SD_OCR_ILLEGAL_CMD ( ( uint32_t ) 0x00400000 ) #define SD_OCR_CARD_ECC_FAILED ( ( uint32_t ) 0x00200000 ) #define SD_OCR_CC_ERROR ( ( uint32_t ) 0x00100000 ) #define SD_OCR_GENERAL_UNKNOWN_ERROR ( ( uint32_t ) 0x00080000 ) #define SD_OCR_STREAM_READ_UNDERRUN ( ( uint32_t ) 0x00040000 ) #define SD_OCR_STREAM_WRITE_OVERRUN ( ( uint32_t ) 0x00020000 ) #define SD_OCR_CID_CSD_OVERWRITE ( ( uint32_t ) 0x00010000 ) #define SD_OCR_WP_ERASE_SKIP ( ( uint32_t ) 0x00008000 ) #define SD_OCR_CARD_ECC_DISABLED ( ( uint32_t ) 0x00004000 ) #define SD_OCR_ERASE_RESET ( ( uint32_t ) 0x00002000 ) #define SD_OCR_AKE_SEQ_ERROR ( ( uint32_t ) 0x00000008 ) #define SD_OCR_ERRORBITS ( ( uint32_t ) 0xFDFFE008 ) /** * @brief Masks for R6 Response */ #define SD_R6_GENERAL_UNKNOWN_ERROR ( ( uint32_t ) 0x00002000 ) #define SD_R6_ILLEGAL_CMD ( ( uint32_t ) 0x00004000 ) #define SD_R6_COM_CRC_FAILED ( ( uint32_t ) 0x00008000 ) #define SD_VOLTAGE_WINDOW_SD ( ( uint32_t ) 0x80100000 ) #define SD_HIGH_CAPACITY ( ( uint32_t ) 0x40000000 ) #define SD_STD_CAPACITY ( ( uint32_t ) 0x00000000 ) #define SD_CHECK_PATTERN ( ( uint32_t ) 0x000001AA ) #define SD_MAX_VOLT_TRIAL ( ( uint32_t ) 0x0000FFFF ) #define SD_ALLZERO ( ( uint32_t ) 0x00000000 ) #define SD_WIDE_BUS_SUPPORT ( ( uint32_t ) 0x00040000 ) #define SD_SINGLE_BUS_SUPPORT ( ( uint32_t ) 0x00010000 ) #define SD_CARD_LOCKED ( ( uint32_t ) 0x02000000 ) #define SD_DATATIMEOUT ( ( uint32_t ) 0xFFFFFFFF ) #define SD_0TO7BITS ( ( uint32_t ) 0x000000FF ) #define SD_8TO15BITS ( ( uint32_t ) 0x0000FF00 ) #define SD_16TO23BITS ( ( uint32_t ) 0x00FF0000 ) #define SD_24TO31BITS ( ( uint32_t ) 0xFF000000 ) #define SD_MAX_DATA_LENGTH ( ( uint32_t ) 0x01FFFFFF ) #define SD_HALFFIFO ( ( uint32_t ) 0x00000008 ) #define SD_HALFFIFOBYTES ( ( uint32_t ) 0x00000020 ) /** * @brief Command Class Supported */ #define SD_CCCC_LOCK_UNLOCK ( ( uint32_t ) 0x00000080 ) #define SD_CCCC_WRITE_PROT ( ( uint32_t ) 0x00000040 ) #define SD_CCCC_ERASE ( ( uint32_t ) 0x00000020 ) /** * @brief Following commands are SD Card Specific commands. * SDIO_APP_CMD should be sent before sending these commands. */ #define SD_SDIO_SEND_IF_COND ( ( uint32_t ) SD_CMD_HS_SEND_EXT_CSD ) /** * @} */ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /** @addtogroup SD_Private_Functions_Prototypes * @{ */ static HAL_SD_ErrorTypedef SD_Initialize_Cards( SD_HandleTypeDef * hsd ); static HAL_SD_ErrorTypedef SD_Select_Deselect( SD_HandleTypeDef * hsd, uint64_t addr ); static HAL_SD_ErrorTypedef SD_PowerON( SD_HandleTypeDef * hsd ); static HAL_SD_ErrorTypedef SD_PowerOFF( SD_HandleTypeDef * hsd ); static HAL_SD_ErrorTypedef SD_SendStatus( SD_HandleTypeDef * hsd, uint32_t * pCardStatus ); static HAL_SD_CardStateTypedef SD_GetState( SD_HandleTypeDef * hsd ); static HAL_SD_ErrorTypedef SD_IsCardProgramming( SD_HandleTypeDef * hsd, uint8_t * pStatus ); static HAL_SD_ErrorTypedef SD_CmdError( SD_HandleTypeDef * hsd ); static HAL_SD_ErrorTypedef SD_CmdResp1Error( SD_HandleTypeDef * hsd, uint8_t SD_CMD ); static HAL_SD_ErrorTypedef SD_CmdResp7Error( SD_HandleTypeDef * hsd ); static HAL_SD_ErrorTypedef SD_CmdResp3Error( SD_HandleTypeDef * hsd ); static HAL_SD_ErrorTypedef SD_CmdResp2Error( SD_HandleTypeDef * hsd ); static HAL_SD_ErrorTypedef SD_CmdResp6Error( SD_HandleTypeDef * hsd, uint8_t SD_CMD, uint16_t * pRCA ); static HAL_SD_ErrorTypedef SD_WideBus_Enable( SD_HandleTypeDef * hsd ); static HAL_SD_ErrorTypedef SD_WideBus_Disable( SD_HandleTypeDef * hsd ); static HAL_SD_ErrorTypedef SD_FindSCR( SD_HandleTypeDef * hsd, uint32_t * pSCR ); static void SD_DMA_RxCplt( DMA_HandleTypeDef * hdma ); static void SD_DMA_RxError( DMA_HandleTypeDef * hdma ); static void SD_DMA_TxCplt( DMA_HandleTypeDef * hdma ); static void SD_DMA_TxError( DMA_HandleTypeDef * hdma ); /** * @} */ /* Exported functions --------------------------------------------------------*/ /** @addtogroup SD_Exported_Functions * @{ */ /** @addtogroup SD_Exported_Functions_Group1 * @brief Initialization and de-initialization functions * * @verbatim * ============================================================================== ##### Initialization and de-initialization functions ##### #####============================================================================== #####[..] #####This section provides functions allowing to initialize/de-initialize the SD #####card device to be ready for use. ##### ##### #####@endverbatim * @{ */ /** * @brief Initializes the SD card according to the specified parameters in the * SD_HandleTypeDef and create the associated handle. * @param hsd SD handle * @param SDCardInfo HAL_SD_CardInfoTypedef structure for SD card information * @retval HAL SD error state */ HAL_SD_ErrorTypedef HAL_SD_Init( SD_HandleTypeDef * hsd, HAL_SD_CardInfoTypedef * SDCardInfo ) { __IO HAL_SD_ErrorTypedef errorstate = SD_OK; SD_InitTypeDef tmpinit; /* Initialize the low level hardware (MSP) */ HAL_SD_MspInit( hsd ); /* Default SDIO peripheral configuration for SD card initialization */ tmpinit.ClockEdge = SDIO_CLOCK_EDGE_RISING; tmpinit.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; tmpinit.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; #if ( BUS_4BITS != 0 ) { tmpinit.BusWide = SDIO_BUS_WIDE_4B; } #else { tmpinit.BusWide = SDIO_BUS_WIDE_1B; } #endif tmpinit.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; tmpinit.ClockDiv = SDIO_INIT_CLK_DIV; /* Initialize SDIO peripheral interface with default configuration */ SDIO_Init( hsd->Instance, tmpinit ); /* Identify card operating voltage */ errorstate = SD_PowerON( hsd ); if( errorstate != SD_OK ) { return errorstate; } /* Initialize the present SDIO card(s) and put them in idle state */ errorstate = SD_Initialize_Cards( hsd ); if( errorstate != SD_OK ) { return errorstate; } /* Read CSD/CID MSD registers */ errorstate = HAL_SD_Get_CardInfo( hsd, SDCardInfo ); if( errorstate == SD_OK ) { /* Select the Card */ errorstate = SD_Select_Deselect( hsd, ( uint32_t ) ( ( ( uint32_t ) SDCardInfo->RCA ) << 16 ) ); } /* Configure SDIO peripheral interface */ SDIO_Init( hsd->Instance, hsd->Init ); return errorstate; } /** * @brief De-Initializes the SD card. * @param hsd SD handle * @retval HAL status */ HAL_StatusTypeDef HAL_SD_DeInit( SD_HandleTypeDef * hsd ) { /* Set SD power state to off */ SD_PowerOFF( hsd ); /* De-Initialize the MSP layer */ HAL_SD_MspDeInit( hsd ); return HAL_OK; } /** * @brief Initializes the SD MSP. * @param hsd SD handle * @retval None */ __weak void HAL_SD_MspInit( SD_HandleTypeDef * hsd ) { /* NOTE : This function Should not be modified, when the callback is needed, * the HAL_SD_MspInit could be implemented in the user file */ } /** * @brief De-Initialize SD MSP. * @param hsd SD handle * @retval None */ __weak void HAL_SD_MspDeInit( SD_HandleTypeDef * hsd ) { /* NOTE : This function Should not be modified, when the callback is needed, * the HAL_SD_MspDeInit could be implemented in the user file */ } /** * @} */ /** @addtogroup SD_Exported_Functions_Group2 * @brief Data transfer functions * * @verbatim * ============================================================================== ##### IO operation functions ##### #####============================================================================== #####[..] #####This subsection provides a set of functions allowing to manage the data #####transfer from/to SD card. ##### #####@endverbatim * @{ */ /** * @brief Reads block(s) from a specified address in a card. The Data transfer * is managed by polling mode. * @param hsd SD handle * @param pReadBuffer pointer to the buffer that will contain the received data * @param ReadAddr Address from where data is to be read * @param BlockSize SD card Data block size * @note BlockSize must be 512 bytes. * @param NumberOfBlocks Number of SD blocks to read * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_ReadBlocks( SD_HandleTypeDef * hsd, uint32_t * pReadBuffer, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; SDIO_DataInitTypeDef sdmmc_datainitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t count = 0, * tempbuff = ( uint32_t * ) pReadBuffer; __IO uint32_t * pulFIFO = &( hsd->Instance->FIFO ); /* Initialize data control register */ hsd->Instance->DCTRL = 0; if( hsd->CardType == HIGH_CAPACITY_SD_CARD ) { BlockSize = 512; ReadAddr /= 512; } /* Set Block Size for Card */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) BlockSize; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SET_BLOCKLEN ); if( errorstate != SD_OK ) { return errorstate; } /* Configure the SD DPSM (Data Path State Machine) */ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT; sdmmc_datainitstructure.DataLength = NumberOfBlocks * BlockSize; sdmmc_datainitstructure.DataBlockSize = DATA_BLOCK_SIZE; sdmmc_datainitstructure.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; sdmmc_datainitstructure.TransferMode = SDIO_TRANSFER_MODE_BLOCK; sdmmc_datainitstructure.DPSM = SDIO_DPSM_ENABLE; SDIO_DataConfig( hsd->Instance, &sdmmc_datainitstructure ); if( NumberOfBlocks > 1 ) { /* Send CMD18 READ_MULT_BLOCK with argument data address */ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_READ_MULT_BLOCK; } else { /* Send CMD17 READ_SINGLE_BLOCK */ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_READ_SINGLE_BLOCK; } sdmmc_cmdinitstructure.Argument = ( uint32_t ) ReadAddr; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, sdmmc_cmdinitstructure.CmdIndex ); if( errorstate != SD_OK ) { return errorstate; } /* Read block(s) in polling mode */ if( NumberOfBlocks > 1 ) { /* Poll on SDIO flags */ while( !__HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR ) ) { if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXFIFOHF ) ) { /* Read data from SDIO Rx FIFO */ tempbuff[ 0 ] = *( pulFIFO ); tempbuff[ 1 ] = *( pulFIFO ); tempbuff[ 2 ] = *( pulFIFO ); tempbuff[ 3 ] = *( pulFIFO ); tempbuff[ 4 ] = *( pulFIFO ); tempbuff[ 5 ] = *( pulFIFO ); tempbuff[ 6 ] = *( pulFIFO ); tempbuff[ 7 ] = *( pulFIFO ); tempbuff += 8; } } } else { /* In case of single block transfer, no need of stop transfer at all */ while( !__HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR ) ) { if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXFIFOHF ) ) { /* Read data from SDIO Rx FIFO */ tempbuff[ 0 ] = *( pulFIFO ); tempbuff[ 1 ] = *( pulFIFO ); tempbuff[ 2 ] = *( pulFIFO ); tempbuff[ 3 ] = *( pulFIFO ); tempbuff[ 4 ] = *( pulFIFO ); tempbuff[ 5 ] = *( pulFIFO ); tempbuff[ 6 ] = *( pulFIFO ); tempbuff[ 7 ] = *( pulFIFO ); tempbuff += 8; } } } /* Send stop transmission command in case of multiblock read */ if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DATAEND ) && ( NumberOfBlocks > 1 ) ) { if( ( hsd->CardType == STD_CAPACITY_SD_CARD_V1_1 ) || \ ( hsd->CardType == STD_CAPACITY_SD_CARD_V2_0 ) || \ ( hsd->CardType == HIGH_CAPACITY_SD_CARD ) ) { /* Send stop transmission command */ errorstate = HAL_SD_StopTransfer( hsd ); } } /* Get error state */ if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DTIMEOUT ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DTIMEOUT ); errorstate = SD_DATA_TIMEOUT; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DCRCFAIL ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DCRCFAIL ); errorstate = SD_DATA_CRC_FAIL; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXOVERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_RXOVERR ); errorstate = SD_RX_OVERRUN; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_STBITERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_STBITERR ); errorstate = SD_START_BIT_ERR; return errorstate; } else { /* No error flag set */ } count = SD_DATATIMEOUT; /* Empty FIFO if there is still any data */ while( ( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXDAVL ) ) && ( count > 0 ) ) { *tempbuff = SDIO_ReadFIFO( hsd->Instance ); tempbuff++; count--; } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); return errorstate; } /** * @brief Allows to write block(s) to a specified address in a card. The Data * transfer is managed by polling mode. * @param hsd SD handle * @param pWriteBuffer pointer to the buffer that will contain the data to transmit * @param WriteAddr Address from where data is to be written * @param BlockSize SD card Data block size * @note BlockSize must be 512 bytes. * @param NumberOfBlocks Number of SD blocks to write * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_WriteBlocks( SD_HandleTypeDef * hsd, uint32_t * pWriteBuffer, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; /*SDIO_DataInitTypeDef sdmmc_datainitstructure; */ HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t totalnumberofbytes, bytesRemaining; uint32_t tmpreg; uint32_t last_sta; uint32_t * tempbuff = ( uint32_t * ) pWriteBuffer; uint8_t cardstate = 0; __IO uint32_t * pulFIFO = &( hsd->Instance->FIFO ); uint32_t ulEndFags; uint32_t ulHasHWFlowControl; /* Initialize data control register */ hsd->Instance->DCTRL = 0; if( hsd->CardType == HIGH_CAPACITY_SD_CARD ) { BlockSize = 512; WriteAddr /= 512; } /* Set Block Size for Card */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) BlockSize; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SET_BLOCKLEN ); if( errorstate != SD_OK ) { return errorstate; } if( NumberOfBlocks > 1 ) { /* Send CMD25 WRITE_MULT_BLOCK with argument data address */ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_WRITE_MULT_BLOCK; /* Test for DATAEND : Data end (data counter, SDID count) is zero) */ ulEndFags = SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR; } else { /* Send CMD24 WRITE_SINGLE_BLOCK */ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK; /* Test for DBCKEND : Data Block Sent/Received (CRC check passed) */ ulEndFags = SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR; } ulEndFags |= SDIO_FLAG_TXUNDERR; sdmmc_cmdinitstructure.Argument = ( uint32_t ) WriteAddr; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, sdmmc_cmdinitstructure.CmdIndex ); if( errorstate != SD_OK ) { return errorstate; } ulHasHWFlowControl = ( hsd->Instance->CLKCR & SDIO_HARDWARE_FLOW_CONTROL_ENABLE ) != 0; /* Set total number of bytes to write */ totalnumberofbytes = NumberOfBlocks * BlockSize; bytesRemaining = 4 * ( ( totalnumberofbytes + 3 ) / 4 ); /* Configure the SD DPSM (Data Path State Machine) */ /* * sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT; * sdmmc_datainitstructure.DataLength = NumberOfBlocks * BlockSize; * sdmmc_datainitstructure.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; * sdmmc_datainitstructure.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; * sdmmc_datainitstructure.TransferMode = SDIO_TRANSFER_MODE_BLOCK; * sdmmc_datainitstructure.DPSM = SDIO_DPSM_ENABLE; * SDIO_DataConfig(hsd->Instance, &sdmmc_datainitstructure); */ /* Set the SDIO Data Timeout value */ hsd->Instance->DTIMER = SD_DATATIMEOUT; /* Set the SDIO DataLength value */ hsd->Instance->DLEN = NumberOfBlocks * BlockSize; tmpreg = hsd->Instance->DCTRL & ~( DCTRL_CLEAR_MASK ); /* Set the SDIO data configuration parameters */ tmpreg |= ( uint32_t ) ( SDIO_DATABLOCK_SIZE_512B | SDIO_TRANSFER_DIR_TO_CARD | SDIO_TRANSFER_MODE_BLOCK | SDIO_DCTRL_DTEN ); /* Write to SDIO DCTRL */ hsd->Instance->DCTRL = tmpreg; for( ; ; ) { last_sta = hsd->Instance->STA; if( ( last_sta & ( SDIO_FLAG_TXFIFOHE | SDIO_FLAG_TXFIFOE ) ) != 0 ) { /* SDIO_FLAG_TXFIFOHE: Transmit FIFO Half Empty * May write 32 bytes. */ if( bytesRemaining < 32 ) { /* Write data to SDIO Tx FIFO */ while( bytesRemaining > 0 ) { *pulFIFO = *( tempbuff++ ); bytesRemaining -= 4; } } else { /* Write data to SDIO Tx FIFO */ *pulFIFO = tempbuff[ 0 ]; *pulFIFO = tempbuff[ 1 ]; *pulFIFO = tempbuff[ 2 ]; *pulFIFO = tempbuff[ 3 ]; *pulFIFO = tempbuff[ 4 ]; *pulFIFO = tempbuff[ 5 ]; *pulFIFO = tempbuff[ 6 ]; *pulFIFO = tempbuff[ 7 ]; tempbuff += 8; bytesRemaining -= 32; if( ( last_sta & SDIO_FLAG_TXFIFOE ) != 0 ) { /* SDIO_FLAG_TXFIFOE: Transmit FIFO empty * May write 24 or 32 extra bytes, depending on * ulHasHWFlowControl. */ *pulFIFO = tempbuff[ 0 ]; *pulFIFO = tempbuff[ 1 ]; *pulFIFO = tempbuff[ 2 ]; *pulFIFO = tempbuff[ 3 ]; *pulFIFO = tempbuff[ 4 ]; *pulFIFO = tempbuff[ 5 ]; if( ulHasHWFlowControl != 0 ) { tempbuff += 6; bytesRemaining -= 24; } else { *pulFIFO = tempbuff[ 6 ]; *pulFIFO = tempbuff[ 7 ]; tempbuff += 8; bytesRemaining -= 32; } } } } if( ( last_sta & ulEndFags ) != 0 ) { break; } } if( ( ( last_sta & SDIO_FLAG_TXUNDERR ) != 0 ) || ( bytesRemaining != 0 ) ) { FF_PRINTF( "TX underflow %lu < %lu\n", bytesRemaining, totalnumberofbytes ); } /* Send stop transmission command in case of multiblock write */ if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DATAEND ) && ( NumberOfBlocks > 1 ) ) { if( ( hsd->CardType == STD_CAPACITY_SD_CARD_V1_1 ) || ( hsd->CardType == STD_CAPACITY_SD_CARD_V2_0 ) || \ ( hsd->CardType == HIGH_CAPACITY_SD_CARD ) ) { /* Send stop transmission command */ errorstate = HAL_SD_StopTransfer( hsd ); } } /* Get error state */ if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DTIMEOUT ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DTIMEOUT ); errorstate = SD_DATA_TIMEOUT; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DCRCFAIL ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DCRCFAIL ); errorstate = SD_DATA_CRC_FAIL; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_TXUNDERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_TXUNDERR ); errorstate = SD_TX_UNDERRUN; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_STBITERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_STBITERR ); errorstate = SD_START_BIT_ERR; return errorstate; } else { /* No error flag set */ } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); /* Wait till the card is in programming state */ do { errorstate = SD_IsCardProgramming( hsd, &cardstate ); } while( ( errorstate == SD_OK ) && ( ( cardstate == SD_CARD_PROGRAMMING ) || ( cardstate == SD_CARD_RECEIVING ) ) ); return errorstate; } /** * @brief Reads block(s) from a specified address in a card. The Data transfer * is managed by DMA mode. * @note This API should be followed by the function HAL_SD_CheckReadOperation() * to check the completion of the read process * @param hsd SD handle * @param pReadBuffer Pointer to the buffer that will contain the received data * @param ReadAddr Address from where data is to be read * @param BlockSize SD card Data block size * @note BlockSize must be 512 bytes. * @param NumberOfBlocks Number of blocks to read. * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_ReadBlocks_DMA( SD_HandleTypeDef * hsd, uint32_t * pReadBuffer, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumberOfBlocks ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; SDIO_DataInitTypeDef sdmmc_datainitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; /* Initialize data control register */ hsd->Instance->DCTRL = 0; /* Initialize handle flags */ hsd->SdTransferCplt = 0; hsd->DmaTransferCplt = 0; hsd->SdTransferErr = SD_OK; if( hsd->EventSetupFunction != NULL ) { hsd->EventSetupFunction( hsd ); } /* Initialize SD Read operation */ if( NumberOfBlocks > 1 ) { hsd->SdOperation = SD_READ_MULTIPLE_BLOCK; } else { hsd->SdOperation = SD_READ_SINGLE_BLOCK; } /* Enable transfer interrupts */ __HAL_SD_SDIO_ENABLE_IT( hsd, ( SDIO_IT_DCRCFAIL | \ SDIO_IT_DTIMEOUT | \ SDIO_IT_DATAEND | \ SDIO_IT_RXOVERR | \ SDIO_IT_STBITERR ) ); /* Enable SDIO DMA transfer */ __HAL_SD_SDIO_DMA_ENABLE(); /* Configure DMA user callbacks */ hsd->hdmarx->XferCpltCallback = SD_DMA_RxCplt; hsd->hdmarx->XferErrorCallback = SD_DMA_RxError; /* Enable the DMA Stream */ HAL_DMA_Start_IT( hsd->hdmarx, ( uint32_t ) &hsd->Instance->FIFO, ( uint32_t ) pReadBuffer, ( uint32_t ) ( BlockSize * NumberOfBlocks ) / 4 ); if( hsd->CardType == HIGH_CAPACITY_SD_CARD ) { BlockSize = 512; ReadAddr /= 512; } /* Set Block Size for Card */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) BlockSize; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SET_BLOCKLEN ); if( errorstate != SD_OK ) { return errorstate; } /* Configure the SD DPSM (Data Path State Machine) */ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT; sdmmc_datainitstructure.DataLength = BlockSize * NumberOfBlocks; sdmmc_datainitstructure.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; sdmmc_datainitstructure.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; sdmmc_datainitstructure.TransferMode = SDIO_TRANSFER_MODE_BLOCK; sdmmc_datainitstructure.DPSM = SDIO_DPSM_ENABLE; SDIO_DataConfig( hsd->Instance, &sdmmc_datainitstructure ); /* Check number of blocks command */ if( NumberOfBlocks > 1 ) { /* Send CMD18 READ_MULT_BLOCK with argument data address */ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_READ_MULT_BLOCK; } else { /* Send CMD17 READ_SINGLE_BLOCK */ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_READ_SINGLE_BLOCK; } sdmmc_cmdinitstructure.Argument = ( uint32_t ) ReadAddr; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, sdmmc_cmdinitstructure.CmdIndex ); /* Update the SD transfer error in SD handle */ hsd->SdTransferErr = errorstate; return errorstate; } /** * @brief Writes block(s) to a specified address in a card. The Data transfer * is managed by DMA mode. * @note This API should be followed by the function HAL_SD_CheckWriteOperation() * to check the completion of the write process (by SD current status polling). * @param hsd SD handle * @param pWriteBuffer pointer to the buffer that will contain the data to transmit * @param WriteAddr Address from where data is to be read * @param BlockSize the SD card Data block size * @note BlockSize must be 512 bytes. * @param NumberOfBlocks Number of blocks to write * @retval SD Card error state */ void FF_Sleep( uint32_t ulTime_ms ); const char * pcShowEnds( uint8_t * apBuf, uint32_t aSecCount ); int lUDPLoggingPrintf( const char * pcFormatString, ... ); HAL_SD_ErrorTypedef HAL_SD_WriteBlocks_DMA( SD_HandleTypeDef * hsd, uint32_t * pWriteBuffer, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumberOfBlocks ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; /*SDIO_DataInitTypeDef sdmmc_datainitstructure;*/ HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t tmpreg; /* Initialize data control register */ hsd->Instance->DCTRL = 0; /* Initialize handle flags */ hsd->SdTransferCplt = 0; hsd->DmaTransferCplt = 0; hsd->SdTransferErr = SD_OK; if( hsd->EventSetupFunction != NULL ) { hsd->EventSetupFunction( hsd ); } hsd->Instance->DLEN = NumberOfBlocks * BlockSize; /* Initialize SD Write operation */ if( NumberOfBlocks > 1 ) { hsd->SdOperation = SD_WRITE_MULTIPLE_BLOCK; } else { hsd->SdOperation = SD_WRITE_SINGLE_BLOCK; } /* Enable transfer interrupts */ __HAL_SD_SDIO_ENABLE_IT( hsd, ( SDIO_IT_DCRCFAIL | \ SDIO_IT_DTIMEOUT | \ SDIO_IT_DATAEND | \ SDIO_IT_TXUNDERR | \ SDIO_IT_STBITERR ) ); /* Configure DMA user callbacks */ hsd->hdmatx->XferCpltCallback = SD_DMA_TxCplt; hsd->hdmatx->XferErrorCallback = SD_DMA_TxError; /* Enable the DMA Stream */ HAL_DMA_Start_IT( hsd->hdmatx, ( uint32_t ) pWriteBuffer, ( uint32_t ) &hsd->Instance->FIFO, ( uint32_t ) ( BlockSize * NumberOfBlocks ) / 4 ); /* Enable SDIO DMA transfer */ __HAL_SD_SDIO_DMA_ENABLE(); if( hsd->CardType == HIGH_CAPACITY_SD_CARD ) { BlockSize = 512; WriteAddr /= 512; } /* Set Block Size for Card */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) BlockSize; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SET_BLOCKLEN ); if( errorstate != SD_OK ) { return errorstate; } /* Check number of blocks command */ if( NumberOfBlocks <= 1 ) { /* Send CMD24 WRITE_SINGLE_BLOCK */ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_WRITE_SINGLE_BLOCK; } else { /* Send CMD25 WRITE_MULT_BLOCK with argument data address */ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_WRITE_MULT_BLOCK; } sdmmc_cmdinitstructure.Argument = ( uint32_t ) WriteAddr; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, sdmmc_cmdinitstructure.CmdIndex ); if( errorstate != SD_OK ) { return errorstate; } /* Configure the SD DPSM (Data Path State Machine) */ /* * sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT; * sdmmc_datainitstructure.DataLength = BlockSize * NumberOfBlocks; * sdmmc_datainitstructure.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; * sdmmc_datainitstructure.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; * sdmmc_datainitstructure.TransferMode = SDIO_TRANSFER_MODE_BLOCK; * sdmmc_datainitstructure.DPSM = SDIO_DPSM_ENABLE; * SDIO_DataConfig(hsd->Instance, &sdmmc_datainitstructure); */ /* Set the SDIO Data Timeout value */ hsd->Instance->DTIMER = SD_DATATIMEOUT; /* / * Set the SDIO DataLength value * / */ /* hsd->Instance->DLEN = NumberOfBlocks * BlockSize; */ tmpreg = hsd->Instance->DCTRL & ~( DCTRL_CLEAR_MASK ); /* Set the SDIO data configuration parameters */ tmpreg |= ( uint32_t ) ( SDIO_DATABLOCK_SIZE_512B | SDIO_TRANSFER_DIR_TO_CARD | SDIO_TRANSFER_MODE_BLOCK | SDIO_DCTRL_DTEN ); /* Write to SDIO DCTRL */ hsd->Instance->DCTRL = tmpreg; hsd->SdTransferErr = errorstate; return errorstate; } /** * @brief This function waits until the SD DMA data read transfer is finished. * This API should be called after HAL_SD_ReadBlocks_DMA() function * to insure that all data sent by the card is already transferred by the * DMA controller. * @param hsd SD handle * @param Timeout Timeout duration * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_CheckReadOperation( SD_HandleTypeDef * hsd, uint32_t ulMaxTime ) { HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t ulStarted = xTaskGetTickCount(); BaseType_t xHadTimeout = pdFALSE; /* Wait for DMA/SD transfer end or SD error variables to be in SD handle */ while( 1 ) { HAL_SD_ErrorTypedef xError; if( ( hsd->DmaTransferCplt != 0 ) && ( hsd->SdTransferCplt != 0 ) ) { HAL_DMA_Abort( hsd->hdmarx ); break; } xError = ( HAL_SD_ErrorTypedef ) hsd->SdTransferErr; if( xError != SD_OK ) { break; } if( hsd->EventWaitFunction != NULL ) { if( hsd->EventWaitFunction( ( void * ) hsd ) != 0 ) { FF_PRINTF( "EventWaitFunction: RX timeout!\n" ); /* A timeout is reached. */ break; } } else { if( ( xTaskGetTickCount() - ulStarted ) >= ulMaxTime ) { xHadTimeout = pdTRUE; break; } } } ulStarted = xTaskGetTickCount(); /* Wait until the Rx transfer is no longer active */ while( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXACT ) ) { if( ( xTaskGetTickCount() - ulStarted ) >= ulMaxTime ) { xHadTimeout = pdTRUE; break; } } /* Send stop command in multiblock read */ if( hsd->SdOperation == SD_READ_MULTIPLE_BLOCK ) { errorstate = HAL_SD_StopTransfer( hsd ); } if( ( xHadTimeout != pdFALSE ) && ( errorstate == SD_OK ) ) { errorstate = SD_DATA_TIMEOUT; } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); /* Return error state */ if( hsd->SdTransferErr != SD_OK ) { return ( HAL_SD_ErrorTypedef ) hsd->SdTransferErr; } return errorstate; } /** * @brief This function waits until the SD DMA data write transfer is finished. * This API should be called after HAL_SD_WriteBlocks_DMA() function * to insure that all data sent by the card is already transferred by the * DMA controller. * @param hsd SD handle * @param Timeout Timeout duration * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_CheckWriteOperation( SD_HandleTypeDef * hsd, uint32_t ulMaxTime ) { HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t ulStarted = 0; BaseType_t xHadTimeout = pdFALSE; /* Wait for DMA/SD transfer end or SD error variables to be in SD handle */ while( 1 ) { HAL_SD_ErrorTypedef xError; if( ( hsd->DmaTransferCplt != 0 ) && ( hsd->SdTransferCplt != 0 ) ) { HAL_DMA_Abort( hsd->hdmatx ); break; } xError = ( HAL_SD_ErrorTypedef ) hsd->SdTransferErr; if( xError != SD_OK ) { break; } if( hsd->EventWaitFunction != NULL ) { if( hsd->EventWaitFunction( ( void * ) hsd ) != 0 ) { FF_PRINTF( "EventWaitFunction: TX timeout!\n" ); /* A timeout is reached. */ break; } } else { if( ( xTaskGetTickCount() - ulStarted ) >= ulMaxTime ) { xHadTimeout = pdTRUE; break; } } } ulStarted = xTaskGetTickCount(); /* Wait until the Tx transfer is no longer active */ /* while( ( hsd->Instance->STA & SDIO_FLAG_TXACT ) != 0 ) { } */ while( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_TXACT ) ) { if( ( xTaskGetTickCount() - ulStarted ) >= ulMaxTime ) { xHadTimeout = pdTRUE; break; } } /* Send stop command in multiblock write */ if( hsd->SdOperation == SD_WRITE_MULTIPLE_BLOCK ) { errorstate = HAL_SD_StopTransfer( hsd ); } if( ( xHadTimeout != pdFALSE ) && ( errorstate == SD_OK ) ) { errorstate = SD_DATA_TIMEOUT; } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); /* Return error state */ if( hsd->SdTransferErr != SD_OK ) { errorstate = ( HAL_SD_ErrorTypedef ) ( hsd->SdTransferErr ); } else { /* Wait until write is complete */ while( HAL_SD_GetStatus( hsd ) != SD_TRANSFER_OK ) { } } return errorstate; } /** * @brief Erases the specified memory area of the given SD card. * @param hsd SD handle * @param startaddr Start byte address * @param endaddr End byte address * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_Erase( SD_HandleTypeDef * hsd, uint64_t startaddr, uint64_t endaddr ) { HAL_SD_ErrorTypedef errorstate = SD_OK; SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; uint32_t delay = 0; __IO uint32_t maxdelay = 0; uint8_t cardstate = 0; /* Check if the card command class supports erase command */ if( ( ( hsd->CSD[ 1 ] >> 20 ) & SD_CCCC_ERASE ) == 0 ) { errorstate = SD_REQUEST_NOT_APPLICABLE; return errorstate; } /* Get max delay value */ maxdelay = 120000 / ( ( ( hsd->Instance->CLKCR ) & 0xFF ) + 2 ); if( ( SDIO_GetResponse( SDIO_RESP1 ) & SD_CARD_LOCKED ) == SD_CARD_LOCKED ) { errorstate = SD_LOCK_UNLOCK_FAILED; return errorstate; } /* Get start and end block for high capacity cards */ if( hsd->CardType == HIGH_CAPACITY_SD_CARD ) { startaddr /= 512; endaddr /= 512; } /* According to sd-card spec 1.0 ERASE_GROUP_START (CMD32) and erase_group_end(CMD33) */ if( ( hsd->CardType == STD_CAPACITY_SD_CARD_V1_1 ) || ( hsd->CardType == STD_CAPACITY_SD_CARD_V2_0 ) || \ ( hsd->CardType == HIGH_CAPACITY_SD_CARD ) ) { /* Send CMD32 SD_ERASE_GRP_START with argument as addr */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) startaddr; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SD_ERASE_GRP_START; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SD_ERASE_GRP_START ); if( errorstate != SD_OK ) { return errorstate; } /* Send CMD33 SD_ERASE_GRP_END with argument as addr */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) endaddr; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SD_ERASE_GRP_END; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SD_ERASE_GRP_END ); if( errorstate != SD_OK ) { return errorstate; } } /* Send CMD38 ERASE */ sdmmc_cmdinitstructure.Argument = 0; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_ERASE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_ERASE ); if( errorstate != SD_OK ) { return errorstate; } for( ; delay < maxdelay; delay++ ) { } /* Wait until the card is in programming state */ errorstate = SD_IsCardProgramming( hsd, &cardstate ); delay = SD_DATATIMEOUT; while( ( delay > 0 ) && ( errorstate == SD_OK ) && ( ( cardstate == SD_CARD_PROGRAMMING ) || ( cardstate == SD_CARD_RECEIVING ) ) ) { errorstate = SD_IsCardProgramming( hsd, &cardstate ); delay--; } return errorstate; } /** * @brief This function handles SD card interrupt request. * @param hsd SD handle * @retval None */ void HAL_SD_IRQHandler( SD_HandleTypeDef * hsd ) { /* Check for SDIO interrupt flags */ if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_IT_DATAEND ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_IT_DATAEND ); /* SD transfer is complete */ hsd->SdTransferCplt = 1; /* No transfer error */ hsd->SdTransferErr = SD_OK; HAL_SD_XferCpltCallback( hsd ); } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_IT_DCRCFAIL ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DCRCFAIL ); hsd->SdTransferErr = SD_DATA_CRC_FAIL; HAL_SD_XferErrorCallback( hsd ); } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_IT_DTIMEOUT ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DTIMEOUT ); hsd->SdTransferErr = SD_DATA_TIMEOUT; HAL_SD_XferErrorCallback( hsd ); } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_IT_RXOVERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_RXOVERR ); hsd->SdTransferErr = SD_RX_OVERRUN; HAL_SD_XferErrorCallback( hsd ); } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_IT_TXUNDERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_TXUNDERR ); hsd->SdTransferErr = SD_TX_UNDERRUN; HAL_SD_XferErrorCallback( hsd ); } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_IT_STBITERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_STBITERR ); hsd->SdTransferErr = SD_START_BIT_ERR; HAL_SD_XferErrorCallback( hsd ); } else { /* No error flag set */ } /* Disable all SDIO peripheral interrupt sources */ __HAL_SD_SDIO_DISABLE_IT( hsd, SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | \ SDIO_IT_TXFIFOHE | SDIO_IT_RXFIFOHF | SDIO_IT_TXUNDERR | \ SDIO_IT_RXOVERR | SDIO_IT_STBITERR ); } /** * @brief SD end of transfer callback. * @param hsd SD handle * @retval None */ __weak void HAL_SD_XferCpltCallback( SD_HandleTypeDef * hsd ) { /* NOTE : This function Should not be modified, when the callback is needed, * the HAL_SD_XferCpltCallback could be implemented in the user file */ } /** * @brief SD Transfer Error callback. * @param hsd SD handle * @retval None */ __weak void HAL_SD_XferErrorCallback( SD_HandleTypeDef * hsd ) { /* NOTE : This function Should not be modified, when the callback is needed, * the HAL_SD_XferErrorCallback could be implemented in the user file */ } /** * @brief SD Transfer complete Rx callback in non blocking mode. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ __weak void HAL_SD_DMA_RxCpltCallback( DMA_HandleTypeDef * hdma ) { /* NOTE : This function Should not be modified, when the callback is needed, * the HAL_SD_DMA_RxCpltCallback could be implemented in the user file */ } /** * @brief SD DMA transfer complete Rx error callback. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ __weak void HAL_SD_DMA_RxErrorCallback( DMA_HandleTypeDef * hdma ) { /* NOTE : This function Should not be modified, when the callback is needed, * the HAL_SD_DMA_RxErrorCallback could be implemented in the user file */ } /** * @brief SD Transfer complete Tx callback in non blocking mode. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ __weak void HAL_SD_DMA_TxCpltCallback( DMA_HandleTypeDef * hdma ) { /* NOTE : This function Should not be modified, when the callback is needed, * the HAL_SD_DMA_TxCpltCallback could be implemented in the user file */ } /** * @brief SD DMA transfer complete error Tx callback. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ __weak void HAL_SD_DMA_TxErrorCallback( DMA_HandleTypeDef * hdma ) { /* NOTE : This function Should not be modified, when the callback is needed, * the HAL_SD_DMA_TxErrorCallback could be implemented in the user file */ } /** * @} */ /** @addtogroup SD_Exported_Functions_Group3 * @brief management functions * * @verbatim * ============================================================================== ##### Peripheral Control functions ##### #####============================================================================== #####[..] #####This subsection provides a set of functions allowing to control the SD card #####operations. ##### #####@endverbatim * @{ */ /** * @brief Returns information about specific card. * @param hsd SD handle * @param pCardInfo Pointer to a HAL_SD_CardInfoTypedef structure that * contains all SD cardinformation * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_Get_CardInfo( SD_HandleTypeDef * hsd, HAL_SD_CardInfoTypedef * pCardInfo ) { HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t tmp = 0; pCardInfo->CardType = ( uint8_t ) ( hsd->CardType ); pCardInfo->RCA = ( uint16_t ) ( hsd->RCA ); /* Byte 0 */ tmp = ( hsd->CSD[ 0 ] & 0xFF000000 ) >> 24; pCardInfo->SD_csd.CSDStruct = ( uint8_t ) ( ( tmp & 0xC0 ) >> 6 ); pCardInfo->SD_csd.SysSpecVersion = ( uint8_t ) ( ( tmp & 0x3C ) >> 2 ); pCardInfo->SD_csd.Reserved1 = tmp & 0x03; /* Byte 1 */ tmp = ( hsd->CSD[ 0 ] & 0x00FF0000 ) >> 16; pCardInfo->SD_csd.TAAC = ( uint8_t ) tmp; /* Byte 2 */ tmp = ( hsd->CSD[ 0 ] & 0x0000FF00 ) >> 8; pCardInfo->SD_csd.NSAC = ( uint8_t ) tmp; /* Byte 3 */ tmp = hsd->CSD[ 0 ] & 0x000000FF; pCardInfo->SD_csd.MaxBusClkFrec = ( uint8_t ) tmp; /* Byte 4 */ tmp = ( hsd->CSD[ 1 ] & 0xFF000000 ) >> 24; pCardInfo->SD_csd.CardComdClasses = ( uint16_t ) ( tmp << 4 ); /* Byte 5 */ tmp = ( hsd->CSD[ 1 ] & 0x00FF0000 ) >> 16; pCardInfo->SD_csd.CardComdClasses |= ( uint16_t ) ( ( tmp & 0xF0 ) >> 4 ); pCardInfo->SD_csd.RdBlockLen = ( uint8_t ) ( tmp & 0x0F ); /* Byte 6 */ tmp = ( hsd->CSD[ 1 ] & 0x0000FF00 ) >> 8; pCardInfo->SD_csd.PartBlockRead = ( uint8_t ) ( ( tmp & 0x80 ) >> 7 ); pCardInfo->SD_csd.WrBlockMisalign = ( uint8_t ) ( ( tmp & 0x40 ) >> 6 ); pCardInfo->SD_csd.RdBlockMisalign = ( uint8_t ) ( ( tmp & 0x20 ) >> 5 ); pCardInfo->SD_csd.DSRImpl = ( uint8_t ) ( ( tmp & 0x10 ) >> 4 ); pCardInfo->SD_csd.Reserved2 = 0; /*!< Reserved */ if( ( hsd->CardType == STD_CAPACITY_SD_CARD_V1_1 ) || ( hsd->CardType == STD_CAPACITY_SD_CARD_V2_0 ) ) { pCardInfo->SD_csd.DeviceSize = ( tmp & 0x03 ) << 10; /* Byte 7 */ tmp = ( uint8_t ) ( hsd->CSD[ 1 ] & 0x000000FF ); pCardInfo->SD_csd.DeviceSize |= ( tmp ) << 2; /* Byte 8 */ tmp = ( uint8_t ) ( ( hsd->CSD[ 2 ] & 0xFF000000 ) >> 24 ); pCardInfo->SD_csd.DeviceSize |= ( tmp & 0xC0 ) >> 6; pCardInfo->SD_csd.MaxRdCurrentVDDMin = ( tmp & 0x38 ) >> 3; pCardInfo->SD_csd.MaxRdCurrentVDDMax = ( tmp & 0x07 ); /* Byte 9 */ tmp = ( uint8_t ) ( ( hsd->CSD[ 2 ] & 0x00FF0000 ) >> 16 ); pCardInfo->SD_csd.MaxWrCurrentVDDMin = ( tmp & 0xE0 ) >> 5; pCardInfo->SD_csd.MaxWrCurrentVDDMax = ( tmp & 0x1C ) >> 2; pCardInfo->SD_csd.DeviceSizeMul = ( tmp & 0x03 ) << 1; /* Byte 10 */ tmp = ( uint8_t ) ( ( hsd->CSD[ 2 ] & 0x0000FF00 ) >> 8 ); pCardInfo->SD_csd.DeviceSizeMul |= ( tmp & 0x80 ) >> 7; pCardInfo->CardCapacity = ( pCardInfo->SD_csd.DeviceSize + 1 ); pCardInfo->CardCapacity *= ( 1 << ( pCardInfo->SD_csd.DeviceSizeMul + 2 ) ); pCardInfo->CardBlockSize = 1 << ( pCardInfo->SD_csd.RdBlockLen ); pCardInfo->CardCapacity *= pCardInfo->CardBlockSize; } else if( hsd->CardType == HIGH_CAPACITY_SD_CARD ) { /* Byte 7 */ tmp = ( uint8_t ) ( hsd->CSD[ 1 ] & 0x000000FF ); pCardInfo->SD_csd.DeviceSize = ( tmp & 0x3F ) << 16; /* Byte 8 */ tmp = ( uint8_t ) ( ( hsd->CSD[ 2 ] & 0xFF000000 ) >> 24 ); pCardInfo->SD_csd.DeviceSize |= ( tmp << 8 ); /* Byte 9 */ tmp = ( uint8_t ) ( ( hsd->CSD[ 2 ] & 0x00FF0000 ) >> 16 ); pCardInfo->SD_csd.DeviceSize |= ( tmp ); /* Byte 10 */ tmp = ( uint8_t ) ( ( hsd->CSD[ 2 ] & 0x0000FF00 ) >> 8 ); pCardInfo->CardCapacity = ( uint64_t ) ( ( ( ( uint64_t ) pCardInfo->SD_csd.DeviceSize + 1 ) ) * 512 * 1024 ); pCardInfo->CardBlockSize = 512; } else { /* Not supported card type */ errorstate = SD_ERROR; } pCardInfo->SD_csd.EraseGrSize = ( tmp & 0x40 ) >> 6; pCardInfo->SD_csd.EraseGrMul = ( tmp & 0x3F ) << 1; /* Byte 11 */ tmp = ( uint8_t ) ( hsd->CSD[ 2 ] & 0x000000FF ); pCardInfo->SD_csd.EraseGrMul |= ( tmp & 0x80 ) >> 7; pCardInfo->SD_csd.WrProtectGrSize = ( tmp & 0x7F ); /* Byte 12 */ tmp = ( uint8_t ) ( ( hsd->CSD[ 3 ] & 0xFF000000 ) >> 24 ); pCardInfo->SD_csd.WrProtectGrEnable = ( tmp & 0x80 ) >> 7; pCardInfo->SD_csd.ManDeflECC = ( tmp & 0x60 ) >> 5; pCardInfo->SD_csd.WrSpeedFact = ( tmp & 0x1C ) >> 2; pCardInfo->SD_csd.MaxWrBlockLen = ( tmp & 0x03 ) << 2; /* Byte 13 */ tmp = ( uint8_t ) ( ( hsd->CSD[ 3 ] & 0x00FF0000 ) >> 16 ); pCardInfo->SD_csd.MaxWrBlockLen |= ( tmp & 0xC0 ) >> 6; pCardInfo->SD_csd.WriteBlockPaPartial = ( tmp & 0x20 ) >> 5; pCardInfo->SD_csd.Reserved3 = 0; pCardInfo->SD_csd.ContentProtectAppli = ( tmp & 0x01 ); /* Byte 14 */ tmp = ( uint8_t ) ( ( hsd->CSD[ 3 ] & 0x0000FF00 ) >> 8 ); pCardInfo->SD_csd.FileFormatGrouop = ( tmp & 0x80 ) >> 7; pCardInfo->SD_csd.CopyFlag = ( tmp & 0x40 ) >> 6; pCardInfo->SD_csd.PermWrProtect = ( tmp & 0x20 ) >> 5; pCardInfo->SD_csd.TempWrProtect = ( tmp & 0x10 ) >> 4; pCardInfo->SD_csd.FileFormat = ( tmp & 0x0C ) >> 2; pCardInfo->SD_csd.ECC = ( tmp & 0x03 ); /* Byte 15 */ tmp = ( uint8_t ) ( hsd->CSD[ 3 ] & 0x000000FF ); pCardInfo->SD_csd.CSD_CRC = ( tmp & 0xFE ) >> 1; pCardInfo->SD_csd.Reserved4 = 1; /* Byte 0 */ tmp = ( uint8_t ) ( ( hsd->CID[ 0 ] & 0xFF000000 ) >> 24 ); pCardInfo->SD_cid.ManufacturerID = tmp; /* Byte 1 */ tmp = ( uint8_t ) ( ( hsd->CID[ 0 ] & 0x00FF0000 ) >> 16 ); pCardInfo->SD_cid.OEM_AppliID = tmp << 8; /* Byte 2 */ tmp = ( uint8_t ) ( ( hsd->CID[ 0 ] & 0x000000FF00 ) >> 8 ); pCardInfo->SD_cid.OEM_AppliID |= tmp; /* Byte 3 */ tmp = ( uint8_t ) ( hsd->CID[ 0 ] & 0x000000FF ); pCardInfo->SD_cid.ProdName1 = tmp << 24; /* Byte 4 */ tmp = ( uint8_t ) ( ( hsd->CID[ 1 ] & 0xFF000000 ) >> 24 ); pCardInfo->SD_cid.ProdName1 |= tmp << 16; /* Byte 5 */ tmp = ( uint8_t ) ( ( hsd->CID[ 1 ] & 0x00FF0000 ) >> 16 ); pCardInfo->SD_cid.ProdName1 |= tmp << 8; /* Byte 6 */ tmp = ( uint8_t ) ( ( hsd->CID[ 1 ] & 0x0000FF00 ) >> 8 ); pCardInfo->SD_cid.ProdName1 |= tmp; /* Byte 7 */ tmp = ( uint8_t ) ( hsd->CID[ 1 ] & 0x000000FF ); pCardInfo->SD_cid.ProdName2 = tmp; /* Byte 8 */ tmp = ( uint8_t ) ( ( hsd->CID[ 2 ] & 0xFF000000 ) >> 24 ); pCardInfo->SD_cid.ProdRev = tmp; /* Byte 9 */ tmp = ( uint8_t ) ( ( hsd->CID[ 2 ] & 0x00FF0000 ) >> 16 ); pCardInfo->SD_cid.ProdSN = tmp << 24; /* Byte 10 */ tmp = ( uint8_t ) ( ( hsd->CID[ 2 ] & 0x0000FF00 ) >> 8 ); pCardInfo->SD_cid.ProdSN |= tmp << 16; /* Byte 11 */ tmp = ( uint8_t ) ( hsd->CID[ 2 ] & 0x000000FF ); pCardInfo->SD_cid.ProdSN |= tmp << 8; /* Byte 12 */ tmp = ( uint8_t ) ( ( hsd->CID[ 3 ] & 0xFF000000 ) >> 24 ); pCardInfo->SD_cid.ProdSN |= tmp; /* Byte 13 */ tmp = ( uint8_t ) ( ( hsd->CID[ 3 ] & 0x00FF0000 ) >> 16 ); pCardInfo->SD_cid.Reserved1 |= ( tmp & 0xF0 ) >> 4; pCardInfo->SD_cid.ManufactDate = ( tmp & 0x0F ) << 8; /* Byte 14 */ tmp = ( uint8_t ) ( ( hsd->CID[ 3 ] & 0x0000FF00 ) >> 8 ); pCardInfo->SD_cid.ManufactDate |= tmp; /* Byte 15 */ tmp = ( uint8_t ) ( hsd->CID[ 3 ] & 0x000000FF ); pCardInfo->SD_cid.CID_CRC = ( tmp & 0xFE ) >> 1; pCardInfo->SD_cid.Reserved2 = 1; return errorstate; } /** * @brief Enables wide bus operation for the requested card if supported by * card. * @param hsd SD handle * @param WideMode Specifies the SD card wide bus mode * This parameter can be one of the following values: * @arg SDIO_BUS_WIDE_8B: 8-bit data transfer (Only for MMC) * @arg SDIO_BUS_WIDE_4B: 4-bit data transfer * @arg SDIO_BUS_WIDE_1B: 1-bit data transfer * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_WideBusOperation_Config( SD_HandleTypeDef * hsd, uint32_t WideMode ) { HAL_SD_ErrorTypedef errorstate = SD_OK; SDIO_InitTypeDef tmpinit; /* MMC Card does not support this feature */ if( hsd->CardType == MULTIMEDIA_CARD ) { errorstate = SD_UNSUPPORTED_FEATURE; return errorstate; } else if( ( hsd->CardType == STD_CAPACITY_SD_CARD_V1_1 ) || ( hsd->CardType == STD_CAPACITY_SD_CARD_V2_0 ) || \ ( hsd->CardType == HIGH_CAPACITY_SD_CARD ) ) { if( WideMode == SDIO_BUS_WIDE_8B ) { errorstate = SD_UNSUPPORTED_FEATURE; } else if( WideMode == SDIO_BUS_WIDE_4B ) { errorstate = SD_WideBus_Enable( hsd ); } else if( WideMode == SDIO_BUS_WIDE_1B ) { errorstate = SD_WideBus_Disable( hsd ); } else { /* WideMode is not a valid argument*/ errorstate = SD_INVALID_PARAMETER; } if( errorstate == SD_OK ) { /* Configure the SDIO peripheral */ tmpinit.ClockEdge = hsd->Init.ClockEdge; tmpinit.ClockBypass = hsd->Init.ClockBypass; tmpinit.ClockPowerSave = hsd->Init.ClockPowerSave; tmpinit.BusWide = WideMode; tmpinit.HardwareFlowControl = hsd->Init.HardwareFlowControl; tmpinit.ClockDiv = hsd->Init.ClockDiv; SDIO_Init( hsd->Instance, tmpinit ); } } return errorstate; } /** * @brief Aborts an ongoing data transfer. * @param hsd SD handle * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_StopTransfer( SD_HandleTypeDef * hsd ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; /* Send CMD12 STOP_TRANSMISSION */ sdmmc_cmdinitstructure.Argument = 0; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_STOP_TRANSMISSION; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_STOP_TRANSMISSION ); return errorstate; } /** * @brief Switches the SD card to High Speed mode. * This API must be used after "Transfer State" * @note This operation should be followed by the configuration * of PLL to have SDIOCK clock between 67 and 75 MHz * @param hsd SD handle * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_HighSpeed( SD_HandleTypeDef * hsd ) { HAL_SD_ErrorTypedef errorstate = SD_OK; SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; SDIO_DataInitTypeDef sdmmc_datainitstructure; uint8_t SD_hs[ 64 ] = { 0 }; uint32_t SD_scr[ 2 ] = { 0, 0 }; uint32_t SD_SPEC = 0; uint32_t count = 0, * tempbuff = ( uint32_t * ) SD_hs; /* Initialize the Data control register */ hsd->Instance->DCTRL = 0; /* Get SCR Register */ errorstate = SD_FindSCR( hsd, SD_scr ); if( errorstate != SD_OK ) { return errorstate; } /* Test the Version supported by the card*/ SD_SPEC = ( SD_scr[ 1 ] & 0x01000000 ) | ( SD_scr[ 1 ] & 0x02000000 ); if( SD_SPEC != SD_ALLZERO ) { /* Set Block Size for Card */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) 64; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SET_BLOCKLEN ); if( errorstate != SD_OK ) { return errorstate; } /* Configure the SD DPSM (Data Path State Machine) */ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT; sdmmc_datainitstructure.DataLength = 64; sdmmc_datainitstructure.DataBlockSize = SDIO_DATABLOCK_SIZE_64B; sdmmc_datainitstructure.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; sdmmc_datainitstructure.TransferMode = SDIO_TRANSFER_MODE_BLOCK; sdmmc_datainitstructure.DPSM = SDIO_DPSM_ENABLE; SDIO_DataConfig( hsd->Instance, &sdmmc_datainitstructure ); /* Send CMD6 switch mode */ sdmmc_cmdinitstructure.Argument = 0x80FFFF01; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_HS_SWITCH; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_HS_SWITCH ); if( errorstate != SD_OK ) { return errorstate; } while( !__HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR ) ) { if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXFIFOHF ) ) { for( count = 0; count < 8; count++ ) { *( tempbuff + count ) = SDIO_ReadFIFO( hsd->Instance ); } tempbuff += 8; } } if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DTIMEOUT ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DTIMEOUT ); errorstate = SD_DATA_TIMEOUT; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DCRCFAIL ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DCRCFAIL ); errorstate = SD_DATA_CRC_FAIL; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXOVERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_RXOVERR ); errorstate = SD_RX_OVERRUN; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_STBITERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_STBITERR ); errorstate = SD_START_BIT_ERR; return errorstate; } else { /* No error flag set */ } count = SD_DATATIMEOUT; while( ( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXDAVL ) ) && ( count > 0 ) ) { *tempbuff = SDIO_ReadFIFO( hsd->Instance ); tempbuff++; count--; } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); /* Test if the switch mode HS is ok */ if( ( SD_hs[ 13 ] & 2 ) != 2 ) { errorstate = SD_UNSUPPORTED_FEATURE; } } return errorstate; } /** * @} */ /** @addtogroup SD_Exported_Functions_Group4 * @brief Peripheral State functions * * @verbatim * ============================================================================== ##### Peripheral State functions ##### #####============================================================================== #####[..] #####This subsection permits to get in runtime the status of the peripheral #####and the data flow. ##### #####@endverbatim * @{ */ /** * @brief Returns the current SD card's status. * @param hsd SD handle * @param pSDstatus Pointer to the buffer that will contain the SD card status * SD Status register) * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_SendSDStatus( SD_HandleTypeDef * hsd, uint32_t * pSDstatus ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; SDIO_DataInitTypeDef sdmmc_datainitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t count = 0; /* Check SD response */ if( ( SDIO_GetResponse( SDIO_RESP1 ) & SD_CARD_LOCKED ) == SD_CARD_LOCKED ) { errorstate = SD_LOCK_UNLOCK_FAILED; return errorstate; } /* Set block size for card if it is not equal to current block size for card */ sdmmc_cmdinitstructure.Argument = 64; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SET_BLOCKLEN ); if( errorstate != SD_OK ) { return errorstate; } /* Send CMD55 */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) ( hsd->RCA << 16 ); sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_APP_CMD ); if( errorstate != SD_OK ) { return errorstate; } /* Configure the SD DPSM (Data Path State Machine) */ sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT; sdmmc_datainitstructure.DataLength = 64; sdmmc_datainitstructure.DataBlockSize = SDIO_DATABLOCK_SIZE_64B; sdmmc_datainitstructure.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; sdmmc_datainitstructure.TransferMode = SDIO_TRANSFER_MODE_BLOCK; sdmmc_datainitstructure.DPSM = SDIO_DPSM_ENABLE; SDIO_DataConfig( hsd->Instance, &sdmmc_datainitstructure ); /* Send ACMD13 (SD_APP_STATUS) with argument as card's RCA */ sdmmc_cmdinitstructure.Argument = 0; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SD_APP_STATUS; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SD_APP_STATUS ); if( errorstate != SD_OK ) { return errorstate; } /* Get status data */ while( !__HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR ) ) { if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXFIFOHF ) ) { for( count = 0; count < 8; count++ ) { *( pSDstatus + count ) = SDIO_ReadFIFO( hsd->Instance ); } pSDstatus += 8; } } if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DTIMEOUT ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DTIMEOUT ); errorstate = SD_DATA_TIMEOUT; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DCRCFAIL ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DCRCFAIL ); errorstate = SD_DATA_CRC_FAIL; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXOVERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_RXOVERR ); errorstate = SD_RX_OVERRUN; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_STBITERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_STBITERR ); errorstate = SD_START_BIT_ERR; return errorstate; } else { /* No error flag set */ } count = SD_DATATIMEOUT; while( ( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXDAVL ) ) && ( count > 0 ) ) { *pSDstatus = SDIO_ReadFIFO( hsd->Instance ); pSDstatus++; count--; } /* Clear all the static status flags*/ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); return errorstate; } /** * @brief Gets the current sd card data status. * @param hsd SD handle * @retval Data Transfer state */ HAL_SD_TransferStateTypedef HAL_SD_GetStatus( SD_HandleTypeDef * hsd ) { HAL_SD_CardStateTypedef cardstate = SD_CARD_TRANSFER; /* Get SD card state */ cardstate = SD_GetState( hsd ); /* Find SD status according to card state*/ if( cardstate == SD_CARD_TRANSFER ) { return SD_TRANSFER_OK; } else if( cardstate == SD_CARD_ERROR ) { return SD_TRANSFER_ERROR; } else { return SD_TRANSFER_BUSY; } } /** * @brief Gets the SD card status. * @param hsd SD handle * @param pCardStatus Pointer to the HAL_SD_CardStatusTypedef structure that * will contain the SD card status information * @retval SD Card error state */ HAL_SD_ErrorTypedef HAL_SD_GetCardStatus( SD_HandleTypeDef * hsd, HAL_SD_CardStatusTypedef * pCardStatus ) { HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t tmp = 0; uint32_t sd_status[ 16 ]; errorstate = HAL_SD_SendSDStatus( hsd, sd_status ); if( errorstate != SD_OK ) { return errorstate; } /* Byte 0 */ tmp = ( sd_status[ 0 ] & 0xC0 ) >> 6; pCardStatus->DAT_BUS_WIDTH = ( uint8_t ) tmp; /* Byte 0 */ tmp = ( sd_status[ 0 ] & 0x20 ) >> 5; pCardStatus->SECURED_MODE = ( uint8_t ) tmp; /* Byte 2 */ tmp = ( sd_status[ 2 ] & 0xFF ); pCardStatus->SD_CARD_TYPE = ( uint8_t ) ( tmp << 8 ); /* Byte 3 */ tmp = ( sd_status[ 3 ] & 0xFF ); pCardStatus->SD_CARD_TYPE |= ( uint8_t ) tmp; /* Byte 4 */ tmp = ( sd_status[ 4 ] & 0xFF ); pCardStatus->SIZE_OF_PROTECTED_AREA = ( uint8_t ) ( tmp << 24 ); /* Byte 5 */ tmp = ( sd_status[ 5 ] & 0xFF ); pCardStatus->SIZE_OF_PROTECTED_AREA |= ( uint8_t ) ( tmp << 16 ); /* Byte 6 */ tmp = ( sd_status[ 6 ] & 0xFF ); pCardStatus->SIZE_OF_PROTECTED_AREA |= ( uint8_t ) ( tmp << 8 ); /* Byte 7 */ tmp = ( sd_status[ 7 ] & 0xFF ); pCardStatus->SIZE_OF_PROTECTED_AREA |= ( uint8_t ) tmp; /* Byte 8 */ tmp = ( sd_status[ 8 ] & 0xFF ); pCardStatus->SPEED_CLASS = ( uint8_t ) tmp; /* Byte 9 */ tmp = ( sd_status[ 9 ] & 0xFF ); pCardStatus->PERFORMANCE_MOVE = ( uint8_t ) tmp; /* Byte 10 */ tmp = ( sd_status[ 10 ] & 0xF0 ) >> 4; pCardStatus->AU_SIZE = ( uint8_t ) tmp; /* Byte 11 */ tmp = ( sd_status[ 11 ] & 0xFF ); pCardStatus->ERASE_SIZE = ( uint8_t ) ( tmp << 8 ); /* Byte 12 */ tmp = ( sd_status[ 12 ] & 0xFF ); pCardStatus->ERASE_SIZE |= ( uint8_t ) tmp; /* Byte 13 */ tmp = ( sd_status[ 13 ] & 0xFC ) >> 2; pCardStatus->ERASE_TIMEOUT = ( uint8_t ) tmp; /* Byte 13 */ tmp = ( sd_status[ 13 ] & 0x3 ); pCardStatus->ERASE_OFFSET = ( uint8_t ) tmp; return errorstate; } /** * @} */ /** * @} */ /* Private function ----------------------------------------------------------*/ /** @addtogroup SD_Private_Functions * @{ */ /** * @brief SD DMA transfer complete Rx callback. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ static void SD_DMA_RxCplt( DMA_HandleTypeDef * hdma ) { SD_HandleTypeDef * hsd = ( SD_HandleTypeDef * ) ( ( DMA_HandleTypeDef * ) hdma )->Parent; /* DMA transfer is complete */ hsd->DmaTransferCplt = 1; /* / * Wait until SD transfer is complete * / */ /* while(hsd->SdTransferCplt == 0) */ /* { */ /* } */ /* */ /* / * Disable the DMA channel * / */ /* HAL_DMA_Abort(hdma); */ /* Transfer complete user callback */ HAL_SD_DMA_RxCpltCallback( hsd->hdmarx ); } /** * @brief SD DMA transfer Error Rx callback. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ static void SD_DMA_RxError( DMA_HandleTypeDef * hdma ) { SD_HandleTypeDef * hsd = ( SD_HandleTypeDef * ) ( ( DMA_HandleTypeDef * ) hdma )->Parent; /* Transfer complete user callback */ HAL_SD_DMA_RxErrorCallback( hsd->hdmarx ); } /** * @brief SD DMA transfer complete Tx callback. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ static void SD_DMA_TxCplt( DMA_HandleTypeDef * hdma ) { SD_HandleTypeDef * hsd = ( SD_HandleTypeDef * ) ( ( DMA_HandleTypeDef * ) hdma )->Parent; /* DMA transfer is complete */ hsd->DmaTransferCplt = 1; /* / * Wait until SD transfer is complete * / */ /* while(hsd->SdTransferCplt == 0) */ /* { */ /* } */ /* */ /* / * Disable the DMA channel * / */ /* HAL_DMA_Abort(hdma); */ /* Transfer complete user callback */ HAL_SD_DMA_TxCpltCallback( hsd->hdmatx ); } /** * @brief SD DMA transfer Error Tx callback. * @param hdma pointer to a DMA_HandleTypeDef structure that contains * the configuration information for the specified DMA module. * @retval None */ static void SD_DMA_TxError( DMA_HandleTypeDef * hdma ) { SD_HandleTypeDef * hsd = ( SD_HandleTypeDef * ) ( ( DMA_HandleTypeDef * ) hdma )->Parent; /* Transfer complete user callback */ HAL_SD_DMA_TxErrorCallback( hsd->hdmatx ); } /** * @brief Returns the SD current state. * @param hsd SD handle * @retval SD card current state */ static HAL_SD_CardStateTypedef SD_GetState( SD_HandleTypeDef * hsd ) { uint32_t resp1 = 0; if( SD_SendStatus( hsd, &resp1 ) != SD_OK ) { return SD_CARD_ERROR; } else { return ( HAL_SD_CardStateTypedef ) ( ( resp1 >> 9 ) & 0x0F ); } } /** * @brief Initializes all cards or single card as the case may be Card(s) come * into standby state. * @param hsd SD handle * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_Initialize_Cards( SD_HandleTypeDef * hsd ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; uint16_t sd_rca = 1; if( SDIO_GetPowerState( hsd->Instance ) == 0 ) /* Power off */ { errorstate = SD_REQUEST_NOT_APPLICABLE; return errorstate; } if( hsd->CardType != SECURE_DIGITAL_IO_CARD ) { /* Send CMD2 ALL_SEND_CID */ sdmmc_cmdinitstructure.Argument = 0; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_ALL_SEND_CID; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_LONG; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp2Error( hsd ); if( errorstate != SD_OK ) { return errorstate; } /* Get Card identification number data */ hsd->CID[ 0 ] = SDIO_GetResponse( SDIO_RESP1 ); hsd->CID[ 1 ] = SDIO_GetResponse( SDIO_RESP2 ); hsd->CID[ 2 ] = SDIO_GetResponse( SDIO_RESP3 ); hsd->CID[ 3 ] = SDIO_GetResponse( SDIO_RESP4 ); } if( ( hsd->CardType == STD_CAPACITY_SD_CARD_V1_1 ) || ( hsd->CardType == STD_CAPACITY_SD_CARD_V2_0 ) || \ ( hsd->CardType == SECURE_DIGITAL_IO_COMBO_CARD ) || ( hsd->CardType == HIGH_CAPACITY_SD_CARD ) ) { /* Send CMD3 SET_REL_ADDR with argument 0 */ /* SD Card publishes its RCA. */ sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_REL_ADDR; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp6Error( hsd, SD_CMD_SET_REL_ADDR, &sd_rca ); if( errorstate != SD_OK ) { return errorstate; } } if( hsd->CardType != SECURE_DIGITAL_IO_CARD ) { /* Get the SD card RCA */ hsd->RCA = sd_rca; /* Send CMD9 SEND_CSD with argument as card's RCA */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) ( hsd->RCA << 16 ); sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SEND_CSD; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_LONG; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp2Error( hsd ); if( errorstate != SD_OK ) { return errorstate; } /* Get Card Specific Data */ hsd->CSD[ 0 ] = SDIO_GetResponse( SDIO_RESP1 ); hsd->CSD[ 1 ] = SDIO_GetResponse( SDIO_RESP2 ); hsd->CSD[ 2 ] = SDIO_GetResponse( SDIO_RESP3 ); hsd->CSD[ 3 ] = SDIO_GetResponse( SDIO_RESP4 ); } /* All cards are initialized */ return errorstate; } /** * @brief Selects of Deselects the corresponding card. * @param hsd SD handle * @param addr Address of the card to be selected * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_Select_Deselect( SD_HandleTypeDef * hsd, uint64_t addr ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; /* Send CMD7 SDIO_SEL_DESEL_CARD */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) addr; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SEL_DESEL_CARD; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SEL_DESEL_CARD ); return errorstate; } /** * @brief Enquires cards about their operating voltage and configures clock * controls and stores SD information that will be needed in future * in the SD handle. * @param hsd SD handle * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_PowerON( SD_HandleTypeDef * hsd ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; __IO HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t response = 0, count = 0, validvoltage = 0; uint32_t sdtype = SD_STD_CAPACITY; /* Power ON Sequence -------------------------------------------------------*/ /* Disable SDIO Clock */ __HAL_SD_SDIO_DISABLE(); /* Set Power State to ON */ SDIO_PowerState_ON( hsd->Instance ); /* 1ms: required power up waiting time before starting the SD initialization * sequence */ HAL_Delay( 1 ); /* Enable SDIO Clock */ __HAL_SD_SDIO_ENABLE(); /* CMD0: GO_IDLE_STATE -----------------------------------------------------*/ /* No CMD response required */ sdmmc_cmdinitstructure.Argument = 0; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_GO_IDLE_STATE; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_NO; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdError( hsd ); if( errorstate != SD_OK ) { /* CMD Response Timeout (wait for CMDSENT flag) */ return errorstate; } /* CMD8: SEND_IF_COND ------------------------------------------------------*/ /* Send CMD8 to verify SD card interface operating condition */ /* Argument: - [31:12]: Reserved (shall be set to '0') * - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V) * - [7:0]: Check Pattern (recommended 0xAA) */ /* CMD Response: R7 */ sdmmc_cmdinitstructure.Argument = SD_CHECK_PATTERN; sdmmc_cmdinitstructure.CmdIndex = SD_SDIO_SEND_IF_COND; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp7Error( hsd ); if( errorstate == SD_OK ) { /* SD Card 2.0 */ FF_PRINTF( "It's a 2.0 card, check SDHC\n" ); hsd->CardType = STD_CAPACITY_SD_CARD_V2_0; sdtype = SD_HIGH_CAPACITY; } /* Send CMD55 */ sdmmc_cmdinitstructure.Argument = 0; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_APP_CMD ); /* If errorstate is Command Timeout, it is a MMC card */ /* If errorstate is SD_OK it is a SD card: SD card 2.0 (voltage range mismatch) * or SD card 1.x */ if( errorstate == SD_OK ) { /* SD CARD */ /* Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */ while( ( !validvoltage ) && ( count < SD_MAX_VOLT_TRIAL ) ) { /* SEND CMD55 APP_CMD with RCA as 0 */ sdmmc_cmdinitstructure.Argument = 0; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_APP_CMD ); if( errorstate != SD_OK ) { return errorstate; } /* Send CMD41 */ sdmmc_cmdinitstructure.Argument = SD_VOLTAGE_WINDOW_SD | sdtype; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SD_APP_OP_COND; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp3Error( hsd ); if( errorstate != SD_OK ) { return errorstate; } /* Get command response */ response = SDIO_GetResponse( SDIO_RESP1 ); /* Get operating voltage*/ validvoltage = ( ( ( response >> 31 ) == 1 ) ? 1 : 0 ); if( ( count == 0 ) || ( validvoltage != 0 ) ) { FF_PRINTF( "Voltage resp: %08x\n", ( unsigned ) response ); } count++; } if( count >= SD_MAX_VOLT_TRIAL ) { FF_PRINTF( "Can not agree on Voltage\n" ); errorstate = SD_INVALID_VOLTRANGE; return errorstate; } if( ( response & SD_HIGH_CAPACITY ) == SD_HIGH_CAPACITY ) /* (response &= SD_HIGH_CAPACITY) */ { hsd->CardType = HIGH_CAPACITY_SD_CARD; } } /* else MMC Card */ return errorstate; } /** * @brief Turns the SDIO output signals off. * @param hsd SD handle * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_PowerOFF( SD_HandleTypeDef * hsd ) { HAL_SD_ErrorTypedef errorstate = SD_OK; /* Set Power State to OFF */ SDIO_PowerState_OFF( hsd->Instance ); return errorstate; } /** * @brief Returns the current card's status. * @param hsd SD handle * @param pCardStatus pointer to the buffer that will contain the SD card * status (Card Status register) * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_SendStatus( SD_HandleTypeDef * hsd, uint32_t * pCardStatus ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; if( pCardStatus == NULL ) { errorstate = SD_INVALID_PARAMETER; return errorstate; } /* Send Status command */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) ( hsd->RCA << 16 ); sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SEND_STATUS; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SEND_STATUS ); if( errorstate != SD_OK ) { return errorstate; } /* Get SD card status */ *pCardStatus = SDIO_GetResponse( SDIO_RESP1 ); return errorstate; } /** * @brief Checks for error conditions for CMD0. * @param hsd SD handle * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_CmdError( SD_HandleTypeDef * hsd ) { HAL_SD_ErrorTypedef errorstate = SD_OK; /* uint32_t timeout; */ uint32_t tmp; uint32_t ulStarted = xTaskGetTickCount(); uint32_t ulMaxTime = 200; BaseType_t xHadTimeout = pdFALSE; /* timeout = SDIO_CMD0TIMEOUT; */ tmp = __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CMDSENT ); while( tmp == 0 ) { tmp = __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CMDSENT ); if( ( xTaskGetTickCount() - ulStarted ) >= ulMaxTime ) { xHadTimeout = pdTRUE; break; } } if( xHadTimeout != pdFALSE ) { errorstate = SD_CMD_RSP_TIMEOUT; return errorstate; } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); return errorstate; } /** * @brief Checks for error conditions for R7 response. * @param hsd SD handle * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_CmdResp7Error( SD_HandleTypeDef * hsd ) { HAL_SD_ErrorTypedef errorstate = SD_ERROR; /* uint32_t timeout = SDIO_CMD0TIMEOUT; */ uint32_t tmp; uint32_t ulStarted = xTaskGetTickCount(); uint32_t ulMaxTime = 200; BaseType_t xHadTimeout = pdFALSE; tmp = __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT ); while( tmp == 0 ) { tmp = __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT ); if( ( xTaskGetTickCount() - ulStarted ) >= ulMaxTime ) { xHadTimeout = pdTRUE; break; } } tmp = __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CTIMEOUT ); if( ( xHadTimeout != pdFALSE ) || tmp ) { /* Card is not V2.0 compliant or card does not support the set voltage range */ errorstate = SD_CMD_RSP_TIMEOUT; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CTIMEOUT ); return errorstate; } if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CMDREND ) ) { /* Card is SD V2.0 compliant */ errorstate = SD_OK; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CMDREND ); return errorstate; } return errorstate; } /** * @brief Checks for error conditions for R1 response. * @param hsd SD handle * @param SD_CMD The sent command index * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_CmdResp1Error( SD_HandleTypeDef * hsd, uint8_t SD_CMD ) { HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t response_r1; uint32_t remaining_loops = 168000 * 50; while( !__HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT ) ) { if( ( --remaining_loops ) == 0 ) { FF_PRINTF( "SD_CmdResp1Error: times out\n" ); break; } } if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CTIMEOUT ) ) { errorstate = SD_CMD_RSP_TIMEOUT; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CTIMEOUT ); return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL ) ) { errorstate = SD_CMD_CRC_FAIL; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CCRCFAIL ); return errorstate; } /* Check response received is of desired command */ if( SDIO_GetCommandResponse( hsd->Instance ) != SD_CMD ) { FF_PRINTF( "RESPCMD[1] = %08x cmd = %02x\n", ( unsigned ) hsd->Instance->RESPCMD, SD_CMD ); errorstate = SD_ILLEGAL_CMD; return errorstate; } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); /* We have received response, retrieve it for analysis */ response_r1 = SDIO_GetResponse( SDIO_RESP1 ); if( ( response_r1 & SD_OCR_ERRORBITS ) == SD_ALLZERO ) { return errorstate; } if( ( response_r1 & SD_OCR_ADDR_OUT_OF_RANGE ) == SD_OCR_ADDR_OUT_OF_RANGE ) { return( SD_ADDR_OUT_OF_RANGE ); } if( ( response_r1 & SD_OCR_ADDR_MISALIGNED ) == SD_OCR_ADDR_MISALIGNED ) { return( SD_ADDR_MISALIGNED ); } if( ( response_r1 & SD_OCR_BLOCK_LEN_ERR ) == SD_OCR_BLOCK_LEN_ERR ) { return( SD_BLOCK_LEN_ERR ); } if( ( response_r1 & SD_OCR_ERASE_SEQ_ERR ) == SD_OCR_ERASE_SEQ_ERR ) { return( SD_ERASE_SEQ_ERR ); } if( ( response_r1 & SD_OCR_BAD_ERASE_PARAM ) == SD_OCR_BAD_ERASE_PARAM ) { return( SD_BAD_ERASE_PARAM ); } if( ( response_r1 & SD_OCR_WRITE_PROT_VIOLATION ) == SD_OCR_WRITE_PROT_VIOLATION ) { return( SD_WRITE_PROT_VIOLATION ); } if( ( response_r1 & SD_OCR_LOCK_UNLOCK_FAILED ) == SD_OCR_LOCK_UNLOCK_FAILED ) { return( SD_LOCK_UNLOCK_FAILED ); } if( ( response_r1 & SD_OCR_COM_CRC_FAILED ) == SD_OCR_COM_CRC_FAILED ) { return( SD_COM_CRC_FAILED ); } if( ( response_r1 & SD_OCR_ILLEGAL_CMD ) == SD_OCR_ILLEGAL_CMD ) { return( SD_ILLEGAL_CMD ); } if( ( response_r1 & SD_OCR_CARD_ECC_FAILED ) == SD_OCR_CARD_ECC_FAILED ) { return( SD_CARD_ECC_FAILED ); } if( ( response_r1 & SD_OCR_CC_ERROR ) == SD_OCR_CC_ERROR ) { return( SD_CC_ERROR ); } if( ( response_r1 & SD_OCR_GENERAL_UNKNOWN_ERROR ) == SD_OCR_GENERAL_UNKNOWN_ERROR ) { return( SD_GENERAL_UNKNOWN_ERROR ); } if( ( response_r1 & SD_OCR_STREAM_READ_UNDERRUN ) == SD_OCR_STREAM_READ_UNDERRUN ) { return( SD_STREAM_READ_UNDERRUN ); } if( ( response_r1 & SD_OCR_STREAM_WRITE_OVERRUN ) == SD_OCR_STREAM_WRITE_OVERRUN ) { return( SD_STREAM_WRITE_OVERRUN ); } if( ( response_r1 & SD_OCR_CID_CSD_OVERWRITE ) == SD_OCR_CID_CSD_OVERWRITE ) { return( SD_CID_CSD_OVERWRITE ); } if( ( response_r1 & SD_OCR_WP_ERASE_SKIP ) == SD_OCR_WP_ERASE_SKIP ) { return( SD_WP_ERASE_SKIP ); } if( ( response_r1 & SD_OCR_CARD_ECC_DISABLED ) == SD_OCR_CARD_ECC_DISABLED ) { return( SD_CARD_ECC_DISABLED ); } if( ( response_r1 & SD_OCR_ERASE_RESET ) == SD_OCR_ERASE_RESET ) { return( SD_ERASE_RESET ); } if( ( response_r1 & SD_OCR_AKE_SEQ_ERROR ) == SD_OCR_AKE_SEQ_ERROR ) { return( SD_AKE_SEQ_ERROR ); } return errorstate; } /** * @brief Checks for error conditions for R3 (OCR) response. * @param hsd SD handle * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_CmdResp3Error( SD_HandleTypeDef * hsd ) { HAL_SD_ErrorTypedef errorstate = SD_OK; while( !__HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT ) ) { } if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CTIMEOUT ) ) { errorstate = SD_CMD_RSP_TIMEOUT; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CTIMEOUT ); return errorstate; } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); return errorstate; } /** * @brief Checks for error conditions for R2 (CID or CSD) response. * @param hsd SD handle * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_CmdResp2Error( SD_HandleTypeDef * hsd ) { HAL_SD_ErrorTypedef errorstate = SD_OK; while( !__HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT ) ) { } if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CTIMEOUT ) ) { errorstate = SD_CMD_RSP_TIMEOUT; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CTIMEOUT ); return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL ) ) { errorstate = SD_CMD_CRC_FAIL; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CCRCFAIL ); return errorstate; } else { /* No error flag set */ } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); return errorstate; } /** * @brief Checks for error conditions for R6 (RCA) response. * @param hsd SD handle * @param SD_CMD The sent command index * @param pRCA Pointer to the variable that will contain the SD card relative * address RCA * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_CmdResp6Error( SD_HandleTypeDef * hsd, uint8_t SD_CMD, uint16_t * pRCA ) { HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t response_r1; while( !__HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT ) ) { } if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CTIMEOUT ) ) { errorstate = SD_CMD_RSP_TIMEOUT; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CTIMEOUT ); return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL ) ) { errorstate = SD_CMD_CRC_FAIL; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CCRCFAIL ); return errorstate; } else { /* No error flag set */ } /* Check response received is of desired command */ if( SDIO_GetCommandResponse( hsd->Instance ) != SD_CMD ) { FF_PRINTF( "RESPCMD[2] = %08x cmd = %02x\n", ( unsigned ) hsd->Instance->RESPCMD, SD_CMD ); errorstate = SD_ILLEGAL_CMD; return errorstate; } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); /* We have received response, retrieve it. */ response_r1 = SDIO_GetResponse( SDIO_RESP1 ); if( ( response_r1 & ( SD_R6_GENERAL_UNKNOWN_ERROR | SD_R6_ILLEGAL_CMD | SD_R6_COM_CRC_FAILED ) ) == SD_ALLZERO ) { *pRCA = ( uint16_t ) ( response_r1 >> 16 ); return errorstate; } if( ( response_r1 & SD_R6_GENERAL_UNKNOWN_ERROR ) == SD_R6_GENERAL_UNKNOWN_ERROR ) { return( SD_GENERAL_UNKNOWN_ERROR ); } if( ( response_r1 & SD_R6_ILLEGAL_CMD ) == SD_R6_ILLEGAL_CMD ) { FF_PRINTF( "response_r1 = %08x cmd = %02x\n", ( unsigned ) hsd->Instance->RESPCMD, ( unsigned ) SD_R6_ILLEGAL_CMD ); return( SD_ILLEGAL_CMD ); } if( ( response_r1 & SD_R6_COM_CRC_FAILED ) == SD_R6_COM_CRC_FAILED ) { return( SD_COM_CRC_FAILED ); } return errorstate; } /** * @brief Enables the SDIO wide bus mode. * @param hsd SD handle * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_WideBus_Enable( SD_HandleTypeDef * hsd ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t scr[ 2 ] = { 0, 0 }; if( ( SDIO_GetResponse( SDIO_RESP1 ) & SD_CARD_LOCKED ) == SD_CARD_LOCKED ) { errorstate = SD_LOCK_UNLOCK_FAILED; return errorstate; } /* Get SCR Register */ errorstate = SD_FindSCR( hsd, scr ); if( errorstate != SD_OK ) { return errorstate; } /* If requested card supports wide bus operation */ if( ( scr[ 1 ] & SD_WIDE_BUS_SUPPORT ) != SD_ALLZERO ) { /* Send CMD55 APP_CMD with argument as card's RCA.*/ sdmmc_cmdinitstructure.Argument = ( uint32_t ) ( hsd->RCA << 16 ); sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_APP_CMD ); if( errorstate != SD_OK ) { return errorstate; } /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */ sdmmc_cmdinitstructure.Argument = 2; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_SD_SET_BUSWIDTH; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_APP_SD_SET_BUSWIDTH ); if( errorstate != SD_OK ) { return errorstate; } return errorstate; } else { errorstate = SD_REQUEST_NOT_APPLICABLE; return errorstate; } } /** * @brief Disables the SDIO wide bus mode. * @param hsd SD handle * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_WideBus_Disable( SD_HandleTypeDef * hsd ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t scr[ 2 ] = { 0, 0 }; if( ( SDIO_GetResponse( SDIO_RESP1 ) & SD_CARD_LOCKED ) == SD_CARD_LOCKED ) { errorstate = SD_LOCK_UNLOCK_FAILED; return errorstate; } /* Get SCR Register */ errorstate = SD_FindSCR( hsd, scr ); if( errorstate != SD_OK ) { return errorstate; } /* If requested card supports 1 bit mode operation */ if( ( scr[ 1 ] & SD_SINGLE_BUS_SUPPORT ) != SD_ALLZERO ) { /* Send CMD55 APP_CMD with argument as card's RCA */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) ( hsd->RCA << 16 ); sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_APP_CMD ); if( errorstate != SD_OK ) { return errorstate; } /* Send ACMD6 APP_CMD with argument as 0 for single bus mode */ sdmmc_cmdinitstructure.Argument = 0; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_SD_SET_BUSWIDTH; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_APP_SD_SET_BUSWIDTH ); if( errorstate != SD_OK ) { return errorstate; } return errorstate; } else { errorstate = SD_REQUEST_NOT_APPLICABLE; return errorstate; } } /** * @brief Finds the SD card SCR register value. * @param hsd SD handle * @param pSCR pointer to the buffer that will contain the SCR value * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_FindSCR( SD_HandleTypeDef * hsd, uint32_t * pSCR ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; SDIO_DataInitTypeDef sdmmc_datainitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; uint32_t index = 0; uint32_t tempscr[ 2 ] = { 0, 0 }; /* Set Block Size To 8 Bytes */ /* Send CMD55 APP_CMD with argument as card's RCA */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) 8; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SET_BLOCKLEN; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SET_BLOCKLEN ); if( errorstate != SD_OK ) { return errorstate; } /* Send CMD55 APP_CMD with argument as card's RCA */ sdmmc_cmdinitstructure.Argument = ( uint32_t ) ( ( hsd->RCA ) << 16 ); sdmmc_cmdinitstructure.CmdIndex = SD_CMD_APP_CMD; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_APP_CMD ); if( errorstate != SD_OK ) { return errorstate; } sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT; sdmmc_datainitstructure.DataLength = 8; sdmmc_datainitstructure.DataBlockSize = SDIO_DATABLOCK_SIZE_8B; sdmmc_datainitstructure.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; sdmmc_datainitstructure.TransferMode = SDIO_TRANSFER_MODE_BLOCK; sdmmc_datainitstructure.DPSM = SDIO_DPSM_ENABLE; SDIO_DataConfig( hsd->Instance, &sdmmc_datainitstructure ); /* Send ACMD51 SD_APP_SEND_SCR with argument as 0 */ sdmmc_cmdinitstructure.Argument = 0; sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SD_APP_SEND_SCR; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); /* Check for error conditions */ errorstate = SD_CmdResp1Error( hsd, SD_CMD_SD_APP_SEND_SCR ); if( errorstate != SD_OK ) { return errorstate; } while( !__HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND | SDIO_FLAG_STBITERR ) ) { if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXDAVL ) ) { *( tempscr + index ) = SDIO_ReadFIFO( hsd->Instance ); index++; } } if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DTIMEOUT ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DTIMEOUT ); errorstate = SD_DATA_TIMEOUT; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_DCRCFAIL ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_DCRCFAIL ); errorstate = SD_DATA_CRC_FAIL; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_RXOVERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_RXOVERR ); errorstate = SD_RX_OVERRUN; return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_STBITERR ) ) { __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_STBITERR ); errorstate = SD_START_BIT_ERR; return errorstate; } else { /* No error flag set */ } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); *( pSCR + 1 ) = ( ( tempscr[ 0 ] & SD_0TO7BITS ) << 24 ) | ( ( tempscr[ 0 ] & SD_8TO15BITS ) << 8 ) | \ ( ( tempscr[ 0 ] & SD_16TO23BITS ) >> 8 ) | ( ( tempscr[ 0 ] & SD_24TO31BITS ) >> 24 ); *( pSCR ) = ( ( tempscr[ 1 ] & SD_0TO7BITS ) << 24 ) | ( ( tempscr[ 1 ] & SD_8TO15BITS ) << 8 ) | \ ( ( tempscr[ 1 ] & SD_16TO23BITS ) >> 8 ) | ( ( tempscr[ 1 ] & SD_24TO31BITS ) >> 24 ); return errorstate; } /** * @brief Checks if the SD card is in programming state. * @param hsd SD handle * @param pStatus pointer to the variable that will contain the SD card state * @retval SD Card error state */ static HAL_SD_ErrorTypedef SD_IsCardProgramming( SD_HandleTypeDef * hsd, uint8_t * pStatus ) { SDIO_CmdInitTypeDef sdmmc_cmdinitstructure; HAL_SD_ErrorTypedef errorstate = SD_OK; __IO uint32_t responseR1 = 0; sdmmc_cmdinitstructure.Argument = ( uint32_t ) ( hsd->RCA << 16 ); sdmmc_cmdinitstructure.CmdIndex = SD_CMD_SEND_STATUS; sdmmc_cmdinitstructure.Response = SDIO_RESPONSE_SHORT; sdmmc_cmdinitstructure.WaitForInterrupt = SDIO_WAIT_NO; sdmmc_cmdinitstructure.CPSM = SDIO_CPSM_ENABLE; SDIO_SendCommand( hsd->Instance, &sdmmc_cmdinitstructure ); while( !__HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT ) ) { } if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CTIMEOUT ) ) { errorstate = SD_CMD_RSP_TIMEOUT; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CTIMEOUT ); return errorstate; } else if( __HAL_SD_SDIO_GET_FLAG( hsd, SDIO_FLAG_CCRCFAIL ) ) { errorstate = SD_CMD_CRC_FAIL; __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_FLAG_CCRCFAIL ); return errorstate; } else { /* No error flag set */ } /* Check response received is of desired command */ if( ( uint32_t ) SDIO_GetCommandResponse( hsd->Instance ) != SD_CMD_SEND_STATUS ) { FF_PRINTF( "RESPCMD[3] = %08x cmd = %02x\n", ( unsigned ) hsd->Instance->RESPCMD, SD_CMD_SEND_STATUS ); errorstate = SD_ILLEGAL_CMD; return errorstate; } /* Clear all the static flags */ __HAL_SD_SDIO_CLEAR_FLAG( hsd, SDIO_STATIC_FLAGS ); /* We have received response, retrieve it for analysis */ responseR1 = SDIO_GetResponse( SDIO_RESP1 ); /* Find out card status */ *pStatus = ( uint8_t ) ( ( responseR1 >> 9 ) & 0x0000000F ); if( ( responseR1 & SD_OCR_ERRORBITS ) == SD_ALLZERO ) { return errorstate; } if( ( responseR1 & SD_OCR_ADDR_OUT_OF_RANGE ) == SD_OCR_ADDR_OUT_OF_RANGE ) { return( SD_ADDR_OUT_OF_RANGE ); } if( ( responseR1 & SD_OCR_ADDR_MISALIGNED ) == SD_OCR_ADDR_MISALIGNED ) { return( SD_ADDR_MISALIGNED ); } if( ( responseR1 & SD_OCR_BLOCK_LEN_ERR ) == SD_OCR_BLOCK_LEN_ERR ) { return( SD_BLOCK_LEN_ERR ); } if( ( responseR1 & SD_OCR_ERASE_SEQ_ERR ) == SD_OCR_ERASE_SEQ_ERR ) { return( SD_ERASE_SEQ_ERR ); } if( ( responseR1 & SD_OCR_BAD_ERASE_PARAM ) == SD_OCR_BAD_ERASE_PARAM ) { return( SD_BAD_ERASE_PARAM ); } if( ( responseR1 & SD_OCR_WRITE_PROT_VIOLATION ) == SD_OCR_WRITE_PROT_VIOLATION ) { return( SD_WRITE_PROT_VIOLATION ); } if( ( responseR1 & SD_OCR_LOCK_UNLOCK_FAILED ) == SD_OCR_LOCK_UNLOCK_FAILED ) { return( SD_LOCK_UNLOCK_FAILED ); } if( ( responseR1 & SD_OCR_COM_CRC_FAILED ) == SD_OCR_COM_CRC_FAILED ) { return( SD_COM_CRC_FAILED ); } if( ( responseR1 & SD_OCR_ILLEGAL_CMD ) == SD_OCR_ILLEGAL_CMD ) { return( SD_ILLEGAL_CMD ); } if( ( responseR1 & SD_OCR_CARD_ECC_FAILED ) == SD_OCR_CARD_ECC_FAILED ) { return( SD_CARD_ECC_FAILED ); } if( ( responseR1 & SD_OCR_CC_ERROR ) == SD_OCR_CC_ERROR ) { return( SD_CC_ERROR ); } if( ( responseR1 & SD_OCR_GENERAL_UNKNOWN_ERROR ) == SD_OCR_GENERAL_UNKNOWN_ERROR ) { return( SD_GENERAL_UNKNOWN_ERROR ); } if( ( responseR1 & SD_OCR_STREAM_READ_UNDERRUN ) == SD_OCR_STREAM_READ_UNDERRUN ) { return( SD_STREAM_READ_UNDERRUN ); } if( ( responseR1 & SD_OCR_STREAM_WRITE_OVERRUN ) == SD_OCR_STREAM_WRITE_OVERRUN ) { return( SD_STREAM_WRITE_OVERRUN ); } if( ( responseR1 & SD_OCR_CID_CSD_OVERWRITE ) == SD_OCR_CID_CSD_OVERWRITE ) { return( SD_CID_CSD_OVERWRITE ); } if( ( responseR1 & SD_OCR_WP_ERASE_SKIP ) == SD_OCR_WP_ERASE_SKIP ) { return( SD_WP_ERASE_SKIP ); } if( ( responseR1 & SD_OCR_CARD_ECC_DISABLED ) == SD_OCR_CARD_ECC_DISABLED ) { return( SD_CARD_ECC_DISABLED ); } if( ( responseR1 & SD_OCR_ERASE_RESET ) == SD_OCR_ERASE_RESET ) { return( SD_ERASE_RESET ); } if( ( responseR1 & SD_OCR_AKE_SEQ_ERROR ) == SD_OCR_AKE_SEQ_ERROR ) { return( SD_AKE_SEQ_ERROR ); } return errorstate; } /** * @} */ #endif /* HAL_SD_MODULE_ENABLED */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/