SPIMemory library - Formerly SPIFlash - now supports SPI FRAM as well! :)

It works :slight_smile: Many thanks for your help. Much appreciated. Excellent library, especially as you support the Arduino Due which needs the SPI memory more than most.

I have attached a photo of my setup but it is hard to see. The wiring is as stated above and now the examples are working. Perhaps I had a duff chip as I have not knowingly made any changes other than swap the chip out.

Thanks again Stephan

Hi Stephan,

I'm glad it works and that you find the library useful. Connecting a 0.1uF cap across VCC and GND is totally up to whether you think you need to minimize any noise on your power bus. I haven't had the need for one yet. :)

Also, if you choose to use the powerDown() mode for low power while using v2.1.1, I'd recommend that you refer to Issue 15 (on Github).

Good luck with whatever you project is and thanks for the photo. The connections look ok and as you said, it might have just been a bad chip.

Cheers!

Been writing a similar driver for the spansion S25FL132K and similar chips which will have Due and Teensy support as I use a small common library for the low level pin setting. After reading the documentation this library should work for the other chips if single mode is chosen.

I've also implemented it primarily as QSPI but normal SPI mode should work. As the guts of it had QSPI in mind it bitbangs the data too and from the slave device.

Seems the QSPI is quite new as didn't find any other libraries using it.

I’ve never looked at those chips before. They’d be an useful addition to the library. :slight_smile: My plan’s to add support for ATMEL’s flash chips sometime in the future and support for Spansion’s flash chips would make it more widely useful.

I’ve never seen QSPI being used in any other libraries either. The Winbond Chips support DSPI and QSPI. Its something I’d like to integrate into the library if I can.

P.S. Is your code on Github? I’d love to get a look at it if that’s ok :slight_smile:

Marzogh: I've never looked at those chips before. They'd be an useful addition to the library. :) My plan's to add support for ATMEL's flash chips sometime in the future and support for Spansion's flash chips would make it more widely useful.

I've never seen QSPI being used in any other libraries either. The Winbond Chips support DSPI and QSPI. Its something I'd like to integrate into the library if I can.

P.S. Is your code on Github? I'd love to get a look at it if that's ok :)

But, The whole point of DSPI and QSPI is speed. Bit banging QSPI uses more resources (4bit databus + SCK + SS). And it is slower. Using software to build the nibbles, output them, stimulate the Clock, cannot be twice as fast as 4mhz one bit SPI? A single byte SPI at 4mhz takes 32 clock cycles, how many op codes are executed to emulate QSPI?

I realize the SPI.h code is not interrupt driven, I wrote a version that does the transfers in a background interrupt setting. As long as I code the foreground code to politely handle atomic access to the SPI hardware I can do two things at once. If I were to used a bit banged QSPI function I believe it would slow down my code.

What benefit do you receive using QSPI?

Chuck.

Marzogh: I've never looked at those chips before. They'd be an useful addition to the library. :) My plan's to add support for ATMEL's flash chips sometime in the future and support for Spansion's flash chips would make it more widely useful.

I've never seen QSPI being used in any other libraries either. The Winbond Chips support DSPI and QSPI. Its something I'd like to integrate into the library if I can.

P.S. Is your code on Github? I'd love to get a look at it if that's ok :)

Sorry for the long delay in answering. I've only just started testing the library as the breakout boards took so long to arrive "fast aussie delivery". Anyway got the normal serial stuff to work finally. Got the guts working, setting and reading status, read byte(s), verify byte(s), write buffer to location, page dump function for debugging.

I can set quad mode enable (QE) and it sets the correct bit however the quad read function is returning rubbish from my test page which simply has the values 0-255 on the page. I've looked at the datasheet a zillion times, rechecked pin connections but at best the 1st 10 are correct then it goes all bad. I want to eventually put this on github, but when at least the quad mode is working. If it was working, the speed is about 2.5x faster than serial mode. However, it could be faster if the 4 data pins were sequential on the same port and they were all read/set as a single operation.

At the moment I want it just to work... then I'll optimize it and add a few options.

My code at the moment is just a single .ino file with everything in it for testing. If you want a copy pm me and I'll email a copy.

Also found the following link useful http://www.corelis.com/education/SPI_Tutorial.htm as talks about quad speed SPI. It mentions io1, io2 and io3 need to be tristated (high impedance) from what I could figure this means their pinmode should be "input". I have a feeling this is the cause of the problem.

I have recently started using the Spiflash library and need some help with the getAdress() section. I read the .cpp file and a bit confused on how it works in terms of practical application.

If I have 5 strings s1="one", s2= "two",.... ... .. s5 = "five"

and if I want to write them in consecutive order ,so that s1 is on page 0,section 0 , s2 will be on page 0,section (s1.length +1).... or the next available address after the end of string s1. How can I utilize the getAddress() function to indicate the next address? I may be using it out of context but any help to get me started would be appreciated.

Thanks in advance.

Adam

Hi Adam,

My apologies for the delay in getting back to you - I am not usually very active on the forums.

Coming to your issue, I'd recommend you update your version of SPIFlash to the latest version - 2.2.0. It has an example called 'getAddressEx.ino' which should walk you through the process. The latest version also simplifies the getAddress() function when it comes to Strings.

If it still doesn't work, feel free to let me know here - I'll keep an eye on this thread for your reply. :)

Cheers,

Praj

Just pushed through an update to v2.2.0

  • When #RUNDIAGNOSTIC is uncommented, the _troubleshoot() function is now optimised for different µCs
  • Added the ability to check if the address has been previously written to before initiating a write operation.
  • Added a sizeofStr() function to get sizes of String objects, to use with the getAddress() function
  • Fixed a bug with getAddress()
  • Added the ability get the chip’s name via getChipName() (Refer to Diagnostics.ino to see how it can be used)
  • Diagnostics.ino has been made more and efficient and provides a cleaner Serial output
  • Added getAddressEx.ino to examples show how getAdress() works.

As always, you can find this version on Github here → SPIFlash Library for Arduino v2.2.0
A ZIP file is also attached to the first post on this thread. :slight_smile:

@Chuck, I have barely scratched the surface of QSPI or DSPI and as I have a functioning library for a chip that supports both those protocols, I’m curious to see how I can make it work on an Atmega328. My interest is purely academic - unless a miracle happens and bitbanging QSPI turns out to be faster than hardware SPI :P.

@Hoek, I’m quite curious about how far you’ve gotten it working. Will PM you now :slight_smile: Thanks for the link as well! :slight_smile:

Thanks for the Reply:

I found what I was looking for by the example posted below. I will store coordinates from a gps module and just needed single increments of the address block versus using the (page,offset) method. Just helps to keep the code clean.

... The following will successively write to the memory chip and all I would need to do is keep track of which element was last written to.

//globals

uint32_t addy =0x0000; uinit8_t cnt=0;

// This will count to 0x3eb ...(decimal 1000) and the counter will increment by 1 and reset at 250: repeats 4 times

for (addy = 0x0000; addy <= 0x3eb; addy+=0x1) {

flash.writeByte(addy, cnt, true); if(cnt==250){ cnt=0; } else cnt++; }

for (addy= 0x0000; addy <= 0x3eb; addy+=0x1) { Serial.println(); Serial.println(flash.readByte(addy, false)); }

The SPI library you have made is amazing... I will update to the latest version and look forward to utilizing the last known memory allocation to make things easier.

I'm glad you find the library useful. :)

I'm also a little confused, I thought you'd said you needed to store Strings and not Bytes... if you let the address increment by 1 you're just moving forward by one bytespace and it won't work for strings or floats or pretty much anything larger than a byte.

Also in your code when you say

flash.writeByte(addy, cnt, true);
...
Serial.println(flash.readByte(addy, false));
  • the boolean arguments you are supplying at the end are unnecessary. The library defaults to using errorChecking and not using fastRead. Your code will look cleaner as well. :)

So,

flash.writeByte(addy, cnt);
...
Serial.println(flash.readByte(addy));

will work just the same.

Another note: 0x3EB is 1003 dec. 0x3E8 is 1000

Edit: Also, the functions you are setting up in your code effectively duplicate parts of the getAddress() function. Using the builtin getAddress() makes it easier to get addresses for every function in the library.

Your code could be easily re-written as follows:

#include 
#include

#define cs 10

//declare an array to hold data
uint8_t counter[1000];
//This is the library constructor
SPIFlash flash(cs);
void setup() {

  //Fill array with bytes
  uint8_t j = 0;
  while (j < 4) {
    for (uint8_t i = 0; i < 250; i++) {
      counter[(250 * j) + i] = i;
    }
    j++;
  }

  //Get address for array
  uint32_t arrayAddr = flash.getAddress(sizeof(counter));

  //Now write the array to memory
  if (flash.writeByteArray(arrayAddr, counter, 1000)) {  //1000 or 0x3E8 is the size of the array
    Serial.println("Data successfully written to chip");
  }
  else {
    Serial.println("Data write unsuccessful");
  }
  //declare a new array to hold the data being read in
  uint8_t counterRead[1000];

  flash.readByteArray(arrayAddr, counterRead, 1000);    //1000 or 0x3E8 is the size of the array
  //print out the data that has been read in to the Serial port
  for (int i = 0; i < sizeof(counterRead); i++) {
    Serial.print(counterRead[i]);
    Serial.print(", ");
    if ((i%16) == 0) {              //This code just formats the serial output to be neat
      Serial.println();
    }
  }
}

void loop() {}

Doing it this way means your code executes a lot faster.

Cheers,

Praj

P.S. When you insert code, could you please wrap it in [ code ]... /code ? It makes it easier to read the forums. :)

Excellent Lib. Using it with a single 25Q128FVSG (16MB) on a Nano testbed but will try with 2x 25Q128FVSG on a Due tomorrow. Using this wiring without the decoupling cap: |500x285

This library really offers some functionality, other flash libraries do not have.

Unfortunately, I cannot get it running on Teensy 3.2.

Has anyone out there been able to run this library on Teensy?

If not maybe some can help me doing it on my own.

First interesting thing, I would like to know is, which SPI library is used? The SPI libraries that come with Arduino IDE or Teensyduino seem to have different function parameters than the ones called from this SPIFlash library.

Second question may sound a little bit naive but I need to know.
Everywhere in the code I find
#if defined (arm) && defined (SAM3X8E)
action 1
#else
action 2

I would assume for me the path of arm should be the correct one. But I would like to have a more experienced second opinion.

Thank you for reading.

I have yet to get around to testing the library on a Teensy, so I cannot guarantee that it will work there. The library uses the standard SPI.h that comes by default with the Arduino IDE. Which version of the IDE are you running? I've only got this working till 1.6.5. Any version > 1.6.5 causes too many issues for me to bother with adding compatibility.

The bit that says

#if defined (__arm__) && defined (__SAM3X8E__)
action 1
#else
action 2

in the library, is to support the Arduino Due. Both the Due and Teensy use ARM uCs. However, the Due uses the Atmel SAM3X / SAM3A Series ARM uC while the Teensy uses the Freescale MK20DX256VLH7 ARM uC and so, what works for the Due will not work for the Teensy.

Thank you! Your library worked fine with Arduino Pro Mini ATmega328 3V3 and W25Q40BVNIG chip that was included in this eBay-module:

http://www.ebay.com/itm/262054312026?_trksid=p2057872.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT

The W25Q40BVNIG is the hardware SPI flash chip of my ESP8266 modules. That is the reason why I am interested in it.

Unfortunately I couldn't make your library and W25Q40BVNIG work with my ESP-07 module.

Would you have any suggestions for me how to go further? I am trying to connect an external W25Q40BVNIG chip to an ESP8266.

(Win 10; Arduino 1.6.7; Board: NodeMCU 1.0; /CS connected to GPIO2 of the ESP8266; other pins to normal SPI-pins of ESP8266; eBay module includes 10 kohm pullup resistors to DO, /WP, /HOLD, CLK and DI).

My problem is solved. I modified this program

http://www.instructables.com/id/How-to-Design-with-Discrete-SPI-Flash-Memory/step5/Code-Code-Code/

and now I can use W25Q40xxx with ESP8266 :-) This will be good enough for me at the moment.

Thank you, I am looking forward to using this library. Excellent !!

@Robotti: I haven't had the time to add ESP8266 support but it is in the works. The instructable you have linked in is a fantastic way of learning to communicate over SPI - I'm glad it helped. Keep an eye out here on the Github page for updates. I'm working on adding both Teensy and ESP8266 support and should have them going in the next couple of months.

@mcnobby Cheers! I'm glad you find it useful! :)

@Okio is that also the correct wiring for the W25Q256FV with an ATMega328p? And couldn't you save a pin by wiring the Chip Select (Pin 1) straight to GND? There's no harm in always keep the chip selected right? The project I am working on requires a lot of pins and I'm trying to conserve if possible.

If you keep chip select always low, than MISO may always be driven by the chip and may interfere with other SPI devices.

Can always add a shift register (or two or three) and create up to 8 (16, 24, etc.) chip selects that way using just 3 IO pins.