/******************************************************************************* * Function Name : _send_command_hold * Description : None * Input : - cmd: * - arg: * - crc: * Output : None * Return : R1 value, response from card * Attention : None *******************************************************************************/ int _send_command_hold(uint8_t cmd, uint32_t arg, uint8_t crc) { uint8_t r1; uint8_t retry; /* Dummy byte and chip enable */ _spi_read_write(DUMMY_BYTE); _card_enable(); /* Command, argument and crc */ _spi_read_write(cmd | 0x40); _spi_read_write(arg >> 24); _spi_read_write(arg >> 16); _spi_read_write(arg >> 8); _spi_read_write(arg); _spi_read_write(crc); /* Wait response, quit till timeout */ for(retry = 0; retry < 200; retry++) { r1 = _spi_read_write(DUMMY_BYTE); if(r1 != 0xFF) { break; } } return r1; }
/******************************************************************************* * Function Name : MSD_SendCmd * Description : Send 5 bytes command to the MSD card. * Input : - Cmd: the user expected command to send to MSD card * - Arg: the command argument * - Crc: the CRC * Output : None * Return : None *******************************************************************************/ void MSD_SendCmd(u8 Cmd, u32 Arg, u8 Crc) { u32 i = 0x00; u8 Frame[6]; /* Construct byte1 */ Frame[0] = (Cmd | 0x40); /* Construct byte2 */ Frame[1] = (u8)(Arg >> 24); /* Construct byte3 */ Frame[2] = (u8)(Arg >> 16); /* Construct byte4 */ Frame[3] = (u8)(Arg >> 8); /* Construct byte5 */ Frame[4] = (u8)(Arg); /* Construct CRC: byte6 */ Frame[5] = (Crc); /* Send the Cmd bytes */ for (i = 0; i < 6; i++) { //MSD_WriteByte(Frame[i]); _spi_read_write(Frame[i]); } }
/******************************************************************************* * Function Name : _read_buffer * Description : None * Input : - *buff: * - len: * - release: * Output : None * Return : 0:NO_ERR; TRUE: Error * Attention : None *******************************************************************************/ int _read_buffer(uint8_t *buff, uint16_t len, uint8_t release) { uint8_t r1; uint16_t retry; /* Card enable, Prepare to read */ _card_enable(); /* Wait start-token 0xFE */ for(retry = 0; retry < 2000; retry++) { r1 = _spi_read_write(DUMMY_BYTE); if(r1 == 0xFE) { retry = 0; break; } } /* Timeout return */ if(retry == 2000) { _card_disable(); return 1; } /* Start reading */ for(retry = 0; retry < len; retry++) { *(buff + retry) = _spi_read_write(DUMMY_BYTE); } /* 2bytes dummy CRC */ _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); /* chip disable and dummy byte */ if(release) { _card_disable(); _spi_read_write(DUMMY_BYTE); } return 0; }
/******************************************************************************* * Function Name : MSD_GetDataResponse * Description : Get MSD card data response. * Input : None * Output : None * Return : The MSD status: Read data response xxx0<status>1 * - status 010: Data accecpted * - status 101: Data rejected due to a crc error * - status 110: Data rejected due to a Write error. * - status 111: Data rejected due to other error. *******************************************************************************/ u8 MSD_GetDataResponse(void) { u32 i = 0; u8 response, rvalue; while (i <= 64) { /* Read resonse */ //response = MSD_ReadByte(); response = _spi_read_write(DUMMY_BYTE); /* Mask unused bits */ response &= 0x1F; switch (response) { case MSD_DATA_OK: { rvalue = MSD_DATA_OK; break; } case MSD_DATA_CRC_ERROR: return MSD_DATA_CRC_ERROR; case MSD_DATA_WRITE_ERROR: return MSD_DATA_WRITE_ERROR; default: { rvalue = MSD_DATA_OTHER_ERROR; break; } } /* Exit loop in case of data ok */ if (rvalue == MSD_DATA_OK) break; /* Increment loop counter */ i++; } /* Wait null data */ while (_spi_read_write(DUMMY_BYTE) == 0); /* Return response */ return response; }
/******************************************************************************* * Function Name : MSD_GetResponse * Description : Returns the MSD response. * Input : None * Output : None * Return : The MSD Response: - MSD_RESPONSE_FAILURE: Sequence failed * - MSD_RESPONSE_NO_ERROR: Sequence succeed *******************************************************************************/ u8 MSD_GetResponse(u8 Response) { u32 Count = 0xFFF; /* Check if response is got or a timeout is happen */ while ((_spi_read_write(DUMMY_BYTE) != Response) && Count) { Count--; } if (Count == 0) { /* After time out */ return MSD_RESPONSE_FAILURE; } else { /* Right response got */ return MSD_RESPONSE_NO_ERROR; } }
/******************************************************************************* * Function Name : MSD_ReadMultiBlock * Description : None * Input : - sector: * - buffer: * - NbrOfSector: * Output : None * Return : None * Attention : None *******************************************************************************/ int MSD_ReadMultiBlock(uint32_t sector, uint8_t *buffer, uint32_t NbrOfSector) { uint8_t r1; uint32_t i; /* if ver = SD2.0 HC, sector need <<9 */ if(CardInfo.CardType != CARDTYPE_SDV2HC) { sector = sector<<9; } /* Send CMD18 : Read multi block command */ r1 = _send_command(CMD18, sector, 0); if(r1 != 0x00) { return 1; } /* Start read */ for(i=0; i<NbrOfSector; i++) { if(_read_buffer(buffer+i*MSD_BLOCKSIZE, MSD_BLOCKSIZE, HOLD)) { /* Send stop data transmit command - CMD12 */ _send_command(CMD12, 0, 0); /* chip disable and dummy byte */ ; return 2; } } /* Send stop data transmit command - CMD12 */ _send_command(CMD12, 0, 0); /* chip disable and dummy byte */ _CARD_DISABLE(); _spi_read_write(DUMMY_BYTE); return 0; }
/******************************************************************************* * Function Name : MSD_ReadSingleBlock * Description : None * Input : - sector: * - buffer: * Output : None * Return : None * Attention : None *******************************************************************************/ int MSD_ReadSingleBlock_DMA(uint32_t sector, uint8_t *buffer) { DMA_InitTypeDef DMA_InitStructure; u8 rvalue = MSD_RESPONSE_FAILURE; uint8_t r1; uint16_t retry; char DuumyClock = DUMMY_BYTE; if(CardInfo.CardType != CARDTYPE_SDV2HC) { sector = sector << 9; } /*initial dma channel 2*/ DMA_DeInit(DMA1_Channel4); DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI2->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 200; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel4, &DMA_InitStructure); DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&DuumyClock; //512字节的dummy DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_Low; DMA_Init(DMA1_Channel5, &DMA_InitStructure); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE); // DMA_ClearFlag(DMA_FLAG_TC2); /* Send CMD17 : Read single block command */ r1 = _send_command(CMD17, sector, 0); if(r1 != 0x00) { return 1; } /* Card enable, Prepare to read */ _card_enable(); /* Wait start-token 0xFE */ for(retry = 0; retry < 2000; retry++) { r1 = _spi_read_write(DUMMY_BYTE); if(r1 == 0xFE) { retry = 0; break; } } /* Timeout return */ if(retry == 2000) { _card_disable(); return 1; } DMA_Cmd(DMA1_Channel5, ENABLE); DMA_Cmd(DMA1_Channel4, ENABLE); while(!DMA_GetFlagStatus(DMA1_FLAG_TC5)); while(!DMA_GetFlagStatus(DMA1_FLAG_TC4)); DMA_ClearFlag(DMA1_FLAG_TC4); /* 2bytes dummy CRC */ _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); /* chip disable and dummy byte */ _card_disable(); _spi_read_write(DUMMY_BYTE); /* Set response value to success */ rvalue = MSD_RESPONSE_NO_ERROR; DMA_Cmd(DMA1_Channel4, DISABLE); DMA_Cmd(DMA1_Channel5, DISABLE); /* Returns the reponse */ return rvalue; }
/******************************************************************************* * 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_WriteMultipleBlock * Description : None * Input : - sector: * - buffer: * Output : None * Return : None * Attention : None *******************************************************************************/ int MSD_WriteMultipleBlock(uint32_t sector, uc8 *buffer, uint8_t count) { uint8_t r1; uint16_t i; uint32_t retry; /* if ver = SD2.0 HC, sector need <<9 */ if(CardInfo.CardType != CARDTYPE_SDV2HC) { sector = sector << 9; } if(CardInfo.CardType != CARDTYPE_MMC) { _send_command(ACMD23, count, 0); } /* Send CMD25 : Write multiple block command */ r1 = _send_command(CMD25, sector, 0); if(r1 != 0x00) { return 1; } /* Card enable, Prepare to write */ _card_enable(); _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); /* Start data write token: 0xFE */ //_spi_read_write(0xFE); do { _spi_read_write(0xFC); for(i = 0; i < MSD_BLOCKSIZE; i++) { _spi_read_write(*buffer++); } /* 2Bytes dummy CRC */ _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); /* MSD card accept the data */ r1 = _spi_read_write(DUMMY_BYTE); if((r1 & 0x1F) != 0x05) { _card_disable(); return 2; } /* Wait all the data programm finished */ retry = 0; while(_spi_read_write(DUMMY_BYTE) == 0x00) { /* Timeout return */ if(retry++ == 0x40000) { _card_disable(); return 3; } } } while (--count); r1 = _spi_read_write(0xFD); if(r1 == 0x00) { return 4; } /* Wait all the data programm finished */ retry = 0; while(_spi_read_write(DUMMY_BYTE) == 0x00) { /* Timeout return */ if(retry++ == 0x40000) { _card_disable(); return 5; } } /* chip disable and dummy byte */ _card_disable(); _spi_read_write(DUMMY_BYTE); return count; }
/************************************************************************************ * Function Name : MSD_WriteMultipleBlock_DMA(uint32_t sector, uc8 *buffer,u16 NumByteToWrite) * Description : None * Input : - sector: * - buffer: * Output : None * Return : None * Attention : None ************************************************************************************/ int MSD_WriteMultipleBlock_DMA(uint32_t sector, uc8 *buffer, u8 NbrOfSector, u16 NumByteToWrite) { uint8 r1; // uint16_t i=0; uint32_t retry; u8 value = 0; // INT8U err; u8 rvalue = MSD_RESPONSE_FAILURE; DMA_InitTypeDef DMA_InitStructure; //定义DMA初始化结构体 /*begin:yangfei added 2012.11.29*/ // debug("MSD_WriteMultipleBlock_DMA\r\n"); _card_enable(); DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI2->DR; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = NumByteToWrite; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); /* Enable DMA1 Channel5 Transfer Complete interrupt */ DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE); SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); /*end:yangfei added 2012.11.29*/ //SPI_DMA_Send_Init(buffer,MSD_BLOCKSIZE); /* if ver = SD2.0 HC, sector need <<9 */ if(CardInfo.CardType != CARDTYPE_SDV2HC) { sector = sector << 9; } if(CardInfo.CardType != CARDTYPE_MMC) { _send_command(ACMD23, NbrOfSector, 0); } /* Send CMD25 : Write multiple block command */ MSD_SendCmd(CMD25, sector, 0xff); //_spi_read_write(DUMMY_BYTE); //_spi_read_write(DUMMY_BYTE); if (!MSD_GetResponse(MSD_RESPONSE_NO_ERROR)) { _spi_read_write(DUMMY_BYTE); /* Start data write token: 0xFE */ _spi_read_write(0xFC); /*begin:yangfei added 2012.11.28*/ DMA_Cmd(DMA1_Channel5, ENABLE); #ifdef DMA1_IRQ OSFlagPend(Sem_SD_DMA, (OS_FLAGS)1, OS_FLAG_WAIT_SET_ALL, 0, &err); //请求信号量集的第0位置1 DMA_ClearFlag(DMA1_FLAG_TC5); #else while(!DMA_GetFlagStatus(DMA1_FLAG_TC5)) ; DMA_ClearFlag(DMA1_FLAG_TC5); #endif /* 2Bytes dummy CRC */ _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); value = MSD_GetDataResponse(); if (value == MSD_DATA_OK) { rvalue = MSD_RESPONSE_NO_ERROR; } // debug("value=%x\r\n",value); } /* Send end of transmit token: 0xFD */ r1 = _spi_read_write(0xFD); if(r1 == 0x00) { return 4; } /*begin:yangfei added 2012.12.07 for wait programm finished else write error*/ /* Wait all the data programm finished */ retry = 0; while(_spi_read_write(DUMMY_BYTE) == 0x00) { /* Timeout return */ if(retry++ == 0x40000) { _card_disable(); return 3; } } /* chip disable and dummy byte */ _card_disable(); _spi_read_write(DUMMY_BYTE); /*yangfei added*/ DMA_Cmd(DMA1_Channel5, DISABLE); return rvalue; }
/******************************************************************************* * Function Name : MSD_WriteMultiBlock * Description : None * Input : - sector: * - buffer: * - NbrOfSector: * Output : None * Return : None * Attention : None *******************************************************************************/ int MSD_WriteMultiBlock(uint32_t sector, uc8 *buffer, uint32_t NbrOfSector) { uint8_t r1; uint16_t i; uint32_t n; uint32_t retry; /* if ver = SD2.0 HC, sector need <<9 */ if(CardInfo.CardType != CARDTYPE_SDV2HC) { sector = sector<<9; } /* Send command ACMD23 berfore multi write if is not a MMC card */ if(CardInfo.CardType != CARDTYPE_MMC) { _send_command(ACMD23, NbrOfSector, 0x00); } /* Send CMD25 : Write nulti block command */ r1 = _send_command(CMD25, sector, 0); if(r1 != 0x00) { return 1; } /* Card enable, Prepare to write */ _CARD_ENABLE(); _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); for(n=0; n<NbrOfSector; n++) { /* Start multi block write token: 0xFC */ _spi_read_write(0xFC); for(i=0; i<MSD_BLOCKSIZE; i++) { _spi_read_write(*buffer++); } /* 2Bytes dummy CRC */ _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); /* MSD card accept the data */ r1 = _spi_read_write(DUMMY_BYTE); if((r1&0x1F) != 0x05) { _CARD_DISABLE(); return 2; } /* Wait all the data programm finished */ retry = 0; while(_spi_read_write(DUMMY_BYTE) != 0xFF) { /* Timeout return */ if(retry++ == 0x40000) { _CARD_DISABLE(); return 3; } } } /* Send end of transmit token: 0xFD */ r1 = _spi_read_write(0xFD); if(r1 == 0x00) { return 4; } /* Wait all the data programm finished */ retry = 0; while(_spi_read_write(DUMMY_BYTE) != 0xFF) { /* Timeout return */ if(retry++ == 0x40000) { _CARD_DISABLE(); return 5; } } /* chip disable and dummy byte */ _CARD_DISABLE(); _spi_read_write(DUMMY_BYTE); return 0; }
/******************************************************************************* * Function Name : MSD_WriteSingleBlock * Description : None * Input : - sector: * - buffer: * Output : None * Return : None * Attention : None *******************************************************************************/ int MSD_WriteSingleBlock(uint32_t sector, uc8 *buffer) { uint8_t r1; uint16_t i; uint32_t retry; /* if ver = SD2.0 HC, sector need <<9 */ if(CardInfo.CardType != CARDTYPE_SDV2HC) { sector = sector<<9; } /* Send CMD24 : Write single block command */ r1 = _send_command(CMD24, sector, 0); if(r1 != 0x00) { return 1; } /* Card enable, Prepare to write */ _CARD_ENABLE(); _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); /* Start data write token: 0xFE */ _spi_read_write(0xFE); /* Start single block write the data buffer */ for(i=0; i<MSD_BLOCKSIZE; i++) { _spi_read_write(*buffer++); } /* 2Bytes dummy CRC */ _spi_read_write(DUMMY_BYTE); _spi_read_write(DUMMY_BYTE); /* MSD card accept the data */ r1 = _spi_read_write(DUMMY_BYTE); if((r1&0x1F) != 0x05) { _CARD_DISABLE(); return 2; } /* Wait all the data programm finished */ retry = 0; while(_spi_read_write(DUMMY_BYTE) == 0x00) { /* Timeout return */ if(retry++ == 0x40000) { _CARD_DISABLE(); return 3; } } /* chip disable and dummy byte */ _CARD_DISABLE(); _spi_read_write(DUMMY_BYTE); return 0; }
/******************************************************************************* * 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; }