Added CMD13 to check status

Still having trouble with cards not reponding after several minutes of
inactivity.
This commit is contained in:
victorpv 2017-05-27 09:09:48 -05:00
parent 51384097cc
commit 517ad3c418
3 changed files with 158 additions and 12 deletions

View File

@ -0,0 +1,56 @@
#ifndef _STM32_SDFAT_H_INCLUDED
#define _STM32_SDFAT_H_INCLUDED
#include "SdFat.h"
#include "SDIO.h"
class Stm32SdioCard : public BaseBlockDriver {
public:
bool begin() {
return sdio.begin();
}
bool syncBlocks() {
return true;
}
bool readBlock(uint32_t block, uint8_t* dst) {
return sdio.readBlocks(block, dst, 1);
};
bool writeBlock(uint32_t block, const uint8_t* src) {
return sdio.writeBlocks(block, src, 1);
};
bool readBlocks(uint32_t block, uint8_t* dst, size_t nb) {
return sdio.readBlocks(block, dst, nb);
};
bool writeBlocks(uint32_t block, const uint8_t* src, size_t nb) {
return sdio.writeBlocks(block, src, nb);
};
bool erase(uint32_t firstBlock, uint32_t lastBlock) {
return sdio.erase(firstBlock, lastBlock);
};
bool readCID(void* cid){
return sdio.readCID(cid);
};
bool readCSD(void* csd){
return sdio.readCSD(csd);
};
uint32_t cardSize(){
return sdio.cardSize();
};
uint8_t errorCode() {
return sdio.errorCode();
}
uint32_t errorData() {
return sdio.errorData();
}
private:
SDIOClass sdio;
};
class STM32SdFatSdio : public SdFileSystem<Stm32SdioCard> {
public:
bool begin() {
return m_card.begin() && SdFileSystem::begin();
}
};
#endif

View File

@ -31,9 +31,67 @@ inline bool setSdErrorCode(uint8_t code, uint32_t line) {
return false; // setSdErrorCode
}
uint32_t SDMMC_CmdSetWrtBlkEraseCount(SDIO_TypeDef *SDIOx, uint32_t Count){
SDIO_CmdInitTypeDef sdmmc_cmdinit;
uint32_t errorstate = SDMMC_ERROR_NONE;
//First send command 55, then ACMD.
/* Pre-erase Count blocks once Write is received */
sdmmc_cmdinit.Argument = (uint32_t)Count;
sdmmc_cmdinit.CmdIndex = 23;
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
/* Check for error conditions */
//errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_READ_MULT_BLOCK, SDIO_CMDTIMEOUT);
errorstate = SDIO_GetResponse(SDIOx, SDIO_RESP1);
if((errorstate & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO){
return HAL_OK;
}
return errorstate;
}
uint32_t SDMMC_CmdSwitchFunction(SDIO_TypeDef *SDIOx, uint32_t arg){
/*
* Todo: Finish this function, not finished yet, needs to read 64bytes and drop them.
*/
SDIO_CmdInitTypeDef sdmmc_cmdinit;
uint32_t errorstate = SDMMC_ERROR_NONE;
//First send command 55, then ACMD.
/* Pre-erase Count blocks once Write is received */
sdmmc_cmdinit.Argument = (uint32_t)arg;
sdmmc_cmdinit.CmdIndex = 6;
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
/* Check for error conditions */
//errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_READ_MULT_BLOCK, SDIO_CMDTIMEOUT);
errorstate = SDIO_GetResponse(SDIOx, SDIO_RESP1);
if((errorstate & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO){
return HAL_OK;
}
return errorstate;
}
uint32_t SDIOClass::cardStatus(){
HAL_SD_GetCardState(&hsd);
return SDIO_GetResponse(hsd.Instance, SDIO_RESP1);
}
uint8_t SDIOClass::begin() {
//GPIO_InitTypeDef GPIO_InitStruct;
if (hsd.State == HAL_SD_STATE_READY){
/*
* TODO: Check card state, may not be in transfer mode.
*/
return true;
}
__HAL_RCC_SDIO_CLK_ENABLE();
@ -63,7 +121,7 @@ uint8_t SDIOClass::begin() {
}
/*
* TODO: We can move this section to useDMA
* TODO: We can move this section to useDMA, that way none of this code is included if not using DMA
* We would need another section clearing the settings if not using DMA.
*/
_sdio_this = (void*) this;
@ -98,7 +156,11 @@ uint8_t SDIOClass::begin() {
m_errorCode = SD_CARD_ERROR_NONE;
return true;
}
/* TODO: This part needs more work, should set the card to idle state
*
*/
uint8_t SDIOClass::end() {
SDMMC_CmdGoIdleState(hsd.Instance);
return (HAL_SD_DeInit(&hsd) == HAL_OK);
}
@ -159,6 +221,25 @@ uint8_t SDIOClass::writeBlocks(uint32_t block, const uint8_t* src, size_t nb) {
if (((uint32_t)src & 0x3) !=0){
while (1); //Hang here, src was not aligned to word, this is a problem
}
uint32_t tickstart = HAL_GetTick();
while (!(cardStatus() & SDCARD_STATUS_READY_BIT)) {
SDMMC_CmdStopTransfer(hsd.Instance);
if ((HAL_GetTick() - tickstart) > sdBsyTimeout) {
DBGPRNT;
return false;
}
yield();
}
/*
if (nb > 1){
if(SDMMC_CmdAppCommand(hsd.Instance, (uint32_t)(hsd.SdCard.RelCardAdd << 16U)) != SDMMC_ERROR_NONE)
{
return false;
}
SDMMC_CmdSetWrtBlkEraseCount(hsd.Instance,nb);
}
*/
if (!_useDMA){
state = HAL_SD_WriteBlocks(&hsd,(uint8_t*) src, block, (uint32_t) nb, sd_timeout);
@ -186,15 +267,15 @@ uint8_t SDIOClass::writeBlocks(uint32_t block, const uint8_t* src, size_t nb) {
* It may need to be multiplied by a factor depending on number of blocks.
* Finally, perhaps rename sd_timeout to something else
*/
uint32_t tickstart = HAL_GetTick();
tickstart = HAL_GetTick();
while (hsd.State == HAL_SD_STATE_BUSY){
if((HAL_GetTick() - tickstart) >= sdWrTimeout * nb+1)
if((HAL_GetTick() - tickstart) >= sdWrTimeout * (nb+1))
{
/* Abort transfer and send return error */
HAL_SD_Abort(&hsd);
DBGPRNT;
Serial.print ("Timeout on write, over ");
Serial.print (sdRdTimeout * nb+1);
Serial.print (sdWrTimeout * (nb+1));
Serial.println ("ms");
return false;
}

View File

@ -4,10 +4,12 @@
#include "stdint.h"
#include "BlockDriver.h"
#include "stm32_def.h"
#define sdRdTimeout 100
#define sdWrTimeout 500
#define sdRdTimeout 200
#define sdWrTimeout 5000
#define sdBsyTimeout 500
#define sdErTimeout 250
#define sd_timeout 250 // timeout in ms in the new HAL API
#define SDCARD_STATUS_READY_BIT (1UL << 8)
/*
* Auxiliary macros to derive several names from the same values
@ -63,6 +65,12 @@
#endif
/*
* Aux function. Doesn't exist in HAL. Allows to pre-erase blocks when the count of blocks to write is known.
* ACMD23
*/
uint32_t SDMMC_CmdSetWrtBlkEraseCount(SDIO_TypeDef *SDIOx, uint32_t Count);
class SDIOClass {
HAL_StatusTypeDef state;
@ -123,6 +131,7 @@ class SDIOClass {
void _sdioCallback() {HAL_SD_IRQHandler(&hsd);}
private:
uint32_t cardStatus();
SD_HandleTypeDef hsd;
DMA_HandleTypeDef hdma_sdio;
HAL_SD_CardInfoTypeDef SDCardInfo;