1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-16 04:45:24 +03:00

Add PG for 4Bit SDIO, fix whitespaces.

This commit is contained in:
Chris 2018-11-12 11:50:33 +00:00
parent aa8d6b3676
commit cdb4c1ef44
5 changed files with 399 additions and 352 deletions

View file

@ -269,17 +269,17 @@ void SDIO_DMA_ST6_IRQHandler(dmaChannelDescriptor_t *dma);
*/
bool SD_IsDetected(void)
{
__IO uint8_t status = SD_PRESENT;
__IO uint8_t status = SD_PRESENT;
/*!< Check GPIO to detect SD */
#ifdef SDCARD_DETECT_PIN
const IO_t sd_det = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN));
if (IORead(sd_det) != 0)
{
status = SD_NOT_PRESENT;
}
#endif
return status;
/*!< Check GPIO to detect SD */
#ifdef SDCARD_DETECT_PIN
const IO_t sd_det = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN));
if (IORead(sd_det) != 0)
{
status = SD_NOT_PRESENT;
}
#endif
return status;
}
@ -341,8 +341,11 @@ static SD_Error_t SD_CmdResponse(uint8_t SD_CMD, int8_t ResponseType)
uint32_t TimeOut;
uint32_t Flag;
if(ResponseType == -1) Flag = SDIO_STA_CMDSENT;
else Flag = SDIO_STA_CCRCFAIL | SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT;
if(ResponseType == -1) {
Flag = SDIO_STA_CMDSENT;
} else {
Flag = SDIO_STA_CCRCFAIL | SDIO_STA_CMDREND | SDIO_STA_CTIMEOUT;
}
TimeOut = SD_SOFTWARE_COMMAND_TIMEOUT;
do
@ -354,20 +357,34 @@ static SD_Error_t SD_CmdResponse(uint8_t SD_CMD, int8_t ResponseType)
if(ResponseType <= 0)
{
if(TimeOut == 0) return SD_CMD_RSP_TIMEOUT;
else return SD_OK;
if(TimeOut == 0) {
return SD_CMD_RSP_TIMEOUT;
} else {
return SD_OK;
}
}
if((SDIO->STA & SDIO_STA_CTIMEOUT) != 0) return SD_CMD_RSP_TIMEOUT;
if((SDIO->STA & SDIO_STA_CTIMEOUT) != 0) {
return SD_CMD_RSP_TIMEOUT;
}
if(ResponseType == 3)
{
if(TimeOut == 0) return SD_CMD_RSP_TIMEOUT; // Card is not V2.0 compliant or card does not support the set voltage range
else return SD_OK; // Card is SD V2.0 compliant
if(TimeOut == 0) {
return SD_CMD_RSP_TIMEOUT; // Card is not V2.0 compliant or card does not support the set voltage range
} else {
return SD_OK; // Card is SD V2.0 compliant
}
}
if((SDIO->STA & SDIO_STA_CCRCFAIL) != 0) return SD_CMD_CRC_FAIL;
if(ResponseType == 2) return SD_OK;
if((uint8_t)SDIO->RESPCMD != SD_CMD) return SD_ILLEGAL_CMD; // Check if response is of desired command
if((SDIO->STA & SDIO_STA_CCRCFAIL) != 0) {
return SD_CMD_CRC_FAIL;
}
if(ResponseType == 2) {
return SD_OK;
}
if((uint8_t)SDIO->RESPCMD != SD_CMD) {
return SD_ILLEGAL_CMD; // Check if response is of desired command
}
Response_R1 = SDIO->RESP1; // We have received response, retrieve it for analysis
@ -381,9 +398,15 @@ static SD_Error_t SD_CmdResponse(uint8_t SD_CMD, int8_t ResponseType)
{
SD_CardRCA = Response_R1;
}
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) return SD_ILLEGAL_CMD;
if((Response_R1 & SD_R6_COM_CRC_FAILED) == SD_R6_COM_CRC_FAILED) return SD_COM_CRC_FAILED;
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) {
return SD_ILLEGAL_CMD;
}
if((Response_R1 & SD_R6_COM_CRC_FAILED) == SD_R6_COM_CRC_FAILED) {
return SD_COM_CRC_FAILED;
}
}
return SD_OK;
@ -446,26 +469,26 @@ static void SD_GetResponse(uint32_t* pResponse)
static void SD_DMA_Complete(DMA_Stream_TypeDef* pDMA_Stream)
{
if (SD_Handle.RXCplt) {
if (SD_Handle.Operation == ((SDIO_DIR_RX << 1) | SD_MULTIPLE_BLOCK)) {
/* Send stop command in multiblock write */
SD_TransmitCommand((SD_CMD_STOP_TRANSMISSION | SD_CMD_RESPONSE_SHORT), 0, 1);
}
if (SD_Handle.Operation == ((SDIO_DIR_RX << 1) | SD_MULTIPLE_BLOCK)) {
/* Send stop command in multiblock write */
SD_TransmitCommand((SD_CMD_STOP_TRANSMISSION | SD_CMD_RESPONSE_SHORT), 0, 1);
}
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
in the SD DCTRL register */
SDIO->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
in the SD DCTRL register */
SDIO->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
/* Clear all the static flags */
SDIO->ICR = SDIO_ICR_STATIC_FLAGS;
/* Clear all the static flags */
SDIO->ICR = SDIO_ICR_STATIC_FLAGS;
/* Clear flag */
SD_Handle.RXCplt = 0;
/* Clear flag */
SD_Handle.RXCplt = 0;
/* Disable the stream */
pDMA_Stream->CR &= ~DMA_SxCR_EN;
/* Disable the stream */
pDMA_Stream->CR &= ~DMA_SxCR_EN;
} else {
/* Enable Dataend IE */
SDIO->MASK |= SDIO_MASK_DATAENDIE;
/* Enable Dataend IE */
SDIO->MASK |= SDIO_MASK_DATAENDIE;
}
}
@ -536,7 +559,7 @@ static SD_Error_t SD_InitializeCard(void)
*/
static void SD_StartBlockTransfert(uint32_t* pBuffer, uint32_t BlockSize, uint32_t NumberOfBlocks, uint8_t dir)
{
DMA_Stream_TypeDef *pDMA = dma_stream;
DMA_Stream_TypeDef *pDMA = dma_stream;
SDIO->DCTRL = 0; // Initialize data control register
SD_Handle.TransferComplete = 0; // Initialize handle flags
@ -551,31 +574,31 @@ static void SD_StartBlockTransfert(uint32_t* pBuffer, uint32_t BlockSize, uint32
SDIO->MASK |= (SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE | // Enable transfer interrupts
SDIO_MASK_TXUNDERRIE);
}
if (dir == SDIO_DIR_TX) {
SDIO->DCTRL |= SDIO_DCTRL_DMAEN; // Enable SDIO DMA transfer
}
if (dir == SDIO_DIR_TX) {
SDIO->DCTRL |= SDIO_DCTRL_DMAEN; // Enable SDIO DMA transfer
}
pDMA->CR &= ~DMA_SxCR_EN; // Disable the Peripheral
while (pDMA->CR & DMA_SxCR_EN);
pDMA->NDTR = (uint32_t) (BlockSize * NumberOfBlocks) / 4; // Configure DMA Stream data length
pDMA->M0AR = (uint32_t) pBuffer; // Configure DMA Stream memory address
if (dir == SDIO_DIR_RX) {
pDMA->CR &= ~(0x01U << 6U); // Sets peripheral to memory
} else {
pDMA->CR |= DMA_MEMORY_TO_PERIPH; // Sets memory to peripheral
}
if (dma_stream == DMA2_Stream3) {
DMA2->LIFCR = DMA_LIFCR_CTEIF3 | DMA_LIFCR_CDMEIF3 |
DMA_LIFCR_CFEIF3 | DMA_LIFCR_CHTIF3 | DMA_LIFCR_CTCIF3; // Clear the transfer error flag
if (dir == SDIO_DIR_RX) {
pDMA->CR &= ~(0x01U << 6U); // Sets peripheral to memory
} else {
DMA2->HIFCR = DMA_HIFCR_CTEIF6 | DMA_HIFCR_CDMEIF6 |
DMA_HIFCR_CFEIF6 | DMA_HIFCR_CHTIF6 | DMA_HIFCR_CTCIF6; // Clear the transfer error flag
pDMA->CR |= DMA_MEMORY_TO_PERIPH; // Sets memory to peripheral
}
if (dma_stream == DMA2_Stream3) {
DMA2->LIFCR = DMA_LIFCR_CTEIF3 | DMA_LIFCR_CDMEIF3 |
DMA_LIFCR_CFEIF3 | DMA_LIFCR_CHTIF3 | DMA_LIFCR_CTCIF3; // Clear the transfer error flag
} else {
DMA2->HIFCR = DMA_HIFCR_CTEIF6 | DMA_HIFCR_CDMEIF6 |
DMA_HIFCR_CFEIF6 | DMA_HIFCR_CHTIF6 | DMA_HIFCR_CTCIF6; // Clear the transfer error flag
}
pDMA->CR |= DMA_SxCR_TCIE | DMA_SxCR_HTIE | DMA_SxCR_TEIE | DMA_SxCR_DMEIE; // Enable all interrupts
pDMA->FCR |= DMA_SxFCR_FEIE;
pDMA->CR |= DMA_SxCR_EN; // Enable the Peripheral
if (dir == SDIO_DIR_RX) {
SDIO->DCTRL |= SDIO_DCTRL_DMAEN; // Enable SDIO DMA transfer
}
if (dir == SDIO_DIR_RX) {
SDIO->DCTRL |= SDIO_DCTRL_DMAEN; // Enable SDIO DMA transfer
}
}
@ -608,7 +631,7 @@ SD_Error_t SD_ReadBlocks_DMA(uint64_t ReadAddress, uint32_t *buffer, uint32_t Bl
SD_StartBlockTransfert(buffer, BlockSize, NumberOfBlocks, SDIO_DIR_RX);
// Configure the SD DPSM (Data Path State Machine)
SD_DataTransferInit(BlockSize * NumberOfBlocks, SD_DATABLOCK_SIZE_512B, true);
SD_DataTransferInit(BlockSize * NumberOfBlocks, SD_DATABLOCK_SIZE_512B, true);
// Set Block Size for Card
ErrorState = SD_TransmitCommand((SD_CMD_SET_BLOCKLEN | SD_CMD_RESPONSE_SHORT), BlockSize, 1);
@ -618,14 +641,14 @@ SD_Error_t SD_ReadBlocks_DMA(uint64_t ReadAddress, uint32_t *buffer, uint32_t Bl
uint8_t retries = 10;
CmdIndex = (NumberOfBlocks > 1) ? SD_CMD_READ_MULT_BLOCK : SD_CMD_READ_SINGLE_BLOCK;
do {
ErrorState = SD_TransmitCommand((CmdIndex | SD_CMD_RESPONSE_SHORT), (uint32_t)ReadAddress, 1);
if (ErrorState != SD_OK && retries--) {
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), 0, 1);
}
ErrorState = SD_TransmitCommand((CmdIndex | SD_CMD_RESPONSE_SHORT), (uint32_t)ReadAddress, 1);
if (ErrorState != SD_OK && retries--) {
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), 0, 1);
}
} while (ErrorState != SD_OK && retries);
if (ErrorState != SD_OK) {
SD_Handle.RXCplt = 0;
SD_Handle.RXCplt = 0;
}
// Update the SD transfer error in SD handle
@ -669,21 +692,21 @@ SD_Error_t SD_WriteBlocks_DMA(uint64_t WriteAddress, uint32_t *buffer, uint32_t
// Set Block Size for Card
uint8_t retries = 10;
do {
ErrorState = SD_TransmitCommand((CmdIndex | SD_CMD_RESPONSE_SHORT), (uint32_t)WriteAddress, 1);
if (ErrorState != SD_OK && retries--) {
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), 0, 1);
}
ErrorState = SD_TransmitCommand((CmdIndex | SD_CMD_RESPONSE_SHORT), (uint32_t)WriteAddress, 1);
if (ErrorState != SD_OK && retries--) {
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), 0, 1);
}
} while(ErrorState != SD_OK && retries);
if (ErrorState != SD_OK) {
SD_Handle.TXCplt = 0;
return ErrorState;
SD_Handle.TXCplt = 0;
return ErrorState;
}
SD_StartBlockTransfert(buffer, BlockSize, NumberOfBlocks, SDIO_DIR_TX);
// Configure the SD DPSM (Data Path State Machine)
SD_DataTransferInit(BlockSize * NumberOfBlocks, SD_DATABLOCK_SIZE_512B, false);
SD_DataTransferInit(BlockSize * NumberOfBlocks, SD_DATABLOCK_SIZE_512B, false);
SD_Handle.TransferError = ErrorState;
@ -691,13 +714,13 @@ SD_Error_t SD_WriteBlocks_DMA(uint64_t WriteAddress, uint32_t *buffer, uint32_t
}
SD_Error_t SD_CheckWrite(void) {
if (SD_Handle.TXCplt != 0) return SD_BUSY;
return SD_OK;
if (SD_Handle.TXCplt != 0) return SD_BUSY;
return SD_OK;
}
SD_Error_t SD_CheckRead(void) {
if (SD_Handle.RXCplt != 0) return SD_BUSY;
return SD_OK;
if (SD_Handle.RXCplt != 0) return SD_BUSY;
return SD_OK;
}
/** -----------------------------------------------------------------------------------------------------------------*/
@ -1074,7 +1097,7 @@ static SD_Error_t SD_WideBusOperationConfig(uint32_t WideMode)
if((SDIO->RESP1 & SD_CARD_LOCKED) != SD_CARD_LOCKED)
{
// Get SCR Register
ErrorState = SD_FindSCR(SCR);
ErrorState = SD_FindSCR(SCR);
if(ErrorState == SD_OK)
{
Temp = (WideMode == SD_BUS_WIDE_4B) ? SD_WIDE_BUS_SUPPORT : SD_SINGLE_BUS_SUPPORT;
@ -1083,7 +1106,7 @@ static SD_Error_t SD_WideBusOperationConfig(uint32_t WideMode)
if((SCR[1] & Temp) != SD_ALLZERO)
{
// Send CMD55 APP_CMD with argument as card's RCA.
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), SD_CardRCA, 1);
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), SD_CardRCA, 1);
if(ErrorState == SD_OK)
{
Temp = (WideMode == SD_BUS_WIDE_4B) ? 2 : 0;
@ -1111,13 +1134,13 @@ static SD_Error_t SD_WideBusOperationConfig(uint32_t WideMode)
if(ErrorState == SD_OK)
{
// Configure the SDIO peripheral, we need this delay for some reason...
while ((READ_REG(SDIO->CLKCR) & 0x800) != WideMode) {
MODIFY_REG(SDIO->CLKCR, CLKCR_CLEAR_MASK, (uint32_t) WideMode);
}
while ((READ_REG(SDIO->CLKCR) & 0x800) != WideMode) {
MODIFY_REG(SDIO->CLKCR, CLKCR_CLEAR_MASK, (uint32_t) WideMode);
}
}
}
else {
ErrorState = SD_UNSUPPORTED_FEATURE;
ErrorState = SD_UNSUPPORTED_FEATURE;
}
@ -1573,21 +1596,21 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma)
//Configure Pins
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN;
uint8_t is4BitWidth = sdioConfig()->use4BitWidth;
const IO_t d0 = IOGetByTag(IO_TAG(PC8));
#ifndef USE_SDIO_1BIT
const IO_t d1 = IOGetByTag(IO_TAG(PC9));
const IO_t d2 = IOGetByTag(IO_TAG(PC10));
const IO_t d3 = IOGetByTag(IO_TAG(PC11));
#endif
const IO_t clk = IOGetByTag(IO_TAG(PC12));
const IO_t cmd = IOGetByTag(IO_TAG(PD2));
IOInit(d0, OWNER_SDCARD, 0);
#ifndef USE_SDIO_1BIT
IOInit(d1, OWNER_SDCARD, 0);
IOInit(d2, OWNER_SDCARD, 0);
IOInit(d3, OWNER_SDCARD, 0);
#endif
if (is4BitWidth) {
IOInit(d1, OWNER_SDCARD, 0);
IOInit(d2, OWNER_SDCARD, 0);
IOInit(d3, OWNER_SDCARD, 0);
}
IOInit(clk, OWNER_SDCARD, 0);
IOInit(cmd, OWNER_SDCARD, 0);
@ -1596,11 +1619,11 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma)
#define SDIO_CLK IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL)
IOConfigGPIOAF(d0, SDIO_DATA, GPIO_AF_SDIO);
#ifndef USE_SDIO_1BIT
IOConfigGPIOAF(d1, SDIO_DATA, GPIO_AF_SDIO);
IOConfigGPIOAF(d2, SDIO_DATA, GPIO_AF_SDIO);
IOConfigGPIOAF(d3, SDIO_DATA, GPIO_AF_SDIO);
#endif
if (is4BitWidth) {
IOConfigGPIOAF(d1, SDIO_DATA, GPIO_AF_SDIO);
IOConfigGPIOAF(d2, SDIO_DATA, GPIO_AF_SDIO);
IOConfigGPIOAF(d3, SDIO_DATA, GPIO_AF_SDIO);
}
IOConfigGPIOAF(clk, SDIO_CLK, GPIO_AF_SDIO);
IOConfigGPIOAF(cmd, SDIO_CMD, GPIO_AF_SDIO);
@ -1615,31 +1638,31 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma)
dma_stream = dma;
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
if ((uint32_t)dma_stream == (uint32_t)DMA2_Stream3) {
// Initialize DMA2 channel 3
DMA2_Stream3->CR = 0; // Reset DMA Stream control register
DMA2_Stream3->PAR = (uint32_t)&SDIO->FIFO;
DMA2->LIFCR = IFCR_CLEAR_MASK_STREAM3; // Clear all interrupt flags
DMA2_Stream3->CR = (DMA_CHANNEL_4 | DMA_SxCR_PFCTRL | // Prepare the DMA Stream configuration
DMA_MINC_ENABLE | DMA_PDATAALIGN_WORD | // And write to DMA Stream CR register
DMA_MDATAALIGN_WORD | DMA_PRIORITY_VERY_HIGH |
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
DMA_MEMORY_TO_PERIPH);
DMA2_Stream3->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
dmaInit(dmaGetIdentifier(DMA2_Stream3), OWNER_SDCARD, 0);
dmaSetHandler(dmaGetIdentifier(DMA2_Stream3), SDIO_DMA_ST3_IRQHandler, 1, 0);
// Initialize DMA2 channel 3
DMA2_Stream3->CR = 0; // Reset DMA Stream control register
DMA2_Stream3->PAR = (uint32_t)&SDIO->FIFO;
DMA2->LIFCR = IFCR_CLEAR_MASK_STREAM3; // Clear all interrupt flags
DMA2_Stream3->CR = (DMA_CHANNEL_4 | DMA_SxCR_PFCTRL | // Prepare the DMA Stream configuration
DMA_MINC_ENABLE | DMA_PDATAALIGN_WORD | // And write to DMA Stream CR register
DMA_MDATAALIGN_WORD | DMA_PRIORITY_VERY_HIGH |
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
DMA_MEMORY_TO_PERIPH);
DMA2_Stream3->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
dmaInit(dmaGetIdentifier(DMA2_Stream3), OWNER_SDCARD, 0);
dmaSetHandler(dmaGetIdentifier(DMA2_Stream3), SDIO_DMA_ST3_IRQHandler, 1, 0);
} else {
// Initialize DMA2 channel 6
DMA2_Stream6->CR = 0; // Reset DMA Stream control register
DMA2_Stream6->PAR = (uint32_t)&SDIO->FIFO;
DMA2->HIFCR = IFCR_CLEAR_MASK_STREAM6; // Clear all interrupt flags
DMA2_Stream6->CR = (DMA_CHANNEL_4 | DMA_SxCR_PFCTRL | // Prepare the DMA Stream configuration
DMA_MINC_ENABLE | DMA_PDATAALIGN_WORD | // And write to DMA Stream CR register
DMA_MDATAALIGN_WORD | DMA_PRIORITY_VERY_HIGH |
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
DMA_MEMORY_TO_PERIPH);
DMA2_Stream6->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
dmaInit(dmaGetIdentifier(DMA2_Stream6), OWNER_SDCARD, 0);
dmaSetHandler(dmaGetIdentifier(DMA2_Stream6), SDIO_DMA_ST6_IRQHandler, 1, 0);
// Initialize DMA2 channel 6
DMA2_Stream6->CR = 0; // Reset DMA Stream control register
DMA2_Stream6->PAR = (uint32_t)&SDIO->FIFO;
DMA2->HIFCR = IFCR_CLEAR_MASK_STREAM6; // Clear all interrupt flags
DMA2_Stream6->CR = (DMA_CHANNEL_4 | DMA_SxCR_PFCTRL | // Prepare the DMA Stream configuration
DMA_MINC_ENABLE | DMA_PDATAALIGN_WORD | // And write to DMA Stream CR register
DMA_MDATAALIGN_WORD | DMA_PRIORITY_VERY_HIGH |
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
DMA_MEMORY_TO_PERIPH);
DMA2_Stream6->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
dmaInit(dmaGetIdentifier(DMA2_Stream6), OWNER_SDCARD, 0);
dmaSetHandler(dmaGetIdentifier(DMA2_Stream6), SDIO_DMA_ST6_IRQHandler, 1, 0);
}
}
@ -1647,25 +1670,25 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma)
/** -----------------------------------------------------------------------------------------------------------------*/
bool SD_GetState(void)
{
// Check SDCARD status
if(SD_GetStatus() == SD_OK) return true;
return false;
// Check SDCARD status
if(SD_GetStatus() == SD_OK) return true;
return false;
}
/** -----------------------------------------------------------------------------------------------------------------*/
bool SD_Init(void)
{
SD_Error_t ErrorState;
SD_Error_t ErrorState;
// Check if SD card is present
if(SD_IsDetected() != SD_PRESENT)
// Check if SD card is present
if(SD_IsDetected() != SD_PRESENT)
{
return false;
}
// Initialize SDIO peripheral interface with default configuration for SD card initialization
MODIFY_REG(SDIO->CLKCR, CLKCR_CLEAR_MASK, (uint32_t) SDIO_INIT_CLK_DIV);
MODIFY_REG(SDIO->CLKCR, CLKCR_CLEAR_MASK, (uint32_t) SDIO_INIT_CLK_DIV);
if((ErrorState = SD_PowerON()) == SD_OK) // Identify card operating voltage
{
@ -1680,26 +1703,25 @@ bool SD_Init(void)
}
}
// Configure SD Bus width
if(ErrorState == SD_OK)
{
// Enable wide operation
#ifdef USE_SDIO_1BIT
ErrorState = SD_WideBusOperationConfig(SD_BUS_WIDE_1B);
#else
ErrorState = SD_WideBusOperationConfig(SD_BUS_WIDE_4B);
#endif
// Configure SD Bus width
if(ErrorState == SD_OK)
{
// Enable wide operation
if (sdioConfig()->use4BitWidth) {
ErrorState = SD_WideBusOperationConfig(SD_BUS_WIDE_4B);
} else {
ErrorState = SD_WideBusOperationConfig(SD_BUS_WIDE_1B);
}
if (ErrorState == SD_OK && sdioConfig()->clockBypass) {
if (SD_HighSpeed()) {
SDIO->CLKCR |= SDIO_CLKCR_BYPASS;
SDIO->CLKCR |= SDIO_CLKCR_NEGEDGE;
}
}
}
if (ErrorState == SD_OK && sdioConfig()->clockBypass) {
if (SD_HighSpeed()) {
SDIO->CLKCR |= SDIO_CLKCR_BYPASS;
SDIO->CLKCR |= SDIO_CLKCR_NEGEDGE;
}
}
}
// Configure the SDCARD device
return ErrorState;
// Configure the SDCARD device
return ErrorState;
}
/** -----------------------------------------------------------------------------------------------------------------*/
@ -1707,44 +1729,44 @@ bool SD_Init(void)
* @brief This function handles SD card interrupt request.
*/
void SDIO_IRQHandler(void) {
// Check for SDIO interrupt flags
if ((SDIO->STA & SDIO_STA_DATAEND) != 0) {
SDIO->ICR = SDIO_ICR_DATAENDC;
SDIO->ICR = SDIO_ICR_STATIC_FLAGS;
SDIO->MASK &= ~(SDIO_MASK_DATAENDIE | SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE | \
SDIO_MASK_TXUNDERRIE | SDIO_MASK_RXOVERRIE | SDIO_MASK_TXFIFOHEIE | SDIO_MASK_RXFIFOHFIE);
// Check for SDIO interrupt flags
if ((SDIO->STA & SDIO_STA_DATAEND) != 0) {
SDIO->ICR = SDIO_ICR_DATAENDC;
SDIO->ICR = SDIO_ICR_STATIC_FLAGS;
SDIO->MASK &= ~(SDIO_MASK_DATAENDIE | SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE | \
SDIO_MASK_TXUNDERRIE | SDIO_MASK_RXOVERRIE | SDIO_MASK_TXFIFOHEIE | SDIO_MASK_RXFIFOHFIE);
/* Currently doesn't implement multiple block write handling */
if ((SD_Handle.Operation & 0x02) == (SDIO_DIR_TX << 1)) {
/* Disable the stream */
dma_stream->CR &= ~DMA_SxCR_EN;
SDIO->DCTRL &= ~(SDIO_DCTRL_DMAEN);
/* Transfer is complete */
SD_Handle.TXCplt = 0;
if ((SD_Handle.Operation & 0x01) == SD_MULTIPLE_BLOCK) {
/* Send stop command in multiblock write */
SD_TransmitCommand((SD_CMD_STOP_TRANSMISSION | SD_CMD_RESPONSE_SHORT), 0, 1);
}
}
SD_Handle.TransferComplete = 1;
SD_Handle.TransferError = SD_OK; // No transfer error
}
else if ((SDIO->STA & SDIO_STA_DCRCFAIL) != 0)
SD_Handle.TransferError = SD_DATA_CRC_FAIL;
else if ((SDIO->STA & SDIO_STA_DTIMEOUT) != 0)
SD_Handle.TransferError = SD_DATA_TIMEOUT;
else if ((SDIO->STA & SDIO_STA_RXOVERR) != 0)
SD_Handle.TransferError = SD_RX_OVERRUN;
else if ((SDIO->STA & SDIO_STA_TXUNDERR) != 0)
SD_Handle.TransferError = SD_TX_UNDERRUN;
/* Currently doesn't implement multiple block write handling */
if ((SD_Handle.Operation & 0x02) == (SDIO_DIR_TX << 1)) {
/* Disable the stream */
dma_stream->CR &= ~DMA_SxCR_EN;
SDIO->DCTRL &= ~(SDIO_DCTRL_DMAEN);
/* Transfer is complete */
SD_Handle.TXCplt = 0;
if ((SD_Handle.Operation & 0x01) == SD_MULTIPLE_BLOCK) {
/* Send stop command in multiblock write */
SD_TransmitCommand((SD_CMD_STOP_TRANSMISSION | SD_CMD_RESPONSE_SHORT), 0, 1);
}
}
SD_Handle.TransferComplete = 1;
SD_Handle.TransferError = SD_OK; // No transfer error
}
else if ((SDIO->STA & SDIO_STA_DCRCFAIL) != 0)
SD_Handle.TransferError = SD_DATA_CRC_FAIL;
else if ((SDIO->STA & SDIO_STA_DTIMEOUT) != 0)
SD_Handle.TransferError = SD_DATA_TIMEOUT;
else if ((SDIO->STA & SDIO_STA_RXOVERR) != 0)
SD_Handle.TransferError = SD_RX_OVERRUN;
else if ((SDIO->STA & SDIO_STA_TXUNDERR) != 0)
SD_Handle.TransferError = SD_TX_UNDERRUN;
SDIO->ICR = SDIO_ICR_STATIC_FLAGS;
SDIO->ICR = SDIO_ICR_STATIC_FLAGS;
// Disable all SDIO peripheral interrupt sources
SDIO->MASK &= ~(SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE
| SDIO_MASK_DATAENDIE |
SDIO_MASK_TXFIFOHEIE | SDIO_MASK_RXFIFOHFIE | SDIO_MASK_TXUNDERRIE |
SDIO_MASK_RXOVERRIE);
// Disable all SDIO peripheral interrupt sources
SDIO->MASK &= ~(SDIO_MASK_DCRCFAILIE | SDIO_MASK_DTIMEOUTIE
| SDIO_MASK_DATAENDIE |
SDIO_MASK_TXFIFOHEIE | SDIO_MASK_RXFIFOHFIE | SDIO_MASK_TXUNDERRIE |
SDIO_MASK_RXOVERRIE);
}
/** -----------------------------------------------------------------------------------------------------------------*/
@ -1753,7 +1775,7 @@ void SDIO_IRQHandler(void) {
*/
void SDIO_DMA_ST3_IRQHandler(dmaChannelDescriptor_t *dma)
{
UNUSED(dma);
UNUSED(dma);
// Transfer Error Interrupt management
if((DMA2->LISR & DMA_LISR_TEIF3) != 0)
{
@ -1835,7 +1857,7 @@ void SDIO_DMA_ST3_IRQHandler(dmaChannelDescriptor_t *dma)
*/
void SDIO_DMA_ST6_IRQHandler(dmaChannelDescriptor_t *dma)
{
UNUSED(dma);
UNUSED(dma);
// Transfer Error Interrupt management
if((DMA2->HISR & DMA_HISR_TEIF6) != 0)
{

View file

@ -264,17 +264,17 @@ void SDMMC_DMA_ST6_IRQHandler(dmaChannelDescriptor_t *dma);
*/
bool SD_IsDetected(void)
{
__IO uint8_t status = SD_PRESENT;
__IO uint8_t status = SD_PRESENT;
/*!< Check GPIO to detect SD */
#ifdef SDCARD_DETECT_PIN
const IO_t sd_det = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN));
if (IORead(sd_det) != 0)
{
status = SD_NOT_PRESENT;
}
#endif
return status;
/*!< Check GPIO to detect SD */
#ifdef SDCARD_DETECT_PIN
const IO_t sd_det = IOGetByTag(IO_TAG(SDCARD_DETECT_PIN));
if (IORead(sd_det) != 0)
{
status = SD_NOT_PRESENT;
}
#endif
return status;
}
@ -313,7 +313,7 @@ static SD_Error_t SD_TransmitCommand(uint32_t Command, uint32_t Argument, int8_t
WRITE_REG(SDMMC1->ICR, SDMMC_ICR_STATIC_FLAGS); // Clear the Command Flags
WRITE_REG(SDMMC1->ARG, (uint32_t)Argument); // Set the SDMMC1 Argument value
WRITE_REG(SDMMC1->CMD, (uint32_t)(Command | SDMMC_CMD_CPSMEN)); // Set SDMMC1 command parameters
if((Argument == 0) && (ResponseType == 0)) ResponseType = -1; // Go idle command
if((Argument == 0) && (ResponseType == 0)) ResponseType = -1; // Go idle command
ErrorState = SD_CmdResponse(Command & SDMMC_CMD_CMDINDEX, ResponseType);
WRITE_REG(SDMMC1->ICR, SDMMC_ICR_STATIC_FLAGS); // Clear the Command Flags
@ -336,8 +336,11 @@ static SD_Error_t SD_CmdResponse(uint8_t SD_CMD, int8_t ResponseType)
uint32_t TimeOut;
uint32_t Flag;
if(ResponseType == -1) Flag = SDMMC_STA_CMDSENT;
else Flag = SDMMC_STA_CCRCFAIL | SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT;
if(ResponseType == -1) {
Flag = SDMMC_STA_CMDSENT;
} else {
Flag = SDMMC_STA_CCRCFAIL | SDMMC_STA_CMDREND | SDMMC_STA_CTIMEOUT;
}
TimeOut = SD_SOFTWARE_COMMAND_TIMEOUT;
do
@ -349,20 +352,34 @@ static SD_Error_t SD_CmdResponse(uint8_t SD_CMD, int8_t ResponseType)
if(ResponseType <= 0)
{
if(TimeOut == 0) return SD_CMD_RSP_TIMEOUT;
else return SD_OK;
if(TimeOut == 0){
return SD_CMD_RSP_TIMEOUT;
} else {
return SD_OK;
}
}
if((SDMMC1->STA & SDMMC_STA_CTIMEOUT) != 0) return SD_CMD_RSP_TIMEOUT;
if((SDMMC1->STA & SDMMC_STA_CTIMEOUT) != 0) {
return SD_CMD_RSP_TIMEOUT;
}
if(ResponseType == 3)
{
if(TimeOut == 0) return SD_CMD_RSP_TIMEOUT; // Card is not V2.0 compliant or card does not support the set voltage range
else return SD_OK; // Card is SD V2.0 compliant
if(TimeOut == 0) {
return SD_CMD_RSP_TIMEOUT; // Card is not V2.0 compliant or card does not support the set voltage range
} else {
return SD_OK; // Card is SD V2.0 compliant
}
}
if((SDMMC1->STA & SDMMC_STA_CCRCFAIL) != 0) return SD_CMD_CRC_FAIL;
if(ResponseType == 2) return SD_OK;
if((uint8_t)SDMMC1->RESPCMD != SD_CMD) return SD_ILLEGAL_CMD; // Check if response is of desired command
if((SDMMC1->STA & SDMMC_STA_CCRCFAIL) != 0) {
return SD_CMD_CRC_FAIL;
}
if(ResponseType == 2) {
return SD_OK;
}
if((uint8_t)SDMMC1->RESPCMD != SD_CMD) {
return SD_ILLEGAL_CMD; // Check if response is of desired command
}
Response_R1 = SDMMC1->RESP1; // We have received response, retrieve it for analysis
@ -376,9 +393,15 @@ static SD_Error_t SD_CmdResponse(uint8_t SD_CMD, int8_t ResponseType)
{
SD_CardRCA = Response_R1;
}
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) return SD_ILLEGAL_CMD;
if((Response_R1 & SD_R6_COM_CRC_FAILED) == SD_R6_COM_CRC_FAILED) return SD_COM_CRC_FAILED;
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) {
return SD_ILLEGAL_CMD;
}
if((Response_R1 & SD_R6_COM_CRC_FAILED) == SD_R6_COM_CRC_FAILED) {
return SD_COM_CRC_FAILED;
}
}
return SD_OK;
@ -441,26 +464,26 @@ static void SD_GetResponse(uint32_t* pResponse)
static void SD_DMA_Complete(DMA_Stream_TypeDef* pDMA_Stream)
{
if (SD_Handle.RXCplt) {
if (SD_Handle.Operation == ((SDMMC_DIR_RX << 1) | SD_MULTIPLE_BLOCK)) {
/* Send stop command in multiblock write */
SD_TransmitCommand((SD_CMD_STOP_TRANSMISSION | SD_CMD_RESPONSE_SHORT), 0, 1);
}
if (SD_Handle.Operation == ((SDMMC_DIR_RX << 1) | SD_MULTIPLE_BLOCK)) {
/* Send stop command in multiblock write */
SD_TransmitCommand((SD_CMD_STOP_TRANSMISSION | SD_CMD_RESPONSE_SHORT), 0, 1);
}
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
in the SD DCTRL register */
SDMMC1->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
in the SD DCTRL register */
SDMMC1->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
/* Clear all the static flags */
SDMMC1->ICR = SDMMC_ICR_STATIC_FLAGS;
/* Clear all the static flags */
SDMMC1->ICR = SDMMC_ICR_STATIC_FLAGS;
/* Clear flag */
SD_Handle.RXCplt = 0;
/* Clear flag */
SD_Handle.RXCplt = 0;
/* Disable the stream */
pDMA_Stream->CR &= ~DMA_SxCR_EN;
/* Disable the stream */
pDMA_Stream->CR &= ~DMA_SxCR_EN;
} else {
/* Enable Dataend IE */
SDMMC1->MASK |= SDMMC_MASK_DATAENDIE;
/* Enable Dataend IE */
SDMMC1->MASK |= SDMMC_MASK_DATAENDIE;
}
}
@ -531,7 +554,7 @@ static SD_Error_t SD_InitializeCard(void)
*/
static void SD_StartBlockTransfert(uint32_t* pBuffer, uint32_t BlockSize, uint32_t NumberOfBlocks, uint8_t dir)
{
DMA_Stream_TypeDef *pDMA = dma_stream;
DMA_Stream_TypeDef *pDMA = dma_stream;
SDMMC1->DCTRL = 0; // Initialize data control register
SD_Handle.TransferComplete = 0; // Initialize handle flags
@ -546,31 +569,31 @@ static void SD_StartBlockTransfert(uint32_t* pBuffer, uint32_t BlockSize, uint32
SDMMC1->MASK |= (SDMMC_MASK_DCRCFAILIE | SDMMC_MASK_DTIMEOUTIE | // Enable transfer interrupts
SDMMC_MASK_TXUNDERRIE);
}
if (dir == SDMMC_DIR_TX) {
SDMMC1->DCTRL |= SDMMC_DCTRL_DMAEN; // Enable SDMMC1 DMA transfer
}
if (dir == SDMMC_DIR_TX) {
SDMMC1->DCTRL |= SDMMC_DCTRL_DMAEN; // Enable SDMMC1 DMA transfer
}
pDMA->CR &= ~DMA_SxCR_EN; // Disable the Peripheral
while (pDMA->CR & DMA_SxCR_EN);
pDMA->NDTR = (uint32_t) (BlockSize * NumberOfBlocks) / 4; // Configure DMA Stream data length
pDMA->M0AR = (uint32_t) pBuffer; // Configure DMA Stream memory address
if (dir == SDMMC_DIR_RX) {
pDMA->CR &= ~(0x01U << 6U); // Sets peripheral to memory
} else {
pDMA->CR |= DMA_MEMORY_TO_PERIPH; // Sets memory to peripheral
}
if (dma_stream == DMA2_Stream3) {
DMA2->LIFCR = DMA_LIFCR_CTEIF3 | DMA_LIFCR_CDMEIF3 |
DMA_LIFCR_CFEIF3 | DMA_LIFCR_CHTIF3 | DMA_LIFCR_CTCIF3; // Clear the transfer error flag
if (dir == SDMMC_DIR_RX) {
pDMA->CR &= ~(0x01U << 6U); // Sets peripheral to memory
} else {
DMA2->HIFCR = DMA_HIFCR_CTEIF6 | DMA_HIFCR_CDMEIF6 |
DMA_HIFCR_CFEIF6 | DMA_HIFCR_CHTIF6 | DMA_HIFCR_CTCIF6; // Clear the transfer error flag
pDMA->CR |= DMA_MEMORY_TO_PERIPH; // Sets memory to peripheral
}
if (dma_stream == DMA2_Stream3) {
DMA2->LIFCR = DMA_LIFCR_CTEIF3 | DMA_LIFCR_CDMEIF3 |
DMA_LIFCR_CFEIF3 | DMA_LIFCR_CHTIF3 | DMA_LIFCR_CTCIF3; // Clear the transfer error flag
} else {
DMA2->HIFCR = DMA_HIFCR_CTEIF6 | DMA_HIFCR_CDMEIF6 |
DMA_HIFCR_CFEIF6 | DMA_HIFCR_CHTIF6 | DMA_HIFCR_CTCIF6; // Clear the transfer error flag
}
pDMA->CR |= DMA_SxCR_TCIE | DMA_SxCR_HTIE | DMA_SxCR_TEIE | DMA_SxCR_DMEIE; // Enable all interrupts
pDMA->FCR |= DMA_SxFCR_FEIE;
pDMA->CR |= DMA_SxCR_EN; // Enable the Peripheral
if (dir == SDMMC_DIR_RX) {
SDMMC1->DCTRL |= SDMMC_DCTRL_DMAEN; // Enable SDMMC1 DMA transfer
}
if (dir == SDMMC_DIR_RX) {
SDMMC1->DCTRL |= SDMMC_DCTRL_DMAEN; // Enable SDMMC1 DMA transfer
}
}
@ -603,7 +626,7 @@ SD_Error_t SD_ReadBlocks_DMA(uint64_t ReadAddress, uint32_t *buffer, uint32_t Bl
SD_StartBlockTransfert(buffer, BlockSize, NumberOfBlocks, SDMMC_DIR_RX);
// Configure the SD DPSM (Data Path State Machine)
SD_DataTransferInit(BlockSize * NumberOfBlocks, SD_DATABLOCK_SIZE_512B, true);
SD_DataTransferInit(BlockSize * NumberOfBlocks, SD_DATABLOCK_SIZE_512B, true);
// Set Block Size for Card
ErrorState = SD_TransmitCommand((SD_CMD_SET_BLOCKLEN | SD_CMD_RESPONSE_SHORT), BlockSize, 1);
@ -613,14 +636,14 @@ SD_Error_t SD_ReadBlocks_DMA(uint64_t ReadAddress, uint32_t *buffer, uint32_t Bl
uint8_t retries = 10;
CmdIndex = (NumberOfBlocks > 1) ? SD_CMD_READ_MULT_BLOCK : SD_CMD_READ_SINGLE_BLOCK;
do {
ErrorState = SD_TransmitCommand((CmdIndex | SD_CMD_RESPONSE_SHORT), (uint32_t)ReadAddress, 1);
if (ErrorState != SD_OK && retries--) {
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), 0, 1);
}
ErrorState = SD_TransmitCommand((CmdIndex | SD_CMD_RESPONSE_SHORT), (uint32_t)ReadAddress, 1);
if (ErrorState != SD_OK && retries--) {
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), 0, 1);
}
} while (ErrorState != SD_OK && retries);
if (ErrorState != SD_OK) {
SD_Handle.RXCplt = 0;
SD_Handle.RXCplt = 0;
}
// Update the SD transfer error in SD handle
@ -664,21 +687,21 @@ SD_Error_t SD_WriteBlocks_DMA(uint64_t WriteAddress, uint32_t *buffer, uint32_t
// Set Block Size for Card
uint8_t retries = 10;
do {
ErrorState = SD_TransmitCommand((CmdIndex | SD_CMD_RESPONSE_SHORT), (uint32_t)WriteAddress, 1);
if (ErrorState != SD_OK && retries--) {
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), 0, 1);
}
ErrorState = SD_TransmitCommand((CmdIndex | SD_CMD_RESPONSE_SHORT), (uint32_t)WriteAddress, 1);
if (ErrorState != SD_OK && retries--) {
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), 0, 1);
}
} while(ErrorState != SD_OK && retries);
if (ErrorState != SD_OK) {
SD_Handle.TXCplt = 0;
return ErrorState;
SD_Handle.TXCplt = 0;
return ErrorState;
}
SD_StartBlockTransfert(buffer, BlockSize, NumberOfBlocks, SDMMC_DIR_TX);
// Configure the SD DPSM (Data Path State Machine)
SD_DataTransferInit(BlockSize * NumberOfBlocks, SD_DATABLOCK_SIZE_512B, false);
SD_DataTransferInit(BlockSize * NumberOfBlocks, SD_DATABLOCK_SIZE_512B, false);
SD_Handle.TransferError = ErrorState;
@ -686,13 +709,13 @@ SD_Error_t SD_WriteBlocks_DMA(uint64_t WriteAddress, uint32_t *buffer, uint32_t
}
SD_Error_t SD_CheckWrite(void) {
if (SD_Handle.TXCplt != 0) return SD_BUSY;
return SD_OK;
if (SD_Handle.TXCplt != 0) return SD_BUSY;
return SD_OK;
}
SD_Error_t SD_CheckRead(void) {
if (SD_Handle.RXCplt != 0) return SD_BUSY;
return SD_OK;
if (SD_Handle.RXCplt != 0) return SD_BUSY;
return SD_OK;
}
/** -----------------------------------------------------------------------------------------------------------------*/
@ -1069,7 +1092,7 @@ static SD_Error_t SD_WideBusOperationConfig(uint32_t WideMode)
if((SDMMC1->RESP1 & SD_CARD_LOCKED) != SD_CARD_LOCKED)
{
// Get SCR Register
ErrorState = SD_FindSCR(SCR);
ErrorState = SD_FindSCR(SCR);
if(ErrorState == SD_OK)
{
Temp = (WideMode == SD_BUS_WIDE_4B) ? SD_WIDE_BUS_SUPPORT : SD_SINGLE_BUS_SUPPORT;
@ -1078,7 +1101,7 @@ static SD_Error_t SD_WideBusOperationConfig(uint32_t WideMode)
if((SCR[1] & Temp) != SD_ALLZERO)
{
// Send CMD55 APP_CMD with argument as card's RCA.
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), SD_CardRCA, 1);
ErrorState = SD_TransmitCommand((SD_CMD_APP_CMD | SD_CMD_RESPONSE_SHORT), SD_CardRCA, 1);
if(ErrorState == SD_OK)
{
Temp = (WideMode == SD_BUS_WIDE_4B) ? 2 : 0;
@ -1106,13 +1129,13 @@ static SD_Error_t SD_WideBusOperationConfig(uint32_t WideMode)
if(ErrorState == SD_OK)
{
// Configure the SDMMC1 peripheral, we need this delay for some reason...
while ((READ_REG(SDMMC1->CLKCR) & 0x800) != WideMode) {
MODIFY_REG(SDMMC1->CLKCR, CLKCR_CLEAR_MASK, (uint32_t) WideMode);
}
while ((READ_REG(SDMMC1->CLKCR) & 0x800) != WideMode) {
MODIFY_REG(SDMMC1->CLKCR, CLKCR_CLEAR_MASK, (uint32_t) WideMode);
}
}
}
else {
ErrorState = SD_UNSUPPORTED_FEATURE;
ErrorState = SD_UNSUPPORTED_FEATURE;
}
@ -1571,21 +1594,21 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma)
//Configure Pins
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN;
uint8_t is4BitWidth = sdioConfig()->use4BitWidth;
const IO_t d0 = IOGetByTag(IO_TAG(PC8));
#ifndef USE_SDIO_1BIT
const IO_t d1 = IOGetByTag(IO_TAG(PC9));
const IO_t d2 = IOGetByTag(IO_TAG(PC10));
const IO_t d3 = IOGetByTag(IO_TAG(PC11));
#endif
const IO_t clk = IOGetByTag(IO_TAG(PC12));
const IO_t cmd = IOGetByTag(IO_TAG(PD2));
IOInit(d0, OWNER_SDCARD, 0);
#ifndef USE_SDIO_1BIT
IOInit(d1, OWNER_SDCARD, 0);
IOInit(d2, OWNER_SDCARD, 0);
IOInit(d3, OWNER_SDCARD, 0);
#endif
if (is4BitWidth) {
IOInit(d1, OWNER_SDCARD, 0);
IOInit(d2, OWNER_SDCARD, 0);
IOInit(d3, OWNER_SDCARD, 0);
}
IOInit(clk, OWNER_SDCARD, 0);
IOInit(cmd, OWNER_SDCARD, 0);
@ -1594,48 +1617,48 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma)
#define SDMMC_CLK IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_NOPULL)
IOConfigGPIOAF(d0, SDMMC_DATA, GPIO_AF12_SDMMC1);
#ifndef USE_SDIO_1BIT
IOConfigGPIOAF(d1, SDMMC_DATA, GPIO_AF12_SDMMC1);
IOConfigGPIOAF(d2, SDMMC_DATA, GPIO_AF12_SDMMC1);
IOConfigGPIOAF(d3, SDMMC_DATA, GPIO_AF12_SDMMC1);
#endif
if(is4BitWidth) {
IOConfigGPIOAF(d1, SDMMC_DATA, GPIO_AF12_SDMMC1);
IOConfigGPIOAF(d2, SDMMC_DATA, GPIO_AF12_SDMMC1);
IOConfigGPIOAF(d3, SDMMC_DATA, GPIO_AF12_SDMMC1);
}
IOConfigGPIOAF(clk, SDMMC_CLK, GPIO_AF12_SDMMC1);
IOConfigGPIOAF(cmd, SDMMC_CMD, GPIO_AF12_SDMMC1);
uint32_t PriorityGroup = NVIC_GetPriorityGrouping();
// NVIC configuration for SDIO interrupts
NVIC_SetPriority(SDMMC1_IRQn, NVIC_EncodePriority(PriorityGroup, 1, 0));
NVIC_EnableIRQ(SDMMC1_IRQn);
// NVIC configuration for SDIO interrupts
NVIC_SetPriority(SDMMC1_IRQn, NVIC_EncodePriority(PriorityGroup, 1, 0));
NVIC_EnableIRQ(SDMMC1_IRQn);
dma_stream = dma;
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
if ((uint32_t)dma_stream == (uint32_t)DMA2_Stream3) {
// Initialize DMA2 channel 3
DMA2_Stream3->CR = 0; // Reset DMA Stream control register
DMA2_Stream3->PAR = (uint32_t)&SDMMC1->FIFO;
DMA2->LIFCR = IFCR_CLEAR_MASK_STREAM3; // Clear all interrupt flags
DMA2_Stream3->CR = (DMA_CHANNEL_4 | DMA_SxCR_PFCTRL | // Prepare the DMA Stream configuration
DMA_MINC_ENABLE | DMA_PDATAALIGN_WORD | // And write to DMA Stream CR register
DMA_MDATAALIGN_WORD | DMA_PRIORITY_VERY_HIGH |
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
DMA_MEMORY_TO_PERIPH);
DMA2_Stream3->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
dmaInit(dmaGetIdentifier(DMA2_Stream3), OWNER_SDCARD, 0);
dmaSetHandler(dmaGetIdentifier(DMA2_Stream3), SDMMC_DMA_ST3_IRQHandler, 1, 0);
// Initialize DMA2 channel 3
DMA2_Stream3->CR = 0; // Reset DMA Stream control register
DMA2_Stream3->PAR = (uint32_t)&SDMMC1->FIFO;
DMA2->LIFCR = IFCR_CLEAR_MASK_STREAM3; // Clear all interrupt flags
DMA2_Stream3->CR = (DMA_CHANNEL_4 | DMA_SxCR_PFCTRL | // Prepare the DMA Stream configuration
DMA_MINC_ENABLE | DMA_PDATAALIGN_WORD | // And write to DMA Stream CR register
DMA_MDATAALIGN_WORD | DMA_PRIORITY_VERY_HIGH |
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
DMA_MEMORY_TO_PERIPH);
DMA2_Stream3->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
dmaInit(dmaGetIdentifier(DMA2_Stream3), OWNER_SDCARD, 0);
dmaSetHandler(dmaGetIdentifier(DMA2_Stream3), SDMMC_DMA_ST3_IRQHandler, 1, 0);
} else {
// Initialize DMA2 channel 6
DMA2_Stream6->CR = 0; // Reset DMA Stream control register
DMA2_Stream6->PAR = (uint32_t)&SDMMC1->FIFO;
DMA2->HIFCR = IFCR_CLEAR_MASK_STREAM6; // Clear all interrupt flags
DMA2_Stream6->CR = (DMA_CHANNEL_4 | DMA_SxCR_PFCTRL | // Prepare the DMA Stream configuration
DMA_MINC_ENABLE | DMA_PDATAALIGN_WORD | // And write to DMA Stream CR register
DMA_MDATAALIGN_WORD | DMA_PRIORITY_VERY_HIGH |
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
DMA_MEMORY_TO_PERIPH);
DMA2_Stream6->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
dmaInit(dmaGetIdentifier(DMA2_Stream6), OWNER_SDCARD, 0);
dmaSetHandler(dmaGetIdentifier(DMA2_Stream6), SDMMC_DMA_ST6_IRQHandler, 1, 0);
// Initialize DMA2 channel 6
DMA2_Stream6->CR = 0; // Reset DMA Stream control register
DMA2_Stream6->PAR = (uint32_t)&SDMMC1->FIFO;
DMA2->HIFCR = IFCR_CLEAR_MASK_STREAM6; // Clear all interrupt flags
DMA2_Stream6->CR = (DMA_CHANNEL_4 | DMA_SxCR_PFCTRL | // Prepare the DMA Stream configuration
DMA_MINC_ENABLE | DMA_PDATAALIGN_WORD | // And write to DMA Stream CR register
DMA_MDATAALIGN_WORD | DMA_PRIORITY_VERY_HIGH |
DMA_MBURST_INC4 | DMA_PBURST_INC4 |
DMA_MEMORY_TO_PERIPH);
DMA2_Stream6->FCR = (DMA_SxFCR_DMDIS | DMA_SxFCR_FTH); // Configuration FIFO control register
dmaInit(dmaGetIdentifier(DMA2_Stream6), OWNER_SDCARD, 0);
dmaSetHandler(dmaGetIdentifier(DMA2_Stream6), SDMMC_DMA_ST6_IRQHandler, 1, 0);
}
}
@ -1643,25 +1666,25 @@ void SD_Initialize_LL(DMA_Stream_TypeDef *dma)
/** -----------------------------------------------------------------------------------------------------------------*/
bool SD_GetState(void)
{
// Check SDCARD status
if(SD_GetStatus() == SD_OK) return true;
return false;
// Check SDCARD status
if(SD_GetStatus() == SD_OK) return true;
return false;
}
/** -----------------------------------------------------------------------------------------------------------------*/
bool SD_Init(void)
{
SD_Error_t ErrorState;
SD_Error_t ErrorState;
// Check if SD card is present
if(SD_IsDetected() != SD_PRESENT)
// Check if SD card is present
if(SD_IsDetected() != SD_PRESENT)
{
return false;
}
// Initialize SDMMC1 peripheral interface with default configuration for SD card initialization
MODIFY_REG(SDMMC1->CLKCR, CLKCR_CLEAR_MASK, (uint32_t) SDMMC_INIT_CLK_DIV);
MODIFY_REG(SDMMC1->CLKCR, CLKCR_CLEAR_MASK, (uint32_t) SDMMC_INIT_CLK_DIV);
if((ErrorState = SD_PowerON()) == SD_OK) // Identify card operating voltage
{
@ -1676,20 +1699,19 @@ bool SD_Init(void)
}
}
// Configure SD Bus width
if(ErrorState == SD_OK)
{
// Enable wide operation
#ifdef USE_SDIO_1BIT
ErrorState = SD_WideBusOperationConfig(SD_BUS_WIDE_1B);
#else
ErrorState = SD_WideBusOperationConfig(SD_BUS_WIDE_4B);
#endif
// Configure SD Bus width
if(ErrorState == SD_OK)
{
// Enable wide operation
if (sdioConfig()->use4BitWidth) {
ErrorState = SD_WideBusOperationConfig(SD_BUS_WIDE_4B);
} else {
ErrorState = SD_WideBusOperationConfig(SD_BUS_WIDE_1B);
}
}
}
// Configure the SDCARD device
return ErrorState;
// Configure the SDCARD device
return ErrorState;
}
/** -----------------------------------------------------------------------------------------------------------------*/
@ -1697,44 +1719,44 @@ bool SD_Init(void)
* @brief This function handles SD card interrupt request.
*/
void SDMMC1_IRQHandler(void) {
// Check for SDMMC1 interrupt flags
if ((SDMMC1->STA & SDMMC_STA_DATAEND) != 0) {
SDMMC1->ICR = SDMMC_ICR_DATAENDC;
SDMMC1->ICR = SDMMC_ICR_STATIC_FLAGS;
SDMMC1->MASK &= ~(SDMMC_MASK_DATAENDIE | SDMMC_MASK_DCRCFAILIE | SDMMC_MASK_DTIMEOUTIE | \
SDMMC_MASK_TXUNDERRIE | SDMMC_MASK_RXOVERRIE | SDMMC_MASK_TXFIFOHEIE | SDMMC_MASK_RXFIFOHFIE);
// Check for SDMMC1 interrupt flags
if ((SDMMC1->STA & SDMMC_STA_DATAEND) != 0) {
SDMMC1->ICR = SDMMC_ICR_DATAENDC;
SDMMC1->ICR = SDMMC_ICR_STATIC_FLAGS;
SDMMC1->MASK &= ~(SDMMC_MASK_DATAENDIE | SDMMC_MASK_DCRCFAILIE | SDMMC_MASK_DTIMEOUTIE | \
SDMMC_MASK_TXUNDERRIE | SDMMC_MASK_RXOVERRIE | SDMMC_MASK_TXFIFOHEIE | SDMMC_MASK_RXFIFOHFIE);
/* Currently doesn't implement multiple block write handling */
if ((SD_Handle.Operation & 0x02) == (SDMMC_DIR_TX << 1)) {
/* Disable the stream */
dma_stream->CR &= ~DMA_SxCR_EN;
SDMMC1->DCTRL &= ~(SDMMC_DCTRL_DMAEN);
/* Transfer is complete */
SD_Handle.TXCplt = 0;
if ((SD_Handle.Operation & 0x01) == SD_MULTIPLE_BLOCK) {
/* Send stop command in multiblock write */
SD_TransmitCommand((SD_CMD_STOP_TRANSMISSION | SD_CMD_RESPONSE_SHORT), 0, 1);
}
}
SD_Handle.TransferComplete = 1;
SD_Handle.TransferError = SD_OK; // No transfer error
}
else if ((SDMMC1->STA & SDMMC_STA_DCRCFAIL) != 0)
SD_Handle.TransferError = SD_DATA_CRC_FAIL;
else if ((SDMMC1->STA & SDMMC_STA_DTIMEOUT) != 0)
SD_Handle.TransferError = SD_DATA_TIMEOUT;
else if ((SDMMC1->STA & SDMMC_STA_RXOVERR) != 0)
SD_Handle.TransferError = SD_RX_OVERRUN;
else if ((SDMMC1->STA & SDMMC_STA_TXUNDERR) != 0)
SD_Handle.TransferError = SD_TX_UNDERRUN;
/* Currently doesn't implement multiple block write handling */
if ((SD_Handle.Operation & 0x02) == (SDMMC_DIR_TX << 1)) {
/* Disable the stream */
dma_stream->CR &= ~DMA_SxCR_EN;
SDMMC1->DCTRL &= ~(SDMMC_DCTRL_DMAEN);
/* Transfer is complete */
SD_Handle.TXCplt = 0;
if ((SD_Handle.Operation & 0x01) == SD_MULTIPLE_BLOCK) {
/* Send stop command in multiblock write */
SD_TransmitCommand((SD_CMD_STOP_TRANSMISSION | SD_CMD_RESPONSE_SHORT), 0, 1);
}
}
SD_Handle.TransferComplete = 1;
SD_Handle.TransferError = SD_OK; // No transfer error
}
else if ((SDMMC1->STA & SDMMC_STA_DCRCFAIL) != 0)
SD_Handle.TransferError = SD_DATA_CRC_FAIL;
else if ((SDMMC1->STA & SDMMC_STA_DTIMEOUT) != 0)
SD_Handle.TransferError = SD_DATA_TIMEOUT;
else if ((SDMMC1->STA & SDMMC_STA_RXOVERR) != 0)
SD_Handle.TransferError = SD_RX_OVERRUN;
else if ((SDMMC1->STA & SDMMC_STA_TXUNDERR) != 0)
SD_Handle.TransferError = SD_TX_UNDERRUN;
SDMMC1->ICR = SDMMC_ICR_STATIC_FLAGS;
SDMMC1->ICR = SDMMC_ICR_STATIC_FLAGS;
// Disable all SDMMC1 peripheral interrupt sources
SDMMC1->MASK &= ~(SDMMC_MASK_DCRCFAILIE | SDMMC_MASK_DTIMEOUTIE
| SDMMC_MASK_DATAENDIE |
SDMMC_MASK_TXFIFOHEIE | SDMMC_MASK_RXFIFOHFIE | SDMMC_MASK_TXUNDERRIE |
SDMMC_MASK_RXOVERRIE);
// Disable all SDMMC1 peripheral interrupt sources
SDMMC1->MASK &= ~(SDMMC_MASK_DCRCFAILIE | SDMMC_MASK_DTIMEOUTIE
| SDMMC_MASK_DATAENDIE |
SDMMC_MASK_TXFIFOHEIE | SDMMC_MASK_RXFIFOHFIE | SDMMC_MASK_TXUNDERRIE |
SDMMC_MASK_RXOVERRIE);
}
/** -----------------------------------------------------------------------------------------------------------------*/
@ -1743,7 +1765,7 @@ void SDMMC1_IRQHandler(void) {
*/
void SDMMC_DMA_ST3_IRQHandler(dmaChannelDescriptor_t *dma)
{
UNUSED(dma);
UNUSED(dma);
// Transfer Error Interrupt management
if((DMA2->LISR & DMA_LISR_TEIF3) != 0)
{
@ -1825,7 +1847,7 @@ void SDMMC_DMA_ST3_IRQHandler(dmaChannelDescriptor_t *dma)
*/
void SDMMC_DMA_ST6_IRQHandler(dmaChannelDescriptor_t *dma)
{
UNUSED(dma);
UNUSED(dma);
// Transfer Error Interrupt management
if((DMA2->HISR & DMA_HISR_TEIF6) != 0)
{

View file

@ -990,6 +990,7 @@ const clivalue_t valueTable[] = {
#ifdef USE_SDCARD_SDIO
{ "sdio_clk_bypass", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_SDIO_CONFIG, offsetof(sdioConfig_t, clockBypass) },
{ "sdio_use_cache", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_SDIO_CONFIG, offsetof(sdioConfig_t, useCache) },
{ "sdio_use_4bit_width", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_SDIO_CONFIG, offsetof(sdioConfig_t, use4BitWidth) },
#endif
// PG_OSD_CONFIG

View file

@ -30,6 +30,7 @@ PG_REGISTER_WITH_RESET_TEMPLATE(sdioConfig_t, sdioConfig, PG_SDIO_CONFIG, 0);
PG_RESET_TEMPLATE(sdioConfig_t, sdioConfig,
.clockBypass = 0,
.useCache = 0,
.use4BitWidth = 1
);
#endif

View file

@ -25,6 +25,7 @@
typedef struct sdioConfig_s {
uint8_t clockBypass;
uint8_t useCache;
uint8_t use4BitWidth;
} sdioConfig_t;
PG_DECLARE(sdioConfig_t, sdioConfig);