/** * \ingroup sd_raw * Initialize the SPI port as slave * * \return nothing */ void sd_raw_spi_init(void) { uint8_t b; // SS input configure_pin_ss(); // SCK input configure_pin_sck(); // MOSI input configure_pin_mosi(); // MISO output configure_pin_miso(); // enable double-speed // NOT WORKING YET //SPSR |= (1 << SPI2X); // enable SPI SPCR = (1 << SPE); // reading these two register should start spi b = SPDR; b = SPSR; return; }
/** * \ingroup sd_raw * Initializes memory card communication. * * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_init() { uint16_t i; uint8_t response; /* enable inputs for reading card status */ configure_pin_available(); configure_pin_locked(); /* enable outputs for MOSI, SCK, SS, input for MISO */ configure_pin_mosi(); configure_pin_sck(); configure_pin_ss(); configure_pin_miso(); unselect_card(); /* initialize SPI with lowest frequency; max. 400kHz during identification mode of card */ SPCR = (0 << SPIE) | /* SPI Interrupt Enable */ (1 << SPE) | /* SPI Enable */ (0 << DORD) | /* Data Order: MSB first */ (1 << MSTR) | /* Master mode */ (0 << CPOL) | /* Clock Polarity: SCK low when idle */ (0 << CPHA) | /* Clock Phase: sample on rising SCK edge */ (1 << SPR1) | /* Clock Frequency: f_OSC / 128 */ (1 << SPR0); SPSR &= ~(1 << SPI2X); /* No doubled clock frequency */ /* initialization procedure */ if(!sd_raw_available()) return 0; /* card needs 74 cycles minimum to start up */ for(i = 0; i < 10; ++i) { /* wait 8 clock cycles */ sd_raw_rec_byte(); } /* address card */ select_card(); /* reset card */ for(i = 0; ; ++i) { response = sd_raw_send_command_r1(CMD_GO_IDLE_STATE, 0); if(response == (1 << R1_IDLE_STATE)) break; if(i == 0x1ff) { unselect_card(); return 0; } } /* wait for card to get ready */ for(i = 0; ; ++i) { response = sd_raw_send_command_r1(CMD_SEND_OP_COND, 0); if(!(response & (1 << R1_IDLE_STATE))) break; if(i == 0x7fff) { unselect_card(); return 0; } } /* set block size to 512 bytes */ if(sd_raw_send_command_r1(CMD_SET_BLOCKLEN, 512)) { unselect_card(); return 0; } /* deaddress card */ unselect_card(); /* switch to highest SPI frequency possible */ SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */ SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ #if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = 0xffffffff; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) return 0; #endif return 1; }
/** * \ingroup sd_raw * Initializes memory card communication. * * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_init() { /* enable inputs for reading card status */ configure_pin_available(); configure_pin_locked(); /* enable outputs for MOSI, SCK, SS, input for MISO */ configure_pin_mosi(); configure_pin_sck(); configure_pin_ss(); configure_pin_miso(); unselect_card(); /* initialize SPI with lowest frequency; max. 400kHz during identification mode of card */ S0SPCCR = 150; /* Set frequency to 400kHz */ S0SPCR = 0x38; /* initialization procedure */ sd_raw_card_type = 0; if(!sd_raw_available()) return 0; /* card needs 74 cycles minimum to start up */ for(uint8_t i = 0; i < 10; ++i) { /* wait 8 clock cycles */ sd_raw_rec_byte(); } /* address card */ select_card(); /* reset card */ uint8_t response; for(uint16_t i = 0; ; ++i) { response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0); if(response == (1 << R1_IDLE_STATE)) break; if(i == 0x1ff) { unselect_card(); return 0; } } #if SD_RAW_SDHC /* check for version of SD card specification */ response = sd_raw_send_command(CMD_SEND_IF_COND, 0x100 /* 2.7V - 3.6V */ | 0xaa /* test pattern */); if((response & (1 << R1_ILL_COMMAND)) == 0) { sd_raw_rec_byte(); sd_raw_rec_byte(); if((sd_raw_rec_byte() & 0x01) == 0) return 0; /* card operation voltage range doesn't match */ if(sd_raw_rec_byte() != 0xaa) return 0; /* wrong test pattern */ /* card conforms to SD 2 card specification */ sd_raw_card_type |= (1 << SD_RAW_SPEC_2); } else #endif { /* determine SD/MMC card type */ sd_raw_send_command(CMD_APP, 0); response = sd_raw_send_command(CMD_SD_SEND_OP_COND, 0); if((response & (1 << R1_ILL_COMMAND)) == 0) { /* card conforms to SD 1 card specification */ sd_raw_card_type |= (1 << SD_RAW_SPEC_1); } else { /* MMC card */ } } /* wait for card to get ready */ for(uint16_t i = 0; ; ++i) { if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2))) { uint32_t arg = 0; #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) arg = 0x40000000; #endif sd_raw_send_command(CMD_APP, 0); response = sd_raw_send_command(CMD_SD_SEND_OP_COND, arg); } else { response = sd_raw_send_command(CMD_SEND_OP_COND, 0); } if((response & (1 << R1_IDLE_STATE)) == 0) break; if(i == 0x7fff) { unselect_card(); return 0; } } #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) { if(sd_raw_send_command(CMD_READ_OCR, 0)) { unselect_card(); return 0; } if(sd_raw_rec_byte() & 0x40) sd_raw_card_type |= (1 << SD_RAW_SPEC_SDHC); sd_raw_rec_byte(); sd_raw_rec_byte(); sd_raw_rec_byte(); } #endif /* set block size to 512 bytes */ if(sd_raw_send_command(CMD_SET_BLOCKLEN, 512)) { unselect_card(); return 0; } /* deaddress card */ unselect_card(); /* switch to highest SPI frequency possible */ S0SPCCR = 60; /* ~1MHz-- potentially can be faster */ #if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = (offset_t) -1; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) return 0; #endif return 1; }
/** * \ingroup sd_raw * Initializes memory card communication. * * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_init(bool use_crc, uint8_t speed) { #if !SD_POOR_DESIGN (void)speed; #endif #if !SD_RAW_SAVE_RAM sd_use_crc = use_crc; #else (void)use_crc; #endif sd_errno = 0; /* enable inputs for reading card status */ configure_pin_available(); configure_pin_locked(); /* enable outputs for MOSI, SCK, SS, input for MISO */ configure_pin_ss(); /* unselect SS as it may be CS for another SPI device */ unselect_card(); configure_pin_mosi(); configure_pin_sck(); configure_pin_miso(); /* initialize SPI with lowest frequency; max. 400kHz during identification mode of card */ SPCR = (0 << SPIE) | /* SPI Interrupt Enable */ (1 << SPE) | /* SPI Enable */ (0 << DORD) | /* Data Order: MSB first */ (1 << MSTR) | /* Master mode */ (0 << CPOL) | /* Clock Polarity: SCK low when idle */ (0 << CPHA) | /* Clock Phase: sample on rising SCK edge */ (1 << SPR1) | /* Clock Frequency: f_OSC / 128 */ (1 << SPR0); SPSR = 0; // &= ~(1 << SPI2X); /* No doubled clock frequency */ /* initialization procedure */ sd_raw_card_type = 0; if(!sd_raw_available()) { sd_errno = SDR_ERR_NOCARD; return 0; } /* card needs 74 cycles minimum to start up with SS/CS high */ for(uint8_t i = 0; i < 10; ++i) { /* wait 8 clock cycles */ sd_raw_rec_byte(); } /* now lower CS */ select_card(); /* reset card */ uint8_t response; for(uint16_t i = 0; ; ++i) { response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0); if(response == (1 << R1_IDLE_STATE)) break; if(i == 0x1ff) { unselect_card(); sd_errno = SDR_ERR_COMMS; return 0; } } #if !SD_RAW_SAVE_RAM if ( sd_use_crc ) { if ( sd_raw_send_command(CMD_CRC_ON_OFF, 1) != (1 << R1_IDLE_STATE) ) { unselect_card(); sd_errno = SDR_ERR_CRC; return 0; } } #endif #if SD_RAW_SDHC /* check for version of SD card specification */ response = sd_raw_send_command(CMD_SEND_IF_COND, 0x100 /* 2.7V - 3.6V */ | 0xaa /* test pattern */); if((response & (1 << R1_ILL_COMMAND)) == 0) { sd_raw_rec_byte(); sd_raw_rec_byte(); if((sd_raw_rec_byte() & 0x01) == 0) { sd_errno = SDR_ERR_VOLTAGE; return 0; /* card operation voltage range doesn't match */ } if(sd_raw_rec_byte() != 0xaa) { sd_errno = SDR_ERR_PATTERN; return 0; /* wrong test pattern */ } /* card conforms to SD 2 card specification */ sd_raw_card_type |= (1 << SD_RAW_SPEC_2); } else #endif { /* determine SD/MMC card type */ sd_raw_send_command(CMD_APP, 0); response = sd_raw_send_command(CMD_SD_SEND_OP_COND, 0); if((response & (1 << R1_ILL_COMMAND)) == 0) { /* card conforms to SD 1 card specification */ sd_raw_card_type |= (1 << SD_RAW_SPEC_1); } else { /* MMC card */ } } /* wait for card to get ready */ for(uint16_t i = 0; ; ++i) { if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2))) { uint32_t arg = 0; #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) arg = 0x40000000; #endif sd_raw_send_command(CMD_APP, 0); response = sd_raw_send_command(CMD_SD_SEND_OP_COND, arg); } else { response = sd_raw_send_command(CMD_SEND_OP_COND, 0); } if((response & (1 << R1_IDLE_STATE)) == 0) break; if(i == 0x1ff) { unselect_card(); sd_errno = SDR_ERR_COMMS; return 0; } } #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) { if(sd_raw_send_command(CMD_READ_OCR, 0)) { unselect_card(); sd_errno = SDR_ERR_BADRESPONSE; return 0; } if(sd_raw_rec_byte() & 0x40) sd_raw_card_type |= (1 << SD_RAW_SPEC_SDHC); sd_raw_rec_byte(); sd_raw_rec_byte(); sd_raw_rec_byte(); } #endif /* set block size to 512 bytes */ if(sd_raw_send_command(CMD_SET_BLOCKLEN, 512)) { unselect_card(); sd_errno = SDR_ERR_BADRESPONSE; return 0; } /* deaddress card */ unselect_card(); /* switch to highest SPI frequency possible */ #if SD_POOR_DESIGN switch(speed) { /* f_OSC / 2 */ case 0: SPCR &= ~((1 << SPR1) | (1 << SPR0)); SPSR |= (1 << SPI2X); break; /* f_OSC / 4 */ case 1: SPCR &= ~((1 << SPR1) | (1 << SPR0)); SPSR &= ~(1 << SPI2X); break; /* f_OSC / 8 */ case 2: SPCR |= (1 << SPR0); SPCR &= ~(1 << SPR1); SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ break; /* f_OSC / 16 */ case 3: SPCR |= (1 << SPR0); SPCR &= ~(1 << SPR1); SPSR &= ~(1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ break; /* f_OSC / 32 */ case 4: SPCR &= ~(1 << SPR0); SPCR |= (1 << SPR1); SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ break; /* f_OSC / 64 [two ways of achieving] */ case 5: SPCR &= ~(1 << SPR0); SPCR |= (1 << SPR1); SPSR &= ~(1 << SPI2X); break; /* f_OSC / 128 */ case 6: SPCR |= (1 << SPR1) | (1 << SPR0); SPSR &= ~(1 << SPI2X); break; default: sd_errno = SDR_ERR_COMMS; return 0; } #else // MBI used to use f_OSC / 2 // But owing to the lousy SD card bus, that doesn't work well // Then with the introduction of the revH MightyBoard, they dropped // down to f_OSC / 16. // / * f_OSC / 2 */ // SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */ // SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ /* f_OSC / 16 */ SPCR |= ( 1 << SPR0 ); SPCR &= ~( 1 << SPR1 ); SPSR &= ~( 1 << SPI2X ); #endif #if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = (offset_t) -1; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) return 0; #endif #if defined(DEBUG_SD) sd_errno = SDR_ERR_FOO; #endif // sd_errno set by sd_raw_read return 1; }
/** * \ingroup sd_raw * Initializes memory card communication. * * \returns 0 on failure, 1 on success. */ uint8_t sd_raw_init(void) { _sd_infodirty = 1; /* enable inputs for reading card status */ configure_pin_available(); configure_pin_locked(); /* enable outputs for MOSI, SCK, SS, input for MISO */ configure_pin_mosi(); configure_pin_sck(); configure_pin_ss(); configure_pin_miso(); unselect_card(); /* initialize SPI with lowest frequency; max. 400kHz during identification mode of card */ SPCR = (0 << SPIE) | /* SPI Interrupt Enable */ (1 << SPE) | /* SPI Enable */ (0 << DORD) | /* Data Order: MSB first */ (1 << MSTR) | /* Master mode */ (0 << CPOL) | /* Clock Polarity: SCK low when idle */ (0 << CPHA) | /* Clock Phase: sample on rising SCK edge */ (1 << SPR1) | /* Clock Frequency: f_OSC / 128 */ (1 << SPR0); SPSR &= ~(1 << SPI2X); /* No doubled clock frequency */ /* initialization procedure */ sd_raw_card_type = 0; if(!sd_raw_available()) { SD_DEBUG("SD card not available"); return 0; } /* card needs 74 cycles minimum to start up */ uint16_t i; for(i = 0; i < 10; ++i) { /* wait 8 clock cycles */ sd_raw_rec_byte(); } /* address card */ select_card(); /* reset card */ uint8_t response; for(i = 0; ; ++i) { response = sd_raw_send_command(CMD_GO_IDLE_STATE, 0); if(response == (1 << R1_IDLE_STATE)) break; if(i == 0x1ff) { unselect_card(); SD_DEBUG("Some kind of error."); return 0; } } #if SD_RAW_SDHC /* check for version of SD card specification */ response = sd_raw_send_command(CMD_SEND_IF_COND, 0x100 /* 2.7V - 3.6V */ | 0xaa /* test pattern */); if((response & (1 << R1_ILL_COMMAND)) == 0) { sd_raw_rec_byte(); sd_raw_rec_byte(); if((sd_raw_rec_byte() & 0x01) == 0) { SD_DEBUG("Bad voltage"); return 0; /* card operation voltage range doesn't match */ } if(sd_raw_rec_byte() != 0xaa) { SD_DEBUG("Bad test pattern."); return 0; /* wrong test pattern */ } /* card conforms to SD 2 card specification */ sd_raw_card_type |= (1 << SD_RAW_SPEC_2); } else #endif { /* determine SD/MMC card type */ sd_raw_send_command(CMD_APP, 0); response = sd_raw_send_command(CMD_SD_SEND_OP_COND, 0); if((response & (1 << R1_ILL_COMMAND)) == 0) { /* card conforms to SD 1 card specification */ sd_raw_card_type |= (1 << SD_RAW_SPEC_1); } else { /* MMC card */ } } /* wait for card to get ready */ for(i = 0; ; ++i) { if(sd_raw_card_type & ((1 << SD_RAW_SPEC_1) | (1 << SD_RAW_SPEC_2))) { uint32_t arg = 0; #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) arg = 0x40000000; #endif sd_raw_send_command(CMD_APP, 0); response = sd_raw_send_command(CMD_SD_SEND_OP_COND, arg); } else { response = sd_raw_send_command(CMD_SEND_OP_COND, 0); } if((response & (1 << R1_IDLE_STATE)) == 0) break; if(i == 0x7fff) { unselect_card(); SD_DEBUG("Some kind of error."); return 0; } } #if SD_RAW_SDHC if(sd_raw_card_type & (1 << SD_RAW_SPEC_2)) { if(sd_raw_send_command(CMD_READ_OCR, 0)) { unselect_card(); SD_DEBUG("Some kind of error."); return 0; } if(sd_raw_rec_byte() & 0x40) sd_raw_card_type |= (1 << SD_RAW_SPEC_SDHC); sd_raw_rec_byte(); sd_raw_rec_byte(); sd_raw_rec_byte(); } #endif /* set block size to 512 bytes */ if(sd_raw_send_command(CMD_SET_BLOCKLEN, 512)) { unselect_card(); SD_DEBUG("Some kind of error."); return 0; } /* deaddress card */ unselect_card(); /* switch to highest SPI frequency possible */ SPCR &= ~((1 << SPR1) | (1 << SPR0)); /* Clock Frequency: f_OSC / 4 */ SPSR |= (1 << SPI2X); /* Doubled Clock Frequency: f_OSC / 2 */ #if !SD_RAW_SAVE_RAM /* the first block is likely to be accessed first, so precache it here */ raw_block_address = (unsigned long) -1; #if SD_RAW_WRITE_BUFFERING raw_block_written = 1; #endif if(!sd_raw_read(0, raw_block, sizeof(raw_block))) { SD_DEBUG("Some kind of error."); return 0; } #endif return 1; }