LittleFS port to Teensy/SPIFlash

As a follow-up to using the Cypress FRAM chip. After some more testing its just not working properly. Appears that SPI implementation that I posted works once in a while. Not sure what I am doing or what pullups or caps I need to add.
If anyone has any ideas let me know.
..

Didn't order any or glance at their papers - are they SOIC or WSON? Soldered and cleaned well? Not sure if un-CAP'd could make a diff - if they surge power to write? Suppose you checked the CLK speed?

I did order (3) of these for $1.75 each protosupplies.com/product/w25q64jv-64m-bit-serial-flash-module/ - silly LED and a CAP onboard. One in use WORKS as 8MB Flash and planning pull the other two chips off for mounting other chips on the board. I took one of the ILI9341 PJRC test board and short 1" wired a cable plug to it so with CS=10 any Teensy can plug into it. The pads are not generous - may not work for WSON.

Got a bare breakout assortment I didn't use yet - will see about wiring to the same standard as above module to fit plug as needed. And didn't order the OSH board as it was posted.
 
The external delay in the audio library has some code for CY FRAM. I wrote that a long time ago. Turned out, command-wise, the FRAM was pretty similar to SRAM 23LC1024 but had some small differences.
I don't remember the details, but I think a look at the code used there might help.
 
The external delay in the audio library has some code for CY FRAM. I wrote that a long time ago. Turned out, command-wise, the FRAM was pretty similar to SRAM 23LC1024 but had some small differences.
I don't remember the details, but I think a look at the code used there might help.

Thanks Frank - I was looking for it in the Audio Library but couldn't find it, at least in beta5.

However, I did find that Cypress had s dev kit that contained a Arduino library for their FRAM chips. I did manage to get that version working but for some reason that chip doesn't like using SPI transactions or its me. ALso, got my version working based on their lib - again no transactions. Once I add in SPI.beginTransaction it gets upset and won't read the data on the chip. Going to experiment some more and see what happens.
 
Ok got both sketches now working with the Cypress 8Mbit chip. Yeah. anyway here is the sketch:
Code:
#include <SPI.h>

#define SPICONFIG SPISettings(30000000, MSBFIRST, SPI_MODE0)

// address masks
#define ADDR_MSB_MASK   (uint32_t)0x00FF0000
#define ADDR_ISB_MASK   (uint32_t)0x0000FF00
#define ADDR_LSB_MASK   (uint32_t)0x000000FF
#define MSB_ADDR_BYTE(addr)   ((uint8_t)((addr & ADDR_MSB_MASK)>>16))
#define ISB_ADDR_BYTE(addr)   ((uint8_t)((addr & ADDR_ISB_MASK)>>8))
#define LSB_ADDR_BYTE(addr)   ((uint8_t)(addr & ADDR_LSB_MASK))

#define NULL_PTR         ((uint8_t*) 0u)
//#define THREEBYTEADDRESS 0   //Disable 3-byte address access in SPI F-RAMs
#define THREEBYTEADDRESS 1 //Enable 3-byte address in 1Mb and above densities SPI F-RAMs

// Data buffer size
#define BUFFER_SIZE            (32u)

uint8_t pin = 10;

  uint8_t xData[BUFFER_SIZE], buffer[BUFFER_SIZE];

void setup() {
  pinMode(pin, OUTPUT);
  digitalWrite(pin, HIGH);
  
  Serial.begin(115000);
  delay(3000);
  SPI.begin();
  delay(2000);
  
  GetJedecID();

  readStatusRegister(0x05, false);


  uint32_t address = 0;

  memset(buffer, 0xff, BUFFER_SIZE);
  readData(address, buffer, BUFFER_SIZE);

 Serial.println();
  for (uint16_t j = 0; j < 2; j++) {
    for (uint16_t i = 0; i < 16; i++) {
      Serial.printf("0x%02x, ", buffer[j * 16 + i]);
    } Serial.println();
  }


  //writeEnable(true);
  
  bool status = readStatusRegister(0x05, true);
  Serial.println("Write Enabled");
  delay(2);
  
  //memset(buffer, 0xff, BUFFER_SIZE);
  for (uint16_t i = 0; i < BUFFER_SIZE; i++) buffer[i] = i+5;
  writeData(address, buffer, BUFFER_SIZE);
  delay(200);

//writeEnable(false);
  memset(buffer, 0xff, BUFFER_SIZE);
  readData(address, buffer, BUFFER_SIZE);

 Serial.println();
  for (uint16_t j = 0; j < 2; j++) {
    for (uint16_t i = 0; i < 16; i++) {
      Serial.printf("0x%02x, ", buffer[j * 16 + i]);
    } Serial.println();
  }

}

void loop() {
  // put your main code here, to run repeatedly:

}

// JEDEC ID is available even if chip is busy, so no need to stall
void GetJedecID(void) {
 uint8_t data[9];
 
  //SPI.beginTransaction(SPICONFIG);
    digitalWrite(pin, LOW);
    SPI.transfer(0x9f);  //0x9f - JEDEC register
    for(uint8_t i = 0; i<9; i++)
      data[i] = SPI.transfer(0);
    digitalWrite(pin, HIGH); // Chip deselect
  //  SPI.endTransaction();
    //for(uint8_t i = 0; i<3; i++) Serial.println(data[i], HEX);
    Serial.printf("JEDEC: 0x%02X, 0x%02X, 0x%02X\n", data[0], data[1], data[2]);
 }

bool writeEnable(bool enable) {
   uint8_t status;
  if(enable == true) {
    //SPI.beginTransaction(SPICONFIG);
    digitalWrite(pin, LOW);
    SPI.transfer(0x06);
    digitalWrite(pin, HIGH); // Chip deselect
    SPI.endTransaction();
  } else {
    //SPI.beginTransaction(SPICONFIG);
    digitalWrite(pin, LOW);
    SPI.transfer(0x04);
    digitalWrite(pin, HIGH); // Chip deselect
    //SPI.endTransaction();
  }
  
  status = readStatusRegister(0x05, true);
  //Serial.print("Status WEL: ");  Serial.println(status, BIN);
  //Serial.print("Wel Bit Enabled:  "); Serial.println(status & (1<<1));
  if(status & (1<<1) != 2) return false;
  return status & (0x02);
 }

 uint8_t readStatusRegister(uint16_t reg, bool dump)
{
  uint8_t val;
    //SPI.beginTransaction(SPICONFIG);
    digitalWrite(pin, LOW);
    SPI.transfer(0x05);  //0x05 - read status register
    SPI.transfer(reg);
    val = SPI.transfer(0x00);
    digitalWrite(pin, HIGH); // Chip deselect
    //SPI.endTransaction();

  if(dump) {
    Serial.printf("Status of reg 0x%x: \n", reg);
    Serial.printf("(HEX: ) 0x%02X, (Binary: )", val);
    Serial.println(val, BIN);
    Serial.println();
  }
  
  return val;
}


void writeData(uint32_t address, uint8_t * FRAM_wr_data_ptr, uint32_t length)
{
    Serial.println("Writing Data");
    
  uint32_t i;

  // If write pointer is NULL, return
  if(FRAM_wr_data_ptr == NULL_PTR){
    Serial.println("NULL POINTER");
    return;
  }
      
  //SPI.beginTransaction(SPICONFIG);

  // F-RAM WRITE ENABLE COMMAND
  digitalWrite(pin,LOW);  //chip select
  SPI.transfer(0x06);    //transmit write enable opcode
  digitalWrite(pin,HIGH); //release chip, signal end transfer

  // F-RAM WRITE OPERATION
  digitalWrite(pin,LOW);                   //chip select
  SPI.transfer(0x02);                    //transmit write opcode
  
  #if (THREEBYTEADDRESS == 1)
  SPI.transfer(MSB_ADDR_BYTE(address));  //send MSByte address in three byte address  
  #endif
  SPI.transfer(ISB_ADDR_BYTE(address));  //send ISByte address in three byte address (MSByte address in two byte address)
  SPI.transfer(LSB_ADDR_BYTE(address));  //send LSByte address
  
  // Data byte transmission
  for(i=0;i<length;i++)
     SPI.transfer((uint8_t)(FRAM_wr_data_ptr[i]));        //send 1 byte data at a time
  digitalWrite(pin,HIGH);                  //release chip, signal end of transfer
  //SPI.endTransaction();

}


