Arduino 19 ethernet SS assignment problem

I am trying to change the SS pin in Arduino 19 from pin 10 to pin 4. Reading through the library it seems that I should change the line "const static uint8_t SS = 10;" in pins_arduino.h to "const static uint8_t SS = 4;". This is the only point in the ethernet library (and header files) where there is a number assigned for SS. However making this change and recompiling the sketch makes no change at all. Pin 10 is still used for SS!

Is there somewhere else that I need to make a change?
If I had two SPI devices on the bus, how would I run an SS for each one when only one is assigned in arduino?

If you are using the SPI interface on an ATmega328p, pin 10 is used as the SPI "Slave Select" mode pin. That's part of the SPI port hardware and can not be changed by software.

Here's the deal:
Before you initialize the SPI port (with Ethernet.begin()), the mode of Arduino pin 10 must be set to be an OUTPUT.

After the SPI has been initialized, you can use pin 10 for any output function you want. So, if you want to the SPI port with something other than pin10 to be the "Chip Select" for the slave device, that's OK, but you must always initialize pin 10 to be an OUTPUT and keep it as such. If pin 10 ever takes on an INPUT LOW state, the SPI interface in the ATMega will switch to slave mode.

If you want more than one slave device, that's OK; each one has a dedicated "Chip Select" pin that is manipulated by the software of that device's library (or whatever function you are using to read and write the SPI data).

Summary:
To be consistent with the "official" Arduino Ethernet Shield, the Ethernet library comes with pin 10 defined as the Ethernet "Chip Select" pin. If you don't change that definition, Ethernet.begin() will set the mode of pin 10 to OUTPUT (as it must be) and all is well.

If you change the "Chip Select" pin the way that you mentioned, that other pin will be initialized by the Ethernet.begin() function and you will have to explicitly set the pin 10 mode to OUTPUT before calling Ethernet.begin() in your setup() function.

Regards,

Dave

Thanks Dave,

All is clear about pin 10 but how do I assign (say) pin 4 to be the new slave select?

Do I have to change the SPI library?

Well, I'm embarrassed. I didn't notice that you are using arduino-0019 (sorry). I had done some SPI work with arduino-0018 to get several SPI devices, including the Ethernet Shield, to work and I mis-remembered a couple of things. (Some of those things have changed with new software and new hardware anyhow.)

I have just started evaluating arduino-0019, and I haven't tried the Ethernet stuff. It's new. The old Ethernet library had its own self-contained SPI functions and now there is a SPI library used by Ethernet and other applications.

Here's my take on it (so far):

The general things that I said about the "SS" pin still stands. For the Arduino Duemilanove board with an ATmega328p, it is Arduino pin 10. In AVR terminology, it is bit 2 of Port B. The "Chip Select" pin is also pin 10.

For the Arduino Mega board with an ATmega1280, the "SS" pin is pin 0 of port B, which is not one of the usual I/O pins. The "Chip Select" pin for the Ethernet board is bit 4 of Port B on the '1280, which is still Arduino pin 10.

So the first thing is: Do not change the definition of SS in pins_arduino.h

The "SS" and "Chip Select" selections are made automatically, and the "SS" pin is properly initialized by the SPI library and the "Chip Select" pin is toggled properly by the Ethernet library when you compile for the Duemilanove or the Mega.

Now, if you want to change the "Chip Select" for an Ethernet board, you have to change the definitions of initSS(), setSS(), and resetSS() in arduino-0019/libraries/Ethernet/utility/w5100.h If you really need to change it, maybe we can figure it out together. The specific port and bit definitions for a given Arduino pin depend on which processor you are using.

For insight on how to set up other SPI devices, look at the examples in the arduino-0019/libraries/SPI/examples directory. They show how to define the "Chip Select" pin and use it with bus transfers.

