//****************************************************************** //Function : to read a single block from SD card //Arguments : none //return : unsigned char; will be 0 if no error, // otherwise the response byte will be sent //****************************************************************** unsigned char SD_readSingleBlock(unsigned long startBlock, char buffer[BLOCK]) { unsigned char response; unsigned int i, retry=0; response = SD_sendCommand(READ_SINGLE_BLOCK, startBlock); //read a Block command if(response != 0x00) return response; //check for SD status: 0x00 - OK (No flags set) SD_CS_ASSERT; retry = 0; while(SpiReceive() != 0xfe) //wait for start block token 0xfe (0x11111110) if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;} //return if time-out for(i=0; i<BLOCK; i++) //read 512 bytes buffer[i] = SpiReceive(); SpiReceive(); //receive incoming CRC (16-bit), CRC is ignored here SpiReceive(); SpiReceive(); //extra 8 clock pulses SD_CS_DEASSERT; return 0; }
/** * @brief This function handles External line 0 interrupt request. * @param None * @retval None */ void EXTI9_5_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line8) != RESET) { SpiReceive(wlan_rx_buffer); /* Clear the EXTI line 0 pending bit */ EXTI_ClearITPendingBit(EXTI_Line8); } }
void SPI1_ISR(void) { ISR_ENTRY(); if (bit_is_set(SSPMIS, TXMIS)) { /* Tx half empty */ SpiTransmit(); SpiReceive(); SpiEnableRti(); } if ( bit_is_set(SSPMIS, RTMIS)) { /* Rx timeout */ SpiReceive(); SpiClearRti(); /* clear interrupt */ SpiDisableRti(); SpiDisable(); spi_message_received = TRUE; } VICVectAddr = 0x00000000; /* clear this interrupt from the VIC */ ISR_EXIT(); }
void SPI1_ISR(void) { ISR_ENTRY(); if (bit_is_set(SSPMIS, TXMIS)) { /* Tx fifo is half empty */ SpiTransmit(); SpiReceive(); SpiEnableRti(); } if (bit_is_set(SSPMIS, RTMIS)) { /* Rx fifo is not empty and no receive took place in the last 32 bits period */ SpiUnselectCurrentSlave(); SpiReceive(); SpiDisableRti(); SpiClearRti(); /* clear interrupt */ SpiDisable(); spi_message_received = TRUE; } VICVectAddr = 0x00000000; /* clear this interrupt from the VIC */ ISR_EXIT(); }
//****************************************************************** //Function : to write to a single block of SD card //Arguments : none //return : unsigned char; will be 0 if no error, // otherwise the response byte will be sent //****************************************************************** unsigned char SD_writeSingleBlock(unsigned long startBlock, char buffer[BLOCK]) { unsigned char response; unsigned int i, retry=0; response = SD_sendCommand(WRITE_SINGLE_BLOCK, startBlock); //write a Block command if(response != 0x00) return response; //check for SD status: 0x00 - OK (No flags set) SD_CS_ASSERT; SpiTransmit(0xfe); //Send start block token 0xfe (0x11111110) for(i=0; i<BLOCK; i++) //send 512 bytes data SpiTransmit(buffer[i]); SpiTransmit(0xff); //transmit dummy CRC (16-bit), CRC is ignored here SpiTransmit(0xff); response = SpiReceive(); if( (response & 0x1f) != 0x05) //response= 0xXXX0AAA1 ; AAA='010' - data accepted { //AAA='101'-data rejected due to CRC error SD_CS_DEASSERT; //AAA='110'-data rejected due to write error return response; } while(!SpiReceive()) //wait for SD card to complete writing and get idle if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;} SD_CS_DEASSERT; SpiTransmit(0xff); //just spend 8 clock cycle delay before reasserting the CS line SD_CS_ASSERT; //re-asserting the CS line to verify if card is still busy while(!SpiReceive()) //wait for SD card to complete writing and get idle if(retry++ > 0xfffe){SD_CS_DEASSERT; return 1;} SD_CS_DEASSERT; return 0; }
//****************************************************************** //Function : to send a command to SD card //Arguments : unsigned char (8-bit command value) // & unsigned long (32-bit command argument) //return : unsigned char; response byte //****************************************************************** static unsigned char SD_sendCommand(unsigned char cmd, unsigned long arg) { unsigned char response, retry=0, status; //SD card accepts byte address while SDHC accepts block address in multiples of 512 //so, if it's SD card we need to convert block address into corresponding byte address by //multiplying it with 512. which is equivalent to shifting it left 9 times //following 'if' loop does that if(SDHC_flag == 0) if(cmd == READ_SINGLE_BLOCK || cmd == WRITE_SINGLE_BLOCK || cmd == ERASE_BLOCK_START_ADDR|| cmd == ERASE_BLOCK_END_ADDR ) { arg = arg << 9; } SD_CS_ASSERT; SpiTransmit(cmd | 0x40); //send command, first two bits always '01' SpiTransmit(arg>>24); SpiTransmit(arg>>16); SpiTransmit(arg>>8); SpiTransmit(arg); if(cmd == SEND_IF_COND) //it is compulsory to send correct CRC for CMD8 (CRC=0x87) & CMD0 (CRC=0x95) SpiTransmit(0x87); //for remaining commands, CRC is ignored in SPI mode else SpiTransmit(0x95); while((response = SpiReceive()) == 0xff) //wait response if(retry++ > 0xfe) break; //time out error if(response == 0x00 && cmd == 58) //checking response of CMD58 { status = SpiReceive() & 0x40; //first byte of the OCR register (bit 31:24) if(status == 0x40) SDHC_flag = 1; //we need it to verify SDHC card else SDHC_flag = 0; SpiReceive(); //remaining 3 bytes of the OCR register are ignored here SpiReceive(); //one can use these bytes to check power supply limits of SD SpiReceive(); } SpiReceive(); //extra 8 CLK SD_CS_DEASSERT; return response; //return state }