diff --git a/fatfs/shimatta_sdio_driver/shimatta_sdio.c b/fatfs/shimatta_sdio_driver/shimatta_sdio.c index a3f0c4e..d93eaaf 100644 --- a/fatfs/shimatta_sdio_driver/shimatta_sdio.c +++ b/fatfs/shimatta_sdio_driver/shimatta_sdio.c @@ -25,8 +25,8 @@ #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_VOLTAGE_ACCEPTED, CMD8_VOLTAGE_DENIED} CMD8_RESP_t; +typedef enum {ACMD41_RESP_INIT = 0, ACMD41_RESP_ERR, ACMD41_RESP_SDSC, ACMD41_RESP_SDXC} ACMD41_RESP_t; +typedef enum {CMD8_RESP_TIMEOUT = 0, CMD8_VOLTAGE_ACCEPTED, CMD8_VOLTAGE_DENIED} CMD8_RESP_t; typedef uint8_t CID_t; void SDIO_init_hw(); @@ -44,12 +44,16 @@ int SDIO_send_go_idle_CMD0(); CMD8_RESP_t SDIO_send_iface_condition_CMD8(); int SDIO_send_block_length_CMD16(uint32_t blocklen); int SDIO_send_bus_width_ACMD6(uint8_t bus_width); - +int SDIO_send_csd_CMD9(uint16_t rca, uint32_t *responsebuffer); +int SDIO_send_select_card_CMD7(uint16_t rca); +int SDIO_check_status_register_CMD13(uint16_t rca, uint32_t *status); void SDIO_init_detect_pins(); int checkNotInserted(); // Returns 0 if inserted! int checkWriteProtection(); // returns 0 if write protected void switchPrescaler(uint8_t clkdiv); +int SDIO_get_sector_count(uint16_t rca, uint32_t *sector_count); + //BYTE rxtxbuffer[1< 0)); - + } while((resa41 == ACMD41_RESP_INIT) && (--timeout > 0)); switch (resa41) { case ACMD41_RESP_SDSC: detected_card = (hcs_flag ? SD_V2_SC : SD_V1); @@ -119,18 +121,24 @@ DSTATUS SDIO_initialize(){ if (SDIO_send_all_send_cid_CMD2()) return STA_NOINIT; + if (SDIO_send_relative_address_CMD3(&card_info.rca)) return STA_NOINIT; + if (SDIO_get_sector_count(card_info.rca, &card_info.sector_count)) + return STA_NOINIT; + if (SDIO_send_select_card_CMD7(card_info.rca)) + return STA_NOINIT; + if (SDIO_send_block_length_CMD16((uint32_t)(1<CMD = (CMD & SDIO_CMD_CMDINDEX) | SDIO_CMD_CPSMEN | /*SDIO_CMD_WAITPEND |*/ ((expectedAns << 6) & SDIO_CMD_WAITRESP); return 0; } -unsigned int debug; + void SDIO_wait_cmd_sent() { - while (!(SDIO->STA & SDIO_STA_CMDSENT)) - { - debug = SDIO->STA; - } + while (!(SDIO->STA & SDIO_STA_CMDSENT)); SDIO->ICR |= SDIO_ICR_CMDSENTC; } @@ -270,8 +278,9 @@ int SDIO_get_response(uint8_t expectedCMD, uint8_t typeOfAns, uint32_t *response if ((SDIO->STA & SDIO_STA_CCRCFAIL)) { if(expectedCMD == 0xff) { // TODO: This seems odd.. break; - } else + } else { return -CCRCFAIL; + } } @@ -300,7 +309,7 @@ int SDIO_switch_appmode_CMD55(){ uint32_t response; do { //Execute Command and check for valid response - SDIO_send_cmd(55, card_info.rca, SHORT_ANS); + SDIO_send_cmd(55, (card_info.rca<<16)&0xFFFF0000, SHORT_ANS); if (!SDIO_get_response(55, SHORT_ANS, &response)) { @@ -314,14 +323,14 @@ int SDIO_switch_appmode_CMD55(){ return -1; } + ACMD41_RESP_t SDIO_init_card_ACMD41(uint8_t HCS){ uint32_t response; int retry = 0x20; - if (SDIO_switch_appmode_CMD55()) return -1; + if (SDIO_switch_appmode_CMD55()) return ACMD41_RESP_ERR; do { - - SDIO_send_cmd(41, (HCS ? (1<<30) : 0) | (1<<28), SHORT_ANS); + SDIO_send_cmd(41, (HCS ? (1<<30) : 0) | (1<<28) | (1<<20) |(1<<21), SHORT_ANS); if (!SDIO_get_response(0xFF, SHORT_ANS, &response)) { if (response & OCS_BUSY) { // Card is ready... Who knows why this bit is called busy... if (response & OCS_CCS) { @@ -332,10 +341,7 @@ ACMD41_RESP_t SDIO_init_card_ACMD41(uint8_t HCS){ } else { return ACMD41_RESP_INIT; } - } - - }while(--retry > 0); return ACMD41_RESP_ERR; @@ -408,7 +414,7 @@ void SDIO_init_detect_pins() { */ int checkNotInserted() { #if SDIO_ENABLE_INS - return ((INS_PORT->IDR & INS_PIN) == INS_ACTIVE_LEVEL ? 0 : 1); + return ((INS_PORT->IDR & INS_PIN) == (INS_ACTIVE_LEVEL< 0); return res; } +int SDIO_send_select_card_CMD7(uint16_t rca) { + int timeout = 0x20; + uint32_t response; + StatusConv_t status; + int res; + + /* Send CMD7. Selects card */ + do { + SDIO_send_cmd(7, (rca<<16)&0xFFFF0000, SHORT_ANS); + if (!(res = SDIO_get_response(7, SHORT_ANS, &response))) { + break; + } + } while(--timeout > 0); + + /* Check, if card in in TRANS state */ + if (SDIO_check_status_register_CMD13(rca, &(status.value))) + res = -1; + if (status.statusstruct.CURRENT_STATE != CURRENT_STATE_TRAN) + res = -2; + return res; +} + +int SDIO_check_status_register_CMD13(uint16_t rca, uint32_t *status) { + int timeout = 0x20; + uint32_t response; + int res; + do { + SDIO_send_cmd(13, (rca<<16)&0xFFFF0000, SHORT_ANS); + if (!(res = SDIO_get_response(13, SHORT_ANS, &response))) { + *status = response; + break; + } + } while(--timeout > 0); + + return res; +} + +int SDIO_get_sector_count(uint16_t rca, uint32_t *sector_count) { + uint32_t csd[4]; + int res; + uint32_t size, mult, read_len, csd_rev; + + if ((res = SDIO_send_csd_CMD9(rca, csd))) { + return -1; + } + + csd_rev = ((csd[0] >> 30) & (0x3)); + + if (csd_rev == 0) { // SD v1 Card + size = ((csd[1] & 0x3FF) <<2) | (((csd[2]) & ((1<<31) | (1<<30)))>>30); + mult = ((csd[2] & ((1<<17)|(1<<16)|(1<<15)))>>15); + read_len = (1<<((csd[1] & ((1<<19)|(1<<18)|(1<<17)|(1<<16)))>>16)); + *sector_count = (((size +1)*(1<<(mult+2))*read_len) >> BLOCKSIZE); + } else if (csd_rev == 1) { // SD v2 Card + size = (((csd[1] & 0x3F)<<16) | ((csd[2] & 0xFFFF0000) >> 16)); + *sector_count = (size << (19-BLOCKSIZE)); + } + + return 0; +} + +int SDIO_send_csd_CMD9(uint16_t rca, uint32_t *responsebuffer) { + int timeout = 0x20; + int res; + + do { + SDIO_send_cmd(9, (rca<<16)&0xFFFF0000, LONG_ANS); + if (!(res = SDIO_get_response(0xFF, LONG_ANS, responsebuffer))) { + break; + } + } while(--timeout > 0); + + return res; +} + /** * @brief checkWriteProtection * @return 0 if card is writable. */ int checkWriteProtection() { #if SDIO_ENABLE_WRITEPROT - return ((WRITEPROT_PORT->IDR & WRITEPROT_PIN) == WRITEPROT_ACTIVE_LEVEL ? 1 : 0); + return ((WRITEPROT_PORT->IDR & WRITEPROT_PIN) == (WRITEPROT_ACTIVE_LEVEL< 9 -#define BLOCKSIZE 9 //9 -//Hardware Flow: Prevents over- and underruns. -#define HW_FLOW 0 //0 -//1 bit: !=4 -//4 bit: 4 -#define BUSWIDTH 4 //4 -//Initial Transfer CLK (ca. 400kHz) -#define INITCLK 120 //120 -//Working CLK (Maximum) -#define WORKCLK 0 //0 -//Data Timeout in CLK Cycles -#define DTIMEOUT 150 //150 -//DMA Stream used for TX and RX DMA2 Stream 3 or 6 possible -#define DMASTREAM DMA2_Stream3 - - - -//Port Definitions - -#define PORTCLKMASK (RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOCEN) - -#define ALTFUNC 12 - -#define CLKPORT GPIOC -#define D0PORT GPIOC -#define D1PORT GPIOC -#define D2PORT GPIOC -#define D3PORT GPIOC -#define CMDPORT GPIOD - -#define CLKPIN 12 -#define D0PIN 8 -#define D1PIN 9 -#define D2PIN 10 -#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_ */ diff --git a/fatfs/shimatta_sdio_driver/shimatta_sdio_config.h b/fatfs/shimatta_sdio_driver/shimatta_sdio_config.h index 976ff42..d57f24b 100644 --- a/fatfs/shimatta_sdio_driver/shimatta_sdio_config.h +++ b/fatfs/shimatta_sdio_driver/shimatta_sdio_config.h @@ -14,7 +14,7 @@ //Initial Transfer CLK (ca. 400kHz) #define INITCLK 120 //120 //Working CLK (Maximum) -#define WORKCLK 0 //0 +#define WORKCLK 50 //0 //Data Timeout in CLK Cycles #define DTIMEOUT 150 //150 //DMA Stream used for TX and RX DMA2 Stream 3 or 6 possible diff --git a/main.c b/main.c index 1385bf3..2fde6ae 100644 --- a/main.c +++ b/main.c @@ -7,28 +7,27 @@ #include #include #include - +#include #define OUTPUT(pin) (0b01 << (pin * 2)) FATFS SDfs; FIL file; volatile int w; -void SDIO_wait_cmd_sent(); -int SDIO_switch_appmode_CMD55(); -int SDIO_send_all_send_cid_CMD2(); -int SDIO_send_relative_address_CMD3(uint16_t* rca); -int SDIO_send_go_idle_CMD0(); + DSTATUS SDIO_initialize(); -int SDIO_send_block_length_CMD16(uint32_t blocklen); -int SDIO_send_bus_width_ACMD6(uint8_t bus_width); +int initreq = 0xFF; int main() { RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; __DSB(); - GPIOD->MODER |= OUTPUT(12); + GPIOD->MODER |= OUTPUT(12) | OUTPUT(13); SysTick_Config(8*1680000); // f_mount(&SDfs, "0:/", 1); + //SDIO_init_hw(); + w = 0; + while(w<10); + initreq = SDIO_initialize(); while(1); }