SD Examples Updated

Let us know what you think about the chipKIT, and what can be done to make it better!
Post Reply
User avatar
Jacob Christ
Posts: 723
Joined: Sat May 28, 2011 6:34 am
Location: Southern California
Contact:

SD Examples Updated

Post by Jacob Christ » Tue Apr 30, 2013 3:06 pm

I recently changed the SD examples from something like this:

const int chipSelect = 8;

void setup()
{
Serial.begin(9600);
Serial.print("\nInitializing SD card...");
pinMode(10, OUTPUT); // change this to 53 on a mega

to something like this (changed literal 10 to chipSelect):

const int chipSelect = 8;

void setup()
{
Serial.begin(9600);
Serial.print("\nInitializing SD card...");
pinMode(chipSelect, OUTPUT); // change this to 53 on a mega


Talking with one of the guys I work with, he thinks that the pin 10 output is set to make sure the library works when you use the code with some Arduino boards. So I was thinking about changing it to something like this:


const int chipSelect = 8; // CS pin for SD card
const int slaveSelect = 8; // Slave Select line (maybe same as CS or different)

void setup()
{
Serial.begin(9600);
Serial.print("\nInitializing SD card...");
pinMode(chipSelect, OUTPUT);
pinMode(slaveSelect, OUTPUT);

Any thoughts or suggestions?

Jacob
PONTECH Quick240 an industrial form factor platform for chipKIT and Arduino users.

User avatar
Jacob Christ
Posts: 723
Joined: Sat May 28, 2011 6:34 am
Location: Southern California
Contact:

Re: SD Examples Updated

Post by Jacob Christ » Thu May 02, 2013 6:27 pm

Here is a conversation between Keith (from Digilent) and myself on this topic...

Keith:

I looked at the schematics for an Arduino UNO at http://arduino.cc/en/uploads/Main/ardui ... ematic.pdf, you will notice that PIN10 is the CS line that is routed for external SPI CS control as well as to the CS on the Arduino SPI connector. Also notice that the chipKIT Uno32 does the same thing. Pin 10 is sort of the defacto SPI CS for Arduino SPI devices.

HOWEVER, for example, the WiFi shield has 2 SPI devices on it, the WiFi module AND the SD card; and they BOTH share SPI2. So they both could be used at the same time; 2 different CS had to be picked. By default the WiFi module got the typical pin10 CS signal that Arduino uses for most SPI devices; but the SD card got pin4, not the standard Arduino CS for a single SPI device. The assumption is… there very likely could be a second and shared SPI device on the standard Arduino SPI port and you need to make sure you DON’T select it while using the non-standard SD card. You can’t have the other CS line just float. So you want to explicitly hold that other SPI device’s CS HIGH (Deselected).

Now, for chipKIT and because of the WiFi Shield, we really should have code that looks like…

Code: Select all

pinMode(4, OUTPUT);            // CS for the SD Card on a WiFi Shield
digitalWrite(4, HIGH);              // Start off deselected
pinMode(10, OUTPUT);          // Standard Arduio CS, used by the WiFi module on a WiFiShield
digitalWrite(10 HIGH);             // Start off deselected


Fortunately, both the SD and DWIFIcK libraries initialize deselected; but if you are not using one of the libraries AND you are using a WiFiShield, setting the pin as an OUTPUT WITHOUT setting it HIGH can be a real problem. It is better to leave it as an INPUT (tri-stated; do nothing) as there are pullup resistors on the WiFiShield to hold the devices deselected. But if you set it as an output, that pin gets driven and you might drive it LOW (selected) So if you are going to set pin 10 as an output, set it high too to deselect the WiFi module.

In general, Digilent has put all of the chipKIT SD card readers on CS pin 4 and leaving open the Arduino SPI capabilities on CS pin 10. And in general, the WiFi module is on pin10, Hmmm… maybe we should have moved that to a different CS pin as well… well, it is what it is…

Slave Select to me is when you are acting as a Slave, so this would be an INPUT not an OUTPUT. I do not think your second solution is correct. I think when using the SD card, I would just add:

Code: Select all

pinMode(10, OUTPUT);          // Standard Arduio CS, used by the WiFi module on a WiFiShield
digitalWrite(10 HIGH);             // Start off deselected


to turn any other shared SPI device (such as the WiFi module or other defacto Arduino SPI usage) OFF and DESELECTED. In general, putting nothing in for the WiFiShield is fine, but you don’t know what other people have put on the Arduino SPI ports and if they have pull up resistors or not. So it would always be safe to define pin10 as an output as long as you drive it high.

Jacob:

Thanks Keith... Your right I meant SD, too many things floating around in my head.

I see where the problem comes from.

So my goal in modifying the examples is of course to make it easier to get an SD card up and running for a new user. I've been writing a lab for the Fubarino SD for using the SD and when you run through all the SD examples they need to be modified in different ways from example to example. This would be the same if you were using a Uno32 or a Max32. So I was just trying to get all the examples to be consistent.

I only modified the PIC32 SD examples, didn't touch the Arduino ones at this time.

So rather than chipSelect and slaveSelect variables, maybe:

const int chipSelect_SD_default = 10; // Make 10 on Uno and 53 on a Mega (Maybe this should be an ifdef for detecting board type)
const int chipSelect_SD_mine = chipSelect_SD_default; // can be changed if you do not use default CS pin

and in setup()

Code: Select all

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

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


Keith:

And you already caught the slight error in my response, clearly the defacto default for the Mega is pin 53 not pin 10. Also I should point out that we (Digilent) are coming out with a board where the SD CS will NOT be on pin 4. We actually dedicated signals to the SD and the WiFi so they would not share the SPI port (and thus get rid of the interrupt problem with the WiFi SPI implementation). Which brings us to your second observation/suggestion. Somehow we need to have a board definition for some of these common signals, maybe in the variants file? We are now producing boards with SPI stuff on them, and hard wire signals; and I think there is a clean defacto standard for Arduino for the Uno and Mega, so I would be in favor of some kind of Default_SPI_CS in the variants; and IF the board has resources on it like SD or WiFi we should have some standard names for them as well like WiFi_SPI_CS or SD_SPI_CS. We also need to add something if SPI interrupts are going to be used like with the WIFI MRF24.

So here is a half-baked suggestion….

Let’s say in the variants Board_Defs .h you had:

Code: Select all

#define                Default_SPI_CS                10                           // or 53 in a mega board
#define                Default_SPI_PORT          SPI2CON
 
#define                WIFI_SPI_CS                      10
#define                WiFi_SPI_PORT                 SPI2CON
 
#define                SD_SPI_CS                          4
#define                SD_SPI_PORT                    SPI2CON
 
#define                ALL_SPI_INT                      EXTERNAL_1_IRQ            // the WiFi SPI INT, if another INT is used for another SPI port, OR it in here
 



In your sketch code you could have some nasty thing like:

Code: Select all

#ifdef Default_SPI_CS
pinMode(Default_SPI_CS, OUTPUT);
digitalWrite(Default_SPI_CS, HIGH);
#endif
 
#ifdef WIFI_SPI_CS
pinMode(WIFI_SPI_CS, OUTPUT);
digitalWrite(WIFI_SPI_CS, HIGH);
#endif
 
#ifdef SD_SPI_CS
pinMode(SD_SPI_CS, OUTPUT);
digitalWrite(SD_SPI_CS, HIGH);
#endif
 
And then in Sd2Card.cpp we could have something like:
 
//------------------------------------------------------------------------------
void Sd2Card::chipSelectHigh(void) {
  digitalWrite(chipSelectPin_, HIGH);
 
#if
#if defined (ALL_SPI_INT)
  if(fspi_state_saved)
  {
    SD_SPI_PORT = spi_state;
    fspi_state_saved = false;
    restoreIntEnable(ALL_SPI_INT, interrupt_state);
  }
#endif
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectLow(void) {
#if defined (ALL_SPI_INT)
    if(!fspi_state_saved)
    {
        interrupt_state = clearIntEnable(ALL_SPI_INT);
        spi_state = SD_SPI_PORT;
        SPI2CONbits.ON = 0;
        fspi_state_saved = true;
    }
#endif
  digitalWrite(chipSelectPin_, LOW);
} 
PONTECH Quick240 an industrial form factor platform for chipKIT and Arduino users.

User avatar
Jacob Christ
Posts: 723
Joined: Sat May 28, 2011 6:34 am
Location: Southern California
Contact:

Re: SD Examples Updated

Post by Jacob Christ » Thu May 02, 2013 6:32 pm

Keith,

I like your idea of having some defines per board that identify pins and ports... But I prefer something like this:

Code: Select all

#define  SPI_CS_Default       10                          
#define  SPI_PORT_Defualt    SPI2CON
 
#define  SPI_CS_WiFi            10
#define  SPI_PORT_WiFi        SPI2CON
 
#define  SPI_CS_SD             4
#define  SPI_PORT_SD          SPI2CON
 
#define  SPI_INT_ALL            EXTERNAL_1_IRQ            // the WiFi SPI INT, if another INT is used for another SPI port, OR it in here
Jacob
PONTECH Quick240 an industrial form factor platform for chipKIT and Arduino users.

KeithV
Posts: 181
Joined: Tue Sep 13, 2011 4:40 pm
Contact:

Re: SD Examples Updated

Post by KeithV » Fri May 03, 2013 6:25 pm

Look good to me.... Make it so!
KeithV
Digilent

User avatar
Jacob Christ
Posts: 723
Joined: Sat May 28, 2011 6:34 am
Location: Southern California
Contact:

Re: SD Examples Updated

Post by Jacob Christ » Sat May 25, 2013 6:26 am

I just implemented this:

Code: Select all


const int chipSelect_SD_default = 10; // Make 10 on Uno and 53 on a Mega const int chipSelect_SD = chipSelect_SD_default; 

// ... and in setup()

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

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

But didn't want to attack the board_def.h yet.
PONTECH Quick240 an industrial form factor platform for chipKIT and Arduino users.

Post Reply