[SOLVED]Ethernet shield slave select

I usually answer questions about this shield, but this has me a bit stumped. I am considering buying a Due to upgrade from my Mega 2560, but before I do, I would like to know how the Due uses the w5100 slave select using the ethernet library. Can someone tell me which functions the Due would use here? This is from the utility/w5100.h file.

#if defined(ARDUINO_ARCH_AVR)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  inline static void initSS()    { DDRB  |=  _BV(4); };
  inline static void setSS()     { PORTB &= ~_BV(4); };
  inline static void resetSS()   { PORTB |=  _BV(4); };
#elif defined(__AVR_ATmega32U4__)
  inline static void initSS()    { DDRB  |=  _BV(6); };
  inline static void setSS()     { PORTB &= ~_BV(6); };
  inline static void resetSS()   { PORTB |=  _BV(6); }; 
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
  inline static void initSS()    { DDRB  |=  _BV(0); };
  inline static void setSS()     { PORTB &= ~_BV(0); };
  inline static void resetSS()   { PORTB |=  _BV(0); }; 
#else
  inline static void initSS()    { DDRB  |=  _BV(2); };
  inline static void setSS()     { PORTB &= ~_BV(2); };
  inline static void resetSS()   { PORTB |=  _BV(2); };
#endif
#endif // ARDUINO_ARCH_AVR

edit:...so I added a "#pragma message" precompiler message to the code like this. The Mega displays "Mega" and the Uno displays "Default", but the Due displays none of them.

#if defined(ARDUINO_ARCH_AVR)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#pragma message ("Mega")
  inline static void initSS()    { DDRB  |=  _BV(4); };
  inline static void setSS()     { PORTB &= ~_BV(4); };
  inline static void resetSS()   { PORTB |=  _BV(4); };
#elif defined(__AVR_ATmega32U4__)
#pragma message ("32U4")
  inline static void initSS()    { DDRB  |=  _BV(6); };
  inline static void setSS()     { PORTB &= ~_BV(6); };
  inline static void resetSS()   { PORTB |=  _BV(6); };
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
#pragma message ("AT90")
  inline static void initSS()    { DDRB  |=  _BV(0); };
  inline static void setSS()     { PORTB &= ~_BV(0); };
  inline static void resetSS()   { PORTB |=  _BV(0); };
#else
#pragma message ("Default")
  inline static void initSS()    { DDRB  |=  _BV(2); };
  inline static void setSS()     { PORTB &= ~_BV(2); };
  inline static void resetSS()   { PORTB |=  _BV(2); };
#endif
#endif // ARDUINO_ARCH_AVR

For the Due, CS is handed by SPI. Look at init() in WS5100.cpp. For AVR, it calls SPI.begin(), and handled CS using the inline functions you found. For Due, it calls SPI.begin(SPI_CS), and presumably SPI then controls CS. SPI_CS is #defined as 10.

Regards,
Ray L.

That's true in some instances, but there is no code in the ethernet library that uses the Due's SPI ability. Only if you change the SPI.transfer calls does it handle the slave select automatically.

// this expects the sketch to handle the slave select
SPI.transfer(0xFF);
// this handles the slave select on D10 automatically
SPI.transfer(10,0xFF);

The first example is the way the w5100 handles the slave select.

edit: I just looked at the v1.6.3 ethernet code, and it does use the new SPI code in w5100.cpp.

edit2: Maybe the new Due SPI library code is the problem. I have an ethernet library mod that uses the "old way" of manipulating the slave select. Anyone having troubles with the ethernet shield/Due combination and willing to experiment with the library mods, let me know here or PM me.

SurferTim:
That's true in some instances, but there is no code in the ethernet library that uses the Due's SPI ability. Only if you change the SPI.transfer calls does it handle the slave select automatically.

// this expects the sketch to handle the slave select

SPI.transfer(0xFF);
// this handles the slave select on D10 automatically
SPI.transfer(10,0xFF);



The first example is the way the w5100 handles the slave select.
http://www.arduino.cc/en/Reference/DueExtendedSPI

edit: I just looked at the v1.6.3 ethernet code, and it does use the new SPI code in w5100.cpp. 

edit2: Maybe the new Due SPI library code is the problem. I have an ethernet library mod that uses the "old way" of manipulating the slave select. Anyone having troubles with the ethernet shield/Due combination and willing to experiment with the library mods, let me know here or PM me.

Tim,

I'm willing to give it a try, but I'm skeptical it will make any difference. I had the same problem with 1.6.1, and it seems nobody else is having the same problem I am. Surely there must be many people using the Due with Ethernet, and the lack of complaints from others suggests my problem is a bit more unique, no?

Regards,
Ray L.

I can see a couple posts here on page 1 of users having trouble.

Here is the post with the four new files. It says it is not Due compatible, but I think that is incorrect after examining the SPI library for the Due. Insure you back up your original files before replacing them with these!
http://forum.arduino.cc/index.php?topic=217423.msg1962182#msg1962182
These new files use digitalWrite(10,LOW) and digitalWrite(10,HIGH) to control the slave select.

Please let me know what happens, one way or the other.

Tim,

Have you looked at how the SPI hardware on the SAM works? CS is handled directly by the hardware, so the only thing the library needs to do is tell the chip which of its four CS pins to use for a given transfer, which is appears to do in begin().

Regards,
Ray L.

SurferTim:
I can see a couple posts here on page 1 of users having trouble.

Here is the post with the four new files. It says it is not Due compatible, but I think that is incorrect after examining the SPI library for the Due. Insure you back up your original files before replacing them with these!
Change SS pin on Ethernet Shield - #26 by SurferTim - Networking, Protocols, and Devices - Arduino Forum
These new files use digitalWrite(10,LOW) and digitalWrite(10,HIGH) to control the slave select.

