Pages: [1]   Go Down
Author Topic: SD card not working unless I enable pullup on MISO. Is this okay?  (Read 1516 times)
0 Members and 1 Guest are viewing this topic.
Manchester, New Hampshire
Online Online
Edison Member
*
Karma: 4
Posts: 1366
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?

Code:
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();

}

Code:
#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;}

Code:
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.
« Last Edit: February 25, 2013, 02:49:20 pm by scswift » Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

What level shifting circuitry do you have connected between the 5V microcontroller and the 3.3V SD card?
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Manchester, New Hampshire
Online Online
Edison Member
*
Karma: 4
Posts: 1366
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Oh, sorry I posted the wrong part of the schematic.  I've updated the link above. 

Here's the full schematic for my board:
http://mightymicrocontroller.com/Mighty-schematic-full.png
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Some SDcards set miso (and others) open collector during the init sequence, so people indicate problems w/o a pullup (I've seen somewhere 30% cards need pullups). The internal 50k pullup (to +5V) is weak so the card's clamping diodes at the inputs will probably survive (will pass the current to the card's 3V3 thus limit input voltage to 3V3+Vfd). You may connect for example a schottky diode from miso (anode) to the card's 3V3 (cathode) to be on safe side.. Do not turn atmega's miso input to output - this may destroy the sdcard..
« Last Edit: February 25, 2013, 04:25:01 pm by pito » Logged

Manchester, New Hampshire
Online Online
Edison Member
*
Karma: 4
Posts: 1366
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Some SDcards set miso (and others) open collector during the init sequence, so people indicate problems w/o a pullup (I've seen somewhere 30% cards need pullups). The internal 50k pullup (to +5V) is weak so the card's clamping diodes at the inputs will probably survive (will pass the current to the card's 3V3 thus limit input voltage to 3V3+Vfd).

So do you suppose I could enable the 50K pullup during the init sequence, and then disable it from that point on?  Would that even be worthwhile, from the standpoint of trying to protect that diode?  Which portion is considered the init sequence?  Everything in power_on() up to and including the 80 dummy clocks perhaps?

I guess I can try it and see what happens...
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Or you may simply put a 10k pullup from miso (at sdcard's side) to 3V3 and do not enable the pullup in atmega. That is probably the best approach.. Atmega is fine with 3V3 input when powered from 5V.
Logged

Manchester, New Hampshire
Online Online
Edison Member
*
Karma: 4
Posts: 1366
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Or you may simply put a 10k pullup from miso (at sdcard's side) to 3V3 and do not enable the pullup in atmega. That is probably the best approach.. Atmega is fine with 3V3 input when powered from 5V.

I've got a couple hundred boards already manufactured and I'd rather not have to apply yet another patch to them if I don't have to.  I already had to turn the serial port USART1 into a third data bus for my leds because you can't stop sending data to the LED drivers in the middle of an update and that was forcing me to skip samples on the DAC resulting in static. :/ 
« Last Edit: February 25, 2013, 05:17:59 pm by scswift » Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I've got a couple hundred boards already manufactured
There is always a 3rd option: "do nothing". Enable the internal pullup and that's it. You carry the risk, of course..
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

So you've got a 74LVC3G34 to level shift the 5V signals from the atmega to 3.3V for the SD card, however you haven't done any level shifting the other way round. This means that the high level signal voltage from the SD card to the atmega input is marginal. The pullup resistor will increase the high level input voltage to approximately 4V (the voltage at which the protection diode in the SD card conducts, and that probably explains why it fixes the problem.

You would be well advised to include a level-shifting circuit between the SD card and the atmega MISO pin. One simple option is a small signal diode (e.g. 1N4148), cathode to SD card output, anode to MISO pin, along with a pullup resistor of around 10K between MISO and +5V. This will still result some current flowing into the SD card pin protection diode. If you want to reduce that current, replace the diode by the base and emitter of PNP transistor with its collector connected to ground.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Manchester, New Hampshire
Online Online
Edison Member
*
Karma: 4
Posts: 1366
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

dc42:
Could I use the internal pullup rather than adding another resistor?  If not, why not?
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

dc42:
Could I use the internal pullup rather than adding another resistor?  If not, why not?

Yes, you could.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Manchester, New Hampshire
Online Online
Edison Member
*
Karma: 4
Posts: 1366
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well I seem to have gotten it working without the need for the pullup.  I changed the wait_ready function to be like so:

Code:
static
BYTE wait_ready (void)
{
uint8_t res, n = 0;

rcvr_spi();

do {
res = rcvr_spi();
//FLASH_LED_PORT ^= 1<<FLASH_LED_PIN; _delay_ms(25); // Gets here
} while ((res != 0xFF) && (n++ < 255));

return res;
}

With that simple change it now seems to work.  In fact, it works with n < 10, and probably even lower than that, but I did 255 just to be safe.

The idea here is that when the card is first powered up but before CMD 0 is issued, and possibly certain other init commands, the MISO pin may be in an open collector state.  In that state I'll never read 0xFF for ready cause I guess the pin is floating?  Anyway, this acts as a timeout and assumes the card is ready if it doesn't get 0xFF after a bunch of reads.

And it's working for me now.  My firmware loaded fine.

Another thing which lends credence to the idea of this pin floating during init is that I found I could in fact enable that pullup only during the init sequence and then turn it off and the card would continue to work fine.  But since I don't know that that pullup won't fry the card, this timeout solution is better. 
Logged

Pages: [1]   Go Up
Jump to: