/*********************************************************** * Function: * Description: * Input: * Input: * Output: * Return: * Others: ***********************************************************/ static rt_uint8_t _spi_sd_sendcmd_hold( rt_uint8_t cmd, rt_uint32_t arg, rt_uint8_t crc ) { rt_uint32_t r1, n; #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 _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 ); for( n = 0; n < 200; n++ ) { r1 = _spi_send_recv( DUMMY_BYTE ); if( r1 != 0xFF ) { break; } } return ( r1 ); /* Return with the response value */ }
/******************************************************************************* * 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; }
/***************************************************************************** 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 */ }
/******************************************************************************* * 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; }
/***************************************************************************** Write 512 bytes buffer: 512 byte data block to be transmitted token: 0xFE -> single block 0xFC -> multi block 0xFD -> Stop *****************************************************************************/ static rt_uint8_t _spi_sd_writedatablock( const rt_uint8_t *buff, rt_uint8_t token ) { rt_uint8_t resp, i=0; i = i; // avoid warning _card_enable( ); _spi_send_recv( DUMMY_BYTE ); _spi_send_recv( DUMMY_BYTE ); _spi_send_recv( DUMMY_BYTE ); _spi_send_recv( token ); /* send data token first*/ if( token != TOKEN_STOP_TRAN ) { for( i = 512 / 4; i; i-- ) { _spi_send_recv( *buff++ ); _spi_send_recv( *buff++ ); _spi_send_recv( *buff++ ); _spi_send_recv( *buff++ ); } _spi_send_recv( DUMMY_CRC ); /* 16-bit CRC (Dummy) */ _spi_send_recv( DUMMY_CRC ); resp = _spi_send_recv( DUMMY_BYTE ); /* Receive data response */ if( ( resp & 0x1F ) != 0x05 ) /* If not accepted, return with error */ { return false; } if( _spi_sd_wait4ready( ) == false ) /* Wait while Flash Card is busy. */ { return false; } } return true; }
/*********************************************************** * 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; }
/******************************************************************************* * 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_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; }