Commit b867b461 authored by deroo's avatar deroo
Browse files

add example/BLEflashExplore

parent 92db7994
#include <Nano33BLEflash.h>
/*
A sketch to demo using Arduino Nano 33 BLE flash for non-volatile data storage
The Nano 33 BLE uses a nRF52840 microcontroller chip
The Flash on the nRF52840 has 256 pages of 1024 words, each word is 4 bytes.
Each page is individually erasable; each word is individually writable.
The first 16 pages (0-15) are used for the bootloader.
Do not corrupt the bootloader lest your Nano become useless!
The next 19 pages (16-35) are used by this sketch. Larger sketches may use more pages.
(it seems the smallest sketches, like blink, take 19 pages)
To check how many pages your sketch uses, watch the colored text as it uploads (hit the Arduino reset button to abort).
Or, compile and take the number of bytes in "Sketch uses NNNN bytes (X%) of program storage space..."
and divide by 4096, rounding up.
*/
// change this from 1 to 0 the 2nd time uplaoding and running the code.
// Cut and restore power to demo volatile vs non-volatile memory
const int initialUpload = 1;
// basics of where in flash this sketch puts its array
// a random page, more than 16+19=35;
// less than or equal to 255, which is the last page.
const unsigned int flashPage = 253;
// the memory (byte) address of the above page, base of the flash array
const unsigned int flashAddr = flashPage * flashBytesPerPage;
// declaration of variables that use flash, not RAM:
// manually specify the memory location, thus must be via a pointer
// global scope, so they can be seen in both setup() and loop(),
// (as must be any variable that appears in both.)
// otherwise, they could be declared more locally
// and passed by reference like any array.
// the size of the array. keep it <1024 to keep it on one flash page
const unsigned int arraySize = 20;
// an array in flash: tell compiler where, but not how big
// (that's your job to keep track of)
int *ArrayInFlash = (int *)flashAddr;
// an array in RAM: tell compiler how big, but not where
// (that's the compiler's job to keep track of)
int ArrayInRAM[arraySize];
void setup() {
unsigned int index; // the array index
Serial.begin(9600);
while (!Serial);
if (initialUpload == 1) {
// erase the page to initialize the flash array
Serial.println("About to erase");
flashMode(FLASH_ERASE); // enable erasing of pages in Flash
int result = flashErasePage(flashPage); // flash erase happens here.
flashMode(FLASH_READONLY); // protect flash from inadvertent writes
Serial.print("Page ");
if (result >= 0) {
Serial.print(result);
} else {
Serial.print(flashPage);
Serial.print(" not");
}
Serial.println(" erased");
Serial.println("Erase complete");
Serial.println();
// fill the arrays
for ( index = 0; index < arraySize; index++ ) {
int int2write = arbitraryFunction(index); // make up something to write
flashMode(FLASH_WRITE); // enable writing to flash
// write data to array in flash. Surround w/ calls to flashMode()
ArrayInFlash[index] = int2write;
flashMode(FLASH_READONLY); // protect flash from inadvertent writes
ArrayInRAM[index] = int2write; // write data to array in RAM.
}
}
// check the contents of the arrays
// reads an element of the integer arrays, compares to what it should be
for ( index = 0; index < arraySize; index++ ) {
Serial.print("ArrayInFlash[");
Serial.print(index);
Serial.print("] is ");
Serial.print(ArrayInFlash[index]);
Serial.print(" while ArrayInRAM[");
Serial.print(index);
Serial.print("] is ");
Serial.print(ArrayInRAM[index]);
Serial.print(" ... both should be ");
Serial.println(arbitraryFunction(index));
}
Serial.println();
if (initialUpload == 1) {
Serial.print("Now, to demonstrate how flash is non-volatile ");
Serial.println("while RAM is volatile, ");
Serial.println("change the line (near the top of the sketch) from ");
Serial.println("const int initialUpload = 1;");
Serial.println("to ");
Serial.println("const int initialUpload = 0;");
Serial.println("and upload again.");
} else {
Serial.print("Cut power to the Arduino, ");
Serial.println("plug it in again, and watch the output.");
}
}
void loop() {
// put your main code here, to run repeatedly:
yield();
}
int arbitraryFunction(int in) {
// a function to make different integer values
// as a function of the integer array index.
// just to make it clear we are not seeing something trivial
// in the Serial.prints
int out = in*2 + 10; // this is what's arbitrary. Make it whatever you want.
return out;
}
/*
* A sketch to demonstrate an array of double and of int in both RAM and flash.
*/
#include <Nano33BLEflash.h>
#define SZ_ARRAY 5
// global arrays
double doubleArrayInRAM[SZ_ARRAY];
double *doubleArrayInFlash;
//double arrayInFlash[SZ_ARRAY]; // this form of declaration cannot be reassigned to flash
int intArrayInRAM[SZ_ARRAY];
int *intArrayInFlash;
// global variables
double slope=2.,intercept=1.;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while (!Serial);
NANO33BLE_PUT_ARRAY_IN_FLASH(double,doubleArrayInFlash,SZ_ARRAY)
NANO33BLE_PUT_ARRAY_IN_FLASH( int, intArrayInFlash,SZ_ARRAY)
Serial.print("address of doubleArrayInFlash in setup() = 0x");
Serial.print((int)doubleArrayInFlash,HEX);
Serial.println();
Serial.print("address of intArrayInFlash in setup() = 0x");
Serial.print((int)intArrayInFlash,HEX);
Serial.println();
splash_help();
}
void loop() {
// put your main code here, to run repeatedly:
if (Serial.available())
{
char c=Serial.read();
c=tolower(c);
if (c=='h') splash_help();
if (c=='s') splash_suggest();
if (c=='w') write2arrays();
if (c=='r') readArrays();
if (c=='e') eraseArrays();
if (c=='m') updateSlope();
if (c=='b') updateIntercept();
}
}
void splash_help(){
Serial.print("Enter these letters on the SerialMonitor to get these responses:\n");
Serial.print(" h -- this help message\n");
Serial.print(" s -- suggestions on using this sketch to demo properties of flash vs. RAM\n");
Serial.print(" w -- write values to arrays of doubles and ints in flash and RAM. Value written are slope*index+intercept\n");
Serial.print(" r -- read the arrays of doubles in flash and RAM and display on the SerialMonitor\n");
Serial.print(" e -- erase the arrays of doubles in flash and RAM\n");
Serial.print(" m -- update the slope value. default = 2. Currently = ");
Serial.println(slope);
Serial.print(" b -- update the intercept value. default = 1. Currently =");
Serial.println(intercept);
}
void splash_suggest(){
Serial.println("A sequence of things that demonstrate the difference b/t RAM and flash.");
Serial.println("First, see what's there. Read the array contents");
Serial.println("Follow each step below with a read to see what has changed, if anything");
Serial.println("Erase the flash");
Serial.println("Write to the arrays");
Serial.println("Hit the reset button on the Arduino Nano 33 BLE");
Serial.println("Write to the arrays again");
Serial.println("Unplug the USB cable and plug it back in. You may need to select a different port to use the SerialMonitor");
Serial.println("Change the slope and/or intercept values");
Serial.println("Write to the arrays again");
Serial.println("Erase the flash again");
Serial.println("Write to the arrays one last time");
Serial.println();
}
void write2arrays(){
// save values to the arrays.
// what is actually saved in RAM is what was written to RAM
// what is actually saved in flash is a bit-wise or with its previous contents
int idx;
double val2write;
for (idx=0;idx<SZ_ARRAY;idx++) {
Serial.print("Writing to array element #");
Serial.print(idx);
Serial.print(": ");
val2write=slope*idx+intercept;
Serial.print(val2write);
Serial.println();
doubleArrayInRAM[idx]=val2write;
intArrayInRAM[idx]=(int)val2write;
flashMode(FLASH_WRITE);
doubleArrayInFlash[idx]=val2write;
intArrayInFlash[idx]=(int)val2write;
flashMode(FLASH_READONLY);
}
}
void readArrays(){
int idx;
Serial.println("array ___double___ ____int____");
Serial.println("index RAM flash RAM flash");
for (idx=0;idx<SZ_ARRAY;idx++) {
Serial.print(idx);
Serial.print(" ");
Serial.print(doubleArrayInRAM[idx]);
Serial.print(" ");
Serial.print(doubleArrayInFlash[idx]);
Serial.print(" ");
Serial.print( intArrayInRAM[idx]);
Serial.print(" ");
Serial.print( intArrayInFlash[idx]);
Serial.println();
}
}
void eraseArrays(){
// erase the arrays in flash: set all the bits to one
// the next write will faithfully save what was written
// this function does nothing with the arrays in RAM.
// Just write to RAM to erase them.
int page;
flashMode(FLASH_ERASE);
for (page=NANO33BLE_FLASH_LOWEST_PAGE;page<flashNumberOfPages;page++) {
flashErasePage(page);
}
flashMode(FLASH_READONLY);
Serial.println("Flash arrays erased");
}
void updateSlope(){
char varName[10]="slope";
changeVariable(varName,&slope);
}
void updateIntercept(){
char varName[10]="intercept";
changeVariable(varName,&intercept);
}
void changeVariable(char *varName, double *varPtr){
const int sz_buf=8;
char buf[sz_buf];
int lpr=0;
Serial.print("Current value of ");
Serial.print(varName);
Serial.print(" is ");
Serial.print(*varPtr);
Serial.println();
Serial.println("Enter new value:");
while(!Serial.available()) yield(); // wait for user input
while( Serial.available() && lpr<sz_buf ){ // get up to 8 characters
buf[lpr]=Serial.read();
lpr++;
}
while( Serial.available()) Serial.read(); // throw away additional characters, if any
if (isDigit(buf[0]) || (buf[0] == '.' && isDigit(buf[1])) ) {
*varPtr=atof(buf);
Serial.print("New value is ");
Serial.print(*varPtr);
} else {
Serial.print("Non-numeric input. ");
Serial.print(varName);
Serial.print(" is unchanged.");
}
Serial.println();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment