Custom Shield - MicroSD/FRAM

Yep, I caught that speed issue in my code update. I also commented what it was, and what I set it to. Not sure if @kennethlimcp read that though :slight_smile: Thanks for the explicit post about clock speeds. I think it should easily handle 4.5MHz. Might even be able to handle 9MHz ok.

This part is not needed as we are controlling the CS lines directly. SPI.begin(<YOUR_CS_PIN_HERE>);

Just a SPI.begin(); will work.

1 Like

Definitely i read it since you guys put in effort to help :smile:

Things aren't looking good now that the SD card doesn't work as well! Like i end up with an invalid partition. Which means the SPI is working but not reading the card correctly. Formatted using my machine before inserting again didn't worked too.

I wonder if the sharing of SPI bus is causing some issues, Made the CS of the FRAM HIGH but maybe it needs to be in High Impedance mode using HOLD.

AHHH. The code to read the FRAM isn't working as well but i checked and made sure all the cold joints are fixed. So hardware is ok. Gotta see what's going on the SPI.

I don't have a scope but used my DMM. Seems like the SPI isn't being turned on somehow. All the SPI pins simply showed 0v.

EDIT:

Changed the SP .mode to 3 and at least there's something to see.....

I printed the buf2 in HEX format and got this:

Running
Successful read
Failed to read!
0
0
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF----End of setup()
Running
Successful read
Failed to read!0
0
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF----End of setup()
Running
Successful read
Failed to read!
0
0
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF----End of setup()

So FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF is supposed to be Successful read. Not sure why the FRAMRead is giving all 0xFF


Trying to see how i can check if the communication to the FRAM is working. So i tried to read the 0000 0101 Read Status Register

The output:

ÿÿÿÿÿÿÿÿRunning
ÿÿÿÿÿÿÿÿRunning
ÿÿÿÿÿÿÿÿRunning
ÿÿÿÿÿÿÿÿRunning
ÿÿÿÿÿÿÿÿRunning

Code:

> const uint8_t CMD_WREN = 0x06; //0000 0110 Set Write Enable Latch
> const uint8_t CMD_WRDI = 0x04; //0000 0100 Write Disable
> const uint8_t CMD_RDSR = 0x05; //0000 0101 Read Status Register
> const uint8_t CMD_WRSR = 0x01; //0000 0001 Write Status Register
> const uint8_t CMD_READ = 0x03; //0000 0011 Read Memory Data
> const uint8_t CMD_WRITE = 0x02; //0000 0010 Write Memory Data

> const uint16_t U3_CS_PIN = D1; // chip select 1
> const uint16_t U4_CS_PIN = D0; // chip select 2


> // 0x1fff (4192) x 8 bits for 64Kb FRAM

> void setup()
> {

>   Serial.begin(9600);                           // OPEN YOUR SERIAL TERMINAL NOW...
>   while(!Serial.available()) SPARK_WLAN_Loop(); // PRESS ENTER TO CONTINUE
>   Serial.println("Running");

>   pinMode(U3_CS_PIN, OUTPUT);
>   digitalWrite(U3_CS_PIN, HIGH);
>   pinMode(U4_CS_PIN, OUTPUT);
>   digitalWrite(U4_CS_PIN, HIGH);

>   //Setting up the SPI bus
>   SPI.begin(); // Chip Select line will default to A2, however we're going to manual use D0, and D1
>   SPI.setDataMode(SPI_MODE3);  
>   SPI.setBitOrder(MSBFIRST);
>   //SPI.setClockDivider(SPI_CLOCK_DIV2); // this is 16MHz / 2 on arduino = 4MHz
>   SPI.setClockDivider(SPI_CLOCK_DIV16);  // 72MHz / 4MHz = 18, but the closest divider is 16 (4.5MHz)
> }

> void loop()
> {
>   char buf1[]="12345678";

>   while(!Serial.available()) SPARK_WLAN_Loop(); // PRESS ENTER TO CONTINUE

>   Serial.println("Running");

>   digitalWrite(U3_CS_PIN, LOW);

>   SPI.transfer(CMD_RDSR);

>   for (uint16_t i=0; i < 8; i++) buf1[i] = SPI.transfer(0xFF);


>   for (uint16_t i=0; i < 8; i++) Serial.print(buf1[i]);


>   digitalWrite(U3_CS_PIN, HIGH);

>  delay(1000);
> }

