/*********************************************************************** * * 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); }
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); }