bool readData(uint32_t address, uint8_t * FRAM_rd_data_ptr, uint32_t length)
{
 uint32_t i;

  // If read pointer is NULL, return
  if(FRAM_rd_data_ptr == NULL_PTR) {
    Serial.println("NULL POINTER");
    return;
  }

  //FRAM READ OPERATION
  //SPI.beginTransaction(SPICONFIG);
  digitalWrite(pin,LOW);                     //chip select
  SPI.transfer(0x03);                       //transmit read opcode
  
  #if (THREEBYTEADDRESS == 1)
  SPI.transfer(MSB_ADDR_BYTE(address));  //send MSByte address in three byte address  
  #endif
  SPI.transfer(ISB_ADDR_BYTE(address));  //send ISByte address in three byte address (MSByte address in two byte address)
  SPI.transfer(LSB_ADDR_BYTE(address));  //send LSByte address
  
  for(i=0;i<length;i++)
     FRAM_rd_data_ptr[i] = SPI.transfer(0);  //get all the data bytes from F-RAM
  digitalWrite(pin,HIGH);  //release chip, signal end of transfer
  //SPI.endTransaction();

}
and here is the Cypress Arduino code that I got working on the T4.1: View attachment FRAM_SPI_Example.zip

Almost working with LittleFS - that is still a work in progress.
 
Good work @maj513 - I should have gotten some of those to test with but skipped DigiKey order. Larger 64MB Flash seemed like a fun idea - but are way slow to actually format.

Once more set of intervention needed to assure bitmaps are trustworthy. The Traverse of the LFS USED blocks is good to assure used blocks are never - but even that takes 20ms on large 64MB Flash on images made here already. So filling the bitmaps takes more time to save more time.

The added intervention is knowing when PJRC code requests a block format ( leaving the block formatted ) versus LFS Format request which means they have changed their Blocks used to include that one ( making it dirty ) - but may or may not have dropped dirty block(s) in the process.

Also I neglected to touch the _Program code to that effect - simple fix to copy the bit clear code - but then test runs ...
 
@defragster
Thanks but not happy with the weirdness with using it with SPI? Inconsistency with trying to get it to work with LittleFS - probably me doing something wrong. Only just started.

Looks like you are making progress on your end.

Looks like I may get that 2Gb chip on Saturday to play with. Basically looks like it has 2 1-Gbit dies. Access is controlled by using bit 17 of the Page address. Looks like existing code may work with some minor modification. Just started looking at that RM now versus the spi code I have for the 1GB NAND. But will see - its due to arrive on tomorrow so will play with it then. In the meantime think may play with the SPI fram chip a bit until the other one gets here
 
Yeah not comforting if inconsistent and not liking :: SPI.beginTransaction(SPICONFIG);

Progress here on break for other things it seems ...
 
I ordered a few Cypress FRAM chips from Digikey. Since they're limited to 40 MHz, these can only be supported on SPI. They're a lot more expensive than flash, but should give much higher write performance.

The Digikey 3 parts I ordered are 428-3323-ND, 428-4717-ND, 428-3413-ND.

How do these compare to these for $4.16 40 MHz - for interface - SMD model is only 128KB but a third the cost : FERAM / 1MBIT (128KB X 8) / SPI 40MHz 8-SOP
>> datasheet-file_db/Memory/FEDR45V100A-01.pdf
-> this DIP is double size is $7.14 :: FRAM (Ferroelectric RAM) Memory IC 2Mb (256K x 8) SPI 34MHz 8-DIP
Mouser has the same ...

