Solution for Bluetooth SIG hands-on training course
Dependencies: BLE_API mbed-dev-bin nRF51822-bluetooth-mdw
Fork of microbit-dal-bluetooth-mdw_starter by
source/drivers/MicroBitStorage.cpp@30:db87179335d5, 2016-07-13 (annotated)
- Committer:
- LancasterUniversity
- Date:
- Wed Jul 13 12:18:08 2016 +0100
- Revision:
- 30:db87179335d5
- Parent:
- 1:8aa5cdb4ab67
- Child:
- 31:87789e55bac7
Synchronized with git rev 3b435c0d
Author: James Devine
microbit-dal: BUGFIX in MicroBitStorage
There was an off by one error when storing the key of the key value
pair, where the null terminator was dropped. This would mean that if
the returned key of the KeyValuePair were used, it would cause a number
of issues.
Another issue raised was the copying a random 48 bytes from memory
regardless of the position of memory in the stack. If the memory was
smaller than 48 bytes, and existed at the top of the stack, this could
have dire consequences. As a result, MicroBitStorage now accepts a size
parameter which informs the number of bytes to be copied into flash.
#130
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Jonathan Austin |
1:8aa5cdb4ab67 | 1 | /* |
Jonathan Austin |
1:8aa5cdb4ab67 | 2 | The MIT License (MIT) |
Jonathan Austin |
1:8aa5cdb4ab67 | 3 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 4 | Copyright (c) 2016 British Broadcasting Corporation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 5 | This software is provided by Lancaster University by arrangement with the BBC. |
Jonathan Austin |
1:8aa5cdb4ab67 | 6 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 7 | Permission is hereby granted, free of charge, to any person obtaining a |
Jonathan Austin |
1:8aa5cdb4ab67 | 8 | copy of this software and associated documentation files (the "Software"), |
Jonathan Austin |
1:8aa5cdb4ab67 | 9 | to deal in the Software without restriction, including without limitation |
Jonathan Austin |
1:8aa5cdb4ab67 | 10 | the rights to use, copy, modify, merge, publish, distribute, sublicense, |
Jonathan Austin |
1:8aa5cdb4ab67 | 11 | and/or sell copies of the Software, and to permit persons to whom the |
Jonathan Austin |
1:8aa5cdb4ab67 | 12 | Software is furnished to do so, subject to the following conditions: |
Jonathan Austin |
1:8aa5cdb4ab67 | 13 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 14 | The above copyright notice and this permission notice shall be included in |
Jonathan Austin |
1:8aa5cdb4ab67 | 15 | all copies or substantial portions of the Software. |
Jonathan Austin |
1:8aa5cdb4ab67 | 16 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
Jonathan Austin |
1:8aa5cdb4ab67 | 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
Jonathan Austin |
1:8aa5cdb4ab67 | 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
Jonathan Austin |
1:8aa5cdb4ab67 | 20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
Jonathan Austin |
1:8aa5cdb4ab67 | 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
Jonathan Austin |
1:8aa5cdb4ab67 | 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
Jonathan Austin |
1:8aa5cdb4ab67 | 23 | DEALINGS IN THE SOFTWARE. |
Jonathan Austin |
1:8aa5cdb4ab67 | 24 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 25 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 26 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 27 | * Class definition for the MicroBitStorage class. |
Jonathan Austin |
1:8aa5cdb4ab67 | 28 | * This allows reading and writing of FLASH memory. |
Jonathan Austin |
1:8aa5cdb4ab67 | 29 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 30 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 31 | #include "MicroBitConfig.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 32 | #include "MicroBitStorage.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 33 | #include "MicroBitCompat.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 34 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 35 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 36 | * Default constructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 37 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 38 | * Creates an instance of MicroBitStorage which acts like a KeyValueStore |
Jonathan Austin |
1:8aa5cdb4ab67 | 39 | * that allows the retrieval, addition and deletion of KeyValuePairs. |
Jonathan Austin |
1:8aa5cdb4ab67 | 40 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 41 | MicroBitStorage::MicroBitStorage() |
Jonathan Austin |
1:8aa5cdb4ab67 | 42 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 43 | //initialise our magic block, if required. |
Jonathan Austin |
1:8aa5cdb4ab67 | 44 | size(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 45 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 46 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 47 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 48 | * Writes the given number of bytes to the address specified. |
Jonathan Austin |
1:8aa5cdb4ab67 | 49 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 50 | * @param buffer the data to write. |
Jonathan Austin |
1:8aa5cdb4ab67 | 51 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 52 | * @param address the location in memory to write to. |
Jonathan Austin |
1:8aa5cdb4ab67 | 53 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 54 | * @param length the number of bytes to write. |
Jonathan Austin |
1:8aa5cdb4ab67 | 55 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 56 | * @note currently not implemented. |
Jonathan Austin |
1:8aa5cdb4ab67 | 57 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 58 | int MicroBitStorage::writeBytes(uint8_t *buffer, uint32_t address, int length) |
Jonathan Austin |
1:8aa5cdb4ab67 | 59 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 60 | (void) buffer; |
Jonathan Austin |
1:8aa5cdb4ab67 | 61 | (void) address; |
Jonathan Austin |
1:8aa5cdb4ab67 | 62 | (void) length; |
Jonathan Austin |
1:8aa5cdb4ab67 | 63 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 64 | return MICROBIT_OK; |
Jonathan Austin |
1:8aa5cdb4ab67 | 65 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 66 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 67 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 68 | * Method for erasing a page in flash. |
Jonathan Austin |
1:8aa5cdb4ab67 | 69 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 70 | * @param page_address Address of the first word in the page to be erased. |
Jonathan Austin |
1:8aa5cdb4ab67 | 71 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 72 | void MicroBitStorage::flashPageErase(uint32_t * page_address) |
Jonathan Austin |
1:8aa5cdb4ab67 | 73 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 74 | // Turn on flash erase enable and wait until the NVMC is ready: |
Jonathan Austin |
1:8aa5cdb4ab67 | 75 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos); |
Jonathan Austin |
1:8aa5cdb4ab67 | 76 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 77 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy); |
Jonathan Austin |
1:8aa5cdb4ab67 | 78 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 79 | // Erase page: |
Jonathan Austin |
1:8aa5cdb4ab67 | 80 | NRF_NVMC->ERASEPAGE = (uint32_t)page_address; |
Jonathan Austin |
1:8aa5cdb4ab67 | 81 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 82 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy); |
Jonathan Austin |
1:8aa5cdb4ab67 | 83 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 84 | // Turn off flash erase enable and wait until the NVMC is ready: |
Jonathan Austin |
1:8aa5cdb4ab67 | 85 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); |
Jonathan Austin |
1:8aa5cdb4ab67 | 86 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 87 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy); |
Jonathan Austin |
1:8aa5cdb4ab67 | 88 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 89 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 90 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 91 | * Function for copying words from one location to another. |
Jonathan Austin |
1:8aa5cdb4ab67 | 92 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 93 | * @param from the address to copy data from. |
Jonathan Austin |
1:8aa5cdb4ab67 | 94 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 95 | * @param to the address to copy the data to. |
Jonathan Austin |
1:8aa5cdb4ab67 | 96 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 97 | * @param sizeInWords the number of words to copy |
Jonathan Austin |
1:8aa5cdb4ab67 | 98 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 99 | void MicroBitStorage::flashCopy(uint32_t* from, uint32_t* to, int sizeInWords) |
Jonathan Austin |
1:8aa5cdb4ab67 | 100 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 101 | // Turn on flash write enable and wait until the NVMC is ready: |
Jonathan Austin |
1:8aa5cdb4ab67 | 102 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); |
Jonathan Austin |
1:8aa5cdb4ab67 | 103 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 104 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}; |
Jonathan Austin |
1:8aa5cdb4ab67 | 105 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 106 | for(int i = 0; i < sizeInWords; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 107 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 108 | *(to + i) = *(from + i); |
Jonathan Austin |
1:8aa5cdb4ab67 | 109 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}; |
Jonathan Austin |
1:8aa5cdb4ab67 | 110 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 111 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 112 | // Turn off flash write enable and wait until the NVMC is ready: |
Jonathan Austin |
1:8aa5cdb4ab67 | 113 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); |
Jonathan Austin |
1:8aa5cdb4ab67 | 114 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {}; |
Jonathan Austin |
1:8aa5cdb4ab67 | 115 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 116 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 117 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 118 | * Method for writing a word of data in flash with a value. |
Jonathan Austin |
1:8aa5cdb4ab67 | 119 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 120 | * @param address Address of the word to change. |
Jonathan Austin |
1:8aa5cdb4ab67 | 121 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 122 | * @param value Value to be written to flash. |
Jonathan Austin |
1:8aa5cdb4ab67 | 123 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 124 | void MicroBitStorage::flashWordWrite(uint32_t * address, uint32_t value) |
Jonathan Austin |
1:8aa5cdb4ab67 | 125 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 126 | // Turn on flash write enable and wait until the NVMC is ready: |
Jonathan Austin |
1:8aa5cdb4ab67 | 127 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos); |
Jonathan Austin |
1:8aa5cdb4ab67 | 128 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 129 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy); |
Jonathan Austin |
1:8aa5cdb4ab67 | 130 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 131 | *address = value; |
Jonathan Austin |
1:8aa5cdb4ab67 | 132 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 133 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy); |
Jonathan Austin |
1:8aa5cdb4ab67 | 134 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 135 | // Turn off flash write enable and wait until the NVMC is ready: |
Jonathan Austin |
1:8aa5cdb4ab67 | 136 | NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos); |
Jonathan Austin |
1:8aa5cdb4ab67 | 137 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 138 | while (NRF_NVMC->READY == NVMC_READY_READY_Busy); |
Jonathan Austin |
1:8aa5cdb4ab67 | 139 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 140 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 141 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 142 | * Function for populating the scratch page with a KeyValueStore. |
Jonathan Austin |
1:8aa5cdb4ab67 | 143 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 144 | * @param store the KeyValueStore struct to write to the scratch page. |
Jonathan Austin |
1:8aa5cdb4ab67 | 145 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 146 | void MicroBitStorage::scratchKeyValueStore(KeyValueStore store) |
Jonathan Austin |
1:8aa5cdb4ab67 | 147 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 148 | //calculate our various offsets |
Jonathan Austin |
1:8aa5cdb4ab67 | 149 | uint32_t *s = (uint32_t *) &store; |
Jonathan Austin |
1:8aa5cdb4ab67 | 150 | uint32_t pg_size = NRF_FICR->CODEPAGESIZE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 151 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 152 | uint32_t *scratchPointer = (uint32_t *)(pg_size * (NRF_FICR->CODESIZE - MICROBIT_STORAGE_SCRATCH_PAGE_OFFSET)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 153 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 154 | //KeyValueStore is word aligned. |
Jonathan Austin |
1:8aa5cdb4ab67 | 155 | int wordsToWrite = sizeof(KeyValueStore) / 4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 156 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 157 | //write the given KeyValueStore |
Jonathan Austin |
1:8aa5cdb4ab67 | 158 | for (int i = 0; i < wordsToWrite; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 159 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 160 | flashWordWrite(scratchPointer, *s); |
Jonathan Austin |
1:8aa5cdb4ab67 | 161 | scratchPointer++; |
Jonathan Austin |
1:8aa5cdb4ab67 | 162 | s++; |
Jonathan Austin |
1:8aa5cdb4ab67 | 163 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 164 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 165 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 166 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 167 | * Function for populating the scratch page with a KeyValuePair. |
Jonathan Austin |
1:8aa5cdb4ab67 | 168 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 169 | * @param pair the KeyValuePair struct to write to the scratch page. |
Jonathan Austin |
1:8aa5cdb4ab67 | 170 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 171 | * @param flashPointer the pointer in flash where this KeyValuePair resides. This pointer |
Jonathan Austin |
1:8aa5cdb4ab67 | 172 | * is used to determine the offset into the scratch page, where the KeyValuePair should |
Jonathan Austin |
1:8aa5cdb4ab67 | 173 | * be written. |
Jonathan Austin |
1:8aa5cdb4ab67 | 174 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 175 | void MicroBitStorage::scratchKeyValuePair(KeyValuePair pair, uint32_t* flashPointer) |
Jonathan Austin |
1:8aa5cdb4ab67 | 176 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 177 | //we can only write using words |
Jonathan Austin |
1:8aa5cdb4ab67 | 178 | uint32_t *p = (uint32_t *) &pair; |
Jonathan Austin |
1:8aa5cdb4ab67 | 179 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 180 | //calculate our various offsets |
Jonathan Austin |
1:8aa5cdb4ab67 | 181 | uint32_t pg_size = NRF_FICR->CODEPAGESIZE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 182 | uint32_t pg_num = NRF_FICR->CODESIZE - MICROBIT_STORAGE_STORE_PAGE_OFFSET; |
Jonathan Austin |
1:8aa5cdb4ab67 | 183 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 184 | uint32_t *scratchPointer = (uint32_t *)(pg_size * (NRF_FICR->CODESIZE - MICROBIT_STORAGE_SCRATCH_PAGE_OFFSET)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 185 | uint32_t *flashBlockPointer = (uint32_t *)(pg_size * pg_num); |
Jonathan Austin |
1:8aa5cdb4ab67 | 186 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 187 | uint32_t flashPointerOffset = flashPointer - flashBlockPointer; |
Jonathan Austin |
1:8aa5cdb4ab67 | 188 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 189 | scratchPointer += flashPointerOffset; |
Jonathan Austin |
1:8aa5cdb4ab67 | 190 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 191 | //KeyValuePair is word aligned... |
Jonathan Austin |
1:8aa5cdb4ab67 | 192 | int wordsToWrite = sizeof(KeyValuePair) / 4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 193 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 194 | //write |
Jonathan Austin |
1:8aa5cdb4ab67 | 195 | for (int i = 0; i < wordsToWrite; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 196 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 197 | flashWordWrite(scratchPointer, *p); |
Jonathan Austin |
1:8aa5cdb4ab67 | 198 | scratchPointer++; |
Jonathan Austin |
1:8aa5cdb4ab67 | 199 | p++; |
Jonathan Austin |
1:8aa5cdb4ab67 | 200 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 201 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 202 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 203 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 204 | * Places a given key, and it's corresponding value into flash at the earliest |
Jonathan Austin |
1:8aa5cdb4ab67 | 205 | * available point. |
Jonathan Austin |
1:8aa5cdb4ab67 | 206 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 207 | * @param key the unique name that should be used as an identifier for the given data. |
Jonathan Austin |
1:8aa5cdb4ab67 | 208 | * The key is presumed to be null terminated. |
Jonathan Austin |
1:8aa5cdb4ab67 | 209 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 210 | * @param data a pointer to the beginning of the data to be persisted. |
Jonathan Austin |
1:8aa5cdb4ab67 | 211 | * |
LancasterUniversity | 30:db87179335d5 | 212 | * @param dataSize the size of the data to be persisted |
LancasterUniversity | 30:db87179335d5 | 213 | * |
LancasterUniversity | 30:db87179335d5 | 214 | * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if the key or size is too large, |
LancasterUniversity | 30:db87179335d5 | 215 | * MICROBIT_NO_RESOURCES if the storage page is full |
Jonathan Austin |
1:8aa5cdb4ab67 | 216 | */ |
LancasterUniversity | 30:db87179335d5 | 217 | int MicroBitStorage::put(const char *key, uint8_t *data, int dataSize) |
Jonathan Austin |
1:8aa5cdb4ab67 | 218 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 219 | KeyValuePair pair = KeyValuePair(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 220 | |
LancasterUniversity | 30:db87179335d5 | 221 | int keySize = strlen(key) + 1; |
LancasterUniversity | 30:db87179335d5 | 222 | |
LancasterUniversity | 30:db87179335d5 | 223 | if(keySize > (int)sizeof(pair.key) || dataSize > (int)sizeof(pair.value) || dataSize < 0) |
LancasterUniversity | 30:db87179335d5 | 224 | return MICROBIT_INVALID_PARAMETER; |
LancasterUniversity | 30:db87179335d5 | 225 | |
LancasterUniversity | 30:db87179335d5 | 226 | memcpy(pair.key, key, keySize); |
LancasterUniversity | 30:db87179335d5 | 227 | memcpy(pair.value, data, dataSize); |
Jonathan Austin |
1:8aa5cdb4ab67 | 228 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 229 | //calculate our various offsets. |
Jonathan Austin |
1:8aa5cdb4ab67 | 230 | uint32_t pg_size = NRF_FICR->CODEPAGESIZE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 231 | uint32_t *flashPointer = (uint32_t *)(pg_size * (NRF_FICR->CODESIZE - MICROBIT_STORAGE_STORE_PAGE_OFFSET)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 232 | uint32_t *flashBlockPointer = flashPointer; |
Jonathan Austin |
1:8aa5cdb4ab67 | 233 | uint32_t *scratchPointer = (uint32_t *)(pg_size * (NRF_FICR->CODESIZE - MICROBIT_STORAGE_SCRATCH_PAGE_OFFSET)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 234 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 235 | uint32_t kvStoreSize = sizeof(KeyValueStore) / 4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 236 | uint32_t kvPairSize = sizeof(KeyValuePair) / 4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 237 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 238 | int storeSize = size(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 239 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 240 | //our KeyValueStore struct is always at 0 |
Jonathan Austin |
1:8aa5cdb4ab67 | 241 | flashPointer += kvStoreSize; |
Jonathan Austin |
1:8aa5cdb4ab67 | 242 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 243 | KeyValuePair storedPair = KeyValuePair(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 244 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 245 | int found = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 246 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 247 | //erase our scratch page |
Jonathan Austin |
1:8aa5cdb4ab67 | 248 | flashPageErase(scratchPointer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 249 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 250 | //iterate through key value pairs in flash, writing them to the scratch page. |
Jonathan Austin |
1:8aa5cdb4ab67 | 251 | for(int i = 0; i < storeSize; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 252 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 253 | memcpy(&storedPair, flashPointer, sizeof(KeyValuePair)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 254 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 255 | //check if the keys match... |
Jonathan Austin |
1:8aa5cdb4ab67 | 256 | if(strcmp((char *)storedPair.key, (char *)pair.key) == 0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 257 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 258 | found = 1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 259 | //scratch our KeyValueStore struct so that it is preserved. |
Jonathan Austin |
1:8aa5cdb4ab67 | 260 | scratchKeyValueStore(KeyValueStore(MICROBIT_STORAGE_MAGIC, storeSize)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 261 | scratchKeyValuePair(pair, flashPointer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 262 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 263 | else |
Jonathan Austin |
1:8aa5cdb4ab67 | 264 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 265 | scratchKeyValuePair(storedPair, flashPointer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 266 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 267 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 268 | flashPointer += kvPairSize; |
Jonathan Austin |
1:8aa5cdb4ab67 | 269 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 270 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 271 | if(!found) |
Jonathan Austin |
1:8aa5cdb4ab67 | 272 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 273 | //if we haven't got a match for the key, check we can add a new KeyValuePair |
Jonathan Austin |
1:8aa5cdb4ab67 | 274 | if(storeSize == (int)((pg_size - kvStoreSize) / MICROBIT_STORAGE_BLOCK_SIZE)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 275 | return MICROBIT_NO_RESOURCES; |
Jonathan Austin |
1:8aa5cdb4ab67 | 276 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 277 | storeSize += 1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 278 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 279 | //scratch our updated values. |
Jonathan Austin |
1:8aa5cdb4ab67 | 280 | scratchKeyValueStore(KeyValueStore(MICROBIT_STORAGE_MAGIC, storeSize)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 281 | scratchKeyValuePair(pair, flashPointer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 282 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 283 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 284 | //erase our storage page |
Jonathan Austin |
1:8aa5cdb4ab67 | 285 | flashPageErase((uint32_t *)flashBlockPointer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 286 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 287 | //copy from scratch to storage. |
Jonathan Austin |
1:8aa5cdb4ab67 | 288 | flashCopy((uint32_t *)(pg_size * (NRF_FICR->CODESIZE - MICROBIT_STORAGE_SCRATCH_PAGE_OFFSET)), flashBlockPointer, kvStoreSize + (storeSize * kvPairSize)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 289 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 290 | return MICROBIT_OK; |
Jonathan Austin |
1:8aa5cdb4ab67 | 291 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 292 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 293 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 294 | * Places a given key, and it's corresponding value into flash at the earliest |
Jonathan Austin |
1:8aa5cdb4ab67 | 295 | * available point. |
Jonathan Austin |
1:8aa5cdb4ab67 | 296 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 297 | * @param key the unique name that should be used as an identifier for the given data. |
Jonathan Austin |
1:8aa5cdb4ab67 | 298 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 299 | * @param data a pointer to the beginning of the data to be persisted. |
Jonathan Austin |
1:8aa5cdb4ab67 | 300 | * |
LancasterUniversity | 30:db87179335d5 | 301 | * @param dataSize the size of the data to be persisted |
LancasterUniversity | 30:db87179335d5 | 302 | * |
LancasterUniversity | 30:db87179335d5 | 303 | * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if the key or size is too large, |
LancasterUniversity | 30:db87179335d5 | 304 | * MICROBIT_NO_RESOURCES if the storage page is full |
Jonathan Austin |
1:8aa5cdb4ab67 | 305 | */ |
LancasterUniversity | 30:db87179335d5 | 306 | int MicroBitStorage::put(ManagedString key, uint8_t* data, int dataSize) |
Jonathan Austin |
1:8aa5cdb4ab67 | 307 | { |
LancasterUniversity | 30:db87179335d5 | 308 | return put((char *)key.toCharArray(), data, dataSize); |
Jonathan Austin |
1:8aa5cdb4ab67 | 309 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 310 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 311 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 312 | * Retreives a KeyValuePair identified by a given key. |
Jonathan Austin |
1:8aa5cdb4ab67 | 313 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 314 | * @param key the unique name used to identify a KeyValuePair in flash. |
Jonathan Austin |
1:8aa5cdb4ab67 | 315 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 316 | * @return a pointer to a heap allocated KeyValuePair struct, this pointer will be |
Jonathan Austin |
1:8aa5cdb4ab67 | 317 | * NULL if the key was not found in storage. |
Jonathan Austin |
1:8aa5cdb4ab67 | 318 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 319 | * @note it is up to the user to free memory after use. |
Jonathan Austin |
1:8aa5cdb4ab67 | 320 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 321 | KeyValuePair* MicroBitStorage::get(const char* key) |
Jonathan Austin |
1:8aa5cdb4ab67 | 322 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 323 | //calculate our offsets for our storage page |
Jonathan Austin |
1:8aa5cdb4ab67 | 324 | uint32_t pg_size = NRF_FICR->CODEPAGESIZE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 325 | uint32_t pg_num = NRF_FICR->CODESIZE - MICROBIT_STORAGE_STORE_PAGE_OFFSET; |
Jonathan Austin |
1:8aa5cdb4ab67 | 326 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 327 | uint32_t *flashBlockPointer = (uint32_t *)(pg_size * pg_num); |
Jonathan Austin |
1:8aa5cdb4ab67 | 328 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 329 | int storeSize = size(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 330 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 331 | //we haven't got anything stored, so return... |
Jonathan Austin |
1:8aa5cdb4ab67 | 332 | if(storeSize == 0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 333 | return NULL; |
Jonathan Austin |
1:8aa5cdb4ab67 | 334 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 335 | //our KeyValueStore struct is always at 0 |
Jonathan Austin |
1:8aa5cdb4ab67 | 336 | flashBlockPointer += sizeof(KeyValueStore) / 4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 337 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 338 | KeyValuePair *pair = new KeyValuePair(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 339 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 340 | int i; |
Jonathan Austin |
1:8aa5cdb4ab67 | 341 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 342 | //iterate through flash until we have a match, or drop out. |
Jonathan Austin |
1:8aa5cdb4ab67 | 343 | for(i = 0; i < storeSize; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 344 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 345 | memcpy(pair, flashBlockPointer, sizeof(KeyValuePair)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 346 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 347 | if(strcmp(key,(char *)pair->key) == 0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 348 | break; |
Jonathan Austin |
1:8aa5cdb4ab67 | 349 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 350 | flashBlockPointer += sizeof(KeyValuePair) / 4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 351 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 352 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 353 | //clean up |
Jonathan Austin |
1:8aa5cdb4ab67 | 354 | if(i == storeSize) |
Jonathan Austin |
1:8aa5cdb4ab67 | 355 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 356 | delete pair; |
Jonathan Austin |
1:8aa5cdb4ab67 | 357 | return NULL; |
Jonathan Austin |
1:8aa5cdb4ab67 | 358 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 359 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 360 | return pair; |
Jonathan Austin |
1:8aa5cdb4ab67 | 361 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 362 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 363 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 364 | * Retreives a KeyValuePair identified by a given key. |
Jonathan Austin |
1:8aa5cdb4ab67 | 365 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 366 | * @param key the unique name used to identify a KeyValuePair in flash. |
Jonathan Austin |
1:8aa5cdb4ab67 | 367 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 368 | * @return a pointer to a heap allocated KeyValuePair struct, this pointer will be |
Jonathan Austin |
1:8aa5cdb4ab67 | 369 | * NULL if the key was not found in storage. |
Jonathan Austin |
1:8aa5cdb4ab67 | 370 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 371 | * @note it is up to the user to free memory after use. |
Jonathan Austin |
1:8aa5cdb4ab67 | 372 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 373 | KeyValuePair* MicroBitStorage::get(ManagedString key) |
Jonathan Austin |
1:8aa5cdb4ab67 | 374 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 375 | return get((char *)key.toCharArray()); |
Jonathan Austin |
1:8aa5cdb4ab67 | 376 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 377 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 378 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 379 | * Removes a KeyValuePair identified by a given key. |
Jonathan Austin |
1:8aa5cdb4ab67 | 380 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 381 | * @param key the unique name used to identify a KeyValuePair in flash. |
Jonathan Austin |
1:8aa5cdb4ab67 | 382 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 383 | * @return MICROBIT_OK on success, or MICROBIT_NO_DATA if the given key |
Jonathan Austin |
1:8aa5cdb4ab67 | 384 | * was not found in flash. |
Jonathan Austin |
1:8aa5cdb4ab67 | 385 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 386 | int MicroBitStorage::remove(const char* key) |
Jonathan Austin |
1:8aa5cdb4ab67 | 387 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 388 | //calculate our various offsets |
Jonathan Austin |
1:8aa5cdb4ab67 | 389 | uint32_t pg_size = NRF_FICR->CODEPAGESIZE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 390 | uint32_t *flashPointer = (uint32_t *)(pg_size * (NRF_FICR->CODESIZE - MICROBIT_STORAGE_STORE_PAGE_OFFSET)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 391 | uint32_t *flashBlockPointer = flashPointer; |
Jonathan Austin |
1:8aa5cdb4ab67 | 392 | uint32_t *scratchPointer = (uint32_t *)(pg_size * (NRF_FICR->CODESIZE - MICROBIT_STORAGE_SCRATCH_PAGE_OFFSET)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 393 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 394 | uint32_t kvStoreSize = sizeof(KeyValueStore) / 4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 395 | uint32_t kvPairSize = sizeof(KeyValuePair) / 4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 396 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 397 | int storeSize = size(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 398 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 399 | //if we have no data, we have nothing to do. |
Jonathan Austin |
1:8aa5cdb4ab67 | 400 | if(storeSize == 0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 401 | return MICROBIT_NO_DATA; |
Jonathan Austin |
1:8aa5cdb4ab67 | 402 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 403 | //our KeyValueStore struct is always at 0 |
Jonathan Austin |
1:8aa5cdb4ab67 | 404 | flashPointer += kvStoreSize; |
Jonathan Austin |
1:8aa5cdb4ab67 | 405 | scratchPointer += kvStoreSize; |
Jonathan Austin |
1:8aa5cdb4ab67 | 406 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 407 | KeyValuePair storedPair = KeyValuePair(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 408 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 409 | int found = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 410 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 411 | //set up our scratch area |
Jonathan Austin |
1:8aa5cdb4ab67 | 412 | flashPageErase(scratchPointer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 413 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 414 | //iterate through our flash copy pairs to scratch, unless there is a key patch |
Jonathan Austin |
1:8aa5cdb4ab67 | 415 | for(int i = 0; i < storeSize; i++) |
Jonathan Austin |
1:8aa5cdb4ab67 | 416 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 417 | memcpy(&storedPair, flashPointer, sizeof(KeyValuePair)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 418 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 419 | //if we have a match, don't increment our scratchPointer |
Jonathan Austin |
1:8aa5cdb4ab67 | 420 | if(strcmp((char *)storedPair.key, (char *)key) == 0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 421 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 422 | found = 1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 423 | //write our new KeyValueStore data |
Jonathan Austin |
1:8aa5cdb4ab67 | 424 | scratchKeyValueStore(KeyValueStore(MICROBIT_STORAGE_MAGIC, storeSize - 1)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 425 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 426 | else |
Jonathan Austin |
1:8aa5cdb4ab67 | 427 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 428 | //otherwise copy the KeyValuePair from our storage page. |
Jonathan Austin |
1:8aa5cdb4ab67 | 429 | flashCopy(flashPointer, scratchPointer, sizeof(KeyValuePair) / 4); |
Jonathan Austin |
1:8aa5cdb4ab67 | 430 | scratchPointer += sizeof(KeyValuePair) / 4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 431 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 432 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 433 | flashPointer += sizeof(KeyValuePair) / 4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 434 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 435 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 436 | //if we haven't got a match, write our old KeyValueStore struct |
Jonathan Austin |
1:8aa5cdb4ab67 | 437 | if(!found) |
Jonathan Austin |
1:8aa5cdb4ab67 | 438 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 439 | scratchKeyValueStore(KeyValueStore(MICROBIT_STORAGE_MAGIC, storeSize)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 440 | return MICROBIT_NO_DATA; |
Jonathan Austin |
1:8aa5cdb4ab67 | 441 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 442 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 443 | //copy scratch to our storage page |
Jonathan Austin |
1:8aa5cdb4ab67 | 444 | flashPageErase((uint32_t *)flashBlockPointer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 445 | flashCopy((uint32_t *)(pg_size * (NRF_FICR->CODESIZE - MICROBIT_STORAGE_SCRATCH_PAGE_OFFSET)), flashBlockPointer, kvStoreSize + (storeSize * kvPairSize)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 446 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 447 | return MICROBIT_OK; |
Jonathan Austin |
1:8aa5cdb4ab67 | 448 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 449 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 450 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 451 | * Removes a KeyValuePair identified by a given key. |
Jonathan Austin |
1:8aa5cdb4ab67 | 452 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 453 | * @param key the unique name used to identify a KeyValuePair in flash. |
Jonathan Austin |
1:8aa5cdb4ab67 | 454 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 455 | * @return MICROBIT_OK on success, or MICROBIT_NO_DATA if the given key |
Jonathan Austin |
1:8aa5cdb4ab67 | 456 | * was not found in flash. |
Jonathan Austin |
1:8aa5cdb4ab67 | 457 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 458 | int MicroBitStorage::remove(ManagedString key) |
Jonathan Austin |
1:8aa5cdb4ab67 | 459 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 460 | return remove((char *)key.toCharArray()); |
Jonathan Austin |
1:8aa5cdb4ab67 | 461 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 462 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 463 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 464 | * The size of the flash based KeyValueStore. |
Jonathan Austin |
1:8aa5cdb4ab67 | 465 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 466 | * @return the number of entries in the key value store |
Jonathan Austin |
1:8aa5cdb4ab67 | 467 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 468 | int MicroBitStorage::size() |
Jonathan Austin |
1:8aa5cdb4ab67 | 469 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 470 | uint32_t pg_size = NRF_FICR->CODEPAGESIZE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 471 | uint32_t pg_num = NRF_FICR->CODESIZE - MICROBIT_STORAGE_STORE_PAGE_OFFSET; |
Jonathan Austin |
1:8aa5cdb4ab67 | 472 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 473 | uint32_t *flashBlockPointer = (uint32_t *)(pg_size * pg_num); |
Jonathan Austin |
1:8aa5cdb4ab67 | 474 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 475 | KeyValueStore store = KeyValueStore(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 476 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 477 | //read our data! |
Jonathan Austin |
1:8aa5cdb4ab67 | 478 | memcpy(&store, flashBlockPointer, sizeof(KeyValueStore)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 479 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 480 | //if we haven't used flash before, we need to configure it |
Jonathan Austin |
1:8aa5cdb4ab67 | 481 | if(store.magic != MICROBIT_STORAGE_MAGIC) |
Jonathan Austin |
1:8aa5cdb4ab67 | 482 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 483 | store.magic = MICROBIT_STORAGE_MAGIC; |
Jonathan Austin |
1:8aa5cdb4ab67 | 484 | store.size = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 485 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 486 | //erase the scratch page and write our new KeyValueStore |
Jonathan Austin |
1:8aa5cdb4ab67 | 487 | flashPageErase((uint32_t *)(pg_size * (NRF_FICR->CODESIZE - MICROBIT_STORAGE_SCRATCH_PAGE_OFFSET))); |
Jonathan Austin |
1:8aa5cdb4ab67 | 488 | scratchKeyValueStore(store); |
Jonathan Austin |
1:8aa5cdb4ab67 | 489 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 490 | //erase flash, and copy the scratch page over |
Jonathan Austin |
1:8aa5cdb4ab67 | 491 | flashPageErase((uint32_t *)flashBlockPointer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 492 | flashCopy((uint32_t *)(pg_size * (NRF_FICR->CODESIZE - MICROBIT_STORAGE_SCRATCH_PAGE_OFFSET)), flashBlockPointer, pg_size/4); |
Jonathan Austin |
1:8aa5cdb4ab67 | 493 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 494 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 495 | return store.size; |
LancasterUniversity | 30:db87179335d5 | 496 | } |