From 39bae70ecb5cec3419edce7124ea88e400331b30 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Fri, 14 Feb 2020 13:41:19 -0700 Subject: [PATCH 1/5] add configurable EEPROM length since the flashContent buffer is declared on the stack it may be dynamically sized. the user can take advantage of this to allow for any size EEPROM up to the allocated 1 page of flash. - added 'allowedSize' member to EEPROMClass - added setter for allowedSize 'setLength' - adjusted 'length' to return allowedSize - adjusted 'writeBlockToEEPROM' to use the allowedSize of the EEPROM structure when checking flash memory. - added example usage to Example2_AllFunctions --- .../Example2_AllFunctions.ino | 20 ++++++++---- libraries/EEPROM/src/EEPROM.cpp | 25 +++++++++------ libraries/EEPROM/src/EEPROM.h | 32 +++++++++++++------ 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino b/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino index 98569180..b4704e7d 100644 --- a/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino +++ b/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino @@ -23,6 +23,12 @@ void setup() { + // You may choose to enable more or less EEPROM - + // Default length is 1024 bytes (if setLength is not called) + EEPROM.setLength(1080); // this would make the length 1080 bytes + // EEPROM.setLength(AP3_EEPROM_MAX_LENGTH); // the maximum length is 8192 bytes (AP3_EEPROM_MAX_LENGTH) + // Note: larger sizes will increase RAM usage and execution time + Serial.begin(115200); Serial.println("EEPROM Examples"); @@ -44,7 +50,7 @@ void setup() Serial.println("8 bit tests"); byte myValue1 = 200; byte myValue2 = 23; - randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); + randomLocation = random(0, EEPROM.length()); startTime = millis(); EEPROM.write(randomLocation, myValue1); //(location, data) @@ -72,7 +78,7 @@ void setup() //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- uint16_t myValue3 = 3411; int16_t myValue4 = -366; - randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); + randomLocation = random(0, EEPROM.length()); EEPROM.put(randomLocation, myValue3); EEPROM.put(randomLocation + 2, myValue4); @@ -93,7 +99,7 @@ void setup() Serial.printf("Size of int: %d\n", sizeof(int)); int myValue5 = -245000; unsigned int myValue6 = 400123; - randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); + randomLocation = random(0, EEPROM.length()); EEPROM.put(randomLocation, myValue5); EEPROM.put(randomLocation + 4, myValue6); @@ -110,7 +116,7 @@ void setup() //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- int32_t myValue7 = -341002; uint32_t myValue8 = 241544; - randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); + randomLocation = random(0, EEPROM.length()); EEPROM.put(randomLocation, myValue7); EEPROM.put(randomLocation + 4, myValue8); @@ -128,7 +134,7 @@ void setup() Serial.printf("Size of float: %d\n", sizeof(float)); float myValue9 = -7.35; float myValue10 = 5.22; - randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); + randomLocation = random(0, EEPROM.length()); EEPROM.put(randomLocation, myValue9); EEPROM.put(randomLocation + 4, myValue10); @@ -151,7 +157,7 @@ void setup() double myValue12 = 384.95734987; double myValue13 = 917.14159; double myValue14 = 254.8877; - randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); + randomLocation = random(0, EEPROM.length()); startTime = millis(); EEPROM.put(randomLocation, myValue11); @@ -183,7 +189,7 @@ void setup() //String write test //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- char myString[19] = "How are you today?"; - randomLocation = random(0, AP3_FLASH_EEPROM_SIZE); + randomLocation = random(0, EEPROM.length()); EEPROM.put(randomLocation, myString); char readMy[19]; diff --git a/libraries/EEPROM/src/EEPROM.cpp b/libraries/EEPROM/src/EEPROM.cpp index f8b9b802..62bdf1b6 100644 --- a/libraries/EEPROM/src/EEPROM.cpp +++ b/libraries/EEPROM/src/EEPROM.cpp @@ -40,10 +40,12 @@ #include "EEPROM.h" #include "Arduino.h" +EEPROMClass EEPROM; // the (magnificent) one and only EEPROM!!!!! + //Write a byte to a given "EEPROM" location -void write(uint16_t eepromLocation, uint8_t dataToWrite) +void write(uint16_t eepromLocation, uint8_t dataToWrite, uint16_t allowedSize) { - writeBlockToEEPROM(eepromLocation, &dataToWrite, 1); + writeBlockToEEPROM(eepromLocation, &dataToWrite, 1, allowedSize); } //Read a byte from a given location in "EEPROM" @@ -66,23 +68,23 @@ void EEPROMClass::erase() //3) Check if new data is different from flash. //4) Erase flash page (8k) //5) Write SRAM back into flash -void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize) +void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize, uint16_t allowedSize) { //Error check - if (eepromLocation + blockSize >= AP3_FLASH_EEPROM_SIZE) + if (eepromLocation + blockSize >= allowedSize) { - blockSize = AP3_FLASH_EEPROM_SIZE - eepromLocation; + blockSize = allowedSize - eepromLocation; } //Read the contents of current "EEPROM" to SRAM //Flash is written in 32-bit words but user passes in array of bytes //Create an array of 32-bit words but reference it a byte at a time - uint32_t flashContent[AP3_FLASH_EEPROM_SIZE / 4]; + uint32_t flashContent[allowedSize / 4]; //We can't read 32bits at a time because the way flash is oriented (little endian) //So we read a byte at a time uint8_t *eepromContents = (uint8_t *)flashContent; - for (uint16_t x = 0; x < AP3_FLASH_EEPROM_SIZE; x++) + for (uint16_t x = 0; x < allowedSize; x++) { eepromContents[x] = *(uint8_t *)(AP3_FLASH_EEPROM_START + x); } @@ -96,7 +98,7 @@ void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uin //Run a check here to see if the new data is the same as what's in flash. If it's the same, //just return, don't erase flash. bool theSame = true; - for (uint16_t x = 0; x < AP3_FLASH_EEPROM_SIZE; x++) + for (uint16_t x = 0; x < allowedSize; x++) { if (eepromContents[x] != *(uint8_t *)(AP3_FLASH_EEPROM_START + x)) { @@ -116,5 +118,10 @@ void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uin am_hal_flash_program_main(AM_HAL_FLASH_PROGRAM_KEY, flashContent, (uint32_t *)AP3_FLASH_EEPROM_START, - AP3_FLASH_EEPROM_SIZE / 4); + allowedSize / 4); } + +EERef &EERef::operator=(uint8_t in) +{ + return write(index, in, EEPROM.length()), *this; +} \ No newline at end of file diff --git a/libraries/EEPROM/src/EEPROM.h b/libraries/EEPROM/src/EEPROM.h index 56890856..2e216431 100644 --- a/libraries/EEPROM/src/EEPROM.h +++ b/libraries/EEPROM/src/EEPROM.h @@ -59,8 +59,10 @@ //The SparkFun Apollo3 linker script has been modified to limit user code space to less than 0xFE000 #define AP3_FLASH_EEPROM_START 0xFE000 +#define AP3_FLASH_PAGE_SIZE 8192 +#define AP3_EEPROM_MAX_LENGTH AP3_FLASH_PAGE_SIZE -#if AP3_FLASH_EEPROM_START % 8192 +#if AP3_FLASH_EEPROM_START % AP3_FLASH_PAGE_SIZE Error : EEPROM start address must be divisble by 8192 #endif @@ -69,11 +71,11 @@ Error : EEPROM start address must be divisble by 8192 //to 2048 if needed //1024 = 19ms update time //2048 = 23ms update time - const int AP3_FLASH_EEPROM_SIZE = 1024; //In bytes + const uint16_t AP3_DEFAULT_FLASH_EEPROM_SIZE = 1024; //In bytes uint8_t read(uint16_t eepromLocation); -void write(uint16_t eepromLocation, uint8_t dataToWrite); -void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize); +void write(uint16_t eepromLocation, uint8_t dataToWrite, uint16_t allowedSize); +void writeBlockToEEPROM(uint16_t eepromLocation, const uint8_t *dataToWrite, uint16_t blockSize, uint16_t allowedSize); struct EERef { @@ -86,7 +88,7 @@ struct EERef //Assignment/write members. EERef &operator=(const EERef &ref) { return *this = *ref; } - EERef &operator=(uint8_t in) { return write(index, in), *this; } + EERef &operator=(uint8_t in); EERef &operator+=(uint8_t in) { return *this = **this + in; } EERef &operator-=(uint8_t in) { return *this = **this - in; } EERef &operator*=(uint8_t in) { return *this = **this * in; } @@ -163,7 +165,10 @@ struct EEPROMClass //Basic user access methods. EERef operator[](const int idx) { return idx; } uint8_t read(int idx) { return EERef(idx); } - void write(int idx, uint8_t val) { (EERef(idx)) = val; } + void write(int idx, uint8_t val) + { + (EERef(idx)) = val; + } void update(int idx, uint8_t val) { EERef(idx).update(val); } void erase(); @@ -174,7 +179,14 @@ struct EEPROMClass return 0x00; } EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid. - uint16_t length() { return AP3_FLASH_EEPROM_SIZE; } + uint16_t length() + { + return allowedSize; + } + void setLength(uint16_t length) + { + allowedSize = length; + } //Functionality to 'get' and 'put' objects to and from EEPROM. template @@ -192,11 +204,13 @@ struct EEPROMClass { const uint8_t *ptr = (const uint8_t *)&t; - writeBlockToEEPROM(idx, ptr, sizeof(T)); //Address, data, sizeOfData + writeBlockToEEPROM(idx, ptr, sizeof(T), allowedSize); //Address, data, sizeOfData return t; } + + uint16_t allowedSize = AP3_DEFAULT_FLASH_EEPROM_SIZE; }; -static EEPROMClass EEPROM __attribute__((unused)); +extern EEPROMClass EEPROM; #endif //_EEPROM_H From a4fecfbc19b516eac8cff61a62a3a60a03559d38 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Mon, 17 Feb 2020 09:57:52 -0700 Subject: [PATCH 2/5] update comments and cap allowedSize at AP3_EEPROM_MAX_LENGTH taking suggestions from @rustycoat --- libraries/EEPROM/src/EEPROM.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/EEPROM/src/EEPROM.h b/libraries/EEPROM/src/EEPROM.h index 2e216431..2b4c38ef 100644 --- a/libraries/EEPROM/src/EEPROM.h +++ b/libraries/EEPROM/src/EEPROM.h @@ -66,9 +66,10 @@ Error : EEPROM start address must be divisble by 8192 #endif - //By limiting EEPROM size to 1024 bytes, we reduce the amount of SRAM required and - //time needed to read/write words into flash. It can be increased - //to 2048 if needed + //Operations on psuedo-EEPROM require a read-write-modify cycle on the entire + //configured memory area because flash pages cannot be partially erased. The + //larger the memory area the longer this operation will take. Here are some + //benchmarks: //1024 = 19ms update time //2048 = 23ms update time const uint16_t AP3_DEFAULT_FLASH_EEPROM_SIZE = 1024; //In bytes @@ -185,7 +186,7 @@ struct EEPROMClass } void setLength(uint16_t length) { - allowedSize = length; + allowedSize = (length <= AP3_EEPROM_MAX_LENGTH) ? length : AP3_EEPROM_MAX_LENGTH; } //Functionality to 'get' and 'put' objects to and from EEPROM. From b13b4fc4350f28bac01d7ca216c88d436139b652 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Mon, 17 Feb 2020 10:02:30 -0700 Subject: [PATCH 3/5] addtl clarification --- libraries/EEPROM/src/EEPROM.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/EEPROM/src/EEPROM.h b/libraries/EEPROM/src/EEPROM.h index 2b4c38ef..018e54b2 100644 --- a/libraries/EEPROM/src/EEPROM.h +++ b/libraries/EEPROM/src/EEPROM.h @@ -66,6 +66,11 @@ Error : EEPROM start address must be divisble by 8192 #endif + //The size of the EEPROM may be (ptionally) user-configured using the EEPROM.setLength() + //method. Valid values are in the range [0, AP3_EEPROM_MAX_LENGTH]. Reducing the size of + //EEPROM will cause data stored in the higher addresses to be lost. The default size is + //set below. See Example2_AllFunctions for a usage example. + //Operations on psuedo-EEPROM require a read-write-modify cycle on the entire //configured memory area because flash pages cannot be partially erased. The //larger the memory area the longer this operation will take. Here are some From 4b035e6c8b51270fcf3dddba6743754d86c6e796 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Mon, 17 Feb 2020 11:31:28 -0700 Subject: [PATCH 4/5] use 'sizeof()' consistently --- .../Example2_AllFunctions.ino | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino b/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino index b4704e7d..a82646de 100644 --- a/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino +++ b/libraries/EEPROM/examples/Example2_AllFunctions/Example2_AllFunctions.ino @@ -50,12 +50,12 @@ void setup() Serial.println("8 bit tests"); byte myValue1 = 200; byte myValue2 = 23; - randomLocation = random(0, EEPROM.length()); + randomLocation = random(0, EEPROM.length() - sizeof(myValue1)); startTime = millis(); EEPROM.write(randomLocation, myValue1); //(location, data) endTime = millis(); - EEPROM.put(randomLocation + 1, myValue2); + EEPROM.put(randomLocation + sizeof(myValue1), myValue2); Serial.printf("Write byte time: %dms\n", endTime - startTime); @@ -63,12 +63,12 @@ void setup() EEPROM.write(randomLocation, myValue1); //(location, data) endTime = millis(); - Serial.printf("Write identical byte to same location (should be ~1): %dms\n", endTime - startTime); + Serial.printf("Write identical byte to same location: %dms\n", endTime - startTime); byte response1 = EEPROM.read(randomLocation); - byte response2 = EEPROM.read(randomLocation + 1); + byte response2 = EEPROM.read(randomLocation + sizeof(myValue1)); Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue1, response1); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 1, myValue2, response2); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation + sizeof(myValue1), myValue2, response2); //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Serial.println(""); @@ -78,17 +78,17 @@ void setup() //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- uint16_t myValue3 = 3411; int16_t myValue4 = -366; - randomLocation = random(0, EEPROM.length()); + randomLocation = random(0, EEPROM.length() - sizeof(myValue3)); EEPROM.put(randomLocation, myValue3); - EEPROM.put(randomLocation + 2, myValue4); + EEPROM.put(randomLocation + sizeof(myValue3), myValue4); uint16_t response3; int16_t response4; EEPROM.get(randomLocation, response3); - EEPROM.get(randomLocation + 2, response4); + EEPROM.get(randomLocation + sizeof(myValue3), response4); Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue3, response3); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 2, myValue4, response4); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation + sizeof(myValue3), myValue4, response4); //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Serial.println(""); @@ -99,34 +99,34 @@ void setup() Serial.printf("Size of int: %d\n", sizeof(int)); int myValue5 = -245000; unsigned int myValue6 = 400123; - randomLocation = random(0, EEPROM.length()); + randomLocation = random(0, EEPROM.length() - sizeof(myValue5)); EEPROM.put(randomLocation, myValue5); - EEPROM.put(randomLocation + 4, myValue6); + EEPROM.put(randomLocation + sizeof(myValue5), myValue6); int response5; unsigned int response6; EEPROM.get(randomLocation, response5); - EEPROM.get(randomLocation + 4, response6); + EEPROM.get(randomLocation + sizeof(myValue5), response6); Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue5, response5); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 4, myValue6, response6); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation + sizeof(myValue5), myValue6, response6); //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //int32_t and uint32_t sequential test //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- int32_t myValue7 = -341002; uint32_t myValue8 = 241544; - randomLocation = random(0, EEPROM.length()); + randomLocation = random(0, EEPROM.length() - sizeof(myValue7)); EEPROM.put(randomLocation, myValue7); - EEPROM.put(randomLocation + 4, myValue8); + EEPROM.put(randomLocation + sizeof(myValue7), myValue8); int32_t response7; uint32_t response8; EEPROM.get(randomLocation, response7); - EEPROM.get(randomLocation + 4, response8); + EEPROM.get(randomLocation + sizeof(myValue7), response8); Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue7, response7); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 4, myValue8, response8); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation + sizeof(myValue7), myValue8, response8); //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //float (32) sequential test @@ -134,17 +134,17 @@ void setup() Serial.printf("Size of float: %d\n", sizeof(float)); float myValue9 = -7.35; float myValue10 = 5.22; - randomLocation = random(0, EEPROM.length()); + randomLocation = random(0, EEPROM.length() - sizeof(myValue9)); EEPROM.put(randomLocation, myValue9); - EEPROM.put(randomLocation + 4, myValue10); + EEPROM.put(randomLocation + sizeof(myValue9), myValue10); float response9; float response10; EEPROM.get(randomLocation, response9); - EEPROM.get(randomLocation + 4, response10); + EEPROM.get(randomLocation + sizeof(myValue9), response10); Serial.printf("Location %d should be %f: %f\n\r", randomLocation, myValue9, response9); - Serial.printf("Location %d should be %f: %f\n\r", randomLocation + 4, myValue10, response10); + Serial.printf("Location %d should be %f: %f\n\r", randomLocation + sizeof(myValue9), myValue10, response10); //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Serial.println(""); @@ -157,24 +157,24 @@ void setup() double myValue12 = 384.95734987; double myValue13 = 917.14159; double myValue14 = 254.8877; - randomLocation = random(0, EEPROM.length()); + randomLocation = random(0, EEPROM.length() - sizeof(myValue11)); startTime = millis(); EEPROM.put(randomLocation, myValue11); endTime = millis(); Serial.printf("Time to record 64-bits: %dms\n", endTime - startTime); - EEPROM.put(randomLocation + 8, myValue12); + EEPROM.put(randomLocation + sizeof(myValue11), myValue12); EEPROM.put(EEPROM.length() - sizeof(myValue13), myValue13); //Test end of EEPROM space double response11; double response12; double response13; EEPROM.get(randomLocation, response11); - EEPROM.get(randomLocation + 8, response12); + EEPROM.get(randomLocation + sizeof(myValue11), response12); EEPROM.get(EEPROM.length() - sizeof(myValue13), response13); Serial.printf("Location %d should be %lf: %lf\n", randomLocation, myValue11, response11); - Serial.printf("Location %d should be %lf: %lf\n", randomLocation + 8, myValue12, response12); + Serial.printf("Location %d should be %lf: %lf\n", randomLocation + sizeof(myValue11), myValue12, response12); Serial.printf("Edge of EEPROM %d should be %lf: %lf\n", EEPROM.length() - sizeof(myValue13), myValue13, response13); double response14; @@ -189,7 +189,7 @@ void setup() //String write test //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- char myString[19] = "How are you today?"; - randomLocation = random(0, EEPROM.length()); + randomLocation = random(0, EEPROM.length() - sizeof(myString)); EEPROM.put(randomLocation, myString); char readMy[19]; From 843b8afe2b08fcd615c8be167c65c5fec46affe1 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Tue, 18 Feb 2020 09:33:33 -0700 Subject: [PATCH 5/5] prevent crashes from writes to high EEPROM addresses writing to 8176 and above seems likely to cause a crash with 32 and 64-bit wide data types. restricting the size of EEPROM a little bit seems to nearly eliminate these problems. while this is not a true solution or a good fix it is good enough for now --- libraries/EEPROM/src/EEPROM.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/EEPROM/src/EEPROM.h b/libraries/EEPROM/src/EEPROM.h index 018e54b2..ad1353ee 100644 --- a/libraries/EEPROM/src/EEPROM.h +++ b/libraries/EEPROM/src/EEPROM.h @@ -60,13 +60,13 @@ #define AP3_FLASH_EEPROM_START 0xFE000 #define AP3_FLASH_PAGE_SIZE 8192 -#define AP3_EEPROM_MAX_LENGTH AP3_FLASH_PAGE_SIZE +#define AP3_EEPROM_MAX_LENGTH (AP3_FLASH_PAGE_SIZE - 16) #if AP3_FLASH_EEPROM_START % AP3_FLASH_PAGE_SIZE Error : EEPROM start address must be divisble by 8192 #endif - //The size of the EEPROM may be (ptionally) user-configured using the EEPROM.setLength() + //The size of the EEPROM may be (optionally) user-configured using the EEPROM.setLength() //method. Valid values are in the range [0, AP3_EEPROM_MAX_LENGTH]. Reducing the size of //EEPROM will cause data stored in the higher addresses to be lost. The default size is //set below. See Example2_AllFunctions for a usage example.