Added CMD13 to check status
Still having trouble with cards not reponding after several minutes of inactivity.
This commit is contained in:
parent
51384097cc
commit
517ad3c418
|
@ -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
|
|
@ -31,9 +31,67 @@ inline bool setSdErrorCode(uint8_t code, uint32_t line) {
|
||||||
return false; // setSdErrorCode
|
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() {
|
uint8_t SDIOClass::begin() {
|
||||||
//GPIO_InitTypeDef GPIO_InitStruct;
|
//GPIO_InitTypeDef GPIO_InitStruct;
|
||||||
if (hsd.State == HAL_SD_STATE_READY){
|
if (hsd.State == HAL_SD_STATE_READY){
|
||||||
|
/*
|
||||||
|
* TODO: Check card state, may not be in transfer mode.
|
||||||
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
__HAL_RCC_SDIO_CLK_ENABLE();
|
__HAL_RCC_SDIO_CLK_ENABLE();
|
||||||
|
@ -56,14 +114,14 @@ uint8_t SDIOClass::begin() {
|
||||||
}
|
}
|
||||||
HAL_SD_GetCardStatus(&hsd, &CardStatus);
|
HAL_SD_GetCardStatus(&hsd, &CardStatus);
|
||||||
|
|
||||||
state = HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B);
|
state = HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B);
|
||||||
if (state != HAL_OK) {
|
if (state != HAL_OK) {
|
||||||
DBGPRNT;
|
DBGPRNT;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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.
|
* We would need another section clearing the settings if not using DMA.
|
||||||
*/
|
*/
|
||||||
_sdio_this = (void*) this;
|
_sdio_this = (void*) this;
|
||||||
|
@ -98,7 +156,11 @@ uint8_t SDIOClass::begin() {
|
||||||
m_errorCode = SD_CARD_ERROR_NONE;
|
m_errorCode = SD_CARD_ERROR_NONE;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
/* TODO: This part needs more work, should set the card to idle state
|
||||||
|
*
|
||||||
|
*/
|
||||||
uint8_t SDIOClass::end() {
|
uint8_t SDIOClass::end() {
|
||||||
|
SDMMC_CmdGoIdleState(hsd.Instance);
|
||||||
return (HAL_SD_DeInit(&hsd) == HAL_OK);
|
return (HAL_SD_DeInit(&hsd) == HAL_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +176,7 @@ uint8_t SDIOClass::readBlocks(uint32_t block, uint8_t* dst, size_t nb) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//common with dma, so it's down at the end
|
//common with dma, so it's down at the end
|
||||||
//return HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER;
|
//return HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -159,6 +221,25 @@ uint8_t SDIOClass::writeBlocks(uint32_t block, const uint8_t* src, size_t nb) {
|
||||||
if (((uint32_t)src & 0x3) !=0){
|
if (((uint32_t)src & 0x3) !=0){
|
||||||
while (1); //Hang here, src was not aligned to word, this is a problem
|
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){
|
if (!_useDMA){
|
||||||
state = HAL_SD_WriteBlocks(&hsd,(uint8_t*) src, block, (uint32_t) nb, sd_timeout);
|
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.
|
* It may need to be multiplied by a factor depending on number of blocks.
|
||||||
* Finally, perhaps rename sd_timeout to something else
|
* Finally, perhaps rename sd_timeout to something else
|
||||||
*/
|
*/
|
||||||
uint32_t tickstart = HAL_GetTick();
|
tickstart = HAL_GetTick();
|
||||||
while (hsd.State == HAL_SD_STATE_BUSY){
|
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 */
|
/* Abort transfer and send return error */
|
||||||
HAL_SD_Abort(&hsd);
|
HAL_SD_Abort(&hsd);
|
||||||
DBGPRNT;
|
DBGPRNT;
|
||||||
Serial.print ("Timeout on write, over ");
|
Serial.print ("Timeout on write, over ");
|
||||||
Serial.print (sdRdTimeout * nb+1);
|
Serial.print (sdWrTimeout * (nb+1));
|
||||||
Serial.println ("ms");
|
Serial.println ("ms");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,12 @@
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include "BlockDriver.h"
|
#include "BlockDriver.h"
|
||||||
#include "stm32_def.h"
|
#include "stm32_def.h"
|
||||||
#define sdRdTimeout 100
|
#define sdRdTimeout 200
|
||||||
#define sdWrTimeout 500
|
#define sdWrTimeout 5000
|
||||||
|
#define sdBsyTimeout 500
|
||||||
#define sdErTimeout 250
|
#define sdErTimeout 250
|
||||||
#define sd_timeout 250 // timeout in ms in the new HAL API
|
#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
|
* Auxiliary macros to derive several names from the same values
|
||||||
|
@ -63,6 +65,12 @@
|
||||||
|
|
||||||
#endif
|
#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 {
|
class SDIOClass {
|
||||||
HAL_StatusTypeDef state;
|
HAL_StatusTypeDef state;
|
||||||
|
|
||||||
|
@ -123,6 +131,7 @@ class SDIOClass {
|
||||||
void _sdioCallback() {HAL_SD_IRQHandler(&hsd);}
|
void _sdioCallback() {HAL_SD_IRQHandler(&hsd);}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint32_t cardStatus();
|
||||||
SD_HandleTypeDef hsd;
|
SD_HandleTypeDef hsd;
|
||||||
DMA_HandleTypeDef hdma_sdio;
|
DMA_HandleTypeDef hdma_sdio;
|
||||||
HAL_SD_CardInfoTypeDef SDCardInfo;
|
HAL_SD_CardInfoTypeDef SDCardInfo;
|
||||||
|
|
Loading…
Reference in New Issue