... versus cypress ...
428-3323-ND :: $12.14 : FRAM (Ferroelectric RAM) Memory IC 1Mb (128K x 8) SPI 40MHz 8-SOIC
428-3413-ND :: $25.61 : FRAM (Ferroelectric RAM) Memory IC 4Mb (512K x 8) SPI 40MHz 8-SOIC
428-4717-ND :: $35.80 : FRAM (Ferroelectric RAM) Memory IC 8Mb (1M x 8) SPI 40MHz 8-SOIC
 
Is SPI with PSRAM not supported as a recognized chip for LittleFS_SPI? Or did I solder it badly?
Don't think its setup for use with a PSRAM chip mounted on a SPI bus versus under the board. Only flash chips are setup with SPIFlash from what I saw.

Thought I'd play with that FRAM chip a bit so I setup the check42 function to see how fast it is:
Code:
    NAND ========== memory map ======  ====== check42() : WRITE !!!!
		NAND length 0x100000 element size of 1
	 took 2320177 elapsed us
    NAND ============================ check42() : COMPARE !!!
[NOTE - dump chip out as I went]

	 took 2488831 elapsed us
Good, 	Found 42 in NAND 0x100000 Times
this is when it works. If I do the prints between reads it works if not it fails.
 
Thought you all might to see what I just threw together over the last couple of days:
IMG-0287.jpg

The first set of headers are for SPI flash and the second set (closest to the T4.1) is for QSPIFlash. The set of blue wires run to the QSPI lands under the T4.1 :) Makes it easier to swap chips for testing without have to solder up a new T4.1. At some point will add the USB and ethernet headers to the T4.1 as well but forgot on the first go around.
 
Don't think its setup for use with a PSRAM chip mounted on a SPI bus versus under the board. Only flash chips are setup with SPIFlash from what I saw.

Thought I'd play with that FRAM chip a bit so I setup the check42 function to see how fast it is:
Code:
    NAND ========== memory map ======  ====== check42() : WRITE !!!!
		NAND length 0x100000 element size of 1
	 took 2320177 elapsed us
    NAND ============================ check42() : COMPARE !!!
[NOTE - dump chip out as I went]

	 took 2488831 elapsed us
Good, 	Found 42 in NAND 0x100000 Times
this is when it works. If I do the prints between reads it works if not it fails.

I assumed PSRAM not - supported - was hoping it might be added :) It is supported in Audio SPI usage right?

Haven't seen check42() in some time - forget if a quarter second fast/slow in comparison? Good it works though. All though time sensitive - w/prints - is not nice.

Interesting if the p#509 less$ ROHM FERAM's work in similar/code adjustable way, not large size - but if they work could serve the purpose more affordably at "3 to 1"

Spent a few minutes on LittleFS bitmap - but not as much time on posting to users
 
Thought you all might to see what I just threw together over the last couple of days:
...

The first set of headers are for SPI flash and the second set (closest to the T4.1) is for QSPIFlash. The set of blue wires run to the QSPI lands under the T4.1 :) Makes it easier to swap chips for testing without have to solder up a new T4.1. At some point will add the USB and ethernet headers to the T4.1 as well but forgot on the first go around.

I keep soldering T_4.1's - about 6 of them in combination for QSPI.

Here is what I have for SPI ( in addition to two Audio cards )
20201205_105752mp2.jpg
The second is PSRAM was checking if the other modules could have chip swap work - but I can't test it. The mounted is the 8MB as it came for $1.75
 
Last edited:
Sounds like you two have been busy...

I been screwing off ;)

Playing with MTP on T4.1 and have it outputting debug information using SEREMU :D
So can probably get rid of the MTP DISK plus Serial.
 
Sounds like you two have been busy...

I been screwing off ;)

Playing with MTP on T4.1 and have it outputting debug information using SEREMU :D
So can probably get rid of the MTP DISK plus Serial.

Yeah - been seeing what kind of mischief I can get into with the memory chips :) Been trying to keep up with you on MTP thread but been crazy.
 
Went back to work on the FRAM 8Mb chip and figured out to make it work with SPI transactions. Real simple solution - added delayNanoseconds(250) after and before digitalWrites and that seemed to solve the problem So now running at 35Mhz (40 gave me a problem) here are the resutls:
Code:
JEDEC: 0x03, 0x2E, 0xC2

0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 
Status of reg 0x5: 
(HEX: ) 0x40, (Binary: )1000000

Write Enabled

0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 
0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 

    NAND ========== memory map ======  ====== check42() : WRITE !!!!
		NAND length 0x100000 element size of 1
	 took 393465 elapsed us
    NAND ============================ check42() : COMPARE !!!!
	 took 403734 elapsed us
Good, 	Found 42 in NAND 0x100000 Times
and here is the updated sketch with transactions:
Code:
#include <SPI.h>

#define SPICONFIG SPISettings(35000000, MSBFIRST, SPI_MODE0)

// address masks
#define ADDR_MSB_MASK   (uint32_t)0x00FF0000
#define ADDR_ISB_MASK   (uint32_t)0x0000FF00
#define ADDR_LSB_MASK   (uint32_t)0x000000FF
#define MSB_ADDR_BYTE(addr)   ((uint8_t)((addr & ADDR_MSB_MASK)>>16))
#define ISB_ADDR_BYTE(addr)   ((uint8_t)((addr & ADDR_ISB_MASK)>>8))
#define LSB_ADDR_BYTE(addr)   ((uint8_t)(addr & ADDR_LSB_MASK))

#define NULL_PTR         ((uint8_t*) 0u)
//#define THREEBYTEADDRESS 0   //Disable 3-byte address access in SPI F-RAMs
#define THREEBYTEADDRESS 1 //Enable 3-byte address in 1Mb and above densities SPI F-RAMs

// Data buffer size
#define BUFFER_SIZE            (32u)

uint8_t pin = 10;

  uint8_t xData[BUFFER_SIZE], buffer[BUFFER_SIZE];

void setup() {
  pinMode(pin, OUTPUT);
  digitalWrite(pin, HIGH);
  
  Serial.begin(115000);
  delay(3000);
  SPI.begin();
  delay(2000);
  
  GetJedecID();

  readStatusRegister(0x05, false);


  uint32_t address = 0;

  memset(buffer, 0xff, BUFFER_SIZE);
  readBytes(address, buffer, BUFFER_SIZE);

 Serial.println();
  for (uint16_t j = 0; j < 2; j++) {
    for (uint16_t i = 0; i < 16; i++) {
      Serial.printf("0x%02x, ", buffer[j * 16 + i]);
    } Serial.println();
  }

  //check42(false);
  //writeEnable(true);
  
  bool status = readStatusRegister(0x05, true);
  Serial.println("Write Enabled");
  delay(2);
  
  //memset(buffer, 0xff, BUFFER_SIZE);
  for (uint16_t i = 0; i < BUFFER_SIZE; i++) buffer[i] = i+1;
  writeBytes(address, buffer, BUFFER_SIZE);
  delay(200);

//writeEnable(false);
  memset(buffer, 0xff, BUFFER_SIZE);
  readBytes(address, buffer, BUFFER_SIZE);

 Serial.println();
  for (uint16_t j = 0; j < 2; j++) {
    for (uint16_t i = 0; i < 16; i++) {
      Serial.printf("0x%02x, ", buffer[j * 16 + i]);
    } Serial.println();
  }

  check42(true);

}

void loop() {
  // put your main code here, to run repeatedly:

}


