SPIFIO issues

Status
Not open for further replies.

john-mike

Well-known member
Hello,
I keep coming back to SPIFIFO but have yet to get it reading correctly.
I've got it working fine with and DAC as that just involves sending but I simply can't get anything back from this serial flash chip.

This code returns the correct value.
Code:
//setup
   pinMode(10, OUTPUT);
   spi4teensy3::init();

//loop
  digitalWriteFast(cs,LOW);
  spi4teensy3::send(0x05);
  byte s=spi4teensy3::receive();
  digitalWriteFast(cs,HIGH);


These do not.
Code:
//setup
   pinMode(10, OUTPUT);
   SPIFIFO.begin(10,SPI_CLOCK_12MHz);  //other speeds have been tried

//this loop
  SPIFIFO.write(0x05);
  byte s1 =SPIFIFO.read();

//or this
  SPIFIFO.write(0x05, SPI_CONTINUE);
  SPIFIFO.write(0);
  byte s1 =SPIFIFO.read();
  byte s2 =SPIFIFO.read();

//or this
  SPIFIFO.clear();
  SPIFIFO.write(0x05, SPI_CONTINUE);
  byte s1 =SPIFIFO.read();
  SPIFIFO.write(0);
  byte s2 =SPIFIFO.read();

In every situation I get 0 back and don't see anything on the scope on the RX pin of the 3.1. There are things happening on CS, TX and CLK.
What am I missing?

Thanks.
 
Last edited:
Normally, I don't investigate when the "forum rule" isn't followed. But in this case, I'm making an exception, because there's been a few messages lately reporting problems with SPIFIFO, but so far, none following the forum rule with a complete program and hardware details.

I tested with a Winbond W25Q64FV chip connected to Teensy 3.1, using Teensyduino 1.21-test2.

Here's how I connected everything:

flash.jpg

Because a complete program wasn't provided, I had to write one for testing.

Here's what I wrote, to query the JEDEC device identification info. The ID bytes are documented in section 6.2.1 on page 20 of Winbond's datasheet.

Code:
#include "SPIFIFO.h"

void setup() {
  byte manufacturerID, memoryType, capacity;

  while (!Serial) ; // wait for serial monitor
  delay(100);
  Serial.println("SPIFIFO Test");
  SPIFIFO.begin(10, SPI_CLOCK_12MHz);
  delay(1);
  
  SPIFIFO.write(0x9F, SPI_CONTINUE);
  SPIFIFO.write(0, SPI_CONTINUE);
  SPIFIFO.write(0, SPI_CONTINUE);
  SPIFIFO.write(0);
  SPIFIFO.read();
  manufacturerID = SPIFIFO.read();
  memoryType = SPIFIFO.read();
  capacity = SPIFIFO.read();

  Serial.print("manufacturerID = ");
  Serial.println(manufacturerID, HEX);
  Serial.print("memoryType = ");
  Serial.println(memoryType, HEX);
  Serial.print("capacity = ");
  Serial.println(capacity, HEX);
}

void loop() {
}

Here's what I see in the serial monitor:

sc.png
(click for full size)

It certainly seems to be working properly. Just to make sure, I connected my oscilloscope.

scope_0.png
(click for full size)

Had you posted a complete program, I would have tested with your code and likely found the cause of your trouble. But when the forum rule isn't followed, this is the best I can do. Hopefully it helps?
 
Sorry I just wanted to show the differences between them without posting the entire thing 4 times.
There's really nothing else to the test code but I completely understand your frustration and should have just put it up.

Code:
//#include <spi4teensy3.h>
#include <SPIFIFO.h>

/////////////////////////////////////////////////////////

void setup() {
   pinMode(10, OUTPUT);
  // spi4teensy3::init();
   SPIFIFO.begin(10,SPI_CLOCK_12MHz);  //other speeds have been tried

}

/////////////////////////////////////////////////////////

void loop() {
  /*
  digitalWriteFast(10,LOW);
  spi4teensy3::send(0x05);
  byte s=spi4teensy3::receive();
  digitalWriteFast(10,HIGH);
  */

  SPIFIFO.write(0x05, SPI_CONTINUE);
  SPIFIFO.write(0);
  byte s1 =SPIFIFO.read();
  byte s2 =SPIFIFO.read();


  Serial.println(2);
  Serial.println();

  delay(200);

}