So, to get us a little farther along:

  1. What processor and what Arduino board are you using?

  2. What Ethernet Shield are you using?

  3. If you are using old version "Official" Ethernet Shield with a Mega board, it requires some jumpers for MISO, MOSI, and SCK, but the "Chip Select" pin is 10 for the 0019 Ethernet library, and you don't have to modify anything. Old version Shield with Duemilanove should work "out of the box." New version Shield should work with no modifications to hardware or 0019 software (but I don't have a new shield to test, so I can't be sure).

  4. If you are using some other Shield, give us some details. For example, what is it, and why do you need to change the Ethernet "Chip Select" pin?

Regards,

Dave

So, to get us a little farther along:

  1. What processor and what Arduino board are you using?

I am using a 328P on a custom board.( that is why I have to use pin 4 instead of 10. Saves an ugly looking "green wire" across the board)

  1. What Ethernet Shield are you using?

A Wiznet Wiz811MJ that plugs directly into the board mentioned above.

  1. If you are using old version "Official" Ethernet Shield with a Mega board, it requires some jumpers for MISO, MOSI, and SCK, but the "Chip Select" pin is 10 for the 0019 Ethernet library, and you don't have to modify anything. Old version Shield with Duemilanove should work "out of the box." New version Shield should work with no modifications to hardware or 0019 software (but I don't have a new shield to test, so I can't be sure).

  2. If you are using some other Shield, give us some details. For example, what is it, and why do you need to change the Ethernet "Chip Select" pin?

I dont know how to put a photo on this forum but it is a custom board that I had made up that accepts a couple of daughter boards and a WIZ811MJ. I may want to put other SPI devices in the daughterboard positions so that they share the bus with the WIZ811MJ

I thought that SS and SCS were synonomous so I have treated them as the same connection. Controlling the 5100 am I dealing with SS, CS or both? What is the CS meant to do?

OK. Now I have had a chance to test arduino-0019 Ethernet library with a "genuine" Arduino Ethernet Shield and a "genuine" Arduino Duemilanove board and with a "genuine" Arduino Mega board.

For people with "genuine" Arduino boards, here are the results from my tests:

The 0019 Ethernet library works with an unmodified Duemilanove. There are two issues that require minor mods to the old version Ethernet Shield in order for it to power-up without requiring a manual reset and to allow other SPI devices to operate when the Ethernet Shield is plugged in. Unless you have already modified your Shield, I recommend that you check basic functionality before making changes on the board.

For the Mega board and the old version Ethernet Shield, here's what I did:

1. Bend Shield pins 11, 12, and 13 slightly away from the connector so that they do not make contact with the Mega pins. These are the same as what was required in arduino-0018.

2. Leave pin 10 as-is. so that it will plug into the Mega. (This is different from what was required in the 0018 Ethernet library.)

3. Using short male-to-male jumpers, make the following three connections from the header on the Mega to the header on the Shield:


MEGA pin 50 (MISO) to Arduino Ethernet Shield pin 12.
MEGA pin 51 (MOSI) to Arduino Ethernet Shield pin 11.
MEGA pin 52 (SCK)  to Arduino Ethernet Shield pin 13.

That's all. (There are the same reset and SPI issues that I previously mentioned.)

Now, lemming, as to your custom board. Of course I won't be able to test, but maybe I can help.

Because the Ethernet library used arduino pin 10 for "Chip Select" for the ATmega328p, it's easy to miss the point that the functionality of the SPI "Slave Select" is fixed to Arduino pin 10 on the ATmega328p, and can not be changed, and that the function of the device "Chip Select" is different from that of the ATmega hardware SPI "Slave Select" function.

So: There are two different things:

For the 0019 Ethernet library, the "Slave Select" pin is initialized to be an output pin before the SPI port is initialized. This pin is defined in arduino-pins.h and is fixed in hardware. You can not (must not) redefine that value of SS. Your sketch doesn't have to do anything with "SS" when you are using the 0019 Ethernet library, no matter what device "Chip Select" pin you are using.

Each SPI device will have its own "Chip Select" That pin is manipulated by software to begin and end every transaction. For the Ethernet library, the definition of the Ethernet "Chip Select" is set by the functions that I mentioned in the w5100.h header. If you are going to use something other than Arduino pin 10, these three definitions must be changed.

Once you have made the changes in w5100.h, any sketch that uses the 0019 Ethernet library will not have to do anything with the "Chip Select" pin

So: Here's where we stand now:

When you say "Pin 4" what are you referring to? Is it package pin 4 on a 28-pin DIP (bit 2 of Port D)? Is it Arduino pin 4 as defined on the Duemilanove (bit 4 of Port D)? Or what?

If you mean the Arduino pin 4 as defined on the Duemilanove, then edit arduino-0019/libraries/Ethernet/utility/w5100.h as follows, starting somewhere around line 310:

private:
#if defined(__AVR_ATmega1280__)
  inline static void initSS()    { DDRB  |=  _BV(4); };
  inline static void setSS()     { PORTB &= ~_BV(4); };
  inline static void resetSS()   { PORTB |=  _BV(4); };
#else
  // Original code for a "Genuine" Ethernet Shield for ATmega328p
  // For Ethernet Shield that uses Duemilanove Pin 10: bit 2 of Port B
  // Use these next three lines
  //inline static void initSS()    { DDRB  |=  _BV(2); };
  //inline static void setSS()     { PORTB &= ~_BV(2); };
  //inline static void resetSS()   { PORTB |=  _BV(2); };
  //
  // davekw7x
  //
  // For an Ethernet Shield that uses Duemilanove Pin 4: bit 4 of Port D
  // use the next three lines
  inline static void initSS()    { DDRD  |=  _BV(4); };
  inline static void setSS()     { PORTD &= ~_BV(4); };
  inline static void resetSS()   { PORTD |=  _BV(4); };
#endif

Regards,

Dave

Thanks Dave,

That works well. I was referring to arduino pin4 (328 pin 6).
Thank you for the code. I am up and running.

But..........

I like to understand the code rather than just copy form others and I am still confused with the difference between SS and CS.

Pin 10 (SS) is left alone as you suggested. Yet this is the pin that will "get the attention" of the Wiznet.
It is not connected to the Wiznet and yet we are communicating OK. This successful communication must be due to the CS.

However you mention "..the definition of the Ethernet "Chip Select" is set by the functions that I mentioned in the w5100.h header".

These functions have the names "initSS()", "setSS()", "resetSS()". The SS in their names suggests that they are referring to Slave Select and not Chip Select. I have yet to distinguish between the two and which to use for what function.

I assume that with multiple SPI devices on the bus I still would not make any changes to to the SPI library but would use a different SS or CS pin in their respective library?

You have helped enough so I won't bother you more but will go and do some more research.

I am up and running.

Huzzah!

still confused with the difference between SS and CS

People underestimate the importance of hardware signal naming and software variable and function naming.

I shall try to overcome some unfortunate similarities and confusion caused by the fact that for the "genuine" Ethernet Shield the designers chose to use Arduino pin 10 for the "Chip Select." That is not, by any means, a bad design choice, but it's not the only choice they could have made.

"SS" refers to "Slave Select" function of the SPI interface inside the ATMega328p.