uint8_t valERAM;
uint16_t arraySize = 2048;
uint8_t x42[2048];
uint32_t errCnt = 0;
elapsedMicros my_us;
const uint32_t  sizeofNAND = 1048576;

void check42( bool doWrite ) {
  uint32_t test = sizeofNAND / arraySize;

  byte value;
  uint32_t ii;
  uint32_t jj = 0, kk = 0;
  if ( doWrite) {
    Serial.print("\n    NAND ========== memory map ======  ====== check42() : WRITE !!!!\n");
    Serial.printf("\t\tNAND length 0x%X element size of %d\n", sizeofNAND, sizeof(valERAM));
    my_us = 0;


    for ( ii = 0; ii < test; ii++ ) { //write pages
      //Serial.println("Loading data");
      memset(x42, 42, arraySize);
      writeBytes(ii * 2048, x42, arraySize);
    }

    Serial.printf( "\t took %lu elapsed us\n", (uint32_t)my_us );
  }  //end doWrite


  Serial.print("    NAND ============================ check42() : COMPARE !!!!\n");
  my_us = 0;

  for ( ii = 0; ii < test; ii++ ) {
    memset(x42, 0, arraySize);
    readBytes(ii * arraySize, x42, arraySize);
// Serial.println();
//  for (uint16_t j = 0; j < 12; j++) {
//    for (uint16_t i = 0; i < 16; i++) {
//      Serial.printf("0x%02x, ", x42[j * 16 + i]);
//    } Serial.println();
//  }
    for (uint16_t ik = 0; ik < arraySize; ik++) {
      if ( 42 != x42[ik] ) {
        if ( ik != 0 ) {
          Serial.printf( "\t+++ NOT 42 Good Run of %u {bad @ %u}\n", ik, ii );
          ik = 0;
          return;
        }
        if ( jj < 100 ) Serial.printf( "%3u=%8u\n", ik, x42[ik] );
        jj++;
      }
      else kk++;
    }
  }

  Serial.printf( "\t took %lu elapsed us\n", (uint32_t)my_us );
  if ( 0 == jj )
    Serial.printf( "Good, " );
  else
    Serial.printf( "Failed to find 42 in NAND %d Times", jj );
  errCnt += jj;
  Serial.printf( "\tFound 42 in NAND 0x%X Times\n", sizeofNAND - jj );
}





//////////////////////////////////////////////////////////////////
// JEDEC ID is available even if chip is busy, so no need to stall
void GetJedecID(void) {
 uint8_t data[9];
 
    SPI.beginTransaction(SPICONFIG);
    digitalWrite(pin, LOW);
    delayNanoseconds(250);
    SPI.transfer(0x9f);  //0x9f - JEDEC register
    for(uint8_t i = 0; i<9; i++)
      data[i] = SPI.transfer(0);
    delayNanoseconds(250);
    digitalWrite(pin, HIGH); // Chip deselect
    SPI.endTransaction();
    //for(uint8_t i = 0; i<3; i++) Serial.println(data[i], HEX);
    Serial.printf("JEDEC: 0x%02X, 0x%02X, 0x%02X\n", data[0], data[1], data[2]);
 }

bool writeEnable(bool enable) {
   uint8_t status;
  if(enable == true) {
    SPI.beginTransaction(SPICONFIG);
    digitalWrite(pin, LOW);
    delayNanoseconds(250);
    SPI.transfer(0x06);
    delayNanoseconds(250);  
    digitalWrite(pin, HIGH); // Chip deselect
    SPI.endTransaction();
  } else {
    SPI.beginTransaction(SPICONFIG);
    digitalWrite(pin, LOW);
    delayNanoseconds(250);
    SPI.transfer(0x04);
    delayNanoseconds(250);
    digitalWrite(pin, HIGH); // Chip deselect
    SPI.endTransaction();
  }
  
  status = readStatusRegister(0x05, true);
  //Serial.print("Status WEL: ");  Serial.println(status, BIN);
  //Serial.print("Wel Bit Enabled:  "); Serial.println(status & (1<<1));
  if(status & (1<<1) != 2) return false;
  return status & (0x02);
 }

 uint8_t readStatusRegister(uint16_t reg, bool dump)
{
  uint8_t val;
    SPI.beginTransaction(SPICONFIG);
    digitalWrite(pin, LOW);
    delayNanoseconds(250);
    SPI.transfer(0x05);  //0x05 - read status register
    SPI.transfer(reg);
    val = SPI.transfer(0x00);
    delayNanoseconds(250);
    digitalWrite(pin, HIGH); // Chip deselect
    //SPI.endTransaction();

  if(dump) {
    Serial.printf("Status of reg 0x%x: \n", reg);
    Serial.printf("(HEX: ) 0x%02X, (Binary: )", val);
    Serial.println(val, BIN);
    Serial.println();
  }
  
  return val;
}


