SD examples and chip select definition

Using a SD card, I want to try the examples given with the libraries. As warning, it's often written "you have to define correctly the CS pin as output, event if it's not used as the CS pin..."
But, in all example sketch, a bad programming usage is used... here the "Files.ino" sketch fragment:

  Serial.print("Initializing SD card...");
  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
  pinMode(10, OUTPUT);

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }

The code above a no chance to be executed correctly, because CS is defined as 10 in pinmode, but as 4 in SD.begin!!
Why not using the correct reference to, set in Sd2Card.h, as SS_PIN in all occurrences? This is more clean and professionnal.
Have a good day,
//Yves

1 Like

The SS pin referred to in the comment is the SS pin for the Ethernet functionality. The value in the parentheses in the call to SD.begin() is defining which pin is used as the SS pin FOR THE SD CARD.

Different things. The SS pin (pin 10) needs to be defined as an OUTPUT to make SPI work, regardless of whether or not you are using pin 10 as the SS pin for anything.

The code above a no chance to be executed correctly, because CS is defined as 10 in pinmode, but as 4 in SD.begin!!

Have you actually run the code? What failed to be executed properly? You are talking apples and oranges.

The SD library has a long history and many of the examples are out of date or just plain wrong.

This comment is wrong.

  // On the Ethernet Shield, CS is pin 4. It's set as an output by default.
  // Note that even if it's not used as the CS pin, the hardware SS pin 
  // (10 on most Arduino boards, 53 on the Mega) must be left as an output 
  // or the SD library functions will not work. 
  pinMode(10, OUTPUT);

The SD library always sets SS high as an output so no code is needed for that purpose. Here is the code from Sd2Card.cpp in IDE version 1.01.

  // SS must be in output mode even it is not chip select
  pinMode(SS_PIN, OUTPUT);
  digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin

Future versions of the SD.h library will use the SPI.h library and it also makes SS as an output. Here is code from the 1.5 SPI.h library.

  // Set SS to high so a connected chip will be "deselected" by default
  digitalWrite(SS, HIGH);

  // When the SS pin is set as OUTPUT, it can be used as
  // a general purpose output port (it doesn't influence
  // SPI operations).
  pinMode(SS, OUTPUT);

Here is the reason you may need to make some pins outputs and high. If you have more than one device on the SPI bus, you must disable all devices other than the SD by making their chip select pin an output and high.

For the Ethernet shield, pin 10 is chip select for the Ethernet controller and pin 4 is chip select for the SD card. So you should make pin 10 an output and set it high to disable the Ethernet controller, not because pin 10 is SS.

Much confusion results from the fact that on 328 Arduinos pin 10 is also SS. On the Mega, people change the 10 to 53, the SS pin for the Mega, and then the SD on the Ethernet shield will not initialize. The problem is that the Ethernet controller is no longer disabled on the Mega.

For the Ethernet shield you must always make pin 10 an output and high before initializing the SD card. It has nothing to do with SS.

An old thread, but the discussion above is exactly where my concern lies.

After reading up (again) on SPI I'm still not clear on difference between CS_pin and SS_PIN.

