rcc_periph_clock_enable(RCC_SPI_NSS_PORT(FLASH_SDCARD_SPI));// enable clock for NSS pin port peripheral for SD card CD signal
gpio_set_mode(SPI_NSS_PORT(FLASH_SDCARD_SPI),GPIO_MODE_INPUT,GPIO_CNF_INPUT_PULL_UPDOWN,SPI_NSS_PIN(FLASH_SDCARD_SPI));// set NSS pin as input to read CD signal
gpio_clear(SPI_NSS_PORT(FLASH_SDCARD_SPI),SPI_NSS_PIN(FLASH_SDCARD_SPI));// pull pin low to avoid false positive when card in not inserted
return(0!=gpio_get(SPI_NSS_PORT(FLASH_SDCARD_SPI),SPI_NSS_PIN(FLASH_SDCARD_SPI)));// read CD signal: is card is present the internal 50 kOhm pull-up resistor will override our 1 MOhm pull-down resistor and set the signal high (see section 6.2)
uint8_tcommand[5]={0x40+(index&0x3f),argument>>24,argument>>16,argument>>8,argument>>0};// commands are 5 bytes long, plus 1 bytes of CRC (see section 7.3.1.1)
uint8_tcrc7=0x00;// CRC-7 checksum for command message
// send command
for(uint8_ti=0;i<LENGTH(command);i++){
spi_send(SPI(FLASH_SDCARD_SPI),command[i]);// send data
rcc_periph_clock_enable(RCC_SPI_SCK_PORT(FLASH_SDCARD_SPI));// enable clock for GPIO peripheral for clock signal
gpio_set_mode(SPI_SCK_PORT(FLASH_SDCARD_SPI),GPIO_MODE_OUTPUT_50_MHZ,GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,SPI_SCK_PIN(FLASH_SDCARD_SPI));// set SCK as output (clock speed will be negotiated later)
rcc_periph_clock_enable(RCC_SPI_MOSI_PORT(FLASH_SDCARD_SPI));// enable clock for GPIO peripheral for MOSI signal
gpio_set_mode(SPI_MOSI_PORT(FLASH_SDCARD_SPI),GPIO_MODE_OUTPUT_50_MHZ,GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,SPI_MOSI_PIN(FLASH_SDCARD_SPI));// set MOSI as output
rcc_periph_clock_enable(RCC_SPI_MISO_PORT(FLASH_SDCARD_SPI));// enable clock for GPIO peripheral for MISO signal
gpio_set_mode(SPI_MISO_PORT(FLASH_SDCARD_SPI),GPIO_MODE_INPUT,GPIO_CNF_INPUT_PULL_UPDOWN,SPI_MISO_PIN(FLASH_SDCARD_SPI));// set MISO as input
gpio_set(SPI_MISO_PORT(FLASH_SDCARD_SPI),SPI_MISO_PIN(FLASH_SDCARD_SPI));// pull pin high to detect when the card is not answering (or not present) since responses always start with MSb 0
rcc_periph_clock_enable(RCC_SPI_NSS_PORT(FLASH_SDCARD_SPI));// enable clock for GPIO peripheral for NSS (CS) signal
gpio_set_mode(SPI_NSS_PORT(FLASH_SDCARD_SPI),GPIO_MODE_OUTPUT_10_MHZ,GPIO_CNF_OUTPUT_PUSHPULL,SPI_NSS_PIN(FLASH_SDCARD_SPI));// set NSS (CS) as output
rcc_periph_clock_enable(RCC_AFIO);// enable clock for SPI alternate function
rcc_periph_clock_enable(RCC_SPI(FLASH_SDCARD_SPI));// enable clock for SPI peripheral
spi_reset(SPI(FLASH_SDCARD_SPI));// clear SPI values to default
spi_init_master(SPI(FLASH_SDCARD_SPI),SPI_CR1_BAUDRATE_FPCLK_DIV_256,SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,SPI_CR1_CPHA_CLK_TRANSITION_1,SPI_CR1_DFF_8BIT,SPI_CR1_MSBFIRST);// initialise SPI as master, divide clock by 256 (72E6/256=281 kHz) since maximum SD card clock frequency (fOD, see section 7.8/6.6.6) during initial card-identification mode is 400 kHz (maximum SPI PCLK clock is 72 Mhz, depending on which SPI is used), set clock polarity to idle low (not that important), set clock phase to do bit change on falling edge (from SD card spec, polarity depends on clock phase), use 8 bits frames (as per spec), use MSb first
spi_set_full_duplex_mode(SPI(FLASH_SDCARD_SPI));// ensure we are in full duplex mode
spi_enable_software_slave_management(SPI(FLASH_SDCARD_SPI));// control NSS (CS) manually
spi_set_nss_high(SPI(FLASH_SDCARD_SPI));// set NSS high (internally) so we can output
gpio_set(SPI_NSS_PORT(FLASH_SDCARD_SPI),SPI_NSS_PIN(FLASH_SDCARD_SPI));// set CS high to unselect card
// sadly we can't use the interrupts as events to sleep (WFE) since sleep disables also communication (e.g. going to sleep until Rx buffer is not empty prevents transmission)
spi_enable(SPI(FLASH_SDCARD_SPI));// enable SPI
// start card-identification (see section 7.2.1/4.2)
uint8_tr1=0;
// send CMD0 (GO_IDLE_START) to start the card identification (see section 7.2.1)
r1=flash_sdcard_command_response(0,0,NULL,0);// (see table 7-3)
if(0x01!=r1){// error occurred, not in idle state
returnfalse;
}
// send CMD8 (SEND_IF_COND) to inform about voltage (1: 2.7-3.6V, aa: recommended check pattern) (see section 7.2.1)
uint8_tr7[4]={0};// to store response toke R7 (see section 7.3.2.6)
r1=flash_sdcard_command_response(8,0x000001aa,r7,sizeof(r7));// (see table 7-3)
if(0x01==r1){// command supported, in idle state
if(!(r7[2]&0x1)){// 2.7-3.6V not supported (see table 5-1)
returnfalse;
}elseif(0xaa!=r7[3]){// recommended pattern not returned (see section 4.3.13)
returnfalse;
}
}elseif(0x05!=r1){// illegal command (cards < physical spec v2.0 don't support CMD8) (see section 7.2.1)
returnfalse;
}
// send CMD58 (READ_OCR) to read Operation Conditions Register (see section 7.2.1)
uint8_tr3[4]={0};// to store response token R3 (see section 7.3.2.4)
r1=flash_sdcard_command_response(58,0,r3,sizeof(r3));// (see table 7-3)
if(0x01!=r1){// error occurred, not in idle state
returnfalse;
}elseif(!(r3[1]&0x30)){// 3.3V not supported (see table 5-1)
returnfalse;
}
do{
// send CMD55 (APP_CMD) to issue following application command (see table 7-4)
r1=flash_sdcard_command_response(55,0,NULL,0);// (see table 7-3)
if(0x01!=r1){// error occurred, not in idle state
returnfalse;
}
// send ACMD41 (SD_SEND_OP_COND) with Host Capacity Support (0b: SDSC Only Host, 1b: SDHC or SDXC Supported) (see section 7.2.1)
r1=flash_sdcard_command_response(41,0x40000000,NULL,0);// (see table 7-4)
if(r1&0xfe){// error occurred
returnfalse;
}
}while(0x00!=r1);// wait until card is ready (see section 7.2.1)
// send CMD58 (READ_OCR) to read Card Capacity Status (CCS) (see section 7.2.1)
r1=flash_sdcard_command_response(58,0,r3,sizeof(r3));// (see table 7-3)
// ensure block length is 512 bytes for SDSC (should be per default) to we match SDHC/SDXC block size
if(sdsc){
r1=flash_sdcard_command_response(16,512,NULL,0);// set block size using CMD16 (SET_BLOCKLEN) (see table 7-3)
if(r1){// error occurred
returnfalse;
}
}
// try to switch to high speed mode (see section 7.2.14/4.3.10)
if(csd[4]&0x40){// ensure CMD6 is supported by checking if command class 10 is set
uint32_tn_ac_back=n_ac;// backup N_AC
n_ac=100E-3*16E6/8;// temporarily set timeout to 100 ms (see section 4.3.10.1)
// query access mode (group function 1) to check if high speed is supported (fPP=50MHz at 3.3V, we can be faster)
uint8_tfnc[64]={0};// function status response (see table 4-12)
r1=flash_sdcard_data_read(6,0x00fffff1,fnc,sizeof(fnc));// check high speed function using CMD6 (SWITCH_FUNC) to check (mode 0) access mode (function group 1) (see table 7-3/4-30)
if(r1){// error occurred
returnfalse;
}
if(0x1==(fnc[16]&0x0f)){// we can to access mode function 1 (see table 4-12)
r1=flash_sdcard_data_read(6,0x80fffff1,fnc,sizeof(fnc));// switch to high speed function using CMD6 (SWITCH_FUNC) to switch (mode 1) access mode (function group 1) (see table 7-3/4-30)
if(r1){// error occurred
returnfalse;
}
if(0x1!=(fnc[16]&0x0f)){// could not switch to high speed
returnfalse;
}
// we can switch clock frequency to fPP (max. 50 MHz) (see section 6.6.7)
while(!(SPI_SR(SPI(FLASH_SDCARD_SPI))&SPI_SR_TXE));// wait until the end of any transmission
while(SPI_SR(SPI(FLASH_SDCARD_SPI))&SPI_SR_BSY);// wait until not busy before disabling
spi_disable(SPI(FLASH_SDCARD_SPI));// disable SPI to change clock speed
spi_set_baudrate_prescaler(SPI(FLASH_SDCARD_SPI),SPI_CR1_BR_FPCLK_DIV_2);// set clock speed to 36 MHz (72/2=36 < 50 MHz)
spi_enable(SPI(FLASH_SDCARD_SPI));// enable SPI back
n_ac_back/=2;// since we go twice faster the N_AC timeout has to be halved