Go Down

Topic: [SOLVED]Ethernet shield slave select (Read 1 time) previous topic - next topic

SurferTim

May 14, 2015, 11:33 pm Last Edit: Jun 06, 2015, 02:34 pm by SurferTim
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.
Code: [Select]
#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.
Code: [Select]
#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

RayLivingston

#1
May 15, 2015, 03:58 am Last Edit: May 15, 2015, 03:59 am by RayLivingston
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.

SurferTim

#2
May 15, 2015, 04:12 am Last Edit: May 15, 2015, 02:50 pm by 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.
Code: [Select]
// 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.

RayLivingston

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.
Code: [Select]
// 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.

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!
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.

RayLivingston

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.

RayLivingston

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,

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.

SurferTim

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

RayLivingston

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.

SurferTim


RayLivingston

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

Quote
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.

SurferTim

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

RayLivingston

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.

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.
http://forum.arduino.cc/index.php?topic=323002.msg2232451#msg2232451
Code: [Select]
  // 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.

RayLivingston

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
Code: [Select]
  // 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.

Go Up