Please let me know what happens, one way or the other.

Tim,

I'm a bit confused.... That post indicates those files will work only with v15.8, and will NOT work with Due....

Regards,
Ray L.

That meant it wouldn't work with v1.0.x. It should be Due compatible.

Just to be clear:

The W5100 files go in:C:\Arduino\Arduino-1.6.4\libraries\Ethernet\src\utility
The Ethernet files go in: C:\Arduino\Arduino-1.6.4\libraries\Ethernet\src

Correct?

Regards,
Ray L.

Yes.

No luck - it won't even build. The compile just hangs half-way through:

Using library SPI in folder: C:\Users\RayL\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\libraries\SPI
Using library Ethernet in folder: C:\Arduino\Arduino-1.6.4\libraries\Ethernet

C:\Users\RayL\AppData\Roaming\Arduino15\packages\arduino\tools\arm-none-eabi-gcc\4.8.3-2014q1/bin/arm-none-eabi-g++ -c -g -Os -w -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf -MMD -mcpu=cortex-m3 -DF_CPU=84000000L -DARDUINO=10604 -DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM -D__SAM3X8E__ -mthumb -DUSB_VID=0x2341 -DUSB_PID=0x003e -DUSBCON -DUSB_MANUFACTURER="Unknown" -DUSB_PRODUCT="Arduino Due" -IC:\Users\RayL\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\system/libsam -IC:\Users\RayL\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\system/CMSIS/CMSIS/Include/ -IC:\Users\RayL\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\system/CMSIS/Device/ATMEL/ -

...

C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\Ethernet\Dhcp.cpp.o C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\Ethernet\Dns.cpp.o C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\Ethernet\Ethernet.cpp.o C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\Ethernet\EthernetClient.cpp.o C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\Ethernet\EthernetServer.cpp.o C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\Ethernet\EthernetUdp.cpp.o C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\Ethernet\OldEthernet.cpp.o C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\Ethernet\utility\Oldw5100.cpp.o C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\Ethernet\utility\socket.cpp.o C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\Ethernet\utility\w5100.cpp.o C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp\variant.cpp.o C:\Users\RayL\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4\variants\arduino_due_x/libsam_sam3x8e_gcc_rel.a C:\Users\RayL\AppData\Local\Temp\build4304934277396300215.tmp/core.a -Wl,--end-group -lm -gcc

Regards,
Ray L.

I'll try a compile with v1.6.4 later today.

Well, I found my problem. Why this is not documented, and accounted for in the library, is a frickin' mystery to me! If you look at the schematic for the Due, SS0/PWM10 (Ethernet CS) and SS1/PWM4 (SD CS) are both connected to TWO pins on the SAM. Adding the following two lines to the intialization makes it work perfectly first time, every time:

pinMode(87,INPUT_PULLUP);
pinMode(77,INPUT_PULLUP);

Regards,
Ray L.

I don't buy that. If both SAM processor pins are connected to the same IO pin, then setting one as OUTPUT and HIGH should take the other HIGH.

This is from the test I gave you on your other thread in Programming.
http://forum.arduino.cc/index.php?topic=323002.msg2232451#msg2232451

  // disable SD card if one in the slot
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  // disable w5100 SPI
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);

That should have set the ethernet and SD CS pins HIGH.

SurferTim:
I don't buy that. If both SAM processor pins are connected to the same IO pin, then setting one as OUTPUT and HIGH should take the other HIGH.

This is from the test I gave you on your other thread in Programming.
Ethernet Oddities - #6 by SurferTim - Programming Questions - Arduino Forum

  // disable SD card if one in the slot

pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

// disable w5100 SPI
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);



That should have set the ethernet and SD CS pins HIGH.

If both pins are set as outputs, the only time you're guaranteed to have a correct value driven on the line is when either both are outputting HIGH or both are outputting LOW. Under any other conditions, they will be fighting each other, and the state of the line will be unpredictable.

You're welcome to not believe this is the issue, but since adding those two lines, I have not had one single problem. It's worked perfectly, first time, every time, on multiple systems, connecting within a few seconds after reset. Yesterday, it came up right only a very few times over the sources of the entire day.

Regards,
Ray L.

The default for those pins should be INPUT unless something changed them. Can you show me where that is happening?

If in fact those pins were both set to OUTPUT, then the Due is as half-baked as the wifi shield. :frowning:

edit: I believe you now. I checked the schematic, and it appears there are two SAM pins connected to each of D4 and D10. I gotta wonder what designer/programmer would do something like that? Good thing I am not the boss there. Those guys would be looking for a new job tomorrow.

SurferTim:
The default for those pins should be INPUT unless something changed them. Can you show me where that is happening?

If in fact those pins were both set to OUTPUT, then the Due is as half-baked as the wifi shield. :frowning:

edit: I believe you now. I checked the schematic, and it appears there are two SAM pins connected to each of D4 and D10. I gotta wonder what designer/programmer would do something like that? Good thing I am not the boss there. Those guys would be looking for a new job tomorrow.

I have no idea where those pins are being configured as outputs, but it is clearly happening somewhere. I have no intention of tracking it down. I'm sure someone will find it and fix it at some point. I'm just happy my Ethernet is now working properly for the first time ever.

Regards,
Ray L.

Well, if what you say is true, you may actually be the first person to have one working correctly. Didn't you mention that in another post?

How does the Due do other than this? Is it what you expected?

I have a Due now. I found the same problem on mine using my server code. Setting D10 as an OUTPUT causes the problem. Just set it HIGH to enable the pullup.

 // remove this one pinMode line. Leave the digitalWrite
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);

edit: I removed the pinMode call on my playground server example sketches for Due compatibility.