void writeBytes(uint32_t address, uint8_t * FRAM_wr_data_ptr, uint32_t length)
{
    //Serial.println("Writing Data");
    
  uint32_t i;

  // If write pointer is NULL, return
  if(FRAM_wr_data_ptr == NULL_PTR){
    Serial.println("NULL POINTER");
    return;
  }
      
  SPI.beginTransaction(SPICONFIG);

  // F-RAM WRITE ENABLE COMMAND
  digitalWrite(pin,LOW);  //chip select
  delayNanoseconds(250);
  SPI.transfer(0x06);    //transmit write enable opcode
  digitalWrite(pin,HIGH); //release chip, signal end transfer

  // F-RAM WRITE OPERATION
  digitalWrite(pin,LOW);                   //chip select
  SPI.transfer(0x02);                    //transmit write opcode
  
  #if (THREEBYTEADDRESS == 1)
  SPI.transfer(MSB_ADDR_BYTE(address));  //send MSByte address in three byte address  
  #endif
  SPI.transfer(ISB_ADDR_BYTE(address));  //send ISByte address in three byte address (MSByte address in two byte address)
  SPI.transfer(LSB_ADDR_BYTE(address));  //send LSByte address
  
  // Data byte transmission
  for(i=0;i<length;i++)
     SPI.transfer((uint8_t)(FRAM_wr_data_ptr[i]));        //send 1 byte data at a time
  delayNanoseconds(250);
  digitalWrite(pin,HIGH);                  //release chip, signal end of transfer
  SPI.endTransaction();

}


bool readBytes(uint32_t address, uint8_t * FRAM_rd_data_ptr, uint32_t length)
{
 uint32_t i;

  // If read pointer is NULL, return
  if(FRAM_rd_data_ptr == NULL_PTR) {
    Serial.println("NULL POINTER");
    return;
  }

  //FRAM READ OPERATION
  SPI.beginTransaction(SPICONFIG);
  digitalWrite(pin,LOW);                     //chip select
  delayNanoseconds(250);
  SPI.transfer(0x03);                       //transmit read opcode
  
  #if (THREEBYTEADDRESS == 1)
  SPI.transfer(MSB_ADDR_BYTE(address));  //send MSByte address in three byte address  
  #endif
  SPI.transfer(ISB_ADDR_BYTE(address));  //send ISByte address in three byte address (MSByte address in two byte address)
  SPI.transfer(LSB_ADDR_BYTE(address));  //send LSByte address
  
  for(i=0;i<length;i++)
     FRAM_rd_data_ptr[i] = SPI.transfer(0);  //get all the data bytes from F-RAM
  delayNanoseconds(250);
  digitalWrite(pin,HIGH);  //release chip, signal end of transfer
  SPI.endTransaction();

}
note: does fail once in awhile check42 but usually reloading makes it work. Now to go back and edit what I did with LittleFS and FRAM.
 
