UINT8 SD_Init(void) { _SD_PRESENT=_IN; /* Check for SD */ if(SD_PRESENT) return(NO_SD_CARD); /* Initialize SPI Module */ SPI_Init(); /* Start SD card Init */ SPI_SS=ENABLE; SD_CLKDelay(10); // Send 80 clocks SPI_SS=DISABLE; gu8SD_Argument.lword=0; SD_CLKDelay(8); /* IDLE Command */ SPI_SS=ENABLE; if(SD_SendCommand(SD_CMD0|0x40,SD_IDLE)) { SPI_SS=DISABLE; return(INIT_FAILS); } SPI_SS=DISABLE; (void)SPI_Receive_byte(); // Dummy SPI cycle /* Initialize SD Command */ SPI_SS=ENABLE; while(SD_SendCommand(SD_CMD1|0x40,SD_OK)); SPI_SS=DISABLE; (void)SPI_Receive_byte(); // Dummy SPI cycle /* Block Length */ SPI_SS=ENABLE; gu8SD_Argument.lword=SD_BLOCK_SIZE; if(SD_SendCommand(SD_CMD16|0x40,SD_OK)) { SPI_SS=DISABLE; return(INIT_FAILS); } SPI_SS=DISABLE; SPI_High_rate(); SPI_Send_byte(0x00); SPI_Send_byte(0x00); return(OK); }
/***************************************************************************** * ************* SD_Erase_Blocks *********** * * Description: Erase multiple sectors (blocks) no the SD card. * * Inputs: u32SD_Start_Block - the sector (block) number of the first * block to be erased. * u32SD_End_Block - the sector (block) number of the last * block to be erased. * *****************************************************************************/ UINT8 SD_Erase_Blocks(UINT32 u32SD_Start_Block, UINT32 u32SD_End_Block) { UINT8 res; UINT16 u16Counter; SPI_SS = ENABLE; /* Set the address of the first write block to be erased */ gu8SD_Argument.lword = u32SD_Start_Block; // Set ERASE_WR_BLK_START_ADDR // command argument gu8SD_Argument.lword = gu8SD_Argument.lword << SD_BLOCK_SHIFT; // Convert sector number to // byte address if (SD_SendCommand(SD_CMD32 | 0x40, SD_OK)) // ERASE_WR_BLK_START_ADDR command { SPI_SS = DISABLE; return (WRITE_COMMAND_FAILS); } SD_CLKDelay(1); // 8 dummy clocks /* Set the address of the last write block to be erased */ gu8SD_Argument.lword = u32SD_End_Block; // Set ERASE_WR_BLK_END_ADDR // command argument gu8SD_Argument.lword = gu8SD_Argument.lword << SD_BLOCK_SHIFT; // Convert sector number to // byte address if (SD_SendCommand(SD_CMD33 | 0x40, SD_OK)) // ERASE_WR_BLK_END_ADDR command { SPI_SS = DISABLE; return (WRITE_COMMAND_FAILS); } SD_CLKDelay(1); // 8 dummy clocks /* Send the erase command */ gu8SD_Argument.lword = 0x00000000; // stuff bits if (SD_SendCommand(SD_CMD38 | 0x40, SD_OK)) // ERASE command { SPI_SS = DISABLE; return (WRITE_COMMAND_FAILS); } /* Wait while card is busy. Indicated by reading 0x00 from SD Card */ u16Counter = 0; // Counter to see if it is doing something do { res = SPI_Receive_byte(); u16Counter++; } while (res == 0x00); // Wait while the card is busy SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks return (OK); }
void loopUntilReady() { SD_CLKDelay(5); //SPI_Send_byte(0xFF); //while (SPI_Receive_byte() != 0xFF) { // SPI1_Send_byte(0xFF); //} }
UINT8 SD_Read_Block(UINT32 u16SD_Block, UINT8 *pu8DataPointer) { UINT8 u8Temp = 0; UINT16 u16Counter; SPI_SS = ENABLE; gu8SD_Argument.lword = u16SD_Block; gu8SD_Argument.lword = gu8SD_Argument.lword << SD_BLOCK_SHIFT; if (SD_SendCommand(SD_CMD17 | 0x40, SD_OK)) { SPI_SS = DISABLE; return (READ_COMMAND_FAILS); } while (u8Temp != 0xFE) u8Temp = SPI_Receive_byte(); for (u16Counter = 0; u16Counter < BLOCK_SIZE; u16Counter++) *pu8DataPointer++ = SPI_Receive_byte(); (void) ReadSPIByte(); // Dummy SPI cycle, read CRC (void) ReadSPIByte(); SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks return (OK); }
/***************************************************************************** * * *** SD_Read_CSD *** * * Read the SD Card Card-Specific Data Register (CSD). * * The CSD is a 16 byte SD Card register that is read with the * CMD9 SEND_CSD command. * * Output: If read successful return OK with CSD register in gu8SD_CSD[0-16] * with MSB in gu8SD_CSD[0]. * Else return READ_COMMAND_FAILS. * * ******************************************************************************/ UINT8 SD_Read_CSD(void) { UINT8 u8Temp = 0, u8Counter; SPI_SS = ENABLE; gu8SD_Argument.lword = 0x00000000; if (SD_SendCommand(SD_CMD9 | 0x40, SD_OK)) { SPI_SS = DISABLE; return (READ_COMMAND_FAILS); } while (u8Temp != 0xFE) u8Temp = SPI_Receive_byte(); for (u8Counter = 0; u8Counter < 16; u8Counter++) gu8SD_CSD[u8Counter] = SPI_Receive_byte(); (void) ReadSPIByte(); // Dummy SPI cycle for CRC (void) ReadSPIByte(); SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks return (OK); }
uint_8 SD_Init(void) { /* Body */ SPI_Init(); /* SPI Initialization */ SPI_set_SS(); SD_CLKDelay(10); /* Send 80 clocks */ SPI_clr_SS() ; gu8SD_Argument.lword = 0; SD_CLKDelay(8); /* IDLE Command */ SPI_set_SS(); if(SD_SendCommand(SD_CMD0|0x40,SD_IDLE)) { SPI_clr_SS() ; return(1); /* Command IDLE fail */ } /* EndIf */ SPI_clr_SS() ; (void)SPI_Receive_byte(); /* Dummy SPI cycle */ /* Initialize SD Command */ SPI_set_SS(); while(SD_SendCommand(SD_CMD1|0x40,SD_OK)) { __RESET_WATCHDOG(); } /* EndWhile */ SPI_clr_SS() ; (void)SPI_Receive_byte(); /* Dummy SPI cycle */ /* Block Length */ SPI_set_SS(); gu8SD_Argument.lword = SD_BLOCK_SIZE; if(SD_SendCommand(SD_CMD16|0x40,SD_OK)) { SPI_clr_SS() ; return(1); /* Command IDLE fail */ } /* EndIf */ SPI_clr_SS() ; SPI_High_rate(); SPI_Send_byte(0x00); SPI_Send_byte(0x00); return(0); } /* EndBody */
uint_8 SD_Init(void) { SPI_Init(); // SPI Initialization SD_CLKDelay(10); // Send 80 clocks gu8SD_Argument.lword = 0; SD_CLKDelay(8); /* IDLE Command */ if(SD_SendCommand(SD_CMD0|0x40,SD_IDLE)) { return(1); // Command IDLE fail } (void)SPI_Receive_byte(); // Dummy SPI cycle /* Initialize SD Command */ while(SD_SendCommand(SD_CMD1|0x40,SD_OK)) { Watchdog_Reset(); } (void)SPI_Receive_byte(); // Dummy SPI cycle /* Block Length */ gu8SD_Argument.lword = SD_BLOCK_SIZE; if(SD_SendCommand(SD_CMD16|0x40,SD_OK)) { return(1); // Command IDLE fail } SPI_High_rate(); SPI_Send_byte(0x00); SPI_Send_byte(0x00); //(void)SPI_Receive_byte(); // Dummy SPI cycle return(0); }
/*************************************************************************************** * * *** SD_CBufferDataSectorWrite *** * * Description: Write a 512 bytes from the circular buffer as a data sector. * Assume: * - SD Card has been previously erased. * - Write a full sector at a time. * * Entry: void. * ****************************************************************************************/ void SD_CBufferDataSectorWrite(void) { UINT16 u16Counter; SPI_SS = ENABLE; gu8SD_Argument.lword = u32DataSector++; // Set WRITE_BLOCK command argument // to the current data segment gu8SD_Argument.lword = gu8SD_Argument.lword << SD_BLOCK_SHIFT; // Convert sector number to // byte address if (SD_SendCommand(SD_CMD24 | 0x40, SD_OK)) // WRITE_BLOCK command { SPI_SS = DISABLE; return; } WriteSPIByte(0xFE); // Start Block Token for (u16Counter = 0; u16Counter < BLOCK_SIZE; u16Counter++) // Write the block WriteSPIByte(FromCBuffer()); WriteSPIByte(0xFF); // checksum Bytes not needed WriteSPIByte(0xFF); // for(u16Counter=0;u16Counter<BLOCK_SIZE;u16Counter++); // if((ReadSPIByte() & 0x0F) != 0x05) // Read the status token. // Correct response is 0x05 // Foust p5. while ((SPI_Receive_byte() & 0x0F) != 0x05) ; // { // SPI_SS=DISABLE; // return; // } while (SPI_Receive_byte() == 0x00) ; // Wait while the card is busy SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks return; }
/***************************************************************************** * **************SD_Write_Block************ * * Description: Write a 512 byte sector (block) to the SD card. * * Inputs: u16SD_Block - the sector (block) number where the block is * to be written. * pu8DataPointer - the 512 byte buffer that is to be written * to the SD card. * *****************************************************************************/ UINT8 SD_Write_Block(UINT32 u16SD_Block, UINT8 *pu8DataPointer) { UINT16 u16Counter; SPI_SS = ENABLE; gu8SD_Argument.lword = u16SD_Block; // Set WRITE_BLOCK command argument gu8SD_Argument.lword = gu8SD_Argument.lword << SD_BLOCK_SHIFT; // Convert sector number to // byte address if (SD_SendCommand(SD_CMD24 | 0x40, SD_OK)) // WRITE_BLOCK command { SPI_SS = DISABLE; return (WRITE_COMMAND_FAILS); } WriteSPIByte(0xFE); // Start Block Token for (u16Counter = 0; u16Counter < BLOCK_SIZE; u16Counter++) // Write the block WriteSPIByte(*pu8DataPointer++); WriteSPIByte(0xFF); // checksum Bytes not needed WriteSPIByte(0xFF); for (u16Counter = 0; u16Counter < BLOCK_SIZE; u16Counter++) ; if ((ReadSPIByte() & 0x0F) != 0x05) // Read the status token. // Correct response is 0x05 // Foust p5. { SPI_SS = DISABLE; return (WRITE_DATA_FAILS); } while (SPI_Receive_byte() == 0x00) ; // Wait while the card is busy SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks return (OK); }
/*********************************************************************** * * SD_Init * * Description: Configures the SPI2 module and the File system to handle * an SD Card. * * Returns: OK if SPI configured, SD card is present, CMD0 true, * SD card initialised, block length set to 512, * SPI clock set to 4MHz. * NO_SD_CARD if no SD card is present. * INIT_FAILS if CMD0 (idle) fails, block length set fails. * * . * *************************************************************************/ UINT8 SD_Init(void) { UINT8 Count; UINT8 res; UINT8 CRC7_BYTE; UINT8 j; UINT8 i = 0; /* Configure the SD Card inserted detection pin */_SD_PRESENT = _IN; // Configure the data direction as IN. SD_PRESENT_PU = 1; // Enable Internal Pull-UP Resistor /* Initialise SPI Module */InitSPI(); // SS high, 375kHz clock. /* Delay SD card requires a delay of at least 1mSec after power up */ for (j = 0; j < 200; j++) { for (Count = 0; Count < 255; Count++) { i += 1; } } /* Check for SD */ if (SD_PRESENT) // Pin is low when SD Card present // return(NO_SD_CARD); return (0x11); /*** Start SD card Init ***/ /* Minimum of 74 dummy clock cycles with MOSI high & SS enabled (low) */ // SPI_SS = ENABLE; // Enable SS // SD_CLKDelay(10); // Send 80 clocks // SPI_SS_Disable_Delay(); // SPI_SS = DISABLE; SD_CLKDelay(10); // Send 80 clocks with SS disabled SPI_SS_Disable_Delay(); /* CMD0 - GO_IDLE_STATE Reset the sd card & place it in SPI mode. CRC must be valid. Valid reset command is 0x40, 0x00, 0x00, 0x00, 0x00, 0x95. Correct response is R1 (1 byte) = SD_IDLE (0x01). Note that the command frame starts with bits 47:46=0:1 (start & transmission bits) so the CMD byte has b6 set. */ SPI_SS = ENABLE; gu8SD_Argument.lword = 0; // CMD0 argument is 0x00, 0x00, 0x00, 0x00. if (SD_SendCommand(SD_CMD0 | 0x40, SD_IDLE)) // returns OK (0x00) if OK { SPI_SS = DISABLE; // return(INIT_FAILS); return (0x12); } /* Card is in Idle State */ SPI_SS_Disable_Delay(); SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks /* Check if card is Ver2 compliant. Send a SEND_IF_COND (CMD8) with supply voltage (VHS) set to 2.7-3.6volts. Argument will be 0x000001AA and CRC7 + end bit 0x87. CMD8 response is R7 (5 bytes - R1 + argument). */ SPI_SS = ENABLE; gu8SD_Argument.lword = 0x000001AA; CRC7_BYTE = 0x87; if (SD_SendCommandR7(SD_CMD8, CRC7_BYTE)) { SPI_SS = DISABLE; // return(INIT_FAILS); return (0x13); } /* Card is version 2 compliant */ SPI_SS_Disable_Delay(); SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks /* Read the Operation Conditions Register OCR & check for correct voltage range. Valid voltage range of 2.7-3.6 volts is indicated by gu8SD_Response[2:3] = 0xFF:0x80. Ref Table 5-1 P92. Send READ_OCR CMD58. CMD58 response R3 (5bytes - R1 + OCR). */SPI_SS = ENABLE; gu8SD_Argument.lword = 0x00000000; CRC7_BYTE = 0xFD; if (SD_SendCommandR3(SD_CMD58, SD_IDLE, CRC7_BYTE)) // Correct R1 is SD_IDLE (0x01) { SPI_SS = DISABLE; // return(INIT_FAILS); return (0x14); } /* Valid response received */ SPI_SS_Disable_Delay(); SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks /* Check for correct voltage range */ if ((gu8SD_Response[2] != 0xFF) && (gu8SD_Response[3] != 0x80)) { // return(INIT_FAILS); return (0x15); } /* Initialise Card */ /* Send continuous SD_SEND_OP_COND (ACMD41) until R1 b0 clears. */ j = 0; // Clear loop counter do { j++; /* The next command is an application-specific command */ do { // Wait for a successful CMD55 /* The next command is an application-specific command */ SPI_SS = ENABLE; // Enable SS gu8SD_Argument.lword = 0x00000000; // res = SD_SendCommand(SD_CMD55|0x40,0x80); // returns OK (0x00) if res = SD_SendCommand(SD_CMD55 | 0x40, SD_IDLE); // returns OK (0x00) if // any valid response received SPI_SS_Disable_Delay(); SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks } while (res); /* Send SD_SEND_OP_COND (ACMD41) */ do { SPI_SS = ENABLE; // Enable SS /* High Capacity Support (HCS - argument b30) is set if host supports SDHC or SDXC, wgich it does not in this case. */ // gu8SD_Argument.lword = 0x40000000; // HCS set gu8SD_Argument.lword = 0x00000000; // HCS clear res = SD_SendCommand(SD_CMD41 | 0x40, 0x80); // returns OK (0x00) if // res = SD_SendCommand(SD_CMD41|0x40,SD_OK); // returns OK (0x00) if // any valid response received SPI_SS_Disable_Delay(); SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks } while (res); } while ((gu8SD_Response[0] != SD_OK) && (j < SD_IDLE_WAIT_MAX)); /* Assume we're OK if we didn't hit the timeout */ if (j >= SD_IDLE_WAIT_MAX) // return(INIT_FAILS); return (0x16); /* Read the Operation Conditions Register OCR & check the Card Power Up Status bit b31 and Card Capacity Status (CCS) b30. b31 & b30 of the OCR which is gu8SD_Response[1] b6. Power Up Status Bit will be 1 when the card is finished powering up. CCS is 0 for a SDSC. Ref Table 5-1 P92. Send READ_OCR CMD58. CMD58 response R3 (5bytes - R1 + OCR). */SPI_SS = ENABLE; gu8SD_Argument.lword = 0x00000000; CRC7_BYTE = 0xFD; if (SD_SendCommandR3(SD_CMD58, SD_OK, CRC7_BYTE)) // Correct R1 response is SD_OK (0x00) { SPI_SS = DISABLE; // return(INIT_FAILS); return (0x17); } /* Valid response received */ SPI_SS_Disable_Delay(); SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks /* Check Power Up Status */ if ((gu8SD_Response[1] & 0x80) == 0x00) return (0x19); // return Power Up not finished. /* Check CCS */ if (gu8SD_Response[1] & 0x40) return (0x1A); // return Card is not SDSC. /* Set the Block Length to 512 bytes */SPI_SS = ENABLE; gu8SD_Argument.lword = SD_BLOCK_SIZE; // 512 bytes if (SD_SendCommand(SD_CMD16 | 0x40, SD_OK)) { SPI_SS = DISABLE; // return(INIT_FAILS); return (0x18); } SPI_SS_Disable_Delay(); SPI_SS = DISABLE; SD_CLKDelay(1); // 8 dummy clocks // WriteSPIByte(0x00); // WriteSPIByte(0x00); /* Read the Card-Specific Data register (CSD) to gu8SD_CSD[16] */ if (SD_Read_CSD()) { return (0x1B); // error 11. CSD read fail } HighSpeedSPI(); return (OK); }
uint_8 SD_Init(void) { #ifdef MCU_MKL25Z4 SPI_Init(); /* SPI Initialization */ SD_CLKDelay(10); /* Send 80 clocks */ SPI_clr_SS() ; gu8SD_Argument.lword = 0; SPI_set_SS(); SD_CLKDelay(8); /* IDLE Command */ SPI_set_SS(); if(SD_SendCommand(SD_CMD0|0x40,SD_IDLE)) { SPI_clr_SS(); return(FALSE); /* Command IDLE fail */ } SPI_clr_SS(); (void)SPI_Receive_byte(); /* Dummy SPI cycle */ /* Initialize SD Command */ SPI_set_SS(); while(SD_SendCommand(SD_CMD1|0x40,SD_OK)) { Watchdog_Reset(); } SPI_clr_SS() ; (void)SPI_Receive_byte(); /* Dummy SPI cycle */ /* Block Length */ gu8SD_Argument.lword = BYTESWAP32(SD_BLOCK_SIZE); SPI_set_SS(); if(SD_SendCommand(SD_CMD16|0x40,SD_OK)) { SPI_clr_SS() ; return(FALSE); /* Command IDLE fail */ } SPI_clr_SS() ; SPI_High_rate(); SPI_Send_byte(0x00); SPI_Send_byte(0x00); return(TRUE); #else /*Body*/ SPI_Init(); /* SPI Initialization*/ SD_CLKDelay(10); /* Send 80 clocks*/ gu8SD_Argument.lword = 0; SD_CLKDelay(8); /* IDLE Command */ if(SD_SendCommand(SD_CMD0|0x40,SD_IDLE)) { return(FALSE); /* Command IDLE fail*/ }/*Endif*/ (void)SPI_Receive_byte(); /* Dummy SPI cycle*/ /* Initialize SD Command */ while(SD_SendCommand(SD_CMD1|0x40,SD_OK)) { Watchdog_Reset(); }/*EndWhile*/ (void)SPI_Receive_byte(); /*Dummy SPI cycle */ /* Block Length */ gu8SD_Argument.lword = BYTESWAP32(SD_BLOCK_SIZE); if(SD_SendCommand(SD_CMD16|0x40,SD_OK)) { return(FALSE); /* Command IDLE fail */ }/*Endif*/ SPI_High_rate(); SPI_Send_byte(0x00); SPI_Send_byte(0x00); return(TRUE); #endif }/*End Body*/
UINT8 SD_Init(void) { T32_8 gu8SD_Argument; SD_PRESENT_INIT; SD_PROTECTED_INIT; /* Check for SD */ if(SD_PRESENT) { return(NO_SD_CARD); } /* Initialize SPI Module */ SD_DISABLE;/*First init*/ /**********************FSL: SPI start-up*******************************/ //if SPIhandle NULL, serial cannot be used!!! SDhandle = xSPIinit((eSPIPort)SD_CARD_SPI_PORT/*BSP being used*/, spi300,/*300KHz baudrate*/ serIDLEslow, serMiddleSample, serMaster, serInterrupt, SPI_SDCARD_BUFFER_LIMIT/*defined at header file*/); /* Start SD card Init */ SD_ENABLE; SD_CLKDelay(10); // Send 80 clocks SD_DISABLE; gu8SD_Argument.lword=0; SD_CLKDelay(8); /* IDLE Command */ SD_ENABLE; if(SD_SendCommand(SD_CMD0|0x40,gu8SD_Argument,SD_IDLE)) { SD_DISABLE; return(INIT_FAILS); } SD_DISABLE; (void)ReadSPIByte(SDhandle); // Dummy SPI cycle /* Initialize SD Command */ SD_ENABLE; while(SD_SendCommand(SD_CMD1|0x40,gu8SD_Argument,SD_OK)) ; SD_DISABLE; (void)ReadSPIByte(SDhandle); // Dummy SPI cycle /* Block Length */ SD_ENABLE; gu8SD_Argument.lword=SD_BLOCK_SIZE; if(SD_SendCommand(SD_CMD16|0x40,gu8SD_Argument,SD_OK)) { SD_DISABLE; return(INIT_FAILS); } SD_DISABLE; xSPIChangeToPolling(SDhandle); HighSpeedSPI(SD_CARD_SPI_PORT); WriteSPIByte(SDhandle,0x00); WriteSPIByte(SDhandle,0x00); return(OK); }