TL;DR

Status of this Shield - 70% completed.

What to be done:

  1. Make sure that the FRAMs are working fine through SPI
  2. Check through once more on the Pinouts on R4 since some changes are made (D2 & D3 for CS)
  3. Add in Solder masks and label
  4. See if more pads can be added for pins for option to change pins if needed (So far, pads have been added for all CS pins)
  5. Check pin compatibility with SRAM, FLASH etc.

TIME TO TAKE ORDERS :smiley:

UPDATES
So It seems like the FRAM is indeed causing some interference to the microSD after doing some tests.

We might need to end up touching the HOLD pins on the FRAM and see how things turn out.

I’m looking at making a SOIC-8 Breakout board to hook only 1 x FRAM to the Core SPI and see it i can get it working :slight_smile:

What does the output look like in HEX format with the RDSR command? The datasheet does in fact say it will ignore the value clocked into the SI input after it’s in RDSR mode or READ mode After op-code of RDSR is input to SI, 8-cycle clock is input to SCK. The SI value is invalid for this time.

Give me a second. I’ll flash the code OTA.

So i’m guessing i should be seeing 0x05 as the first byte?

I’m reading using for (uint16_t i=0; i < 8; i++) buf1[i] = SPI.transfer(0xFF); and i guess buf1[0] should contain 0x05?

The issue is flaky but i’m confident that the Hardware is ok… But to be on the safe side, i’ll just make a breakout board and pop in a new FRAM just to be sure that only the software is screwing things up!

@BDub, All i’m seeing is 00000000.

Will a oscilloscope be able to capture the signal? I will head for school earlier to hook this up but it only has 2 channels for me to monitor.

Sadly, i don’t have a logic analyser and you guys should start recommending me some :smiley:

HOLD ON A SECOND. Let me change some stuff and come back!

[Saleae Logic 8][1] :smile:

[1]: https://www.saleae.com/[quote="kennethlimcp, post:125, topic:3592"]
All i'm seeing is 00000000.
[/quote]

Hmm, you probably should see all 0's. Try executing the WREN command first then RDSR, you should get 0b00000010 (or 2).

void loop()
{
  while(!Serial.available()) SPARK_WLAN_Loop(); // PRESS ENTER TO CONTINUE

  Serial.println("Running");

  digitalWrite(U3_CS_PIN, LOW);
  SPI.transfer(CMD_RDSR);
  Serial.println(SPI.transfer(0xFF),HEX);
  digitalWrite(U3_CS_PIN, HIGH);

  digitalWrite(U3_CS_PIN, LOW);
  SPI.transfer(CMD_WREN);
  digitalWrite(U3_CS_PIN, HIGH);

  digitalWrite(U3_CS_PIN, LOW);
  SPI.transfer(CMD_RDSR);
  Serial.println(SPI.transfer(0xFF),HEX);
  digitalWrite(U3_CS_PIN, HIGH);

  delay(1000);
}

I think the output should be:

Running
0
2
Running
2
2
Running
2
2

Sadly:

Running
0
0
Running
FF
FF
Running
FF
FF

@BDub, did you bug my router? I was looking along the WREN/WEL line on the datasheet when u posted.... :smiley:

Going nowhere when i'm blind without an oscilloscope. Gonna shower and head out!

Well the lowest bit (BIT 0) is always supposed to be 0, so something is definitely wrong with this picture.

@BDub,

yeah you’re right on that. I’m expecting to see something else than 0xFF.

Nevermind! I have this now:

Thanks to your guidance i can now do it pretty fast!

1 Like

I just ordered 2 of those FRAMs from digikey overnight. I can throw them on some breakouts my buddy made. Also got one in DIP8 flavor, but 2Mbit.

http://imgur.com/xoojUQA

2 Likes

Time to wire this up! I’ll clean the flux off later -_-
http://www.imgur.com/W426G8P

Hope to hear from you in a while!

Sorry but i have been really stretched with all the projects and work on hand :smiley:

Have allocated time for this today and let’s hope we can both get this working!

Then we can narrow down to the hardware issue.

Thanks @BDub, you have been a great help as always :dancer:

Time for code:
http://www.imgur.com/YyOJWWA

Please tell me it’s all working? :D.

Why is there a Spider in the photo? :stuck_out_tongue:

Big Red Dot - Must be a black widow :slight_smile:

@BDub that is awesome. Are those OSHPark Proto Boards ?

It's all working!

Yep!


Ok, so this took a lot longer than it should have. It's all staring me in the face and I just didn't see it. I had the Logic 8 hooked up and all of the commands look good, but there is NOTHING coming back out of the FRAM chip on the SO pin (which connects to the MISO input on the Core). I swear I checked the wiring 7 times... however, I did it with your schematic -__- So on the 8th time I used the datasheet and low and behold I found the problem. You have pins 5 and 6 flipped on your schematic. I swapped those connections and MOSI was talking to SI now and SCK was going to the CLOCK input on the FRAM... finally a write sequence!

http://www.imgur.com/LI1yWVl

Here I send the WREN (0x06) command, then WRITE (0x02), the address (0x00) (0x01), and the data (0xAA)

Here I send the READ (0x03) command, then the address (0x00) (0x01), and the dummy byte (0x7E), the FRAM spits out (0xAA) on the SO pin (MISO input on Core) Woot!

Here it is reading out the last of 16 0xAA's:

Test Code:

#define CMD_WREN      0x06   // 0000 0110 Set Write Enable Latch
#define CMD_WRDI      0x04   // 0000 0100 Write Disable
#define CMD_RDSR      0x05   // 0000 0101 Read Status Register
#define CMD_WRSR      0x01   // 0000 0001 Write Status Register
#define CMD_READ      0x03   // 0000 0011 Read Memory Data
#define CMD_WRITE     0x02   // 0000 0010 Write Memory Data
#define FRAM_ADDR_MAX 0x1fff // Max address value
 
#define U3_CS_PIN D2 // chip select 1
#define U4_CS_PIN D3 // chip select 2
 
/**
 * Write to FRAM (assuming 2 FM25C160 are used)
 * addr: starting address
 * buf: pointer to data
 * count: data length. 
 *        If this parameter is omitted, it is defaulted to one byte.
 * returns: 0 operation is successful
 *          -1 address out of range
 */
int8_t FRAMWrite(uint16_t addr, uint8_t* buf, uint16_t count=1)
{
  uint16_t cs = 0;
   
  if (addr > FRAM_ADDR_MAX)  {
    addr -= FRAM_ADDR_MAX + 1;
    cs = U4_CS_PIN;
  } else {
    cs = U3_CS_PIN;
  }
   
  if (addr > (FRAM_ADDR_MAX * 2) + 1) return -1;
   
  uint8_t addrMSB = (addr >> 8) & 0xff;
  uint8_t addrLSB = addr & 0xff;
   
  digitalWrite(cs, LOW);   
  SPI.transfer(CMD_WREN);  //write enable 
  digitalWrite(cs, HIGH);
   
  digitalWrite(cs, LOW);
  SPI.transfer(CMD_WRITE); //write command
  SPI.transfer(addrMSB);
  SPI.transfer(addrLSB);
   
  for (uint16_t i = 0;i < count;i++) SPI.transfer(buf[i]);
 
  digitalWrite(cs, HIGH);
   
  return 0;
}
 
/**
 * Read from FRAM (assuming 2 FM25C160 are used)
 * addr: starting address
 * buf: pointer to data
 * count: data length. 
 *        If this parameter is omitted, it is defaulted to one byte.
 * returns: 0 operation is successful
 *          -1 address out of range
 */
int8_t FRAMRead(uint16_t addr, uint8_t* buf, uint16_t count=1)
{
  uint16_t cs = 0;
   
  if (addr > FRAM_ADDR_MAX)  {
    addr -= FRAM_ADDR_MAX + 1;
    cs = U4_CS_PIN;
  } else {
    cs = U3_CS_PIN;
  }
   
  if (addr > (FRAM_ADDR_MAX * 2) + 1) return -1;
 
  uint8_t addrMSB = (addr >> 8) & 0xff;
  uint8_t addrLSB = addr & 0xff;
   
  digitalWrite(cs, LOW);
   
  SPI.transfer(CMD_READ);
  SPI.transfer(addrMSB);
  SPI.transfer(addrLSB);
   
  for (uint16_t i=0; i < count; i++) buf[i] = SPI.transfer(0x7e);
 
  digitalWrite(cs, HIGH);
   
  return 0;
}
 
void setup()
{
  Serial.begin(115200);                         // OPEN YOUR SERIAL TERMINAL NOW...
  while(!Serial.available()) SPARK_WLAN_Loop(); // PRESS ENTER TO CONTINUE
  Serial.flush();

  pinMode(U3_CS_PIN, OUTPUT);
  digitalWrite(U3_CS_PIN, HIGH);
  pinMode(U4_CS_PIN, OUTPUT);
  digitalWrite(U4_CS_PIN, HIGH);
 
  //Setting up the SPI bus
  SPI.setDataMode(SPI_MODE0);  
  SPI.setBitOrder(MSBFIRST);
  //SPI.setClockDivider(SPI_CLOCK_DIV2); // this is 16MHz / 2 on arduino = 4MHz
  SPI.setClockDivider(SPI_CLOCK_DIV4);  // 72MHz / 4MHz = 18, but the closest divider is 16 (4.5MHz)
  SPI.begin(); // Chip Select line will default to A2, however we're going to manual use D2, and D3
   
  
}
 
void loop()
{
  //Test
  char buf1[] = {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,'\0'};
  char buf2[] = {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,'\0'};
   
  int8_t status;
  status = FRAMWrite(1, (uint8_t*)buf1, strlen(buf1)); // Write buf1 to FRAM
  if(status == -1) {
    Serial.println("WRITE ERR: Address out of range!");
    while(1) SPARK_WLAN_Loop(); // Die, with the possibility of reincarnation.
  }
  
  delay(10);

  status = FRAMRead(1, (uint8_t*)buf2, strlen(buf1)); // Read saved value back into buf2, if it works it won't display "Failed to read."
  if(status == -1) {
    Serial.println("READ ERR: Address out of range!");
    while(1) SPARK_WLAN_Loop(); // Die, with the possibility of reincarnation.
  }
   
  // printed this way because buf2 may not be null terminated properly.  
  // It is, but this is just because both strings happen to be exactly 16 chars already.
  for(uint8_t i=0; i<16; i++) Serial.print(buf2[i],HEX);
  
  Serial.println(" Press any key to try again!");
  delay(50);
  while(Serial.available()) Serial.read();      // MAKESHIFT FLUSH
  while(!Serial.available()) SPARK_WLAN_Loop(); // PRESS ENTER TO CONTINUE 
}

I also tested it at 4.5MHz and 18MHz. Reading 16 bytes took 67us at 4.5MHz, but with the SPI set 4 times faster the total time was only reduced to 42us. The reason is because even though the SPI is clocking at 18MHz, the delay between transfers is slow, and pads it out to basically the same time. I'm sure this can be improved in the Spark core firmware, otherwise the speed of the Spark is under-utilized. cc: @zachary @satishgn

This FRAM is very nice and I'm sure we'll start to see many people use it for ring buffers and all kinds of cool extra external RAM uses.

3 Likes

So my wiring is swapped ?

Thanks @BDub, i should have totally checked that. GOSH X_X

That was an obvious mistake a newbie to making a new component in Eagle. Lesson learnt!

Yes, even right in your face swapped on the schematic. I didn’t even notice it when hooking up and checking so many times:

SCK does go to A3 correctly on the schematic, but it is NOT pin 5 of the FRAM, it’s pin 6.
SI does go to A5 correctly on the schematic, but it is NOT pin 6 of the FRAM, it’s pin 5.

1 Like

Yes i just changed it.

Really sorry about that! Making this shield has been a great learning journey for me :smile:

Going to push this update to the github library i have for the FRAM.

Sorry for the issue!!

Hey we’ve ALL made the mistakes… all of them. Don’t be sorry. You now have one less obstacle in your path to making this Spark Memory Shield a reality :wink: I had fun working on this as well :spark:

1 Like