arduino-libraries / Ethernet

Ethernet Library for Arduino
http://arduino.cc/
259 stars 264 forks source link

Ethernet.begin() doesn't clean up the SPI bus once it's done. #90

Closed greyltc closed 5 years ago

greyltc commented 5 years ago

The LED on my UNO(R3) never turns on with this sketch. Works fine on my MEGA 2560. I've tried swapping shields. Ethernet is connected.

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };  
byte ip[] = { 10, 0, 0, 177 };    
void setup()
{
  Ethernet.begin(mac, ip);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
}
void loop () {}

This is with ETHERNET SHIELD 2s. The LED turns on if I comment out the Etherenet.begin line.

What can cause begin to never return?

Calling begin() with only mac (DHCP mode) does get an IP address from my DHCP server, but still even then begin() never returns.

PaulStoffregen commented 5 years ago

Could you be more specific about exactly which shield "ETHERNET SHIELD 2s" really is?

greyltc commented 5 years ago

https://uk.rs-online.com/web/p/processor-microcontroller-development-kits/8732285

A000024

PaulStoffregen commented 5 years ago

That is one of the shields I tested with Uno (and many other boards) last year, at the 2.0.0 release. It worked fine here.

https://www.pjrc.com/arduino-ethernet-library-2-0-0/

PaulStoffregen commented 5 years ago

Is the code you gave above the EXACT code you really used for testing? Or is it just an explanation?

I ask this because if you are missing with pin 13 (LED_BUILTIN), on Uno that is the same pin used for SPI SCK to communicate with the ethernet shield

So please make sure you are giving us the EXACT SAME CODE you really ran. This happens all the time, where people report a problem and show code which is meant to explain, but has some small overlooked detail which was the real problem.

greyltc commented 5 years ago

This is the exact code. I've attached the binary: firmware.zip

greyltc commented 5 years ago

So the SPI pins the UNO uses to talk to the shield make LED_BUILTIN unusable. That would probably explain everything since I was debugging with the LED.

PaulStoffregen commented 5 years ago

I ran it here. Indeed the LED fails to turn on, due to SPI.

You can easily verify it is working with this (and watch the Arduino Serial Monitor)

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };  
byte ip[] = { 10, 0, 0, 177 };    
void setup()
{
  Serial.begin(9600);
  Serial.println("Before Ethernet.begin()");
  Ethernet.begin(mac, ip);
  Serial.println("After Ethernet.begin()");
}
void loop () {}

You can also get the LED to "work" the way you originally wanted, with this:

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };  
byte ip[] = { 10, 0, 0, 177 };    
void setup()
{
  Ethernet.begin(mac, ip);
  SPI.end();
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
}
void loop () {}
PaulStoffregen commented 5 years ago

Just curious, why do you not use Serial.print() to see what's happening? Why use only the LED?

greyltc commented 5 years ago

I guess that's one thing bad about abstracting away the actual LED pin number with LED_BUILTIN.

I wasn't using serial because I'm powering via POE so I don't even have the USB plugged in for the the serial link.

Thanks very much for your help.

greyltc commented 5 years ago

By the way, are there any side effects to using SPI.end()? Why wouldn't that be at the end of Ethernet.begin()? Could this impact other other scenarios where other devices and code want to share that SPI bus?

PaulStoffregen commented 5 years ago

Turning off the SPI right after you've started Ethernet is kinda silly, since the Ethernet library uses SPI to communicate with the Wiznet chip on the shield. Presumably you want to actually do some communication with Ethernet, rather than merely turn it on and then shut off the hardware needed to actually use it.

greyltc commented 5 years ago

Maybe I initialize Ethernet, then go on to initialize another device on the shared SPI bus. That seems like perfectly reasonable usage. Or maybe I just want to blink the LED.

Are there actually drawbacks to calling SPI.end()? I suppose if you're trying to set a world record for SPI transmission speed, it could be a bad thing...

PaulStoffregen commented 5 years ago

SPI has beginTransaction() & endTransaction() for this purpose. Libraries like Ethernet use those functions to gain exclusive access to the SPI pins.

PaulStoffregen commented 5 years ago

There is no bug here. Everything is as it should be. I've closed this issue.

greyltc commented 5 years ago

Okay, fair enough. Thanks again for your help!