-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
184 additions
and
133 deletions.
There are no files selected for viewing
51 changes: 51 additions & 0 deletions
51
...es/Storage/Creating a Flash-Optimised Key-Value Store/FlashKeyValueStore/FlashIAPLimits.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/** | ||
* Helper functions for calculating limits for the FlashIAP block device | ||
* */ | ||
|
||
#pragma once | ||
|
||
#include <Arduino.h> | ||
#include <FlashIAP.h> | ||
#include <FlashIAPBlockDevice.h> | ||
|
||
using namespace mbed; | ||
|
||
// An helper struct for FlashIAP limits | ||
struct FlashIAPLimits { | ||
size_t flash_size; | ||
uint32_t start_address; | ||
uint32_t available_size; | ||
}; | ||
|
||
// Get the actual start address and available size for the FlashIAP Block Device | ||
// considering the space already occupied by the sketch. | ||
FlashIAPLimits getFlashIAPLimits() | ||
{ | ||
// Alignment lambdas | ||
auto align_down = [](uint64_t val, uint64_t size) { return (((val) / size)) * size; }; | ||
auto align_up = [](uint32_t val, uint32_t size) { return (((val - 1) / size) + 1) * size; }; | ||
|
||
size_t flash_size; | ||
uint32_t flash_start_address; | ||
uint32_t start_address; | ||
FlashIAP flash; | ||
|
||
auto result = flash.init(); | ||
if (result != 0) | ||
return { }; | ||
|
||
// Find the start of first sector after text area | ||
int sector_size = flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR); | ||
start_address = align_up(FLASHIAP_APP_ROM_END_ADDR, sector_size); | ||
flash_start_address = flash.get_flash_start(); | ||
flash_size = flash.get_flash_size(); | ||
|
||
result = flash.deinit(); | ||
|
||
int available_size = flash_start_address + flash_size - start_address; | ||
if (available_size % (sector_size * 2)) { | ||
available_size = align_down(available_size, sector_size * 2); | ||
} | ||
|
||
return { flash_size, start_address, available_size }; | ||
} |
266 changes: 133 additions & 133 deletions
266
...FlashKeyValueStore/FlashKeyValueStore.ino → ...FlashKeyValueStore/FlashKeyValueStore.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,133 +1,133 @@ | ||
#include <FlashIAPBlockDevice.h> | ||
#include <TDBStore.h> | ||
|
||
using namespace mbed; | ||
|
||
// Get limits of the In Application Program (IAP) flash, ie. the internal MCU flash. | ||
#include "FlashIAPLimits.h" | ||
auto iapLimits { getFlashIAPLimits() }; | ||
|
||
// Create a block device on the available space of the FlashIAP | ||
FlashIAPBlockDevice blockDevice(iapLimits.start_address, iapLimits.available_size); | ||
|
||
// Create a key/value store on the Flash IAP block device | ||
TDBStore store(&blockDevice); | ||
|
||
// Dummy sketch stats for demonstration purposes | ||
struct SketchStats { | ||
uint32_t startupTime; | ||
uint32_t randomValue; | ||
uint32_t runCount; | ||
}; | ||
|
||
void setup() | ||
{ | ||
Serial.begin(115200); | ||
while (!Serial); | ||
|
||
// Wait for terminal to come up | ||
delay(1000); | ||
|
||
Serial.println("FlashIAPBlockDevice + TDBStore Test"); | ||
|
||
// Feed the RNG for later content generation | ||
srand(micros()); | ||
|
||
// Initialize the flash IAP block device and print the memory layout | ||
blockDevice.init(); | ||
Serial.printf("FlashIAP block device size: %llu\r\n", blockDevice.size()); | ||
Serial.printf("FlashIAP block device read size: %llu\r\n", blockDevice.get_read_size()); | ||
Serial.printf("FlashIAP block device program size: %llu\r\n", blockDevice.get_program_size()); | ||
Serial.printf("FlashIAP block device erase size: %llu\r\n", blockDevice.get_erase_size()); | ||
// Deinitialize the device | ||
blockDevice.deinit(); | ||
|
||
// Initialize the key/value store | ||
Serial.print("Initializing TDBStore: "); | ||
auto result = store.init(); | ||
Serial.println(result == MBED_SUCCESS ? "OK" : "KO"); | ||
if (result != MBED_SUCCESS) | ||
while (true); | ||
|
||
// An example key name for the stats on the store | ||
const char statsKey[] { "stats" }; | ||
|
||
// Keep track of the number of sketch executions | ||
uint32_t runCount { 0 }; | ||
|
||
// Previous stats | ||
SketchStats previousStats; | ||
|
||
// Get previous run stats from the key/value store | ||
Serial.println("Retrieving Sketch Stats"); | ||
result = getSketchStats(statsKey, &previousStats); | ||
if (result == MBED_SUCCESS) { | ||
Serial.println("Previous Stats"); | ||
Serial.print("\tStartup Time: "); | ||
Serial.println(previousStats.startupTime); | ||
Serial.print("\tRandom Value: "); | ||
Serial.println(previousStats.randomValue); | ||
Serial.print("\tRun Count: "); | ||
Serial.println(previousStats.runCount); | ||
|
||
runCount = previousStats.runCount; | ||
|
||
} else if (result == MBED_ERROR_ITEM_NOT_FOUND) { | ||
Serial.println("First execution"); | ||
} else { | ||
Serial.println("Error reading from key/value store."); | ||
while (true); | ||
} | ||
|
||
//Update the stats and save them to the store | ||
SketchStats currentStats { millis(), rand(), ++runCount }; | ||
result = setSketchStats(statsKey, currentStats); | ||
|
||
if (result == MBED_SUCCESS) { | ||
Serial.println("Sketch Stats updated"); | ||
Serial.println("Current Stats"); | ||
Serial.print("\tStartup Time: "); | ||
Serial.println(currentStats.startupTime); | ||
Serial.print("\tRandom Value: "); | ||
Serial.println(currentStats.randomValue); | ||
Serial.print("\tRun Count: "); | ||
Serial.println(currentStats.runCount); | ||
} else { | ||
Serial.println("Error storing to key/value store"); | ||
while (true); | ||
} | ||
} | ||
|
||
void loop() | ||
{ | ||
// Do nothing | ||
} | ||
|
||
// Retrieve a SketchStats from the k/v store | ||
int getSketchStats(const char* key, SketchStats* stats) | ||
{ | ||
// Retrieve key/value info | ||
TDBStore::info_t info; | ||
auto result = store.get_info(key, &info); | ||
if (result == MBED_ERROR_ITEM_NOT_FOUND) | ||
return result; | ||
|
||
// Allocate space for the value | ||
uint8_t buffer[info.size] {}; | ||
size_t actual_size; | ||
|
||
// Get the value | ||
result = store.get(key, buffer, sizeof(buffer), &actual_size); | ||
if (result != MBED_SUCCESS) | ||
return result; | ||
|
||
memcpy(stats, buffer, sizeof(SketchStats)); | ||
return result; | ||
} | ||
|
||
// Store a SketchStats to the the k/v store | ||
int setSketchStats(const char* key, SketchStats stats) | ||
{ | ||
auto result = store.set(key, reinterpret_cast<uint8_t*>(&stats), sizeof(SketchStats), 0); | ||
return result; | ||
} | ||
#include <FlashIAPBlockDevice.h> | ||
#include <TDBStore.h> | ||
|
||
using namespace mbed; | ||
|
||
// Get limits of the In Application Program (IAP) flash, ie. the internal MCU flash. | ||
#include "FlashIAPLimits.h" | ||
auto iapLimits { getFlashIAPLimits() }; | ||
|
||
// Create a block device on the available space of the FlashIAP | ||
FlashIAPBlockDevice blockDevice(iapLimits.start_address, iapLimits.available_size); | ||
|
||
// Create a key/value store on the Flash IAP block device | ||
TDBStore store(&blockDevice); | ||
|
||
// Dummy sketch stats for demonstration purposes | ||
struct SketchStats { | ||
uint32_t startupTime; | ||
uint32_t randomValue; | ||
uint32_t runCount; | ||
}; | ||
|
||
void setup() | ||
{ | ||
Serial.begin(115200); | ||
while (!Serial); | ||
|
||
// Wait for terminal to come up | ||
delay(1000); | ||
|
||
Serial.println("FlashIAPBlockDevice + TDBStore Test"); | ||
|
||
// Feed the RNG for later content generation | ||
srand(micros()); | ||
|
||
// Initialize the flash IAP block device and print the memory layout | ||
blockDevice.init(); | ||
Serial.printf("FlashIAP block device size: %llu\r\n", blockDevice.size()); | ||
Serial.printf("FlashIAP block device read size: %llu\r\n", blockDevice.get_read_size()); | ||
Serial.printf("FlashIAP block device program size: %llu\r\n", blockDevice.get_program_size()); | ||
Serial.printf("FlashIAP block device erase size: %llu\r\n", blockDevice.get_erase_size()); | ||
// Deinitialize the device | ||
blockDevice.deinit(); | ||
|
||
// Initialize the key/value store | ||
Serial.print("Initializing TDBStore: "); | ||
auto result = store.init(); | ||
Serial.println(result == MBED_SUCCESS ? "OK" : "KO"); | ||
if (result != MBED_SUCCESS) | ||
while (true); | ||
|
||
// An example key name for the stats on the store | ||
const char statsKey[] { "stats" }; | ||
|
||
// Keep track of the number of sketch executions | ||
uint32_t runCount { 0 }; | ||
|
||
// Previous stats | ||
SketchStats previousStats; | ||
|
||
// Get previous run stats from the key/value store | ||
Serial.println("Retrieving Sketch Stats"); | ||
result = getSketchStats(statsKey, &previousStats); | ||
if (result == MBED_SUCCESS) { | ||
Serial.println("Previous Stats"); | ||
Serial.print("\tStartup Time: "); | ||
Serial.println(previousStats.startupTime); | ||
Serial.print("\tRandom Value: "); | ||
Serial.println(previousStats.randomValue); | ||
Serial.print("\tRun Count: "); | ||
Serial.println(previousStats.runCount); | ||
|
||
runCount = previousStats.runCount; | ||
|
||
} else if (result == MBED_ERROR_ITEM_NOT_FOUND) { | ||
Serial.println("First execution"); | ||
} else { | ||
Serial.println("Error reading from key/value store."); | ||
while (true); | ||
} | ||
|
||
//Update the stats and save them to the store | ||
SketchStats currentStats { millis(), rand(), ++runCount }; | ||
result = setSketchStats(statsKey, currentStats); | ||
|
||
if (result == MBED_SUCCESS) { | ||
Serial.println("Sketch Stats updated"); | ||
Serial.println("Current Stats"); | ||
Serial.print("\tStartup Time: "); | ||
Serial.println(currentStats.startupTime); | ||
Serial.print("\tRandom Value: "); | ||
Serial.println(currentStats.randomValue); | ||
Serial.print("\tRun Count: "); | ||
Serial.println(currentStats.runCount); | ||
} else { | ||
Serial.println("Error storing to key/value store"); | ||
while (true); | ||
} | ||
} | ||
|
||
void loop() | ||
{ | ||
// Do nothing | ||
} | ||
|
||
// Retrieve a SketchStats from the k/v store | ||
int getSketchStats(const char* key, SketchStats* stats) | ||
{ | ||
// Retrieve key/value info | ||
TDBStore::info_t info; | ||
auto result = store.get_info(key, &info); | ||
if (result == MBED_ERROR_ITEM_NOT_FOUND) | ||
return result; | ||
|
||
// Allocate space for the value | ||
uint8_t buffer[info.size] {}; | ||
size_t actual_size; | ||
|
||
// Get the value | ||
result = store.get(key, buffer, sizeof(buffer), &actual_size); | ||
if (result != MBED_SUCCESS) | ||
return result; | ||
|
||
memcpy(stats, buffer, sizeof(SketchStats)); | ||
return result; | ||
} | ||
|
||
// Store a SketchStats to the the k/v store | ||
int setSketchStats(const char* key, SketchStats stats) | ||
{ | ||
auto result = store.set(key, reinterpret_cast<uint8_t*>(&stats), sizeof(SketchStats), 0); | ||
return result; | ||
} |