diff --git a/FATFS/shimatta_sdio_driver/shimatta_sdio-driver.c b/FATFS/shimatta_sdio_driver/shimatta_sdio-driver.c index faf4153..33d5fb2 100644 --- a/FATFS/shimatta_sdio_driver/shimatta_sdio-driver.c +++ b/FATFS/shimatta_sdio_driver/shimatta_sdio-driver.c @@ -20,33 +20,113 @@ #define CCRCFAIL -1 #define CTIMEOUT -2 +/* OCR Register Masks */ +#define OCS_CCS (1<<30) +#define OCS_BUSY (1<<31) + +typedef enum {ACMD41_RESP_INIT, ACMD41_RESP_ERR, ACMD41_RESP_SDSC, ACMD41_RESP_SDXC} ACMD41_RESP_t; +typedef enum {CMD8_RESP_TIMEOUT, CMD8_RESP_ACK, CMD8_RESP_ERR} CMD8_RESP_t; +typedef uint8_t CID_t; -void SDIO_DMA_Init(); void SDIO_InitModule(); int SDIO_sendCmd(uint8_t CMD, uint32_t arg, uint8_t expectedAns); int SDIO_getResp(uint8_t expectedCMD, uint8_t typeOfAns, uint32_t* responseBuffer); -int SDIO_parseR1Ans(uint32_t resp, StatusConv_t converter); -int SDIO_send_ACMD41(); + +void SDIO_wait_cmd_sent(); +ACMD41_RESP_t SDIO_send_ACMD41(uint8_t HCS); int SDIO_send_CMD55(); - +int SDIO_send_CMD2(); +int SDIO_send_CMD3(uint16_t* rca); +int SDIO_send_CMD0(); +CMD8_RESP_t SDIO_send_CMD8(); //BYTE rxtxbuffer[1<IDR & INS_PIN) == INS_ACTIVE_LEVEL)) + return STA_NODISK; +#endif /* SDIO_ENABLE_INS */ + if (cardInfo.type == CARD_NONE) { + return STA_NOINIT; + } +#if SDIO_ENABLE_WRITEPROT==1 + if (!((WRITEPROT_PORT->IDR & WRITEPROT_PIN) == WRITEPROT_ACTIVE_LEVEL)) + return STA_PROTECT; +#endif /* SDIO_ENABLE_WRITEPROT */ + return 0; } DSTATUS SDIO_initialize(){ + CMD8_RESP_t res8; + ACMD41_RESP_t resa41; + uint8_t hcs_flag = 0; cardInfo.rca = 0; cardInfo.type = CARD_NONE; - SDIO_DMA_Init(); SDIO_InitModule(); - return 0; + +#if SDIO_ENABLE_WRITEPROT==1 + WRITEPROT_PORT->PUPDR |= ((WRITEPROT_PULLUP ? 1 : 0)<PUPDR |= ((INS_PULLUP? 1 : 0)<IDR & INS_PIN) == INS_ACTIVE_LEVEL)) + return STA_NODISK; +#endif /* SDIO_ENABLE_INS */ + + SDIO_send_CMD0(); + res8 = SDIO_send_CMD8(); + switch (res8) { + case CMD8_RESP_ACK: // SDV2 Card + hcs_flag = 1; + break; + case CMD8_RESP_ERR: // should not happen + return STA_NOINIT; + break; + case CMD8_RESP_TIMEOUT: // SDV1 Card + hcs_flag=0; + break; + default: + return STA_NOINIT; + break; + } + + do { + resa41 = SDIO_send_ACMD41(hcs_flag); + }while(resa41 == ACMD41_RESP_INIT); + + switch (resa41) { + case ACMD41_RESP_SDSC: + cardInfo.type = (hcs_flag ? SD_V2_SC : SD_V1); + break; + case ACMD41_RESP_SDXC: + cardInfo.type = SD_V2_HC; + break; + default: + return STA_NOINIT; + break; + } + + if (SDIO_send_CMD2()) + return STA_NOINIT; + + if (SDIO_send_CMD3(&cardInfo.rca)) + return STA_NOINIT; + +#if SDIO_ENABLE_WRITEPROT==1 + if (!((WRITEPROT_PORT->IDR & WRITEPROT_PIN) == WRITEPROT_ACTIVE_LEVEL)) + return STA_PROTECT; +#endif /* SDIO_ENABLE_WRITEPROT */ + return 0; } DRESULT SDIO_disk_read(BYTE *buff, DWORD sector, UINT count){ return RES_OK; @@ -83,16 +163,7 @@ DWORD __attribute__((weak)) get_fattime(){ } -void SDIO_DMA_Init(){ - RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; - DMASTREAM->CR = DMAM2P; - //Address Conffiguration - //Memory address is set by write and read block functions - //DMASTREAM->M0AR = (uint32_t)&rxtxbuffer; //Has to be set in read/write func - DMASTREAM->PAR = (uint32_t)&SDIO->FIFO; //Not sure if this works - //DMASTREAM->CR |= DMA_SxCR_EN; -} void SDIO_InitModule(){ //Init Clocks @@ -141,13 +212,18 @@ void SDIO_InitModule(){ //->CRC Fail, complete response, Timeout int SDIO_sendCmd(uint8_t CMD, uint32_t arg, uint8_t expectedAns){ //Clear Flags - SDIO->ICR = SDIO_ICR_CCRCFAILC | SDIO_ICR_CMDRENDC | SDIO_ICR_CTIMEOUTC; + SDIO->ICR = SDIO_ICR_CCRCFAILC | SDIO_ICR_CMDRENDC | SDIO_ICR_CTIMEOUTC | SDIO_ICR_CMDSENTC; //Send command SDIO->ARG = arg; SDIO->CMD = (CMD & SDIO_CMD_CMDINDEX) | SDIO_CMD_CPSMEN | SDIO_CMD_WAITPEND | ((expectedAns << 6) & SDIO_CMD_WAITRESP); return 0; } +void SDIO_wait_cmd_sent() { + while (!(SDIO->STA & SDIO_STA_CMDSENT)); + SDIO->ICR |= SDIO_ICR_CMDSENTC; +} + int SDIO_getResp(uint8_t expectedCMD, uint8_t typeOfAns, uint32_t *responseBuffer) { //Return with success because no data is needed if (typeOfAns == NO_ANS) return 0; @@ -158,7 +234,7 @@ int SDIO_getResp(uint8_t expectedCMD, uint8_t typeOfAns, uint32_t *responseBuffe //Exclude ACMD41 from valid CRC check if ((SDIO->STA & SDIO_STA_CCRCFAIL)) { - if(expectedCMD == 41) { + if(expectedCMD == 0x3f) { //This command does not have a CRC...Doushite.... break;//Hopefully the response is correct. Even without CRC.... } else @@ -181,6 +257,7 @@ int SDIO_getResp(uint8_t expectedCMD, uint8_t typeOfAns, uint32_t *responseBuffe *(responseBuffer++) = SDIO->RESP4; } + } int SDIO_send_CMD55(){ @@ -203,15 +280,75 @@ int SDIO_send_CMD55(){ return -1; } -int SDIO_send_ACMD41(){ +ACMD41_RESP_t SDIO_send_ACMD41(uint8_t HCS){ + uint32_t response; int retry = 0x20; if (SDIO_send_CMD55()) return -1; do { - SDIO_sendCmd(41, 1<<30, SHORT_ANS); - //TODO: Implement Response Check... + SDIO_sendCmd(41, (HCS ? (1<<30) : 0) | (1<<28), SHORT_ANS); + if (!SDIO_getResp(0x3F, SHORT_ANS, &response)) { + if (response & OCS_BUSY) { // Card is ready... Who knows why this bit is called busy... + if (response & OCS_CCS) { + return ACMD41_RESP_SDXC; + } else { + return ACMD41_RESP_SDSC; + } + } else { + return ACMD41_RESP_INIT; + } + + } }while(--retry > 0); + + return ACMD41_RESP_ERR; +} + +int SDIO_send_CMD2() { + uint32_t response[4]; + int retry = 0x20; + do { + SDIO_sendCmd(2, 0, LONG_ANS); + if (!SDIO_getResp(0x3F, LONG_ANS, response)) return 0; + }while(retry-- > 0); +} + +int SDIO_send_CMD3(uint16_t* rca) { + uint32_t response; + int retry = 0x20; + do { + SDIO_sendCmd(3, 0, SHORT_ANS); + if (!SDIO_getResp(3, SHORT_ANS, &response)) { + // TODO: Do some *optional* checking + *rca = ((response & 0xFFFF0000) >> 16); + return 0; + } + }while(retry-- > 0); + return -1; +} + +int SDIO_send_CMD0() { + SDIO_sendCmd(0, 0, NO_ANS); + SDIO_wait_cmd_sent(); + return 0; +} + +CMD8_RESP_t SDIO_send_CMD8() { + uint32_t response; + int res = 0; + int retry = 0x20; + do { + SDIO_sendCmd(8, 0x1CC, SHORT_ANS); + res = SDIO_getResp(8, SHORT_ANS, &response); + if (res == 0) { + if (response & 0x100) + return CMD8_RESP_ACK; + else + return CMD8_RESP_ERR; + } + }while(retry-- > 0); + return CMD8_RESP_TIMEOUT; } diff --git a/FATFS/shimatta_sdio_driver/shimatta_sdio-driver.h b/FATFS/shimatta_sdio_driver/shimatta_sdio-driver.h index 7ab4883..9d0e64d 100644 --- a/FATFS/shimatta_sdio_driver/shimatta_sdio-driver.h +++ b/FATFS/shimatta_sdio_driver/shimatta_sdio-driver.h @@ -62,17 +62,13 @@ typedef struct _CardStatus { uint32_t OUT_OF_RANGE : 1; }CardStatus_t; -#define CARD_SD 1 -#define CARD_MMC 2//Never use. MMC not supported -#define CARD_NONE 0 -#define CCS_SC 0 -#define CCS_HC 1 +typedef enum {CARD_NONE = 0, MMC, SD_V1, SD_V2_SC, SD_V2_HC} card_type_t; + // MMC not supported typedef struct _SDInfo { - uint32_t rca; - uint8_t type; - uint8_t CCS; + uint16_t rca; + card_type_t type; }SDInfo_t; typedef union _StatusConv { @@ -119,4 +115,19 @@ typedef union _StatusConv { #define D3PIN 11 #define CMDPIN 2 +// Write Protection +#define SDIO_ENABLE_WRITEPROT 0 +#define WRITEPROT_PORT GPIOD // Add this port to port clock mask! +#define WRITEPROT_PIN 0 +#define WRITEPROT_PULLUP 0 +#define WRITEPROT_ACTIVE_LEVEL 0 + +// Card inserted pin +#define SDIO_ENABLE_INS 0 +#define INS_PORT GPIOD // Add this port to port clock mask! +#define INS_PIN 0 +#define INS_PULLUP 0 +#define INS_ACTIVE_LEVEL 0 + + #endif /* FATFS_SHIMATTA_SDIO_DRIVER_SHIMATTA_SDIO_DRIVER_H_ */