The issues seems to have been pull-ups on one board and not another. Maybe?
Again the exact same setup worked with spi4 but not FIFO. When pull-ups were added FIFO started working.
This seems odd since I would have seen something on the scope (It's just a DSO nanao 1MHz but you can at least see is something is happening).

Either way what you have posted there Paul should be helpful to others.

Thanks again for all of your time!
 
Last edited:
slightly OT (my apologies), but as it's got to do with SPIFIFO and DACs i didn't want to open another thread.

i was trying to move some code to spififo as it seems to allow for faster DAC update rates than doing things with spi.transfer ... but i'm puzzling over this piece of code, or SPIFIFO.read(); for that matter. i need to send three bytes, which seems to work just fine -- as long as i don't follow the rules (as far as i know, but it looks as if i must be missing something).

ie AFAIK, for every write there should be a corresponding read, but my program crashes as soon as i actually call SPIFIFO.read() three times. once is ok, twice is ok. there's no obvious problems even when i don't call read at all. the code doesn't look that much different from the W25Q64FV example above, except for the write16:


Code:
void set_CHA(uint16_t _data) {
  
                SPIFIFO.write(0x10, SPI_CONTINUE); //  cmd byte
                SPIFIFO.write16(_data); 
                SPIFIFO.read();   
                SPIFIFO.read(); 
               //SPIFIFO.read();    // uncomment this and things crash                        
}

doing this, meanwhile, does work:

Code:
void set_CHA(uint16_t _data) {
  
                SPIFIFO.write(0x10, SPI_CONTINUE); //  cmd byte
                SPIFIFO.write(_data>>8, SPI_CONTINUE);
                SPIFIFO.write(_data); 
                SPIFIFO.read();   
                SPIFIFO.read();  
                SPIFIFO.read();   
                         
}
so i guess i'm unclear about what the corresponding read to write16 would look like ?
 
Last edited:
Code:
               //SPIFIFO.read();    // uncomment this and things crash

Yes, of course it crashes.

You must exactly match every SPIFIFO.write() with a corresponding SPIFIFO.read(). Every 16 bit write much be matched with a 16 bit read, and every 8 bit write must be matched with an 8 bit read.

SPIFIFO is tough to use. You are responsible for remembering what you wrote and later doing the matching reads. It's not easy to write complex code to achieve perfect balance. If you don't perfectly match every write with exactly the same read, or it you ever issue more writes (more than 4) than the FIFO can hold, things go very badly.

The normal Arduino SPI library is meant to be easy to use. The latest version has SPI.transfer(buffer, length) which is optimized. That's much easier to use, but it doesn't give you the ability to mix with other SPI.transfer() and exploit the FIFO across each function. SPIFIFO gives you that, but the cost is the requirement to exactly match every write with a corresponding read.
 
Last edited:
ok, though i was wondering why does it crash only *when* i try to match every write with a read?

i guess my error was assuming that calling SPIFIFO.read(); returns one byte ... which apparently it is not.

this works:

Code:
void set_CHA(uint16_t _data) {
  
                SPIFIFO.write(0x10, SPI_CONTINUE);
                SPIFIFO.write16(_data);
                SPIFIFO.read();   
                uint16_t tmp = SPIFIFO.read();
                         
}
 
Last edited:
Is the maximum SPI-Clock 30MHz (F_BUS/2) ? If so (i'm not sure) are there some lines missing in SPIFIFO.h ? The fastest #define is for 20MHz.
I'm planning to use SPIFIFO for the flashplayer, so this would be good to know.

Edit:

Perhaps

#define SPI_CLOCK_30MHz (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(60 / 2) * ((1+1)/2)

?
 
Last edited:
adding

Code:
#if F_BUS == 60000000
#define HAS_SPIFIFO
#define SPI_CLOCK_30MHz   (SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR) //(60 / 2) * ((1+1)/2) = 30 MHz

seems to work for me.

(that said, i haven't checked whether it improves anything, but SPIFIFO at any rate seems to be much faster than SPI.transfer, at least for the kind of simple stuff above. i'm playing around with some 4-channel DDS thingie. using SPI.h, things would bail out at about 20kHz sample clock (though maybe i was doing something wrong). with SPIFIFO i manage 40kHz (at least -- i haven't tried to max it out) ... that's using the PIT timer; ideally though, i'd probably get the audiolibrary to output to SPI)
 
Last edited:
Status
Not open for further replies.
Back
Top