/******************************************************************************* * Function Name : _send_command * Description : None * Input : - cmd: * - arg: * - crc: * Output : None * Return : R1 value, response from card * Attention : None *******************************************************************************/ int _send_command(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; } } /* Chip disable and dummy byte */ _card_disable(); _spi_read_write(DUMMY_BYTE); return r1; }
/******************************************************************************* * 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_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 */ _card_disable(); 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; }
/***************************************************************************** Send a Command to Flash card and get a Response cmd: cmd index arg: argument for the cmd return the received response of the commond *****************************************************************************/ static rt_uint8_t _spi_sd_sendcmd( rt_uint8_t cmd, rt_uint32_t arg, rt_uint8_t crc ) { rt_uint32_t n; rt_uint8_t r1; #if 1 if( cmd & 0x80 ) /* ACMD<n> is the command sequence of CMD55-CMD<n> */ { cmd &= 0x7F; r1 = _spi_sd_sendcmd( APP_CMD, 0, DUMMY_CRC ); /* CMD55 */ if( r1 > 1 ) { return r1; /* cmd send failed */ } } #endif /* Select the card and wait for ready */ // LPC17xx_SPI_DeSelect(); // LPC17xx_SPI_Select(); // if (_spi_sd_wait4ready() == false ) return 0xFF; _spi_send_recv( DUMMY_BYTE ); _card_enable( ); _spi_send_recv( cmd ); _spi_send_recv( arg >> 24 ); _spi_send_recv( arg >> 16 ); _spi_send_recv( arg >> 8 ); _spi_send_recv( arg ); _spi_send_recv( crc ); #if 0 n = 10; /* Wait for a valid response in timeout of 10 attempts */ do { r1 = _spi_send_recv( DUMMY_BYTE ); } while( ( r1 & 0x80 ) && --n ); #endif #if 1 for( n = 0; n < 200; n++ ) { r1 = _spi_send_recv( DUMMY_BYTE ); if( r1 != 0xFF ) { break; } } #endif _card_disable( ); _spi_send_recv( DUMMY_BYTE ); return r1; /* Return with the response value */ }
/* Read MMC/SD Card device configuration. */ static rt_uint8_t _spi_sd_readcfg( SDCFG *cfg ) { rt_uint8_t i; rt_uint16_t csize; rt_uint8_t n, csd[16]; rt_uint8_t retv = false; /* Read the OCR - Operations Condition Register. */ if( _spi_sd_sendcmd_hold( READ_OCR, 0, DUMMY_CRC ) != 0x00 ) { goto x; } for( i = 0; i < 4; i++ ) { cfg->ocr[i] = _spi_send_recv( DUMMY_BYTE ); } _card_disable( ); _spi_send_recv( DUMMY_BYTE ); /* Read the CID - Card Identification. */ if( _spi_sd_sendcmd_hold( SEND_CID, 0, DUMMY_CRC ) != 0x00 ) { goto x; } if( _spi_sd_readdatablock( cfg->cid, 16, RELEASE ) == false ) { goto x; } rt_kprintf("\r\nCID="); for (i=0;i<16;i++) rt_kprintf("%02x ",cfg->cid[i]); /* Read the CSD - Card Specific Data. */ if( ( _spi_sd_sendcmd_hold( SEND_CSD, 0, DUMMY_CRC ) != 0x00 ) || ( _spi_sd_readdatablock( cfg->csd, 16, RELEASE ) == false ) ) { goto x; } rt_kprintf("\r\nCSD="); for (i=0;i<16;i++) rt_kprintf("%02x ",cfg->csd[i]); cfg->sectorsize = SD_SECTOR_SIZE; /* Get number of sectors on the disk (DWORD) */ if( ( cfg->csd[0] >> 6 ) == 1 ) /* SDC ver 2.00 */ { csize = cfg->csd[9] + ( (rt_uint16_t)cfg->csd[8] << 8 ) + 1; cfg->sectorcnt = (rt_uint32_t)csize << 10; } else /* SDC ver 1.XX or MMC*/ {
/*********************************************************** * Function: * Description: * Input: * Input: * Output: * Return: * Others: ***********************************************************/ static rt_uint8_t _spi_sd_readdatablock( rt_uint8_t *buff, rt_uint32_t cnt, rt_uint8_t release ) { rt_uint8_t r1; rt_uint16_t retry; _card_enable( ); for( retry = 0; retry < 2000; retry++ ) { r1 = _spi_send_recv( DUMMY_BYTE ); if( r1 == 0xFE ) { retry = 0; break; } } if( retry == 2000 ) { _card_disable( ); return false; } for( retry = 0; retry < cnt; retry++ ) { *( buff + retry ) = _spi_send_recv( DUMMY_BYTE ); } // 2bytes dummy CRC _spi_send_recv( DUMMY_BYTE ); _spi_send_recv( DUMMY_BYTE ); // chip disable and dummy byte if( release ) { _card_disable( ); _spi_send_recv( DUMMY_BYTE ); } return true; }
void _spi1_init( ) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE ); RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA, ENABLE ); GPIO_PinAFConfig( GPIOA, GPIO_PinSource5, GPIO_AF_SPI1 ); GPIO_PinAFConfig( GPIOA, GPIO_PinSource6, GPIO_AF_SPI1 ); GPIO_PinAFConfig( GPIOA, GPIO_PinSource7, GPIO_AF_SPI1 ); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_Init( GPIOA, &GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 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( GPIOA, &GPIO_InitStructure ); //_card_power_off(); _card_disable( ); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init( SPI1, &SPI_InitStructure ); SPI_Cmd( SPI1, ENABLE ); }
/***************************************************************************** Write "count" Sector(s) starting from sector index "sector", buff -> [sector, sector+1, ... sector+count-1] if success, return true, otherwise return false *****************************************************************************/ static rt_uint8_t _spi_sd_writesector( rt_uint32_t sector, const rt_uint8_t *buff, rt_uint32_t count ) { if( !( CardType & CT_BLOCK ) ) { sector *= 512; /* Convert to byte address if needed */ } if( count == 1 ) /* Single block write */ { if( ( _spi_sd_sendcmd( WRITE_BLOCK, sector, DUMMY_CRC ) == 0 ) && _spi_sd_writedatablock( buff, TOKEN_SINGLE_BLOCK ) ) { count = 0; } } else /* Multiple block write */ { if( CardType & CT_SDC ) { _spi_sd_sendcmd( SET_WR_BLK_ERASE_COUNT, count, DUMMY_CRC ); } if( _spi_sd_sendcmd( WRITE_MULT_BLOCK, sector, DUMMY_CRC ) == 0 ) { do { if( !_spi_sd_writedatablock( buff, TOKEN_MULTI_BLOCK ) ) { break; } buff += 512; } while( --count ); #if 1 if( !_spi_sd_writedatablock( 0, TOKEN_STOP_TRAN ) ) /* STOP_TRAN token */ { count = 1; } #else _spi_send_recv( TOKEN_STOP_TRAN ); #endif } } //LPC17xx_SPI_Release(); //SPI_SSOutputCmd(SPI1,DISABLE); _card_disable( ); _spi_send_recv( DUMMY_BYTE ); return count ? false : true; }
/***************************************************************************** Read "count" Sector(s) starting from sector index "sector", buff <- [sector, sector+1, ... sector+count-1] if success, return true, otherwise return false *****************************************************************************/ static rt_uint8_t _spi_sd_readsector( rt_uint32_t sector, rt_uint8_t * buff, rt_uint32_t count ) { /* Convert to byte address if needed */ if( !( CardType & CT_BLOCK ) ) { sector *= SD_SECTOR_SIZE; } if( count == 1 ) /* Single block read */ { if( _spi_sd_sendcmd_hold( READ_BLOCK, sector, DUMMY_CRC ) != 0x0 ) { return false; } if( !_spi_sd_readdatablock( buff, SD_SECTOR_SIZE, RELEASE ) ) { return false; } //if (_spi_sd_sendcmd(STOP_TRAN, 0,DUMMY_CRC) != 0x0) return false; return true; } else /* Multiple block read */ { if( !_spi_sd_sendcmd( READ_MULT_BLOCK, sector, DUMMY_CRC ) ) { return false; } do { if( !_spi_sd_readdatablock( buff, SD_SECTOR_SIZE, HOLD ) ) { return false; } buff += SD_SECTOR_SIZE; } while( --count ); _spi_sd_sendcmd( STOP_TRAN, 0, DUMMY_CRC ); /* STOP_TRANSMISSION */ } //LPC17xx_SPI_Release(); //SPI_SSOutputCmd(SPI1,DISABLE); _card_disable( ); _spi_send_recv( DUMMY_BYTE ); return true; }
/******************************************************************************* * 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_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_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( _card_insert() ) { #ifdef PRINT_INFO printf("There is no card detected! \r\n"); #endif // 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 */ for(retry=0; retry<0xFFF; retry++) { r1 = _send_command(CMD0, 0, 0x95); if(r1 == 0x01) { retry = 0; break; } } /* Timeout return */ if(retry == 0xFFF) { #ifdef PRINT_INFO printf("Reset card into IDLE state failed!\r\n"); #endif 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) { #ifdef PRINT_INFO printf("Send CMD55 should return 0x01, response=0x%02x\r\n", r1); #endif 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) { #ifdef PRINT_INFO printf("Send CMD1 should return 0x00, response=0x%02x\r\n", r1); #endif return 2; } CardInfo.CardType = CARDTYPE_MMC; #ifdef PRINT_INFO printf("Card Type : MMC\r\n"); #endif } /* SD1.0 card detected, print information */ #ifdef PRINT_INFO else { printf("Card Type : SD V1\r\n"); } #endif /* Set spi speed high */ MSD_SPIHighSpeed(1); /* CRC disable */ r1 = _send_command(CMD59, 0, 0x01); if(r1 != 0x00) { #ifdef PRINT_INFO printf("Send CMD59 should return 0x00, response=0x%02x\r\n", r1); #endif return r1; /* response error, return r1 */ } /* Set the block size */ r1 = _send_command(CMD16, MSD_BLOCKSIZE, 0xFF); if(r1 != 0x00) { #ifdef PRINT_INFO printf("Send CMD16 should return 0x00, response=0x%02x\r\n", r1); #endif 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) { #ifdef PRINT_INFO printf("Send CMD55 should return 0x01, response=0x%02x\r\n", r1); #endif return r1; } r1 = _send_command(ACMD41, 0x40000000, 0); /* should be return 0x00 */ if(r1 == 0x00) { retry = 0; break; } } /* Timeout return */ if(retry == 0xFFF) { #ifdef PRINT_INFO printf("Send ACMD41 should return 0x00, response=0x%02x\r\n", r1); #endif return 3; } /* Read OCR by CMD58 */ r1 = _send_command_hold(CMD58, 0, 0); if(r1!=0x00) { #ifdef PRINT_INFO printf("Send CMD58 should return 0x00, response=0x%02x\r\n", r1); #endif 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; #ifdef PRINT_INFO printf("Card Type : SD V2HC\r\n"); #endif } else { CardInfo.CardType = CARDTYPE_SDV2; #ifdef PRINT_INFO printf("Card Type : SD V2\r\n"); #endif } /* Set spi speed high */ MSD_SPIHighSpeed(1); } } return 0; }