Shematic:
http://mightymicrocontroller.com/Mighty-schematic-full.png
Hey guys,
For the last week I've been pulling my hair out over this issue with my SD card. It works with my firmware if I burn it directly, but with the code in my bootloader which reads the firmware from the SD card, the SD card refuses to respond when sent CMD 0. Or more specifically, it hangs in the wait_ready() loop before it even sends the command, never getting the 0xFF byte that indicates that it's okay to start sending it commands.
I've compared the code line by line with the code in the firmware that works, and the only difference I can find is that the code in the working version just gives up after a while if the card refuses to send the 0xFF bytes it's looking for to indicate it is ready. I haven't quite figured out what it does after that, but I would assume that it doesn't simply ignore the failure. (the SD card code in the firmware is that which came with the WaveHC lib)
The thing is, as soon as I enable the pullup on MISO, everything works great. The bootloader searches for new firmware, it loads it, and the firmware runs.
But I'm concerned that pulling that MISO pin up to 5V is going to damage the 3.3V SD card. It is through a 50K resistor though, so maybe it's okay?
Anyway, here's the relevant functions in the bootloader. Maybe someone can at least spot where I've gone wrong?
static
void power_on (void)
{
// Set CS pin to output
SD_CS_BLOCK |= (1<<SD_CS_PIN);
// Set CS high
DESELECT();
// Set MOSI pin to output
DDR_MOSI |= (1<<DD_MOSI);
// Set MISO pullup high?
//DDRD &= ~(1<<0);
PORTD |= (1<<0);
UBRR0 = 0; // Baud rate must be set to 0 for initialization.
DDR_SCK |= (1<<DD_SCK); // Set XCK pin as output.
UCSR0C = (1 << UMSEL01) | (1 << UMSEL00); // Put USART in MSPI mode. And set SPI data mode to 0.
UCSR0B = (1 << RXEN0) | (1 << TXEN0); // Enable transmitter and receiver
UBRR0 = 31; // Set clock rate to f_osc/64 for initialization sequence.
//_delay_ms(10); // wait 10 ms
for (uint8_t n = 0; n<10; n++) rcvr_spi(); /* 80 dummy clocks */
// prevent re-init hang by cards that were in partial read
// SELECT();
// for (uint16_t i = 0; i <= 512; i++) rcvr_spi();
}
#define rcvr_spi() xmit_spi(0xFF)
#define rcvr_spi_m(dst) UDR0 = 0xFF; while(!(UCSR0A & (1 << RXC0))); *(dst) = UDR0
inline BYTE xmit_spi(BYTE dat) {UDR0 = dat; while(!(UCSR0A & (1 << RXC0))); return UDR0;}
static
BYTE wait_ready (void)
{
uint8_t res;
rcvr_spi();
do {
//SELECT();
res = rcvr_spi();
//DESELECT();
//FLASH_LED_PORT ^= 1<<FLASH_LED_PIN; _delay_ms(25); // Gets here
} while (res != 0xFF);
return res;
}
The code hangs in that while loop when the booloader tries to send CMD 0 to the card. CMD 0 calls wait_ready() before it executes, and that's where it hangs.
Unless I have that pullup enabled. Then everything works fine.