When the SPI port is initialized, the "SS" functionality is unavoidably hardwired inside the ATmega328p to Arduino pin 10. This sets the mode of the SPI interface. When the SPI interface is initialized, by writing to certain registers in the SPI interface, if the "SS" pin has been previously set to OUTPUT mode, the SPI interface will be operating in Master mode (that's what we want: we need to be the Master).

If the "SS" pin ever gets changed to INPUT mode (or if it was left at its default INPUT mode after being powered up) and if the input value is LOW, then the SPI interface inside the ATmega328p switched to Slave mode. Automatically. Inescapably. We don't want that. So, we will keep the "SS" pin in the OUTPUT mode for the duration of any sketch that uses the Ethernet Shield.

Now, after the SPI interface has been initialized with the "SS" pin in OUTPUT mode, the "SS" pin can be set to any output state you want. In other words, good old pin 10 can be used for any output function that you want. (It can be just left alone if you don't need it for anything.) The only thing that you can't do is to set pin 10 to the INPUT mode and let the value go LOW.

Now...

For every SD device that we want to control, there are three common signals used by all of them: MOSI, MISO, SCK. These are ATmega328p I/O pins corresponding to Arduino pins 11, 12, and 13. These functions take over in place of the normal I/O functions on these pins. When the SPI interface is initialized, Arduino pins 11, 12, and 13 are unavoidably connected to these three SPI signals. When a program writes or reads SPI data registers, these signals automatically perform their magic to shift the data.

Now, for every SPI device there are four signals that control SPI data transfer: The MOSI, MSIO and SCK signals and another signal that I call the "Chip Select." Each SPI device has its own "Chip Select" signal. A "Chip Select" signal can use any Arduino pin except for ones that have already been committed to other functions. So, in particular the "Chip Select" signal for a SPI device can not be pin 11, 12, or 13. If your sketch uses the Hardware UART for data transfer, that function uses Arduino pins 0 and 1, so neither of those pins can be used for a SPI device "Chip Select." Etc.

The Ethernet library reads and writes to the SPI registers to cause data transfer into or out of the SPI port in the following sequence:

  1. It calls a function named setSS() to put the Ethernet Shield "Chip Select" pin in proper state (LOW, as it happens) to perform SPI operations on the Ethernet Shield.

  2. It does some other SPI register stuff to set up things to read or write and to fire off the serial transfer.

  3. It calls a function named resetSS() to put the "Chip Select" pin in proper state (HIGH) to tell the Ethernet Shield to stay off of the SPI bus.

Those functions are actually macros defined in w5100.h and they do direct bit write operations to the pin that is used for the Ethernet Shield "Chip Select".

For the "genuine" Ethernet Shield, the designers decided to use Arduino pin 10 for the "Chip Select." Remember? After the SPI port is initialized, we are allowed to use pin 10 for any output function we want. They wanted to use it for the Ethernet "Chip Select." Fair enough.

On the Arduino Duemilanove, Arduino pin 10 is wired (on the PC board) to bit 2 of the ATMega328p Port B, so setSS() and resetSS() cause that bit to go to zero or one. The macros use direct port bit manipulation instead of the Arduino core function digitalWrite() because direct port bit writing is faster.

If you want to use another pin for your Ethernet "Chip Select" that's OK, but you have to change those functions to use whatever bit on whatever port your board's designers have chosen.

Your Shield uses Arduino Pin 4.

Well...

On the Duemilanove, Arduino Pin 4 is connected to bit 4 of the ATmega328p Port D, so the changes that I showed will result in that pin being brought low and high by the other library functions to effect the SPI bus transfer.

The other function (macro) that depends on which pin you are using for "Chip Select" is initSS(). This function is used when the device is first initialized (by Ethernet.begin()) so that when the SPI port is first initialized, the "Chip Select" pin will be in the inactive state. (It's actually the same as resetSS().)

All of the actual choreography of the sequence of signal changes required to read and write to the SPI bus are taken care of by the Ethernet library functions, out of the sight of the application sketch programmer.

People who use "genuine" Arduino Duemilanove boards and "genuine" Ethernet Shield boards never have to know all of this stuff, and, indeed, many others are happy to have someone give a cookbook approach to whatever changes are required to "make it work." (See Footnote.)

Some of us like to try actually to understand some of the magic. We're funny that way.

Bottom lines:

  1. Leave the "SS" definition in arduino_pins.h alone! It is fixed to a particular CPU pin for a given CPU. The 1280 uses a different port and pin for the SPI "SS", so that's why there is a conditional (#ifdef) that lets the program know which is going to be used.

  2. Change definitions of initSS(), setSS(), and resetSS() to use the ATmega328p port and pin that is connected to your Ethernet Shield's "Chip select" pin.

  3. Sit back and enjoy the ride.

Regards,

Dave

Footnote:
"Pay no attention to that man behind the curtain."
---The Wizard of Oz

Thanks Dave.

This clearly explains the function and operation of the SS and CS pins.

I had gone off and done some googling since my last post, but with poor results. Your explanation is much clearer.

Your post has blown away the fog and now I feel quite confident with my understanding of these pins.

Thanks once again for your assistance.

Cheers

Fred