Help substituting EEPROM.read

hi guys,
ive written some code on the UNO that relies on EEPROM.read and EEPROM.write and I want to be able to do the same thing on a portenta. I have established that there is no EEPROM and following this tutorial:

I have taken the string thats in the flash memory, (which in my case only ever needs to be two digits) and used the toInt() function in order to get an INT from it and be able to manipulate that INT in my original code before saving it again.

my code is here:

#include "QSPIFBlockDevice.h"
#include "MBRBlockDevice.h"

using namespace mbed;

#define BLOCK_DEVICE_SIZE 1024 * 8 // 8 KB
#define PARTITION_TYPE 0x0B // FAT 32
int int11 = 5;
int int12 = 2;
//int intStored=0;

void setup() {
  Serial.begin(115200);
  while (!Serial);

  Serial.println("QSPI Block Device Test");
  Serial.println("------------------------");

  // Feed the random number generator for later content generation
  randomSeed(analogRead(0));

  // Create a block device on the available space of the flash
  QSPIFBlockDevice root(PD_11, PD_12, PF_7, PD_13,  PF_10, PG_6, QSPIF_POLARITY_MODE_1, 40000000);
  MBRBlockDevice blockDevice(&root, 1);
  
  //MBRBlockDevice blockDevice2(&root, 21);

  // Initialize the Flash IAP block device and print the memory layout
  if (blockDevice.init() != 0 || blockDevice.size() != BLOCK_DEVICE_SIZE) {
    Serial.println("Partitioning block device...");
    blockDevice.deinit();
    // Allocate a FAT 32 partition
    MBRBlockDevice::partition(&root, 1, PARTITION_TYPE, 0, BLOCK_DEVICE_SIZE);
    blockDevice.init();
  }
  /*if (blockDevice2.init() != 0 || blockDevice.size() != BLOCK_DEVICE_SIZE) {
    Serial.println("Partitioning block device2...");
    blockDevice2.deinit();
    // Allocate a FAT 32 partition
    MBRBlockDevice::partition(&root, 21, PARTITION_TYPE, 0, BLOCK_DEVICE_SIZE);
    blockDevice2.init();
  }*/

  const auto eraseBlockSize = blockDevice.get_erase_size();
  const auto programBlockSize = blockDevice.get_program_size();

  Serial.println("Block device size: " + String((unsigned int) blockDevice.size() / 1024) + " KB");
  Serial.println("Readable block size: " + String((unsigned int) blockDevice.get_read_size())  + " bytes");
  Serial.println("Programmable block size: " + String((unsigned int) programBlockSize) + " bytes");
  Serial.println("Erasable block size: " + String((unsigned int) eraseBlockSize / 1024) + " KB");

  String int11Mem = String(int11);
  String int12Mem = String(int12);


  // Calculate the amount of bytes needed to store the message
  // This has to be a multiple of the program block size
  const auto messageSize = int11Mem.length() + 1; // C String takes 1 byte for NULL termination
  const unsigned int requiredEraseBlocks = ceil(messageSize / (float)  eraseBlockSize);
  const unsigned int requiredBlocks = ceil(messageSize / (float)  programBlockSize);
  const auto dataSize = requiredBlocks * programBlockSize;
  char buffer[dataSize] {};
 // char buffer[dataSize] {};

  // Read back what was stored at previous execution
  Serial.println("Reading stored int11");
  blockDevice.read(buffer, 0, dataSize);
  Serial.println(buffer);
  String int11Read = buffer;  // variable to store char

  // Erase a block starting at the offset 0 relative
  // to the block device start address
  blockDevice.erase(0, requiredEraseBlocks * eraseBlockSize);
  
 /* Serial.println("Reading stored int12");
  delay(10);
  blockDevice2.read(buffer, 20, dataSize);
  Serial.println(buffer);
  String int12Read = buffer;  // variable to store char

  //Serial.print("int11 stored : ");
  //Serial.println(int11Mem);

  // Erase a block starting at the offset 0 relative
  // to the block device start address
  blockDevice2.erase(20, requiredEraseBlocks * eraseBlockSize);*/

  // Write an updated message to the first block
  Serial.println("int11 string to int");
  int int11Stored = int11Read.toInt();
  Serial.println(int11Stored);
  /*Serial.println("int12 string to int");
  int int12Stored = int12Read.toInt();
  Serial.println(int12Stored);*/




  Serial.print("new int11 incremented : ");
  int11Stored = int11Stored + 1;
  if (int11Stored > 9) {
    int11Stored = 0;
  }
  Serial.println(int11Stored);

  /*Serial.print("new int12 incremented : ");
  int12Stored = int12Stored + 1;
  if (int12Stored > 9) {
    int12Stored = 0;
  }
  Serial.println(int12Stored);*/


  Serial.println("Writing new message 11");
  String messageToStore11 = String(int11Stored);
  Serial.println(messageToStore11);


  blockDevice.program(messageToStore11.c_str(), 0, dataSize);

  /*Serial.println("Writing new message 12");
  String messageToStore12 = String(int12Stored);
  Serial.println(messageToStore12);


  blockDevice.program(messageToStore12.c_str(), 20, dataSize);*/

  // Deinitialize the device
  blockDevice.deinit();
  Serial.println("Done.");
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(300);
  digitalWrite(LED_BUILTIN, LOW);
  delay(300);

}