FRAM and LittleFS
Ok on the off chance that I might get lucky I tried adding in FRAM to LittleFS but keep getting failed to mount and format.
Code:
Initializing Flash Chip
Flash ID: 03 2E C2
Flash size is 1.00 Mbyte
attempting to mount existing media
  flash rd: block=0, offset=0, size=256
  flash rd: block=1, offset=0, size=256
  flash rd: block=0, offset=0, size=256
  flash rd: block=1, offset=0, size=256
couldn't mount media, attemping to format
  flash rd: block=1, offset=0, size=256
  flash er: block=0
  flash rd: block=0, offset=256, size=256
  flash wr: block=0, offset=0, size=256
  flash rd: block=0, offset=0, size=256
format failed :(
initialization failed!
If any one wants to take a look here are the 2 files:

View attachment littlefs.zip

Probably go over again tomorrow since was just playing with the changes I made last night.
 
0xff's ... all 1's. That was just the easy first thought ...

Went back to work on the FRAM 8Mb chip and figured out to make it work with SPI transactions. Real simple solution - added delayNanoseconds(250) after and before digitalWrites and that seemed to solve the problem So now running at 35Mhz (40 gave me a problem) here are the resutls:
...
note: does fail once in awhile check42 but usually reloading makes it work. Now to go back and edit what I did with LittleFS and FRAM.

Cool - now it takes more time :) That is doing 32 bit writes - the slowdown would be less on larger blocks?

Odd it should fail - assuming that is the write failing? That If I had one of them and the code I could adjust it to torment it more/different.

Did you start where I thought morphing the _RAM code to add the FRAM? Not being large {128KB-1MB} blocks like _RAM make sense - always a trade off - #files and file size. But Small files IIRC LittleFS will store in the dir entry block?
ID(id)RC:
Code:
Metadata pairs have a ~4x storage cost, so if our file is smaller than 1/4 the block size,
there's actually no benefit in storing our file outside of our metadata pair.

In this case, we can store the file directly in our directory's metadata pair.
We call this an inline file, and it allows a directory to store many small
files quite efficiently. Our previous 4 byte file now only takes up a
theoretical 16 bytes on disk.

@mjs513 - let me know if you get a chance to scan the ROHM FERAM - if it is usably similar in operation - I could order ... Interesting if they end up working better.
 
@defragster
Took at look at morphing the RAM code but reverted to using the FLASH code as the base since I had to issue certain commands to write/read the data. But I used the blocksize/program sizes just a few minutes ago and still have a problem.

Just took a look at the ROHM datasheet - looks interesting. Pinout is more compatible as a Winbond flash. Think the commands are the same though. Just ordered a couple.

Edit = well its time to crash now. Tomorrow is another day
 
@defragster
Took at look at morphing the RAM code but reverted to using the FLASH code as the base since I had to issue certain commands to write/read the data. But I used the blocksize/program sizes just a few minutes ago and still have a problem.

Just took a look at the ROHM datasheet - looks interesting. Pinout is more compatible as a Winbond flash. Think the commands are the same though. Just ordered a couple.

Edit = well its time to crash now. Tomorrow is another day

Figured you'd have a better read on the FRAM .vs. FERAM parts - I would not have noticed the pinout not having looked at any of them - just assumed they'd be the same - so getting those FRAM wouldn't mount to my little blocks the same. I didn't even look at the PSRAM wiring versus winbond :(

Will go order some - maybe the 256KB DIP too since they need hand wiring anyhow.
 
@defragster
Took at look at morphing the RAM code but reverted to using the FLASH code as the base since I had to issue certain commands to write/read the data. But I used the blocksize/program sizes just a few minutes ago and still have a problem.

Just took a look at the ROHM datasheet - looks interesting. Pinout is more compatible as a Winbond flash. Think the commands are the same though. Just ordered a couple.

Edit = well its time to crash now. Tomorrow is another day

Finally got through all the datasheets - to see pinouts - they all seem the same for SPI {and QSPI} - so ordered some of the smaller MRAMs.

FM25V10, MR45V100A, ESP-PSRAM64, W25Q128JV
 
Back
Top