From d1d78b9b3576610acc7d90572332ce74caa5187e Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Tue, 2 Feb 2016 19:21:58 +0000 Subject: [PATCH] microbit: added MicroBitStorage for Persistent data Integrated simple 1K block buffer to host small amount of persistent data and a 1K FLASH memory block located immediately below the FOTA/DFU bootloader and APPDATA region that intended to hold core configuration information, such as: * BLE bonding information. * Compass Calibration data. * Thermometer Calibration data. The block is resident at 0x0003B400 - 0x0003B800. --- inc/MicroBit.h | 1 + inc/MicroBitStorage.h | 74 +++++++++++++++++++++ source/CMakeLists.txt | 1 + source/MicroBitStorage.cpp | 129 +++++++++++++++++++++++++++++++++++++ 4 files changed, 205 insertions(+) create mode 100644 inc/MicroBitStorage.h create mode 100644 source/MicroBitStorage.cpp diff --git a/inc/MicroBit.h b/inc/MicroBit.h index 903c976..9c8bd12 100644 --- a/inc/MicroBit.h +++ b/inc/MicroBit.h @@ -36,6 +36,7 @@ #include "MicroBitBLEManager.h" #include "MicroBitRadio.h" +#include "MicroBitStorage.h" // MicroBit::flags values #define MICROBIT_FLAG_SCHEDULER_RUNNING 0x00000001 diff --git a/inc/MicroBitStorage.h b/inc/MicroBitStorage.h new file mode 100644 index 0000000..ed31b0a --- /dev/null +++ b/inc/MicroBitStorage.h @@ -0,0 +1,74 @@ +#ifndef MICROBIT_STORAGE_H +#define MICROBIT_STORAGE_H + +#include "mbed.h" +#include "MicroBitBLEManager.h" +#include "MicroBitCompass.h" + +#define MICROBIT_STORAGE_CONFIG_MAGIC 0xCAFECAFE + +struct BLESysAttribute +{ + uint32_t magic; + uint8_t sys_attr[8]; +}; + +struct MicroBitConfigurationBlock +{ + uint32_t magic; + BLESysAttribute sysAttrs[MICROBIT_BLE_MAXIMUM_BONDS]; + CompassSample compassCalibrationData; + int thermometerCalibration; +}; + + +/** + * Class definition for the MicroBitStorage class. + * This allows reading and writing of small blocks of data to FLASH memory. + */ +class MicroBitStorage +{ + public: + + /* + * Default constructor. + */ + MicroBitStorage(); + + /* + * Writes the given number of bytes to the address specified. + * @param buffer the data to write. + * @param address the location in memory to write to. + * @param length the number of bytes to write. + * TODO: Write this one! + */ + int writeBytes(uint8_t *buffer, uint32_t address, int length); + + /** + * Method for erasing a page in flash. + * @param page_address Address of the first word in the page to be erased. + */ + void flashPageErase(uint32_t * page_address); + + /** + * Method for writing a word of data in flash with a value. + + * @param address Address of the word to change. + * @param value Value to be written to flash. + */ + void flashWordWrite(uint32_t * address, uint32_t value); + + /* + * Reads the micro:bit's configuration data block from FLASH into a RAM buffer. + * @return a structure containing the stored data. + */ + MicroBitConfigurationBlock *getConfigurationBlock(); + + /* + * Writes the micro:bit's configuration data block from FLASH into a RAM buffer. + * @return a structure containing the stored data. + */ + int setConfigurationBlock(MicroBitConfigurationBlock *block); +}; + +#endif diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index b73cb45..8134b7e 100755 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -32,6 +32,7 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES "MicroBitLightSensor.cpp" "RefCounted.cpp" "MemberFunctionCallback.cpp" + "MicroBitStorage.cpp" "ble-services/MicroBitBLEManager.cpp" "ble-services/MicroBitDFUService.cpp" "ble-services/MicroBitEventService.cpp" diff --git a/source/MicroBitStorage.cpp b/source/MicroBitStorage.cpp new file mode 100644 index 0000000..b5dac01 --- /dev/null +++ b/source/MicroBitStorage.cpp @@ -0,0 +1,129 @@ +/** + * Class definition for the MicroBitStorage class. + * This allows reading and writing of FLASH memory. + */ + +#include "MicroBit.h" + +/* + * Default constructor + */ +MicroBitStorage::MicroBitStorage() +{ +} + +/* + * Writes the given number of bytes to the address specified. + * TODO: Complete this function to provide an abstraction across SD and no SD builds. + * + * @param buffer the data to write. + * @param address the location in memory to write to. + * @param length the number of bytes to write. + */ +int MicroBitStorage::writeBytes(uint8_t *buffer, uint32_t address, int length) +{ + (void) buffer; + (void) address; + (void) length; + + return MICROBIT_OK; +} + +/** + * Method for erasing a page in flash. + * + * @param page_address Address of the first word in the page to be erased. + */ +void MicroBitStorage::flashPageErase(uint32_t * page_address) +{ + // Turn on flash erase enable and wait until the NVMC is ready: + NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos); + + while (NRF_NVMC->READY == NVMC_READY_READY_Busy); + + // Erase page: + NRF_NVMC->ERASEPAGE = (uint32_t)page_address; + + while (NRF_NVMC->READY == NVMC_READY_READY_Busy); + + // Turn off flash erase enable and wait until the NVMC is ready: + NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); + + while (NRF_NVMC->READY == NVMC_READY_READY_Busy); +} + + +/* + * Reads the micro:bit's configuration data block from FLASH into a RAM buffer. + * @return a pointer to the structure containing the stored data. + * NOTE: it is the callers responsibility to free the buffer. + */ + +MicroBitConfigurationBlock *MicroBitStorage::getConfigurationBlock() +{ + uint32_t pg_size = NRF_FICR->CODEPAGESIZE; + uint32_t pg_num = NRF_FICR->CODESIZE - 19; // Use the page just below the BLE Bond Data + + MicroBitConfigurationBlock *block = new MicroBitConfigurationBlock(); + memcpy(block, (uint32_t *)(pg_size * pg_num), sizeof(MicroBitConfigurationBlock)); + + if (block->magic != MICROBIT_STORAGE_CONFIG_MAGIC) + memclr(block, sizeof(MicroBitConfigurationBlock)); + + return block; +} + +/** + * Function for filling a page in flash with a value. + * + * @param address Address of the first word in the page to be filled. + * @param value Value to be written to flash. + */ +void MicroBitStorage::flashWordWrite(uint32_t * address, uint32_t value) +{ + // Turn on flash write enable and wait until the NVMC is ready: + NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); + + while (NRF_NVMC->READY == NVMC_READY_READY_Busy); + + *address = value; + + while (NRF_NVMC->READY == NVMC_READY_READY_Busy); + + // Turn off flash write enable and wait until the NVMC is ready: + NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); + + while (NRF_NVMC->READY == NVMC_READY_READY_Busy); +} + + +/* + * Writes the micro:bit's configuration data block from FLASH into a RAM buffer. + * @return a structure containing the stored data. + */ +int MicroBitStorage::setConfigurationBlock(MicroBitConfigurationBlock *block) +{ + uint32_t * addr; + uint32_t pg_size; + uint32_t pg_num; + int wordsToWrite = sizeof(MicroBitConfigurationBlock) / 4 + 1; + + pg_size = NRF_FICR->CODEPAGESIZE; + pg_num = NRF_FICR->CODESIZE - 19; // Use the page just below the BLE Bond Data + + addr = (uint32_t *)(pg_size * pg_num); + + flashPageErase(addr); + + uint32_t *b = (uint32_t *) block; + + for (int i = 0; i < wordsToWrite; i++) + { + flashWordWrite(addr, *b); + addr++; + b++; + } + + return MICROBIT_OK; +} +