Skip to main content

Memory

The Quarto has 96kB of user-accessible non-volatile memory (NVM) (sometimes called EEPROM). This is memory that will persist across reboots and reflashings of the Quarto. You can read and write to this memory with the following functions:

readNVM

uint16_t readNVM(uint32_t address);

This function returns a unsigned 16-bit word with the data stored in the non-volatile memory at a specified address.

  • address Address of NVM to read. Range of values is from 0 to 98,303 (0x00 - 0x17FFF). Note that input address must be aligned to 16-bit reads, meaning an even address number. Odd address values will be be rounded down, so readNVM(0x05) will return the same result as readNVM(0x04).

Example

uint16_t something = readNVM(0x1234);

readNVMblock

void readNVMblock(void* data,uint16_t length, uint32_t start_addr);

Similar to readNVM, this function also reads from the NVM, but it can read an arbitrary length of data and puts that data into the memory specified by the argument data. Because data is passed as a pointer, make sure that the memory location at data can store the amount of data specified by length. Otherwise other memory can be overwritten, causing unpredictable behavior (this would be a buffer overrun).

  • *data Pointer to any type of memory to store the read data
  • length How much data (in bytes) to read from the NVM and store into the data
  • start_addr Starting NVM address to read from. Same range as address in readNVM function

Example

float stored_data[10] = {1.1,2.2,3.3,4,4}; // create memory to store 10 floats
readNVMblock(&stored_data,sizeof(stored_data),0x1000); /* loads the next 40 bytes
/ of NVM data from 0x1000 into stored_data array */
Serial.print(stored_data[0]); //use stored_data now that it is loaded with the NVM data.

writeNVMpages

void writeNVMpages(void* data,uint16_t data_size, uint16_t first_page);

Writing to the NVM is done in pages. Each page is 128 bytes long, and there NVM has 768 pages. If you write less than a page, the remainder of that page will get erased, so if you use, example, the first 64 bytes of a page but only want to update the first 32 bytes, you will need to read the full 64 bytes, change the lower 32 and then write the full 64 bytes back. Otherwise bytes 32 - 64 will get erased.

  • *data Pointer to any type of memory that contains the data to store in NVM
  • data_size Length of data to write to NVM
  • first_page What page to start writing to. Value can be 0 through 767.

Example

struct Cal {
uint16_t cal_a;
double cal_b;
uint16_t cal_c;
};

struct Cal cal1;
cal1.cal_a = 56;
cal1.cal_b = 1.2345678;
cal1.cal_c = 9876;

writeNVMpages(&cal1,sizeof(cal1), 500); //Store struct cal1 in NVM starting at page 500
Serial.printf("Checking cal_a in NVM is: %u\n",readNVM(500*128)); /* returns 56,
* reads uint16_t stored at start of page 500, or address 500*128 = 0xFA00 */

struct Cal cal2;
readNVMblock(&cal2,sizeof(cal2),0xFA00); //loads NVM cal into new cal2 structure.
Serial.println(cal2.cal_c); //this will print 9876.

cal2.cal_a = 100; //change value of cal_a
writeNVMpages(&cal1,2, 500); //Write 2 bytes of page 500 with cal2 data (just cal_a data)
readNVMblock(&cal1,sizeof(cal1),0xFA00); //load the stoed NVM data into cal1
Serial.println(cal1.cal_a); // value is now 100
Serial.println(cal1.cal_c); // value is 0 as writeNVMpages erased values in the page that were not written to