The SD-Slot on the EthernetShield is not officially supported. So there's no driver. Most available SD-SPI Drivers rely on the Hardware SPI Pins, which are Pins 10 to 13.
On the Ethernetshield the SD-Port is wired as follows.
Arduino Pin | SD SPI-Mode | SD 4Wire Mode |
---|---|---|
3 | MISO | DAT0 |
4 | DAT1 | |
5 | DAT2 | |
6 | CS | DAT3 |
8 | MOSI | CMD |
9 | CLK | CLK |
The reason why they chose this way is unknown.
One solution to this is to rewire the SD-Slot to use the Hardware-SPI pins. The Picture shows how you can reroute the Pins.
Since SPI is a Bus we have to select which device is active. So for Chipselect Pin 6 is still used because the CS on Pin 10 is needed for the ethernet Chip. MISO, MOSI and CLK are now on PIN 11-13.
So wiring is as follows:
Arduino Pin | Rerouted to Pin | SD SPI-Mode |
---|---|---|
3 | 12 | MISO |
6 | 6 | CS |
8 | 11 | MOSI |
9 | 13 | CLK |
For the Wire on Pin 8 see my Addition at the End.
Now you should be able to use most of the available SD Libraries. But you have to change the CS Pin in the Code to Pin 6, since the default CS Pin is used for the Ethernet Device.
The upper Solution works fine but has the Problem that it still uses all Pins 3 to 6, 8 and 9 which is kind of a waste. Since I needed the Shield for a project where I need as many free ports as possible I decided to build a permanent solution. The Picture below shows the rewiring I did. So the only additionally used Port is 6 for the CS. Ports 3,4,5 and 9 are available (note the cut paths on those pins). For the Wire on Pin 8 read the text about the Buggy Wiznet at the End of this Article.
In an Application Note Wiznet states that the SPI Part of their chip is broken, which pollutes the MISO Line when the Chip is not active. This should disable other Devices from using the SPI Bus. Their proposed solution is to disable the Chips SPI Part when not in use.
There is a Pin called SPI_EN on the Wiznet chip which is connected to the lower Pad of the Pads labeled "PROG" on the EthernetShield. So I connected this Pin to Pin 7 in the temporary solution and Pin 8 in the permanent solution.
I did a little change to the Ethernet Library, so the SPI Part is only active when Ethernet is used.
In libraries/Ethernet/utilty/spi.h find the following after
#define SPI0_SendByte(Data) SPI0_TxData(Data);SPI0_WaitForSend() #define SPI0_RecvBute() SPI0_RxData()
and replace all that follows with this code: