Go Down

Topic: Winbond SPI Flash library (Read 28482 times) previous topic - next topic

Marzogh

#30
Dec 01, 2015, 01:00 am Last Edit: Dec 01, 2015, 03:30 am by Marzogh
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
Code: [Select]
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,
Code: [Select]
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:
Code: [Select]

#include <SPIFlash.h>
#include<SPI.h>

#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 ] (without the spaces)? It makes it easier to read the forums. :)

Okio

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:

Clemi_81

#32
Feb 04, 2016, 03:30 pm Last Edit: Feb 04, 2016, 03:58 pm by Clemi_81
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.

Marzogh

#33
Feb 20, 2016, 04:55 am Last Edit: Feb 20, 2016, 05:01 am by Marzogh
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
Code: [Select]
#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.

Robotti

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).

Robotti

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.

mcnobby

Thank you, I am looking forward to using this library. Excellent !!
http://www.youtube.com/user/Recovered
http://www.smartshow.lighting

Marzogh

@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! :)

wsteelmanj

@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.




CrossRoads

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.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

chucktodd

@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.
No,
 you must toggle the CS pin at the start and end of each transaction.  the SPI interface is just a bit stream, the CS pin is used to alert the device that It should start watching the SCK and MOSI pins.

Without an active CS pin, you can only do ONE command either a READ or WRITE, then you would have to power down and start over.

This is because the chip (W25xx) expects a command byte, possibly address bytes, then an unknown number of data bytes. the digitalWrite(CS,HIGH) terminates the transmission which causes the chip to recycle it's machine state back to where it is expecting a command byte.

If you have many SPI devices you can use a 2:4 decoder which allows 2 Arduino Pins to select one of three SPI devices.  Or you can use a 3:8 decode which allows 3 arduino pins to control seven SPI devices.

Here is a schematic of how I use a 3:8 decoder to control 5 devices with 3 pins.


With this circuit, D8..D10 are my CS pins, of the 8 possible value 0x07 is reserved to mean NONE are selected.  I keep D8..D10 high to unselect all SPI devices I can Select my SDCard, FLASH, or RAM devices by changing only one pin to low, to Select my RS232 or RS485 I have to do two or three digitalWrite() commands.  Between the digitalWrite() commands, the WRONG device is selected.  After I set D8..D10 to the correct value, I delay for short time(500ns) to let the chips settle out.

Chuck.
Currently building mega http server 90% done, the Last 10% is killing me.

wsteelmanj

Thanks Chuck. I got my chip all wired up and now I have another question about programming.

I am using a W25Q128FVSIG which is 16MB. So how would I go about putting say 5MB of data on the chip? I'm thinking I want to read the data from a text file on my pc via the serial port, but I don't want it to take several hours if possible. Is there a way for the arduino to access and read a file on my computer? Or should I be writing some code on my computer which sends the data through the serial monitor? And if the latter than what is the best software to do that with? Thanks guys.

chucktodd

Thanks Chuck. I got my chip all wired up and now I have another question about programming.

I am using a W25Q128FVSIG which is 16MB. So how would I go about putting say 5MB of data on the chip? I'm thinking I want to read the data from a text file on my pc via the serial port, but I don't want it to take several hours if possible. Is there a way for the arduino to access and read a file on my computer? Or should I be writing some code on my computer which sends the data through the serial monitor? And if the latter than what is the best software to do that with? Thanks guys.
You'll have to write software, That is what I am doing.  I have a similar setup.  AtMega2560, SPIram(64kB) SPIFlash(8MB).  I am writing a simple block transmission client and server.  It is part of a bigger project.
the client (Mega2560) watches for for single byte control characters, all data is transmitted as ASCII coded HEX with using the Intel Hex format. with a few extra commands to specify chip,type, offset.

Chuck.
Currently building mega http server 90% done, the Last 10% is killing me.

frackers

#43
May 09, 2016, 02:21 am Last Edit: May 09, 2016, 03:09 am by frackers
I've been trying to use an array in the first page of a block to indicate which pages in a block are available for use. To do this I've attempted to set the array elements to 1 or 2 depending on usage and then change to 0 to say that page is now junk.

On EVERY NOR flash I've used in the last 20 years, any '1' can be programmed down to a '0' but is it really true that for the Winbond W25Q series (and I quote the spec):

"The Page Program instruction allows from one byte to 256 bytes (a page) of data to be programmed at
previously erased (FFh) memory locations. "

which means that an arbitrary value can't be changed to a '0' and my whole design is stuffed (I was hoping to use 'spiffs' at some point which relies on this property of NOR flash).

I've tried it and it certainly appears to be the case that a byte MUST be 0xff to be programmed :(
Robin Down Under (or are you Up Over!)

frackers

#44
May 09, 2016, 03:33 am Last Edit: May 09, 2016, 03:47 am by frackers
On EVERY NOR flash I've used in the last 20 years, any '1' can be programmed down to a '0' but is it really true that for the Winbond W25Q series (and I quote the spec):
It appears that I misinterpreted how "SPIFlash::_notPrevWritten" is supposed to work - by putting the code into "HIGHSPEED" mode all my problems go away. Can't help thinking that this function is dangerous!!

Found another potential bug - if the address is 0x0000000 then _prepRead & _prepWrite return this value which just happens to be 'false' !!

Robin Down Under (or are you Up Over!)

Go Up