that works ok, or at least it seems, for one String turning into one INT. I need to do it at least two, preferably 6 times. Could anyone provide me some help and pointers as to what I need to do in order to get this running multiple times? as you can see ive tried just dumb luck duplicating code and changing variable names etc, but to no avail

thanks in advance

Why turn a number into a string before writing it to EEPROM, so that later when reading it, convert it back?
It's not easier to write it in EEPROM as number?

my main problem is that you cannot write to eeprom with the portenta H7. It seems I have to use the spare flash memory after writing the sketch to use as persistent memory between resets.

That is not surprising at all. It never works. I'm sure a block device will accept any kind of data for storage.

sorry, i dont understand
First you said

but now

so how does the code work or not?

is it possible to create several block devices in the available flash? regardless of the data type for now

You don't need several block devices.

well the code there, works by writing a string to a block device in the available falsh memory after the sketch is uploaded.
the code using eeprom.read and .write works on the UNO as explained, but not on the portenta

in which case, do you know of a way to write several seperate integers into it and read them back?
please bear in mind that until trying this for the first time today id not even heard of a block device

It writes a string, but you can write anything in there, it's just raw memory. They picked a string as a demonstration.

What for?
Your device size is 8k

If you want to save 6 int variables, it requred only 24 bytes

What is your level of experience? Programming is a progressive skill.

im not what id would call great, ive spent about 2 months getting some code working as I need it, one way or the other i have it working, minus the caveat of eeprom.read not being available now on the portenta.

if you know of any good tutorials for use of the block device im all ears, or a better way of achieving a persistant calibration data on the portenta h7 between power cycles...... either of the two would be great

// reading
blockDevice.read(&int11, 0, sizeof(int11));

//writing
blockDevice.program(&int11, 0,  sizeof(int11));
1 Like

For your simple storage emulating an eeprom, KV Store the key value pair NVS storage API of the MBED OS may be more simple to implement.

KV Store works well on the Nano 33 BLE but I have no experience with the Portenta H7.

Have you read the documentation for the block device API? Along with the suggestion from post #14, you should be able to get something going...

The reason I ask about experience, TBH the interface is really for advanced programmers, it assumes a lot about their expertise. It's basically no more than what API is necessary to do the job. No sugar coating like the EEPROM library. Thus no surprise it's not easy for you.

post 14 looks interesting, im going to have a play with that and get back to you

blockDevice.program(&int11,1,  sizeof(int11));
  
// reading
blockDevice.read(&int11, 1, sizeof(int11));
Serial.print("int11 : ");
Serial.println(int11);

this always gives me a serial output of int11 : 0
int11 is set as 35.
am I missing something? other than a university degree in programming ?

I hope your code still contain all stages of blockdevice initialisation?

I don't have Portenta and I can't check. But if your code from the first post worked (did you say so?), then this one should work too

ive finally got somewhere with it :

int int11 = 35;
  Serial.print("writing int11 = : ");
  Serial.println(int11);
  blockDevice.erase(0, requiredEraseBlocks * eraseBlockSize);
  blockDevice.program(&int11, 0,  sizeof(int11));

  // reading
  int int12;
  blockDevice.read(&int12, 0, sizeof(int11));
  Serial.print("reading int12  = : ");
  Serial.println(int12);
  

  int int22 = 49;
  blockDevice.erase(50, requiredEraseBlocks * eraseBlockSize);
  //blockDevice.erase(50, sizeof(int22));
  Serial.print("writing int22 = : ");
  Serial.println(int22);
  blockDevice.program(&int22, 50,  sizeof(int22));

  // reading
  int int23;
  blockDevice.read(&int23, 50, sizeof(int22));
  Serial.print("reading int23  = : ");
  Serial.println(int23);

   int int33 = 99;
  blockDevice.erase(150, requiredEraseBlocks * eraseBlockSize);
  //blockDevice.erase(150, sizeof(int22));
  Serial.print("writing int33 = : ");
  Serial.println(int33);
  blockDevice.program(&int33, 150,  sizeof(int22));

  // reading
  int int34;
  blockDevice.read(&int34, 150, sizeof(int22));
   Serial.print("reading int34  = : ");
  Serial.println(int34);

gives me :

QSPI Block Device Test
------------------------
Partitioning block device...
Block device size: 4 KB
Readable block size: 1 bytes
Programmable block size: 1 bytes
Erasable block size: 4 KB
writing int11 = : 35
reading int12  = : 35
writing int22 = : 49
reading int23  = : 49
writing int33 = : 99
reading int34  = : 99

which is what I want to see.

would anyone be kind enough to explain why it goes wrong when I change :
blockDevice.erase(0, requiredEraseBlocks * eraseBlockSize);
to :
blockDevice.erase(0, sizeof(int11));