Finished SD initialization, implemented iotcl, ready to implement block transfers
This commit is contained in:
parent
b935f93ae1
commit
3831de162f
@ -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<<BLOCKSIZE]; //Data RX and TX Buffer not needed anymore. thanks to DMA
|
||||
SDInfo_t card_info; // = {.type = CARD_NONE};
|
||||
|
||||
@ -67,9 +71,8 @@ DSTATUS SDIO_status(){
|
||||
return returnval;
|
||||
}
|
||||
|
||||
|
||||
DSTATUS SDIO_initialize(){
|
||||
int timeout = 200;
|
||||
int timeout = 0x2000;
|
||||
CMD8_RESP_t res8;
|
||||
ACMD41_RESP_t resa41;
|
||||
uint8_t hcs_flag = 0;
|
||||
@ -104,7 +107,6 @@ DSTATUS SDIO_initialize(){
|
||||
do {
|
||||
resa41 = SDIO_init_card_ACMD41(hcs_flag);
|
||||
} 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<<BLOCKSIZE)))
|
||||
return STA_NOINIT;
|
||||
|
||||
if (SDIO_send_bus_width_ACMD6(BUSWIDTH))
|
||||
return STA_NOINIT;
|
||||
|
||||
|
||||
switchPrescaler(WORKCLK);
|
||||
|
||||
|
||||
card_info.type = detected_card;
|
||||
|
||||
if (checkWriteProtection()) {
|
||||
return STA_PROTECT;
|
||||
} else
|
||||
@ -152,8 +160,11 @@ DRESULT SDIO_disk_ioctl(BYTE cmd, void* buff){
|
||||
*((WORD*)buff) = (WORD)(1<<BLOCKSIZE);
|
||||
break;
|
||||
case GET_SECTOR_COUNT:
|
||||
if (card_info.type != CARD_NONE) {
|
||||
*((DWORD*)buff) = (DWORD)card_info.sector_count;
|
||||
} else {
|
||||
res = RES_ERROR;
|
||||
//TODO: Implement
|
||||
}
|
||||
break;
|
||||
case CTRL_SYNC:
|
||||
res = RES_OK;
|
||||
@ -251,12 +262,9 @@ int SDIO_send_cmd(uint8_t CMD, uint32_t arg, uint8_t expectedAns){
|
||||
SDIO->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,9 +278,10 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SDIO->STA & SDIO_STA_CTIMEOUT)
|
||||
@ -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<<INS_PIN) ? 0 : 1);
|
||||
#else
|
||||
return 0; // Assume Card is inserted
|
||||
#endif
|
||||
@ -420,9 +426,85 @@ int SDIO_send_block_length_CMD16(uint32_t blocklen) {
|
||||
uint32_t response;
|
||||
|
||||
do {
|
||||
SDIO_send_cmd(16, (0x1<<BLOCKSIZE), SHORT_ANS);
|
||||
if (!(res = SDIO_get_response(16, SHORT_ANS, &response)))
|
||||
SDIO_send_cmd(16, blocklen, SHORT_ANS);
|
||||
if (!(res = SDIO_get_response(16, SHORT_ANS, &response))) {
|
||||
return 0;
|
||||
}
|
||||
}while(--timeout > 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;
|
||||
@ -434,7 +516,7 @@ int SDIO_send_block_length_CMD16(uint32_t blocklen) {
|
||||
*/
|
||||
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<<WRITEPROT_PIN) ? 1 : 0);
|
||||
#else
|
||||
return 0; // Assume Card is not write protected
|
||||
#endif
|
||||
|
@ -68,6 +68,7 @@ typedef enum {CARD_NONE = 0, MMC, SD_V1, SD_V2_SC, SD_V2_HC} card_type_t;
|
||||
typedef struct _SDInfo {
|
||||
uint16_t rca;
|
||||
card_type_t type;
|
||||
uint32_t sector_count;
|
||||
}SDInfo_t;
|
||||
|
||||
typedef union _StatusConv {
|
||||
@ -75,58 +76,4 @@ typedef union _StatusConv {
|
||||
uint32_t value;
|
||||
}StatusConv_t;
|
||||
|
||||
//General Definitions
|
||||
//Blocksize: 512 = 2^9 => 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_ */
|
||||
|
@ -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
|
||||
|
17
main.c
17
main.c
@ -7,28 +7,27 @@
|
||||
#include <stm32f4xx.h>
|
||||
#include <cmsis/arm_math.h>
|
||||
#include <fatfs/ff.h>
|
||||
|
||||
#include <fatfs/diskio.h>
|
||||
#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);
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user