I'm using the MEGA SPI port (50,51,52) to drive a sparkfun microSD shield
The UNO SPI pins 11,12,13 are re-directed in my design.
The CS_pin is on D8, the microSD default (i.e. SD.begin(CS_pin).
I don't define SS_PIN as it is set to pin53 and an output by the SD library (in sd2PinMap.h) automatically for a MEGA. The SD card is functioning correctly.

But I want to use pin 10 for a non-SD related task (backlight on an LCD) but as soon as SD is accessed the backlight fails.

Why is pin 10 unavailable, when the SS_PIN is 53 on MEGA?

thanks

ninja2:
An old thread, but the discussion above is exactly where my concern lies.

After reading up (again) on SPI I'm still not clear on difference between CS_pin and SS_PIN.

I'm using the MEGA SPI port (50,51,52) to drive a sparkfun microSD shield
The UNO SPI pins 11,12,13 are re-directed in my design.
The CS_pin is on D8, the microSD default (i.e. SD.begin(CS_pin).
I don't define SS_PIN as it is set to pin53 and an output by the SD library (in sd2PinMap.h) automatically for a MEGA. The SD card is functioning correctly.

But I want to use pin 10 for a non-SD related task (backlight on an LCD) but as soon as SD is accessed the backlight fails.

Why is pin 10 unavailable, when the SS_PIN is 53 on MEGA?

thanks

The reason to make the SS pin Output, high has to do with the SPI hardware in the Chip. if the SS pin is currently INPUT, when you start using the SPI functions the chip goes into SLAVE SPI mode instead MASTER SPI mode.
The Master SPI device control the Clock. If the chip is in SLAVE SPI mode, The SPI.transfer() function will hang forever waiting for the 'Master' to provide the clock signal.

So anytime you use SPI, pinMode(SS,OUTPUT); must be executed. The digitaWrite(SS,HIGH); is optional. Personally I use SS(slave Select) as a CS_pin(chip Select) when ever I can. That is what SS was to do.
Because you are using SPI Master mode the SS pin must be an output while any SPI transfers are executing.

A typical SPI transfer:

// SPI has already been initialzed with bit order, modes

// select specific SPI device, multiple device can be connected to SPI(MOSI,MISO,CLK)
// but each device needs its own SS pin, usually call CS_pin

digitalWrite(CS_pin, LOW); //  CS_pin may equal SS_Pin, this depends on your specific hardware config
uint8_t inbyte = SPI.transfer(outbyte); // send one byte out, receive one byte in
digitalWrite(CS_pin, HIGH);// finished with SPI transfer, de-select device. all done

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.

Chuck

That all makes sense, but why can't I use pin 10?

Here's a piece of code from sd2Card.h in the SD library:

/* SD Chip Select pin
 *
 * Warning if this pin is redefined the hardware SS will pin will be enabled
 * as an output by init().  An avr processor will not function as an SPI
 * master unless SS is set to output mode.
 */
/** The default chip select pin for the SD card is SS. */
uint8_t const  SD_CHIP_SELECT_PIN = SS_PIN;

I read this to say pin 53 on MEGA doubles as SS and CS, unless SD_CHIP_SELECT_PIN is redefined

I'm using Sparkfun microSD with and following:

#define CS_pin 8 
if (!SD.begin(CS_pin)){
        Serial << "[SD init FAILED]\n";
        SD_OK = false;
        lcd.setCursor(0,1); lcd.print("[SD init FAILED]"); delay(2000);} 
  else {root = SD.open("/"); Serial << "[SD OK]\n"; printDirectory(root, 0);}

(note my term CS_pin is not SD_CHIP_SELECT_PIN)

I assume pin 53 is "the hardware SS" and cannot be changed on a MEGA.
I've tested with and without following in my code and it makes no difference to SD functionality

# define SS_pin 53
pinMode(SS_pin, OUTPUT);

and either way pin 10 seems to be unavailable for other non-SD tasks.
(again my term SS_pin does not override SS_PIN in the library)

Now I don't bother making pin 53 an output, because it seems to be done for me.

Still not quite adding up!

ninja2:
Chuck

That all makes sense, but why can't I use pin 10?

and either way pin 10 seems to be unavailable for other non-SD tasks.
(again my term SS_pin does not override SS_PIN in the library)

Now I don't bother making pin 53 an output, because it seems to be done for me.

Still not quite adding up!

On the Mega2560, the SS pin is digital pin 53, for SPI to function correctly pinMode(53,OUTPUT); must be executed. You can use pin 53 for any task as long as it it configured as an OUTPUT. It can be LOW or HIGH The library does not care.
The SPI Library does two configuration step to the SS pin in SPI.begin();

First it check if SS pin is configured as input if it is an input is turns on the Pullup resister, If the pin is not connected to anything the Pullup resistor pull the pin HIGH. ( every thing is happy as long as the pin is high). This configuration work is incase you use the SPI in SLAVE mode, just incase.

The Second thing is it changes the pinMode of SS to output. It does not change the value(HIGH,LOW) Just forces it to output. Most people use SPI in Master mode, configuring to work makes peoples live better.

That is the only time the SPI library messes with SS. If later in your program you change pinMode(SS) to INPUT AND use SPI AND SS is LOW the SPI hardware will automagically switch from MASTER Mode to SLAVE Mode and your SKETCH with Hang.

I use SS as a chip select in my latest Kickstarter Project Memory Panes

It works fine.

Here is the SPI.begin() function from the latest release.

void SPIClass::begin()
{
  uint8_t sreg = SREG;
  noInterrupts(); // Protect from a scheduler and prevent transactionBegin
  if (!initialized) {
    // Set SS to high so a connected chip will be "deselected" by default
    uint8_t port = digitalPinToPort(SS);
    uint8_t bit = digitalPinToBitMask(SS);
    volatile uint8_t *reg = portModeRegister(port);

    // if the SS pin is not already configured as an output
    // then set it high (to enable the internal pull-up resistor)
    if(!(*reg & bit)){
      digitalWrite(SS, HIGH);  ****************** this is where is sets the PULLUP Resistor ON
    }

    // When the SS pin is set as OUTPUT, it can be used as
    // a general purpose output port (it doesn't influence
    // SPI operations).
    pinMode(SS, OUTPUT);  ****************************  This is were is Sets pinMode

    // Warning: if the SS pin ever becomes a LOW INPUT then SPI
    // automatically switches to Slave, so the data direction of
    // the SS pin MUST be kept as OUTPUT.
    SPCR |= _BV(MSTR);
    SPCR |= _BV(SPE);

    // Set direction register for SCK and MOSI pin.
    // MISO pin automatically overrides to INPUT.
    // By doing this AFTER enabling SPI, we avoid accidentally
    // clocking in a single bit since the lines go directly
    // from "input" to SPI control.
    // http://code.google.com/p/arduino/issues/detail?id=888
    pinMode(SCK, OUTPUT);
    pinMode(MOSI, OUTPUT);
  }
  initialized++; // reference count
  SREG = sreg;
}

I don't understand what you meant by:

[quote author=ninja2 link=msg=2279182 date=1434500599

I assume pin 53 is "the hardware SS" and cannot be changed on a MEGA.
I've tested with and without following in my code and it makes no difference to SD functionality
Code: [Select]

define SS_pin 53

pinMode(SS_pin, OUTPUT);

and either way pin 10 seems to be unavailable for other non-SD tasks.
(again my term SS_pin does not override SS_PIN in the library)

Now I don't bother making pin 53 an output, because it seems to be done for me.
[/quote]

How is pin 10 unavailable for other tasks?

The only way it would be unavailable is if it was used by some hardware.

What do you mean 'pin 10 seems unavailable'? Where is it unavailable?

Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.

Hi chucktodd,

some time passed since your last comment here but I've looked exactly for this topic (SS pin 53 as an output on Mega in communication by SPI e.g. the ethernet shield).

As I studied the datasheet of the ATmega2560 I found an interesting statement in table 21-1 (page 192 in the complete version of the datasheet).
It explains that it does NOT matter ("user defined"), if this pin is defined as in- or output in the MASTER-mode.

Are you sure this is an hardware-issue. As the hardware appearently accepts either data direction IMHO it only can be a software- (library-) issue. Maybe only one additional codeline is enough to define the Mega as master before starting every single communication.

I haven't even tried it yet but it seems to be able to be solved easily.

I am sure you have much more experience in the arduino- libraries, so I'd like to know your opinion if it is worth it to dig into their intestines and explore (and maybe fix) the reason for SPI not working with pin 53 as an input.

deschain

deschain:
Hi chucktodd,

some time passed since your last comment here but I've looked exactly for this topic (SS pin 53 as an output on Mega in communication by SPI e.g. the ethernet shield).

As I studied the datasheet of the ATmega2560 I found an interesting statement in table 21-1 (page 192 in the complete version of the datasheet).
It explains that it does NOT matter ("user defined"), if this pin is defined as in- or output in the MASTER-mode.

Are you sure this is an hardware-issue. As the hardware appearently accepts either data direction IMHO it only can be a software- (library-) issue. Maybe only one additional codeline is enough to define the Mega as master before starting every single communication.

I haven't even tried it yet but it seems to be able to be solved easily.

I am sure you have much more experience in the arduino- libraries, so I'd like to know your opinion if it is worth it to dig into their intestines and explore (and maybe fix) the reason for SPI not working with pin 53 as an input.

deschain

DesChain,
Read a little more of the Datasheet, In section 21.1.2 page 200 of 2549P–AVR–10/2012. It tells you the bad things that will happen if the SS pin is INPUT and LOW with the SPI interface enabled in Master mode.

Since this sequence of events changes the SPI hardware from Master mode to Slave mode, AND the SPI library is in a tight loop waiting for:

 /* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)))

AND Slave mode changes SCK to input (external Clock), And Since the ARDUINO was the clock source the Library code is FOREVER lock in this tight loop waiting for SPSR (SPI Status Register, SPIF bit (SPI Interrupt Flag, set when a byte is completely shifted out) to be set.

Since the Clock has no one driving it the SPI Hardware never set this flag. So your Arduino sketch hangs.

Chuck.

Hi Chuck,

you are completely right, I have better read the entire passage about SPI.
Sorry for the inconviniences and lots of thanks for your assistance.

greets, deschian

Hi, regarding Mega2560 (or DUE) and Ethernet 25j60 (or W5100) and SD card at the same time:
There are many notes, instructions and warnings on this topic. Unfortunately, the problem persists.
Please ask: is there a functional demo for the combination ?:
Board: Mega2560 (or DUE) a
Module / shield: 28j60 / W5100 together with SD card?
Of course, with reference to specific libraries? Thank you, mpcz, 18aug2019

Based on the picture, the SD module may be the wrong type to use with a 5V Aduino. See this thread:

https://forum.arduino.cc/index.php?topic=626295.0

I think current versions of the internet shield may include a microSD card slot, with appropriate voltage translation.

This is the wrong conclusion.
1 / Mega2560 i DUE is a 3V system. SD card with both Mega2560 and DUE works OK. Ethernet 28j60 or W5100 with both Mega and DUE works OK.
2/ But Ethernet does not work with the SD card at the same time. This is clearly an SPI problem. The problem for many years. Many posts on this topic. Unfortunately, Ethernet and SD card is a very desirable combination, but no post solves the problem correctly. mpcz, 19aug2019

Yes, I looked at the wrong 2560. So the module should work fine for you, as you say it does when used alone.

I haven't seen the previous discussions, but it would seem that the three output lines from the processor, MOSI, CLK and CS - should just be connected directly to the corresponding Ethernet and SD module pins, but with each slave having its own CS. However the MISO outputs of Ethernet and SD are both driving that input at the processor, and the question arises as to the state of a MISO output if its CS is turned off. Is it tri-state or open-drain as it should be, or is it an active output high or low? If either MISO output is active even when its CS is off, that could be the problem. And actually, that could even vary with the brand of SD card used since some may have open-drain outputs on MISO while others may not.

If a MISO is active high when its CS is off, you could insert a diode into that line so that it can bring the line low when it needs to, but cannot force the line high and interfere with the other MISO. The SD module already has a 10K pullup resistor on MISO, so you wouldn't need to add that.

If this idea has already been covered before, then I don't know what to suggest.