Go Down

Topic: Ethernet shield SD card initialization failed (Read 26653 times) previous topic - next topic

fat16lib

Quote
I disagree with the library/software solution


This provides help for legacy hardware.  You mostly post in regard to the Ethernet shield where either the SD or Enet may not be used and this will still be a problem for current hardware.  I get a lot of mail from users with libraries for all their SPI devices with initialization problems.  The constructor solution would handle these cases.

Another problem that I now see more often is use of multiple SPI devices that conflict in mode and speed.  Many libraries, including the old version of SdFat in SD.h, do not set all SPI options each time the SPI bus is used.  These libraries need update since this problem is becoming more common.

The hardware solution is clearly best and I use it on all hardware I design.  I have Arduino test systems with three or four shields stacked and never need to worry about what is being used.

SurferTim

The software solution works only if the user adds the include to the sketch. Look at the OP post in reply#4. The code is trying to use the SD card on the ethernet shield without adding "#include <Ethernet.h>" to the sketch. If this was used on a Mega, it would cause a failure of the SD startup. The w5100 SPI slave select (D10) is set as OUTPUT without changing the pin to HIGH and would corrupt the SD startup stuff.

I agree with the SPI mode and speed modifications to the SPI device libraries. Too many differences now.

Hardware solution is best.

fat16lib

The hardware solution would fail also.
Code: [Select]
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output
  // or the SD library functions will not work.
  pinMode(10, OUTPUT);     // change this to 53 on a mega


I tried to get Limor Fried to remove this but she wouldn't.  Randomly setting pin 10 to output which pulls it low often causes problem on Mega and nothing fixes it.  Any working library already handles setting SS to an output.




SurferTim

Quote
I tried to get Limor Fried to remove this but she wouldn't.

Wow! Even after being told it is wrong, she wouldn't change it? I can't believe she would refuse you.  :smiley-eek:

wtiger

Quote
In general, the safest procedure is to set chip select for all SPI devices to output mode and high in setup before initializing any SPI device.

-->Including the hardware SS pin?

I had in mind that setting the SS pin to OUTPUT was meant to indicate to the card that there were some devices that were using SPI,  does it still work when you set it up to HIGH?

To make my card work, i set the ethernet chip select and the ss pin to OUTPUT and HIGH.( i tried without putting the SS pin to HIGH and the initialisation failed)
Using the SD library, there is a function to read  files on your SD card. I assume that to do that, the card must be put on a slave mode ( if i have understood well how SPI connection works ?) . How can i do that?

SurferTim

Quote
-->Including the hardware SS pin?

The default hardware slave select should be set to OUTPUT, and any slave selects connected to a SPI device should be set to OUTPUT and HIGH. On an Uno, the w5100 and the hardware slave select are the same pin (D10). On a Mega, they are not. The Mega D10 pin must be set to OUTPUT and HIGH by your code or the SD startup will probably fail due to the w5100 trashing up the SPI bus.

fat16lib

Most users should never use the SS symbol in their code.  There is no need to set SS as an output.  Libraries that use the SPI bus configure SS correctly unless the library has a bug.

You must not use SS as an input in your code.
Quote

In master mode, the SS pin must be held high to ensure master SPI operation if this pin is configured as an input pin. A low level will switch the SPI into slave mode and the hardware of the SPI will perform the following actions:

1. The master bit (MSTR) in the SPI Control Register (SPCR) is cleared and the SPI system becomes a slave. The direction of the pins will be switched according to Table 2-1.

2. The SPI Interrupt Flag (SPIF) in the SPI Status Register (SPSR) will be set. If the SPI interrupt and the global interrupts are enabled the interrupt routine will be executed.


Quote
I had in mind that setting the SS pin to OUTPUT was meant to indicate to the card that there were some devices that were using SPI,  does it still work when you set it up to HIGH?

The SD card is a slave and doesn't care or do anything with other devices.   SD libraries don't look at the previous state of SS.  The libraries just configure SS as an output and sets it high.

The key thing is to set chip select for all SPI devices to output mode and high before calling any library that uses the SPI bus.  Chip select for a device may be the SS pin but that is irrelevant.

wtiger

I use a Mega2560, so i set  D10 on OUTPUT and HIGH, and D53 on OUTPUT. Should i set D53 on HIGH too?

SurferTim

You really don't need to do anything with D53. The SPI.begin() function will set that pin as OUTPUT and HIGH.

wtiger

#24
Jul 04, 2014, 04:45 pm Last Edit: Jul 04, 2014, 04:59 pm by wtiger Reason: 1
SPI.begin() is called with SD.begin()? I actually use card.init() ... I haven't been able to find out what difference there is between thes two methods :/

SurferTim

#25
Jul 04, 2014, 04:51 pm Last Edit: Jul 04, 2014, 04:54 pm by SurferTim Reason: 1
Here is the first lines in the card.init() function. Note it sets the chipSelectPin as OUTPUT and HIGH after the "set pin modes" comment.
Code: [Select]
uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
 errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0;
 chipSelectPin_ = chipSelectPin;
 // 16-bit init start time allows over a minute
 uint16_t t0 = (uint16_t)millis();
 uint32_t arg;

 // set pin modes
 pinMode(chipSelectPin_, OUTPUT);
 chipSelectHigh();

  // and then later...
#ifndef SOFTWARE_SPI
  // SS must be in output mode even it is not chip select
  pinMode(SS_PIN, OUTPUT);
  digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin


edit: Added code later in the init function that sets the hardware SS as OUTPUT and HIGH.

wtiger

yes, i've been able to find thoses lines in the SD library i've downloaded ! The initialization works ( for now at least ^^' )
Thanks ! =)

RobRomijnders

Thanks SurferTim, including the lines to disable the ethernetconnection worked for me:)

fantasyebuk

there is no much difference in classes of SD cards like class 10 or 7

SurferTim

No difference on the Arduinos. The SPI bus is the limiting factor on the speed.

Go Up