/******************************************************************************* * Function Name : MSD_SPI_Configuration * Description : SD Card SPI Configuration * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ void MSD_SPI_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); /* SPI1 Remap enable */ // GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE ); /** * SPI1_SCK -> PA5 , SPI1_MISO -> PA6 , SPI1_MOSI -> PA7 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /** * SD_CS -> PA4 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /** * SD_CD -> PB0 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure); _card_disable(); MSD_SPIHighSpeed(0); SPI_Cmd(SPI1, ENABLE); }
/******************************************************************************* * Function Name : MSD_Init * Description : SD Card initializtion * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ int MSD_Init(void) { uint8_t r1; uint8_t buff[6] = {0}; uint16_t retry; uint16_t retry_time = 5; // uint32 lu32SDStatus = 0; // uint8 err; gu8SDStatus = 0; /* Check , if no card insert */ //if( _card_insert() ) //{ /* FATFS error flag */ //return -1; //} /* Power on and delay some times */ for(retry = 0; retry < 0x100; retry++) { _card_power_on(); } /* Satrt send 74 clocks at least */ for(retry = 0; retry < 10; retry++) { _spi_read_write(DUMMY_BYTE); } /* Start send CMD0 till return 0x01 means in IDLE state */ /*begin:yangfei modified 2013-09-28 for SD卡重试次数太多,等待时间太长,SD卡正常的时候只需1次就能成功*/ #if 0 for(retry = 0; retry < 0xFFF; retry++) #else for(retry = 0; retry < retry_time; retry++) #endif { r1 = _send_command(CMD0, 0, 0x95); if(r1 == 0x01) { retry = 0; break; } } /* Timeout return */ #if 0 if(retry == 0xFFF) #else if(retry == retry_time) #endif { gu8SDStatus = 1; return 1; } /*end:yangfei modified 2013-09-28 for SD卡重试次数太多,等待时间太长,SD卡正常的时候只需1次就能成功*/ /* Get the card type, version */ r1 = _send_command_hold(CMD8, 0x1AA, 0x87); /* r1=0x05 -> V1.0 */ if(r1 == 0x05) { CardInfo.CardType = CARDTYPE_SDV1; /* End of CMD8, chip disable and dummy byte */ _card_disable(); _spi_read_write(DUMMY_BYTE); /* SD1.0/MMC start initialize */ /* Send CMD55+ACMD41, No-response is a MMC card, otherwise is a SD1.0 card */ for(retry = 0; retry < 0xFFF; retry++) { r1 = _send_command(CMD55, 0, 0); /* should be return 0x01 */ if(r1 != 0x01) { return r1; } r1 = _send_command(ACMD41, 0, 0); /* should be return 0x00 */ if(r1 == 0x00) { retry = 0; break; } } /* MMC card initialize start */ if(retry == 0xFFF) { for(retry = 0; retry < 0xFFF; retry++) { r1 = _send_command(CMD1, 0, 0); /* should be return 0x00 */ if(r1 == 0x00) { retry = 0; break; } } /* Timeout return */ if(retry == 0xFFF) { gu8SDStatus = 2; return 2; } CardInfo.CardType = CARDTYPE_MMC; } /* Set spi speed high */ MSD_SPIHighSpeed(1); /* CRC disable */ r1 = _send_command(CMD59, 0, 0x01); if(r1 != 0x00) { return r1; /* response error, return r1 */ } /* Set the block size */ r1 = _send_command(CMD16, MSD_BLOCKSIZE, 0xFF); if(r1 != 0x00) { return r1; /* response error, return r1 */ } } /* r1=0x01 -> V2.x, read OCR register, check version */ else if(r1 == 0x01) { /* 4Bytes returned after CMD8 sent */ buff[0] = _spi_read_write(DUMMY_BYTE); /* should be 0x00 */ buff[1] = _spi_read_write(DUMMY_BYTE); /* should be 0x00 */ buff[2] = _spi_read_write(DUMMY_BYTE); /* should be 0x01 */ buff[3] = _spi_read_write(DUMMY_BYTE); /* should be 0xAA */ /* End of CMD8, chip disable and dummy byte */ _card_disable(); _spi_read_write(DUMMY_BYTE); /* Check voltage range be 2.7-3.6V */ if(buff[2] == 0x01 && buff[3] == 0xAA) { for(retry = 0; retry < 0xFFF; retry++) { r1 = _send_command(CMD55, 0, 0); /* should be return 0x01 */ if(r1 != 0x01) { return r1; } r1 = _send_command(ACMD41, 0x40000000, 0); /* should be return 0x00 */ if(r1 == 0x00) { retry = 0; break; } } /* Timeout return */ if(retry == 0xFFF) { gu8SDStatus = 3; return 3; } /* Read OCR by CMD58 */ r1 = _send_command_hold(CMD58, 0, 0); if(r1 != 0x00) { return r1; /* response error, return r1 */ } buff[0] = _spi_read_write(DUMMY_BYTE); buff[1] = _spi_read_write(DUMMY_BYTE); buff[2] = _spi_read_write(DUMMY_BYTE); buff[3] = _spi_read_write(DUMMY_BYTE); /* End of CMD58, chip disable and dummy byte */ _card_disable(); _spi_read_write(DUMMY_BYTE); /* OCR -> CCS(bit30) 1: SDV2HC 0: SDV2 */ if(buff[0] & 0x40) { CardInfo.CardType = CARDTYPE_SDV2HC; } else { CardInfo.CardType = CARDTYPE_SDV2; } /* Set spi speed high */ MSD_SPIHighSpeed(1); } } return 0; }
/******************************************************************************* * Function Name : MSD_SPI_Configuration * Description : SD Card SPI Configuration * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ void MSD_SPI_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(SD_SPI_CLK, ENABLE); RCC_AHB1PeriphClockCmd( SD_SPI_SCK_GPIO_CLK | SD_SPI_MISO_GPIO_CLK | SD_SPI_MOSI_GPIO_CLK | SD_CS_GPIO_CLK | SD_DETECT_GPIO_CLK , ENABLE); /** * SCK -> PB.13 (100Mhz) */ GPIO_InitStructure.GPIO_Pin = SD_SPI_SCK_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(SD_SPI_SCK_GPIO_PORT, &GPIO_InitStructure); /** * MISO -> PB.14 (50MHz) */ GPIO_InitStructure.GPIO_Pin = SD_SPI_MISO_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(SD_SPI_MISO_GPIO_PORT, &GPIO_InitStructure); /** * MOSI -> PB.15 (50MHz) */ GPIO_InitStructure.GPIO_Pin = SD_SPI_MOSI_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(SD_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure); /* Connect SCK, MISO, MOSI pins to SPI alternate function */ GPIO_PinAFConfig(SD_SPI_SCK_GPIO_PORT , SD_SPI_SCK_SOURCE , SD_SPI_SCK_AF); GPIO_PinAFConfig(SD_SPI_MISO_GPIO_PORT, SD_SPI_MISO_SOURCE, SD_SPI_MISO_AF); GPIO_PinAFConfig(SD_SPI_MOSI_GPIO_PORT, SD_SPI_MOSI_SOURCE, SD_SPI_MOSI_AF); /** * CS -> PB.12 */ GPIO_InitStructure.GPIO_Pin = SD_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(SD_CS_GPIO_PORT, &GPIO_InitStructure); /** * CD (Card Detect) -> PB.11 */ GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStructure); _CARD_DISABLE(); MSD_SPIHighSpeed(0); SPI_Cmd(SD_SPI, ENABLE); }
/******************************************************************************* * Function Name : MSD_Init * Description : SD Card initializtion * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ int MSD_Init(void) { uint8_t r1; uint8_t buff[6] = {0}; uint16_t retry; /* Check , if no card insert */ if(_NO_CARD_INSERT()) { //printf("There is no card detected! \r\n"); return -1; } /* Power on and delay some times */ for(retry=0; retry<0x100; retry++) { _CARD_POWER_ON(); } /* Satrt send 74 clocks at least */ for(retry=0; retry<10; retry++) { _spi_read_write(DUMMY_BYTE); } /* Start send CMD0 till return 0x01 means in IDLE state */ for(retry=0; retry<0xFFF; retry++) { r1 = _send_command(CMD0, 0, 0x95); if(r1 == 0x01) { retry = 0; break; } } /* Timeout return */ if(retry == 0xFFF) { //printf("Reset card into IDLE state failed!\r\n"); return 1; } /* Get the card type, version */ r1 = _send_command_hold(CMD8, 0x1AA, 0x87); /* r1=0x05 -> V1.0 */ if(r1 == 0x05) { CardInfo.CardType = CARDTYPE_SDV1; /* End of CMD8, chip disable and dummy byte */ _CARD_DISABLE(); _spi_read_write(DUMMY_BYTE); /* SD1.0/MMC start initialize */ /* Send CMD55+ACMD41, No-response is a MMC card, otherwise is a SD1.0 card */ for(retry=0; retry<0xFFF; retry++) { r1 = _send_command(CMD55, 0, 0); /* should be return 0x01 */ if(r1 != 0x01) { //printf("Send CMD55 should return 0x01, response=0x%02x\r\n", r1); return r1; } r1 = _send_command(ACMD41, 0, 0); /* should be return 0x00 */ if(r1 == 0x00) { retry = 0; break; } } /* MMC card initialize start */ if(retry == 0xFFF) { for(retry=0; retry<0xFFF; retry++) { r1 = _send_command(CMD1, 0, 0); /* should be return 0x00 */ if(r1 == 0x00) { retry = 0; break; } } /* Timeout return */ if(retry == 0xFFF) { //printf("Send CMD1 should return 0x00, response=0x%02x\r\n", r1); return 2; } CardInfo.CardType = CARDTYPE_MMC; //printf("Card Type: MMC\r\n"); } /* SD1.0 card detected, print information */ else { //printf("Card Type: SD V1\r\n"); } /* Set spi speed high */ MSD_SPIHighSpeed(1); /* CRC disable */ r1 = _send_command(CMD59, 0, 0x01); if(r1 != 0x00) { //printf("Send CMD59 should return 0x00, response=0x%02x\r\n", r1); return r1; /* response error, return r1 */ } /* Set the block size */ r1 = _send_command(CMD16, MSD_BLOCKSIZE, 0xFF); if(r1 != 0x00) { //printf("Send CMD16 should return 0x00, response=0x%02x\r\n", r1); return r1; /* response error, return r1 */ } } /* r1=0x01 -> V2.x, read OCR register, check version */ else if(r1 == 0x01) { /* 4Bytes returned after CMD8 sent */ buff[0] = _spi_read_write(DUMMY_BYTE); /* should be 0x00 */ buff[1] = _spi_read_write(DUMMY_BYTE); /* should be 0x00 */ buff[2] = _spi_read_write(DUMMY_BYTE); /* should be 0x01 */ buff[3] = _spi_read_write(DUMMY_BYTE); /* should be 0xAA */ /* End of CMD8, chip disable and dummy byte */ _CARD_DISABLE(); _spi_read_write(DUMMY_BYTE); /* Check voltage range be 2.7-3.6V */ if(buff[2]==0x01 && buff[3]==0xAA) { for(retry=0; retry<0xFFF; retry++) { r1 = _send_command(CMD55, 0, 0); /* should be return 0x01 */ if(r1!=0x01) { //printf("Send CMD55 should return 0x01, response=0x%02x\r\n", r1); return r1; } r1 = _send_command(ACMD41, 0x40000000, 0); /* should be return 0x00 */ if(r1 == 0x00) { retry = 0; break; } } /* Timeout return */ if(retry == 0xFFF) { //printf("Send ACMD41 should return 0x00, response=0x%02x\r\n", r1); return 3; } /* Read OCR by CMD58 */ r1 = _send_command_hold(CMD58, 0, 0); if(r1!=0x00) { //printf("Send CMD58 should return 0x00, response=0x%02x\r\n", r1); return r1; /* response error, return r1 */ } buff[0] = _spi_read_write(DUMMY_BYTE); buff[1] = _spi_read_write(DUMMY_BYTE); buff[2] = _spi_read_write(DUMMY_BYTE); buff[3] = _spi_read_write(DUMMY_BYTE); /* End of CMD58, chip disable and dummy byte */ _CARD_DISABLE(); _spi_read_write(DUMMY_BYTE); /* OCR -> CCS(bit30) 1: SDV2HC 0: SDV2 */ if(buff[0] & 0x40) { CardInfo.CardType = CARDTYPE_SDV2HC; //printf("Card Type: SD V2HC\r\n"); } else { CardInfo.CardType = CARDTYPE_SDV2; //printf("Card Type: SD V2\r\n"); } /* Set spi speed high */ MSD_SPIHighSpeed(1); } } return 0; }