iOSのBLEコントローラアプリ「RCBController」とmbed HRM1017を接続し、RCサーボモータを操作するテストプログラムです。

Dependencies:   BLE_API_Native_IRC Servo mbed

Fork of BLE_RCBController by Junichi Katsu

  • 古いBLEライブラリを使っているのでプラットフォームは”Nordic nRF51822”を選択してください。
  • ライブラリ類はUpdateしないでください。コンパイルエラーになります。

うまく接続できない時は、iPhone/iPadのBluetoothをOFF->ONしてキャッシュをクリアしてみてください。

/media/uploads/robo8080/img_1560.jpg

Committer:
jksoft
Date:
Thu Jul 10 14:21:52 2014 +0000
Revision:
0:8c643bfe55b7
??

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jksoft 0:8c643bfe55b7 1 /* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
jksoft 0:8c643bfe55b7 2 *
jksoft 0:8c643bfe55b7 3 * The information contained herein is property of Nordic Semiconductor ASA.
jksoft 0:8c643bfe55b7 4 * Terms and conditions of usage are described in detail in NORDIC
jksoft 0:8c643bfe55b7 5 * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
jksoft 0:8c643bfe55b7 6 *
jksoft 0:8c643bfe55b7 7 * Licensees are granted free, non-transferable use of the information. NO
jksoft 0:8c643bfe55b7 8 * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
jksoft 0:8c643bfe55b7 9 * the file.
jksoft 0:8c643bfe55b7 10 *
jksoft 0:8c643bfe55b7 11 */
jksoft 0:8c643bfe55b7 12
jksoft 0:8c643bfe55b7 13 #include <stdlib.h>
jksoft 0:8c643bfe55b7 14 #include <stdint.h>
jksoft 0:8c643bfe55b7 15 #include <string.h>
jksoft 0:8c643bfe55b7 16 #include "nordic_common.h"
jksoft 0:8c643bfe55b7 17 #include "nrf_error.h"
jksoft 0:8c643bfe55b7 18 #include "nrf_assert.h"
jksoft 0:8c643bfe55b7 19 //#include "nrf.h"
jksoft 0:8c643bfe55b7 20 #include "nrf_soc.h"
jksoft 0:8c643bfe55b7 21 #include "app_util.h"
jksoft 0:8c643bfe55b7 22 #include "pstorage.h"
jksoft 0:8c643bfe55b7 23
jksoft 0:8c643bfe55b7 24
jksoft 0:8c643bfe55b7 25 #define INVALID_OPCODE 0x00 /**< Invalid op code identifier. */
jksoft 0:8c643bfe55b7 26 #define SOC_MAX_WRITE_SIZE 1024 /**< Maximum write size allowed for a single call to \ref sd_flash_write as specified in the SoC API. */
jksoft 0:8c643bfe55b7 27
jksoft 0:8c643bfe55b7 28 /**
jksoft 0:8c643bfe55b7 29 * @defgroup api_param_check API Parameters check macros.
jksoft 0:8c643bfe55b7 30 *
jksoft 0:8c643bfe55b7 31 * @details Macros that verify parameters passed to the module in the APIs. These macros
jksoft 0:8c643bfe55b7 32 * could be mapped to nothing in final versions of code to save execution and size.
jksoft 0:8c643bfe55b7 33 *
jksoft 0:8c643bfe55b7 34 * @{
jksoft 0:8c643bfe55b7 35 */
jksoft 0:8c643bfe55b7 36 /**
jksoft 0:8c643bfe55b7 37 * @brief Check if the input pointer is NULL, if it is returns NRF_ERROR_NULL.
jksoft 0:8c643bfe55b7 38 */
jksoft 0:8c643bfe55b7 39 #define NULL_PARAM_CHECK(PARAM) \
jksoft 0:8c643bfe55b7 40 if ((PARAM) == NULL) \
jksoft 0:8c643bfe55b7 41 { \
jksoft 0:8c643bfe55b7 42 return NRF_ERROR_NULL; \
jksoft 0:8c643bfe55b7 43 }
jksoft 0:8c643bfe55b7 44
jksoft 0:8c643bfe55b7 45 /**
jksoft 0:8c643bfe55b7 46 * @brief Verifies the module identifier supplied by the application is within permissible
jksoft 0:8c643bfe55b7 47 * range.
jksoft 0:8c643bfe55b7 48 */
jksoft 0:8c643bfe55b7 49 #define MODULE_ID_RANGE_CHECK(ID) \
jksoft 0:8c643bfe55b7 50 if ((((ID)->module_id) >= PSTORAGE_MAX_APPLICATIONS) || \
jksoft 0:8c643bfe55b7 51 (m_app_table[(ID)->module_id].cb == NULL)) \
jksoft 0:8c643bfe55b7 52 { \
jksoft 0:8c643bfe55b7 53 return NRF_ERROR_INVALID_PARAM; \
jksoft 0:8c643bfe55b7 54 }
jksoft 0:8c643bfe55b7 55
jksoft 0:8c643bfe55b7 56 /**
jksoft 0:8c643bfe55b7 57 * @brief Verifies the block identifier supplied by the application is within the permissible
jksoft 0:8c643bfe55b7 58 * range.
jksoft 0:8c643bfe55b7 59 */
jksoft 0:8c643bfe55b7 60 #define BLOCK_ID_RANGE_CHECK(ID) \
jksoft 0:8c643bfe55b7 61 if (((ID)->block_id) >= (m_app_table[(ID)->module_id].base_id + \
jksoft 0:8c643bfe55b7 62 (m_app_table[(ID)->module_id].block_count * MODULE_BLOCK_SIZE(ID)))) \
jksoft 0:8c643bfe55b7 63 { \
jksoft 0:8c643bfe55b7 64 return NRF_ERROR_INVALID_PARAM; \
jksoft 0:8c643bfe55b7 65 }
jksoft 0:8c643bfe55b7 66
jksoft 0:8c643bfe55b7 67
jksoft 0:8c643bfe55b7 68 /**
jksoft 0:8c643bfe55b7 69 * @brief Verifies the block size requested by the application can be supported by the module.
jksoft 0:8c643bfe55b7 70 */
jksoft 0:8c643bfe55b7 71 #define BLOCK_SIZE_CHECK(X) \
jksoft 0:8c643bfe55b7 72 if (((X) > PSTORAGE_MAX_BLOCK_SIZE) || ((X) < PSTORAGE_MIN_BLOCK_SIZE)) \
jksoft 0:8c643bfe55b7 73 { \
jksoft 0:8c643bfe55b7 74 return NRF_ERROR_INVALID_PARAM; \
jksoft 0:8c643bfe55b7 75 }
jksoft 0:8c643bfe55b7 76
jksoft 0:8c643bfe55b7 77 /**
jksoft 0:8c643bfe55b7 78 * @brief Verifies block size requested by Application in registration API.
jksoft 0:8c643bfe55b7 79 */
jksoft 0:8c643bfe55b7 80 #define BLOCK_COUNT_CHECK(COUNT, SIZE) \
jksoft 0:8c643bfe55b7 81 if (((COUNT) == 0) || ((m_next_page_addr + ((COUNT) *(SIZE)) > PSTORAGE_DATA_END_ADDR))) \
jksoft 0:8c643bfe55b7 82 { \
jksoft 0:8c643bfe55b7 83 return NRF_ERROR_INVALID_PARAM; \
jksoft 0:8c643bfe55b7 84 }
jksoft 0:8c643bfe55b7 85
jksoft 0:8c643bfe55b7 86 /**
jksoft 0:8c643bfe55b7 87 * @brief Verifies size parameter provided by application in API.
jksoft 0:8c643bfe55b7 88 */
jksoft 0:8c643bfe55b7 89 #define SIZE_CHECK(ID, SIZE) \
jksoft 0:8c643bfe55b7 90 if(((SIZE) == 0) || ((SIZE) > MODULE_BLOCK_SIZE(ID))) \
jksoft 0:8c643bfe55b7 91 { \
jksoft 0:8c643bfe55b7 92 return NRF_ERROR_INVALID_PARAM; \
jksoft 0:8c643bfe55b7 93 }
jksoft 0:8c643bfe55b7 94
jksoft 0:8c643bfe55b7 95 /**
jksoft 0:8c643bfe55b7 96 * @brief Verifies offset parameter provided by application in API.
jksoft 0:8c643bfe55b7 97 */
jksoft 0:8c643bfe55b7 98 #define OFFSET_CHECK(ID, OFFSET, SIZE) \
jksoft 0:8c643bfe55b7 99 if(((SIZE) + (OFFSET)) > MODULE_BLOCK_SIZE(ID)) \
jksoft 0:8c643bfe55b7 100 { \
jksoft 0:8c643bfe55b7 101 return NRF_ERROR_INVALID_PARAM; \
jksoft 0:8c643bfe55b7 102 }
jksoft 0:8c643bfe55b7 103
jksoft 0:8c643bfe55b7 104 #ifdef PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 105
jksoft 0:8c643bfe55b7 106 /**
jksoft 0:8c643bfe55b7 107 * @brief Verifies the module identifier supplied by the application is registered for raw mode.
jksoft 0:8c643bfe55b7 108 */
jksoft 0:8c643bfe55b7 109 #define MODULE_RAW_ID_RANGE_CHECK(ID) \
jksoft 0:8c643bfe55b7 110 if ((PSTORAGE_MAX_APPLICATIONS+1 != ((ID)->module_id)) || \
jksoft 0:8c643bfe55b7 111 (m_raw_app_table.cb == NULL)) \
jksoft 0:8c643bfe55b7 112 { \
jksoft 0:8c643bfe55b7 113 return NRF_ERROR_INVALID_PARAM; \
jksoft 0:8c643bfe55b7 114 }
jksoft 0:8c643bfe55b7 115
jksoft 0:8c643bfe55b7 116 #endif // PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 117
jksoft 0:8c643bfe55b7 118 /**@} */
jksoft 0:8c643bfe55b7 119
jksoft 0:8c643bfe55b7 120 /**@brief Verify module's initialization status.
jksoft 0:8c643bfe55b7 121 *
jksoft 0:8c643bfe55b7 122 * @details Verify module's initialization status. Returns NRF_ERROR_INVALID_STATE in case a
jksoft 0:8c643bfe55b7 123 * module API is called without initializing the module.
jksoft 0:8c643bfe55b7 124 */
jksoft 0:8c643bfe55b7 125 #define VERIFY_MODULE_INITIALIZED() \
jksoft 0:8c643bfe55b7 126 do \
jksoft 0:8c643bfe55b7 127 { \
jksoft 0:8c643bfe55b7 128 if (!m_module_initialized) \
jksoft 0:8c643bfe55b7 129 { \
jksoft 0:8c643bfe55b7 130 return NRF_ERROR_INVALID_STATE; \
jksoft 0:8c643bfe55b7 131 } \
jksoft 0:8c643bfe55b7 132 } while(0)
jksoft 0:8c643bfe55b7 133
jksoft 0:8c643bfe55b7 134 /**@brief Macro to fetch the block size registered for the module. */
jksoft 0:8c643bfe55b7 135 #define MODULE_BLOCK_SIZE(ID) (m_app_table[(ID)->module_id].block_size)
jksoft 0:8c643bfe55b7 136
jksoft 0:8c643bfe55b7 137 /**@} */
jksoft 0:8c643bfe55b7 138
jksoft 0:8c643bfe55b7 139 /**
jksoft 0:8c643bfe55b7 140 * @brief Application registration information.
jksoft 0:8c643bfe55b7 141 *
jksoft 0:8c643bfe55b7 142 * @details Define application specific information that application needs to maintain to be able
jksoft 0:8c643bfe55b7 143 * to process requests from each one of them.
jksoft 0:8c643bfe55b7 144 */
jksoft 0:8c643bfe55b7 145 typedef struct
jksoft 0:8c643bfe55b7 146 {
jksoft 0:8c643bfe55b7 147 pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of result of flash access. */
jksoft 0:8c643bfe55b7 148 pstorage_block_t base_id; /**< Base block id assigned to the module */
jksoft 0:8c643bfe55b7 149 pstorage_size_t block_size; /**< Size of block for the module */
jksoft 0:8c643bfe55b7 150 pstorage_size_t block_count; /**< Number of block requested by application */
jksoft 0:8c643bfe55b7 151 pstorage_size_t no_of_pages; /**< Variable to remember how many pages have been allocated for this module. This information is used for clearing of block, so that application does not need to have knowledge of number of pages its using. */
jksoft 0:8c643bfe55b7 152 } pstorage_module_table_t;
jksoft 0:8c643bfe55b7 153
jksoft 0:8c643bfe55b7 154 #ifdef PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 155 /**
jksoft 0:8c643bfe55b7 156 * @brief Application registration information.
jksoft 0:8c643bfe55b7 157 *
jksoft 0:8c643bfe55b7 158 * @details Define application specific information that application registered for raw mode.
jksoft 0:8c643bfe55b7 159 */
jksoft 0:8c643bfe55b7 160 typedef struct
jksoft 0:8c643bfe55b7 161 {
jksoft 0:8c643bfe55b7 162 pstorage_ntf_cb_t cb; /**< Callback registered with the module to be notified of result of flash access. */
jksoft 0:8c643bfe55b7 163 uint16_t no_of_pages; /**< Variable to remember how many pages have been allocated for this module. This information is used for clearing of block, so that application does not need to have knowledge of number of pages its using. */
jksoft 0:8c643bfe55b7 164 } pstorage_raw_module_table_t;
jksoft 0:8c643bfe55b7 165 #endif // PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 166
jksoft 0:8c643bfe55b7 167
jksoft 0:8c643bfe55b7 168
jksoft 0:8c643bfe55b7 169
jksoft 0:8c643bfe55b7 170 /**
jksoft 0:8c643bfe55b7 171 * @brief Defines command queue element.
jksoft 0:8c643bfe55b7 172 *
jksoft 0:8c643bfe55b7 173 * @details Defines command queue element. Each element encapsulates needed information to process
jksoft 0:8c643bfe55b7 174 * a flash access command.
jksoft 0:8c643bfe55b7 175 */
jksoft 0:8c643bfe55b7 176 typedef struct
jksoft 0:8c643bfe55b7 177 {
jksoft 0:8c643bfe55b7 178 uint8_t op_code; /**< Identifies flash access operation being queued. Element is free is op-code is INVALID_OPCODE */
jksoft 0:8c643bfe55b7 179 pstorage_size_t size; /**< Identifies size in bytes requested for the operation. */
jksoft 0:8c643bfe55b7 180 pstorage_size_t offset; /**< Offset requested by the application for access operation. */
jksoft 0:8c643bfe55b7 181 pstorage_handle_t storage_addr; /**< Address/Identifier for persistent memory. */
jksoft 0:8c643bfe55b7 182 uint8_t * p_data_addr; /**< Address/Identifier for data memory. This is assumed to be resident memory. */
jksoft 0:8c643bfe55b7 183 } cmd_queue_element_t;
jksoft 0:8c643bfe55b7 184
jksoft 0:8c643bfe55b7 185
jksoft 0:8c643bfe55b7 186 /**
jksoft 0:8c643bfe55b7 187 * @brief Defines command queue, an element is free is op_code field is not invalid.
jksoft 0:8c643bfe55b7 188 *
jksoft 0:8c643bfe55b7 189 * @details Defines commands enqueued for flash access. At any point of time, this queue has one or
jksoft 0:8c643bfe55b7 190 * more flash access operation pending if the count field is not zero. When the queue is
jksoft 0:8c643bfe55b7 191 * not empty, the rp (read pointer) field points to the flash access command in progress
jksoft 0:8c643bfe55b7 192 * or to requested next. The queue implements a simple first in first out algorithm.
jksoft 0:8c643bfe55b7 193 * Data addresses are assumed to be resident.
jksoft 0:8c643bfe55b7 194 */
jksoft 0:8c643bfe55b7 195 typedef struct
jksoft 0:8c643bfe55b7 196 {
jksoft 0:8c643bfe55b7 197 uint8_t rp; /**< Read pointer, pointing to flash access that is ongoing or to be requested next. */
jksoft 0:8c643bfe55b7 198 uint8_t count; /**< Number of elements in the queue. */
jksoft 0:8c643bfe55b7 199 bool flash_access; /**< Flag to ensure an flash event received is for an request issued by the module. */
jksoft 0:8c643bfe55b7 200 cmd_queue_element_t cmd[PSTORAGE_CMD_QUEUE_SIZE]; /**< Array to maintain flash access operation details */
jksoft 0:8c643bfe55b7 201 }cmd_queue_t;
jksoft 0:8c643bfe55b7 202
jksoft 0:8c643bfe55b7 203 static cmd_queue_t m_cmd_queue; /**< Flash operation request queue. */
jksoft 0:8c643bfe55b7 204 static pstorage_module_table_t m_app_table[PSTORAGE_MAX_APPLICATIONS]; /**< Registered application information table. */
jksoft 0:8c643bfe55b7 205
jksoft 0:8c643bfe55b7 206 #ifdef PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 207 static pstorage_raw_module_table_t m_raw_app_table; /**< Registered application information table for raw mode. */
jksoft 0:8c643bfe55b7 208 #endif // PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 209
jksoft 0:8c643bfe55b7 210 static pstorage_size_t m_next_app_instance; /**< Points to the application module instance that can be allocated next */
jksoft 0:8c643bfe55b7 211 static uint32_t m_next_page_addr; /**< Points to the flash address that can be allocated to a module next, this is needed as blocks of a module can span across flash pages. */
jksoft 0:8c643bfe55b7 212 static bool m_module_initialized = false; /**< Flag for checking if module has been initialized. */
jksoft 0:8c643bfe55b7 213 static pstorage_size_t m_round_val; /**< Round value for multiple round operations. For erase operations, the round value will contain current round counter which is identical to number of pages erased. For store operations, the round value contains current round of operation * SOC_MAX_WRITE_SIZE to ensure each store to the SoC Flash API is within the SoC limit. */
jksoft 0:8c643bfe55b7 214
jksoft 0:8c643bfe55b7 215 static uint32_t process_cmd(void);
jksoft 0:8c643bfe55b7 216 static void app_notify (uint32_t reason);
jksoft 0:8c643bfe55b7 217
jksoft 0:8c643bfe55b7 218 /**
jksoft 0:8c643bfe55b7 219 * @defgroup utility_functions Utility internal functions.
jksoft 0:8c643bfe55b7 220 * @{
jksoft 0:8c643bfe55b7 221 * @details Utility functions needed for interfacing with flash through SoC APIs.
jksoft 0:8c643bfe55b7 222 * SoC APIs are non blocking and provide the result of flash access through an event.
jksoft 0:8c643bfe55b7 223 *
jksoft 0:8c643bfe55b7 224 * @note Only one flash access operation is permitted at a time by SoC. Hence a queue is
jksoft 0:8c643bfe55b7 225 * maintained by this module.
jksoft 0:8c643bfe55b7 226 */
jksoft 0:8c643bfe55b7 227
jksoft 0:8c643bfe55b7 228 /**
jksoft 0:8c643bfe55b7 229 * @brief Initializes command queue element.
jksoft 0:8c643bfe55b7 230 */
jksoft 0:8c643bfe55b7 231 static void cmd_queue_init_element(uint32_t index)
jksoft 0:8c643bfe55b7 232 {
jksoft 0:8c643bfe55b7 233 // Internal function and checks on range of index can be avoided
jksoft 0:8c643bfe55b7 234 m_cmd_queue.cmd[index].op_code = INVALID_OPCODE;
jksoft 0:8c643bfe55b7 235 m_cmd_queue.cmd[index].size = 0;
jksoft 0:8c643bfe55b7 236 m_cmd_queue.cmd[index].storage_addr.module_id = PSTORAGE_MAX_APPLICATIONS;
jksoft 0:8c643bfe55b7 237 m_cmd_queue.cmd[index].storage_addr.block_id = 0;
jksoft 0:8c643bfe55b7 238 m_cmd_queue.cmd[index].p_data_addr = NULL;
jksoft 0:8c643bfe55b7 239 m_cmd_queue.cmd[index].offset = 0;
jksoft 0:8c643bfe55b7 240 }
jksoft 0:8c643bfe55b7 241
jksoft 0:8c643bfe55b7 242
jksoft 0:8c643bfe55b7 243 /**
jksoft 0:8c643bfe55b7 244 * @brief Initializes command queue.
jksoft 0:8c643bfe55b7 245 */
jksoft 0:8c643bfe55b7 246 static void cmd_queue_init (void)
jksoft 0:8c643bfe55b7 247 {
jksoft 0:8c643bfe55b7 248 uint32_t cmd_index;
jksoft 0:8c643bfe55b7 249
jksoft 0:8c643bfe55b7 250 m_round_val = 0;
jksoft 0:8c643bfe55b7 251 m_cmd_queue.rp = 0;
jksoft 0:8c643bfe55b7 252 m_cmd_queue.count = 0;
jksoft 0:8c643bfe55b7 253 m_cmd_queue.flash_access = false;
jksoft 0:8c643bfe55b7 254
jksoft 0:8c643bfe55b7 255 for(cmd_index = 0; cmd_index < PSTORAGE_CMD_QUEUE_SIZE; cmd_index++)
jksoft 0:8c643bfe55b7 256 {
jksoft 0:8c643bfe55b7 257 cmd_queue_init_element(cmd_index);
jksoft 0:8c643bfe55b7 258 }
jksoft 0:8c643bfe55b7 259 }
jksoft 0:8c643bfe55b7 260
jksoft 0:8c643bfe55b7 261
jksoft 0:8c643bfe55b7 262 /**
jksoft 0:8c643bfe55b7 263 * @brief Routine to enqueue a flash access operation.
jksoft 0:8c643bfe55b7 264 */
jksoft 0:8c643bfe55b7 265 static uint32_t cmd_queue_enqueue(uint8_t opcode, pstorage_handle_t * p_storage_addr,uint8_t * p_data_addr, pstorage_size_t size, pstorage_size_t offset)
jksoft 0:8c643bfe55b7 266 {
jksoft 0:8c643bfe55b7 267 uint32_t retval;
jksoft 0:8c643bfe55b7 268 uint8_t write_index = 0;
jksoft 0:8c643bfe55b7 269 retval = NRF_ERROR_NO_MEM;
jksoft 0:8c643bfe55b7 270
jksoft 0:8c643bfe55b7 271 // Check if flash access is ongoing.
jksoft 0:8c643bfe55b7 272 if ((m_cmd_queue.flash_access == false) && (m_cmd_queue.count == 0))
jksoft 0:8c643bfe55b7 273 {
jksoft 0:8c643bfe55b7 274 m_cmd_queue.rp = 0;
jksoft 0:8c643bfe55b7 275 m_cmd_queue.cmd[m_cmd_queue.rp].op_code = opcode;
jksoft 0:8c643bfe55b7 276 m_cmd_queue.cmd[m_cmd_queue.rp].p_data_addr = p_data_addr;
jksoft 0:8c643bfe55b7 277 m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr = (*p_storage_addr);
jksoft 0:8c643bfe55b7 278 m_cmd_queue.cmd[m_cmd_queue.rp].size = size;
jksoft 0:8c643bfe55b7 279 m_cmd_queue.cmd[m_cmd_queue.rp].offset = offset;
jksoft 0:8c643bfe55b7 280 m_cmd_queue.count++;
jksoft 0:8c643bfe55b7 281 retval = process_cmd();
jksoft 0:8c643bfe55b7 282 if ((retval == NRF_SUCCESS) || (retval == NRF_ERROR_BUSY))
jksoft 0:8c643bfe55b7 283 {
jksoft 0:8c643bfe55b7 284 // In case of busy error code, it is possible to attempt to access flash
jksoft 0:8c643bfe55b7 285 retval = NRF_SUCCESS;
jksoft 0:8c643bfe55b7 286 }
jksoft 0:8c643bfe55b7 287 }
jksoft 0:8c643bfe55b7 288 else if (m_cmd_queue.count != PSTORAGE_CMD_QUEUE_SIZE)
jksoft 0:8c643bfe55b7 289 {
jksoft 0:8c643bfe55b7 290 // Enqueue the command if it is queue is not full
jksoft 0:8c643bfe55b7 291 write_index = m_cmd_queue.rp + m_cmd_queue.count;
jksoft 0:8c643bfe55b7 292
jksoft 0:8c643bfe55b7 293 if (write_index >= PSTORAGE_CMD_QUEUE_SIZE)
jksoft 0:8c643bfe55b7 294 {
jksoft 0:8c643bfe55b7 295 write_index -= PSTORAGE_CMD_QUEUE_SIZE;
jksoft 0:8c643bfe55b7 296 }
jksoft 0:8c643bfe55b7 297
jksoft 0:8c643bfe55b7 298 m_cmd_queue.cmd[write_index].op_code = opcode;
jksoft 0:8c643bfe55b7 299 m_cmd_queue.cmd[write_index].p_data_addr = p_data_addr;
jksoft 0:8c643bfe55b7 300 m_cmd_queue.cmd[write_index].storage_addr = (*p_storage_addr);
jksoft 0:8c643bfe55b7 301 m_cmd_queue.cmd[write_index].size = size;
jksoft 0:8c643bfe55b7 302 m_cmd_queue.cmd[write_index].offset = offset;
jksoft 0:8c643bfe55b7 303 m_cmd_queue.count++;
jksoft 0:8c643bfe55b7 304
jksoft 0:8c643bfe55b7 305 retval = NRF_SUCCESS;
jksoft 0:8c643bfe55b7 306
jksoft 0:8c643bfe55b7 307 }
jksoft 0:8c643bfe55b7 308
jksoft 0:8c643bfe55b7 309 return retval;
jksoft 0:8c643bfe55b7 310 }
jksoft 0:8c643bfe55b7 311
jksoft 0:8c643bfe55b7 312
jksoft 0:8c643bfe55b7 313 /**
jksoft 0:8c643bfe55b7 314 * @brief Dequeues a command element.
jksoft 0:8c643bfe55b7 315 */
jksoft 0:8c643bfe55b7 316 static uint32_t cmd_queue_dequeue(void)
jksoft 0:8c643bfe55b7 317 {
jksoft 0:8c643bfe55b7 318 uint32_t retval;
jksoft 0:8c643bfe55b7 319
jksoft 0:8c643bfe55b7 320 cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
jksoft 0:8c643bfe55b7 321 // Update count and read pointer to process any queued requests
jksoft 0:8c643bfe55b7 322 if(m_round_val >= p_cmd->size)
jksoft 0:8c643bfe55b7 323 {
jksoft 0:8c643bfe55b7 324 // Initialize/free the element as it is now processed.
jksoft 0:8c643bfe55b7 325 cmd_queue_init_element(m_cmd_queue.rp);
jksoft 0:8c643bfe55b7 326 m_round_val = 0;
jksoft 0:8c643bfe55b7 327 m_cmd_queue.count--;
jksoft 0:8c643bfe55b7 328 m_cmd_queue.rp++;
jksoft 0:8c643bfe55b7 329 }
jksoft 0:8c643bfe55b7 330
jksoft 0:8c643bfe55b7 331 retval = NRF_SUCCESS;
jksoft 0:8c643bfe55b7 332
jksoft 0:8c643bfe55b7 333 // If any flash operation is enqueued, schedule
jksoft 0:8c643bfe55b7 334 if (m_cmd_queue.count)
jksoft 0:8c643bfe55b7 335 {
jksoft 0:8c643bfe55b7 336 retval = process_cmd();
jksoft 0:8c643bfe55b7 337
jksoft 0:8c643bfe55b7 338 if (retval != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 339 {
jksoft 0:8c643bfe55b7 340 // Flash could be accessed by modules other than Bond Manager, hence a busy error is
jksoft 0:8c643bfe55b7 341 // acceptable, but any other error needs to be indicated to the bond manager
jksoft 0:8c643bfe55b7 342 if (retval != NRF_ERROR_BUSY)
jksoft 0:8c643bfe55b7 343 {
jksoft 0:8c643bfe55b7 344 app_notify (retval);
jksoft 0:8c643bfe55b7 345 }
jksoft 0:8c643bfe55b7 346 else
jksoft 0:8c643bfe55b7 347 {
jksoft 0:8c643bfe55b7 348 // In case of busy next trigger will be a success or a failure event
jksoft 0:8c643bfe55b7 349 }
jksoft 0:8c643bfe55b7 350 }
jksoft 0:8c643bfe55b7 351 }
jksoft 0:8c643bfe55b7 352 else
jksoft 0:8c643bfe55b7 353 {
jksoft 0:8c643bfe55b7 354 // No flash access request pending
jksoft 0:8c643bfe55b7 355 }
jksoft 0:8c643bfe55b7 356
jksoft 0:8c643bfe55b7 357 return retval;
jksoft 0:8c643bfe55b7 358 }
jksoft 0:8c643bfe55b7 359
jksoft 0:8c643bfe55b7 360
jksoft 0:8c643bfe55b7 361 /**
jksoft 0:8c643bfe55b7 362 * @brief Routine to notify application of any errors.
jksoft 0:8c643bfe55b7 363 */
jksoft 0:8c643bfe55b7 364 static void app_notify (uint32_t result)
jksoft 0:8c643bfe55b7 365 {
jksoft 0:8c643bfe55b7 366 pstorage_ntf_cb_t ntf_cb;
jksoft 0:8c643bfe55b7 367 uint8_t op_code = m_cmd_queue.cmd[m_cmd_queue.rp].op_code;
jksoft 0:8c643bfe55b7 368
jksoft 0:8c643bfe55b7 369 #ifdef PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 370 if(m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr.module_id == (PSTORAGE_MAX_APPLICATIONS + 1))
jksoft 0:8c643bfe55b7 371 {
jksoft 0:8c643bfe55b7 372 ntf_cb = m_raw_app_table.cb;
jksoft 0:8c643bfe55b7 373 }
jksoft 0:8c643bfe55b7 374 else
jksoft 0:8c643bfe55b7 375 #endif // PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 376 {
jksoft 0:8c643bfe55b7 377 ntf_cb = m_app_table[m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr.module_id].cb;
jksoft 0:8c643bfe55b7 378 }
jksoft 0:8c643bfe55b7 379
jksoft 0:8c643bfe55b7 380 // Indicate result to client.
jksoft 0:8c643bfe55b7 381 // For PSTORAGE_CLEAR_OP_CODE no size is returned as the size field is used only internally
jksoft 0:8c643bfe55b7 382 // for clients registering multiple pages.
jksoft 0:8c643bfe55b7 383 ntf_cb(&m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr,
jksoft 0:8c643bfe55b7 384 op_code,
jksoft 0:8c643bfe55b7 385 result,
jksoft 0:8c643bfe55b7 386 m_cmd_queue.cmd[m_cmd_queue.rp].p_data_addr,
jksoft 0:8c643bfe55b7 387 op_code == PSTORAGE_CLEAR_OP_CODE ? 0 : m_cmd_queue.cmd[m_cmd_queue.rp].size);
jksoft 0:8c643bfe55b7 388 }
jksoft 0:8c643bfe55b7 389
jksoft 0:8c643bfe55b7 390
jksoft 0:8c643bfe55b7 391 /**
jksoft 0:8c643bfe55b7 392 * @brief Handles Flash Access Result Events.
jksoft 0:8c643bfe55b7 393 */
jksoft 0:8c643bfe55b7 394 void pstorage_sys_event_handler (uint32_t sys_evt)
jksoft 0:8c643bfe55b7 395 {
jksoft 0:8c643bfe55b7 396 uint32_t retval;
jksoft 0:8c643bfe55b7 397
jksoft 0:8c643bfe55b7 398 retval = NRF_SUCCESS;
jksoft 0:8c643bfe55b7 399
jksoft 0:8c643bfe55b7 400 // Its possible the flash access was not initiated by bond manager, hence
jksoft 0:8c643bfe55b7 401 // event is processed only if the event triggered was for an operation requested by the
jksoft 0:8c643bfe55b7 402 // bond manager.
jksoft 0:8c643bfe55b7 403 if (m_cmd_queue.flash_access == true)
jksoft 0:8c643bfe55b7 404 {
jksoft 0:8c643bfe55b7 405 cmd_queue_element_t * p_cmd;
jksoft 0:8c643bfe55b7 406 m_cmd_queue.flash_access = false;
jksoft 0:8c643bfe55b7 407 switch (sys_evt)
jksoft 0:8c643bfe55b7 408 {
jksoft 0:8c643bfe55b7 409 case NRF_EVT_FLASH_OPERATION_SUCCESS:
jksoft 0:8c643bfe55b7 410 p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
jksoft 0:8c643bfe55b7 411 if ((p_cmd->op_code != PSTORAGE_CLEAR_OP_CODE) || (m_round_val >= p_cmd->size))
jksoft 0:8c643bfe55b7 412 {
jksoft 0:8c643bfe55b7 413 app_notify(retval);
jksoft 0:8c643bfe55b7 414 }
jksoft 0:8c643bfe55b7 415 // Schedule any queued flash access operations
jksoft 0:8c643bfe55b7 416 retval = cmd_queue_dequeue ();
jksoft 0:8c643bfe55b7 417 if (retval != NRF_SUCCESS)
jksoft 0:8c643bfe55b7 418 {
jksoft 0:8c643bfe55b7 419 app_notify(retval);
jksoft 0:8c643bfe55b7 420 }
jksoft 0:8c643bfe55b7 421
jksoft 0:8c643bfe55b7 422 break;
jksoft 0:8c643bfe55b7 423 case NRF_EVT_FLASH_OPERATION_ERROR:
jksoft 0:8c643bfe55b7 424 app_notify(NRF_ERROR_TIMEOUT);
jksoft 0:8c643bfe55b7 425 break;
jksoft 0:8c643bfe55b7 426 default:
jksoft 0:8c643bfe55b7 427 // No implementation needed.
jksoft 0:8c643bfe55b7 428 break;
jksoft 0:8c643bfe55b7 429 }
jksoft 0:8c643bfe55b7 430 }
jksoft 0:8c643bfe55b7 431 }
jksoft 0:8c643bfe55b7 432
jksoft 0:8c643bfe55b7 433
jksoft 0:8c643bfe55b7 434 /**
jksoft 0:8c643bfe55b7 435 * @brief Routine called to actually issue the flash access request to the SoftDevice.
jksoft 0:8c643bfe55b7 436 */
jksoft 0:8c643bfe55b7 437 static uint32_t process_cmd(void)
jksoft 0:8c643bfe55b7 438 {
jksoft 0:8c643bfe55b7 439 uint32_t retval;
jksoft 0:8c643bfe55b7 440 uint32_t storage_addr;
jksoft 0:8c643bfe55b7 441 cmd_queue_element_t * p_cmd;
jksoft 0:8c643bfe55b7 442
jksoft 0:8c643bfe55b7 443 retval = NRF_ERROR_FORBIDDEN;
jksoft 0:8c643bfe55b7 444
jksoft 0:8c643bfe55b7 445 p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
jksoft 0:8c643bfe55b7 446
jksoft 0:8c643bfe55b7 447 storage_addr = p_cmd->storage_addr.block_id;
jksoft 0:8c643bfe55b7 448
jksoft 0:8c643bfe55b7 449 if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE)
jksoft 0:8c643bfe55b7 450 {
jksoft 0:8c643bfe55b7 451 // Calculate page number before copy.
jksoft 0:8c643bfe55b7 452 uint32_t page_number;
jksoft 0:8c643bfe55b7 453
jksoft 0:8c643bfe55b7 454 page_number = ((storage_addr / PSTORAGE_FLASH_PAGE_SIZE) +
jksoft 0:8c643bfe55b7 455 m_round_val);
jksoft 0:8c643bfe55b7 456
jksoft 0:8c643bfe55b7 457 retval = sd_flash_page_erase(page_number);
jksoft 0:8c643bfe55b7 458
jksoft 0:8c643bfe55b7 459 if (NRF_SUCCESS == retval)
jksoft 0:8c643bfe55b7 460 {
jksoft 0:8c643bfe55b7 461 m_round_val++;
jksoft 0:8c643bfe55b7 462 }
jksoft 0:8c643bfe55b7 463 }
jksoft 0:8c643bfe55b7 464 else if (p_cmd->op_code == PSTORAGE_STORE_OP_CODE)
jksoft 0:8c643bfe55b7 465 {
jksoft 0:8c643bfe55b7 466 uint32_t size;
jksoft 0:8c643bfe55b7 467 uint8_t * p_data_addr = p_cmd->p_data_addr;
jksoft 0:8c643bfe55b7 468
jksoft 0:8c643bfe55b7 469 p_data_addr += m_round_val;
jksoft 0:8c643bfe55b7 470
jksoft 0:8c643bfe55b7 471 storage_addr += (p_cmd->offset + m_round_val);
jksoft 0:8c643bfe55b7 472
jksoft 0:8c643bfe55b7 473 size = p_cmd->size - m_round_val;
jksoft 0:8c643bfe55b7 474
jksoft 0:8c643bfe55b7 475 if (size < SOC_MAX_WRITE_SIZE)
jksoft 0:8c643bfe55b7 476 {
jksoft 0:8c643bfe55b7 477 retval = sd_flash_write(((uint32_t *)storage_addr),
jksoft 0:8c643bfe55b7 478 (uint32_t *)p_data_addr,
jksoft 0:8c643bfe55b7 479 size / sizeof(uint32_t));
jksoft 0:8c643bfe55b7 480 }
jksoft 0:8c643bfe55b7 481 else
jksoft 0:8c643bfe55b7 482 {
jksoft 0:8c643bfe55b7 483 retval = sd_flash_write(((uint32_t *)storage_addr),
jksoft 0:8c643bfe55b7 484 (uint32_t *)p_data_addr,
jksoft 0:8c643bfe55b7 485 SOC_MAX_WRITE_SIZE / sizeof(uint32_t));
jksoft 0:8c643bfe55b7 486 }
jksoft 0:8c643bfe55b7 487
jksoft 0:8c643bfe55b7 488
jksoft 0:8c643bfe55b7 489 if (retval == NRF_SUCCESS)
jksoft 0:8c643bfe55b7 490 {
jksoft 0:8c643bfe55b7 491 m_round_val += SOC_MAX_WRITE_SIZE;
jksoft 0:8c643bfe55b7 492 }
jksoft 0:8c643bfe55b7 493 }
jksoft 0:8c643bfe55b7 494 else
jksoft 0:8c643bfe55b7 495 {
jksoft 0:8c643bfe55b7 496 // Should never reach here.
jksoft 0:8c643bfe55b7 497 }
jksoft 0:8c643bfe55b7 498
jksoft 0:8c643bfe55b7 499 if (retval == NRF_SUCCESS)
jksoft 0:8c643bfe55b7 500 {
jksoft 0:8c643bfe55b7 501 m_cmd_queue.flash_access = true;
jksoft 0:8c643bfe55b7 502 }
jksoft 0:8c643bfe55b7 503
jksoft 0:8c643bfe55b7 504 return retval;
jksoft 0:8c643bfe55b7 505 }
jksoft 0:8c643bfe55b7 506 /** @} */
jksoft 0:8c643bfe55b7 507
jksoft 0:8c643bfe55b7 508
jksoft 0:8c643bfe55b7 509 /**
jksoft 0:8c643bfe55b7 510 * @brief Module initialization routine to be called once by the application.
jksoft 0:8c643bfe55b7 511 */
jksoft 0:8c643bfe55b7 512 uint32_t pstorage_init(void)
jksoft 0:8c643bfe55b7 513 {
jksoft 0:8c643bfe55b7 514 unsigned int index;
jksoft 0:8c643bfe55b7 515 cmd_queue_init();
jksoft 0:8c643bfe55b7 516
jksoft 0:8c643bfe55b7 517 m_next_app_instance = 0;
jksoft 0:8c643bfe55b7 518 m_next_page_addr = PSTORAGE_DATA_START_ADDR;
jksoft 0:8c643bfe55b7 519 m_round_val = 0;
jksoft 0:8c643bfe55b7 520
jksoft 0:8c643bfe55b7 521 for(index = 0; index < PSTORAGE_MAX_APPLICATIONS; index++)
jksoft 0:8c643bfe55b7 522 {
jksoft 0:8c643bfe55b7 523 m_app_table[index].cb = NULL;
jksoft 0:8c643bfe55b7 524 m_app_table[index].block_size = 0;
jksoft 0:8c643bfe55b7 525 m_app_table[index].no_of_pages = 0;
jksoft 0:8c643bfe55b7 526 m_app_table[index].block_count = 0;
jksoft 0:8c643bfe55b7 527 }
jksoft 0:8c643bfe55b7 528
jksoft 0:8c643bfe55b7 529 #ifdef PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 530 m_raw_app_table.cb = NULL;
jksoft 0:8c643bfe55b7 531 m_raw_app_table.no_of_pages = 0;
jksoft 0:8c643bfe55b7 532 #endif //PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 533
jksoft 0:8c643bfe55b7 534 m_module_initialized = true;
jksoft 0:8c643bfe55b7 535 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 536 }
jksoft 0:8c643bfe55b7 537
jksoft 0:8c643bfe55b7 538 /**
jksoft 0:8c643bfe55b7 539 * @brief Registration routine to request persistent memory of certain sizes based on
jksoft 0:8c643bfe55b7 540 * application module requirements.
jksoft 0:8c643bfe55b7 541 */
jksoft 0:8c643bfe55b7 542 uint32_t pstorage_register(pstorage_module_param_t * p_module_param,
jksoft 0:8c643bfe55b7 543 pstorage_handle_t * p_block_id)
jksoft 0:8c643bfe55b7 544 {
jksoft 0:8c643bfe55b7 545 uint16_t page_count;
jksoft 0:8c643bfe55b7 546 uint32_t total_size;
jksoft 0:8c643bfe55b7 547
jksoft 0:8c643bfe55b7 548 VERIFY_MODULE_INITIALIZED();
jksoft 0:8c643bfe55b7 549 NULL_PARAM_CHECK(p_module_param);
jksoft 0:8c643bfe55b7 550 NULL_PARAM_CHECK(p_block_id);
jksoft 0:8c643bfe55b7 551 NULL_PARAM_CHECK(p_module_param->cb);
jksoft 0:8c643bfe55b7 552 BLOCK_SIZE_CHECK(p_module_param->block_size);
jksoft 0:8c643bfe55b7 553 BLOCK_COUNT_CHECK(p_module_param->block_count, p_module_param->block_size);
jksoft 0:8c643bfe55b7 554
jksoft 0:8c643bfe55b7 555 if (m_next_app_instance == PSTORAGE_MAX_APPLICATIONS)
jksoft 0:8c643bfe55b7 556 {
jksoft 0:8c643bfe55b7 557 return NRF_ERROR_NO_MEM;
jksoft 0:8c643bfe55b7 558 }
jksoft 0:8c643bfe55b7 559
jksoft 0:8c643bfe55b7 560 p_block_id->module_id = m_next_app_instance;
jksoft 0:8c643bfe55b7 561 p_block_id->block_id = m_next_page_addr;
jksoft 0:8c643bfe55b7 562 m_app_table[m_next_app_instance].base_id = p_block_id->block_id;
jksoft 0:8c643bfe55b7 563 m_app_table[m_next_app_instance].cb = p_module_param->cb;
jksoft 0:8c643bfe55b7 564 m_app_table[m_next_app_instance].block_size = p_module_param->block_size;
jksoft 0:8c643bfe55b7 565 m_app_table[m_next_app_instance].block_count = p_module_param->block_count;
jksoft 0:8c643bfe55b7 566
jksoft 0:8c643bfe55b7 567 // Calculate number of flash pages allocated for the device.
jksoft 0:8c643bfe55b7 568 page_count = 0;
jksoft 0:8c643bfe55b7 569 total_size = p_module_param->block_size * p_module_param->block_count;
jksoft 0:8c643bfe55b7 570 do
jksoft 0:8c643bfe55b7 571 {
jksoft 0:8c643bfe55b7 572 page_count++;
jksoft 0:8c643bfe55b7 573 if (total_size > PSTORAGE_FLASH_PAGE_SIZE)
jksoft 0:8c643bfe55b7 574 {
jksoft 0:8c643bfe55b7 575 total_size -= PSTORAGE_FLASH_PAGE_SIZE;
jksoft 0:8c643bfe55b7 576 }
jksoft 0:8c643bfe55b7 577 else
jksoft 0:8c643bfe55b7 578 {
jksoft 0:8c643bfe55b7 579 total_size = 0;
jksoft 0:8c643bfe55b7 580 }
jksoft 0:8c643bfe55b7 581 m_next_page_addr += PSTORAGE_FLASH_PAGE_SIZE;
jksoft 0:8c643bfe55b7 582 }while(total_size >= PSTORAGE_FLASH_PAGE_SIZE);
jksoft 0:8c643bfe55b7 583
jksoft 0:8c643bfe55b7 584 m_app_table[m_next_app_instance].no_of_pages = page_count;
jksoft 0:8c643bfe55b7 585 m_next_app_instance++;
jksoft 0:8c643bfe55b7 586
jksoft 0:8c643bfe55b7 587 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 588 }
jksoft 0:8c643bfe55b7 589
jksoft 0:8c643bfe55b7 590
jksoft 0:8c643bfe55b7 591 /**
jksoft 0:8c643bfe55b7 592 * @brief API to get the next block identifier.
jksoft 0:8c643bfe55b7 593 */
jksoft 0:8c643bfe55b7 594 uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
jksoft 0:8c643bfe55b7 595 pstorage_size_t block_num,
jksoft 0:8c643bfe55b7 596 pstorage_handle_t * p_block_id)
jksoft 0:8c643bfe55b7 597 {
jksoft 0:8c643bfe55b7 598 pstorage_handle_t temp_id;
jksoft 0:8c643bfe55b7 599
jksoft 0:8c643bfe55b7 600 VERIFY_MODULE_INITIALIZED();
jksoft 0:8c643bfe55b7 601 NULL_PARAM_CHECK(p_base_id);
jksoft 0:8c643bfe55b7 602 NULL_PARAM_CHECK(p_block_id);
jksoft 0:8c643bfe55b7 603 MODULE_ID_RANGE_CHECK(p_base_id);
jksoft 0:8c643bfe55b7 604
jksoft 0:8c643bfe55b7 605 temp_id = (*p_base_id);
jksoft 0:8c643bfe55b7 606 temp_id.block_id += (block_num * MODULE_BLOCK_SIZE(p_base_id));
jksoft 0:8c643bfe55b7 607 BLOCK_ID_RANGE_CHECK(&temp_id);
jksoft 0:8c643bfe55b7 608 (*p_block_id) = temp_id;
jksoft 0:8c643bfe55b7 609
jksoft 0:8c643bfe55b7 610 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 611 }
jksoft 0:8c643bfe55b7 612
jksoft 0:8c643bfe55b7 613
jksoft 0:8c643bfe55b7 614 /**
jksoft 0:8c643bfe55b7 615 * @brief API to store data persistently.
jksoft 0:8c643bfe55b7 616 */
jksoft 0:8c643bfe55b7 617 uint32_t pstorage_store(pstorage_handle_t * p_dest,
jksoft 0:8c643bfe55b7 618 uint8_t * p_src,
jksoft 0:8c643bfe55b7 619 pstorage_size_t size,
jksoft 0:8c643bfe55b7 620 pstorage_size_t offset)
jksoft 0:8c643bfe55b7 621 {
jksoft 0:8c643bfe55b7 622 VERIFY_MODULE_INITIALIZED();
jksoft 0:8c643bfe55b7 623 NULL_PARAM_CHECK(p_src);
jksoft 0:8c643bfe55b7 624 NULL_PARAM_CHECK(p_dest);
jksoft 0:8c643bfe55b7 625 MODULE_ID_RANGE_CHECK (p_dest);
jksoft 0:8c643bfe55b7 626 BLOCK_ID_RANGE_CHECK(p_dest);
jksoft 0:8c643bfe55b7 627 SIZE_CHECK(p_dest,size);
jksoft 0:8c643bfe55b7 628 OFFSET_CHECK(p_dest,offset,size);
jksoft 0:8c643bfe55b7 629
jksoft 0:8c643bfe55b7 630 // Verify word alignment.
jksoft 0:8c643bfe55b7 631 if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset)))
jksoft 0:8c643bfe55b7 632 {
jksoft 0:8c643bfe55b7 633 return NRF_ERROR_INVALID_ADDR;
jksoft 0:8c643bfe55b7 634 }
jksoft 0:8c643bfe55b7 635
jksoft 0:8c643bfe55b7 636 return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
jksoft 0:8c643bfe55b7 637 }
jksoft 0:8c643bfe55b7 638
jksoft 0:8c643bfe55b7 639
jksoft 0:8c643bfe55b7 640 /**
jksoft 0:8c643bfe55b7 641 * @brief API to load data from persistent memory.
jksoft 0:8c643bfe55b7 642 */
jksoft 0:8c643bfe55b7 643 uint32_t pstorage_load(uint8_t * p_dest,
jksoft 0:8c643bfe55b7 644 pstorage_handle_t * p_src,
jksoft 0:8c643bfe55b7 645 pstorage_size_t size,
jksoft 0:8c643bfe55b7 646 pstorage_size_t offset)
jksoft 0:8c643bfe55b7 647 {
jksoft 0:8c643bfe55b7 648 VERIFY_MODULE_INITIALIZED();
jksoft 0:8c643bfe55b7 649 NULL_PARAM_CHECK(p_src);
jksoft 0:8c643bfe55b7 650 NULL_PARAM_CHECK(p_dest);
jksoft 0:8c643bfe55b7 651 MODULE_ID_RANGE_CHECK (p_src);
jksoft 0:8c643bfe55b7 652 BLOCK_ID_RANGE_CHECK(p_src);
jksoft 0:8c643bfe55b7 653 SIZE_CHECK(p_src,size);
jksoft 0:8c643bfe55b7 654 OFFSET_CHECK(p_src,offset,size);
jksoft 0:8c643bfe55b7 655
jksoft 0:8c643bfe55b7 656 // Verify word alignment.
jksoft 0:8c643bfe55b7 657 if ((!is_word_aligned (p_dest)) || (!is_word_aligned (p_dest + offset)))
jksoft 0:8c643bfe55b7 658 {
jksoft 0:8c643bfe55b7 659 return NRF_ERROR_INVALID_ADDR;
jksoft 0:8c643bfe55b7 660 }
jksoft 0:8c643bfe55b7 661
jksoft 0:8c643bfe55b7 662 memcpy (p_dest, (((uint8_t *)p_src->block_id) + offset), size);
jksoft 0:8c643bfe55b7 663
jksoft 0:8c643bfe55b7 664 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 665 }
jksoft 0:8c643bfe55b7 666
jksoft 0:8c643bfe55b7 667
jksoft 0:8c643bfe55b7 668 /**
jksoft 0:8c643bfe55b7 669 * @brief API to clear data in blocks of persistent memory.
jksoft 0:8c643bfe55b7 670 */
jksoft 0:8c643bfe55b7 671 uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
jksoft 0:8c643bfe55b7 672 {
jksoft 0:8c643bfe55b7 673 uint32_t retval;
jksoft 0:8c643bfe55b7 674 uint32_t pages;
jksoft 0:8c643bfe55b7 675
jksoft 0:8c643bfe55b7 676 VERIFY_MODULE_INITIALIZED();
jksoft 0:8c643bfe55b7 677 NULL_PARAM_CHECK(p_dest);
jksoft 0:8c643bfe55b7 678 MODULE_ID_RANGE_CHECK(p_dest);
jksoft 0:8c643bfe55b7 679 BLOCK_ID_RANGE_CHECK(p_dest);
jksoft 0:8c643bfe55b7 680
jksoft 0:8c643bfe55b7 681 pages = m_app_table[p_dest->module_id].no_of_pages;
jksoft 0:8c643bfe55b7 682
jksoft 0:8c643bfe55b7 683 retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL , pages , 0);
jksoft 0:8c643bfe55b7 684
jksoft 0:8c643bfe55b7 685 return retval;
jksoft 0:8c643bfe55b7 686 }
jksoft 0:8c643bfe55b7 687
jksoft 0:8c643bfe55b7 688
jksoft 0:8c643bfe55b7 689 #ifdef PSTORAGE_RAW_MODE_ENABLE
jksoft 0:8c643bfe55b7 690
jksoft 0:8c643bfe55b7 691 /**
jksoft 0:8c643bfe55b7 692 * @brief Registration routine to request persistent memory of certain sizes based on
jksoft 0:8c643bfe55b7 693 * application module requirements.
jksoft 0:8c643bfe55b7 694 */
jksoft 0:8c643bfe55b7 695 uint32_t pstorage_raw_register(pstorage_module_param_t * p_module_param,
jksoft 0:8c643bfe55b7 696 pstorage_handle_t * p_block_id)
jksoft 0:8c643bfe55b7 697 {
jksoft 0:8c643bfe55b7 698 VERIFY_MODULE_INITIALIZED();
jksoft 0:8c643bfe55b7 699 NULL_PARAM_CHECK(p_module_param);
jksoft 0:8c643bfe55b7 700 NULL_PARAM_CHECK(p_block_id);
jksoft 0:8c643bfe55b7 701 NULL_PARAM_CHECK(p_module_param->cb);
jksoft 0:8c643bfe55b7 702
jksoft 0:8c643bfe55b7 703 if (m_raw_app_table.cb != NULL)
jksoft 0:8c643bfe55b7 704 {
jksoft 0:8c643bfe55b7 705 return NRF_ERROR_NO_MEM;
jksoft 0:8c643bfe55b7 706 }
jksoft 0:8c643bfe55b7 707
jksoft 0:8c643bfe55b7 708 p_block_id->module_id = PSTORAGE_MAX_APPLICATIONS + 1;
jksoft 0:8c643bfe55b7 709 m_raw_app_table.cb = p_module_param->cb;
jksoft 0:8c643bfe55b7 710
jksoft 0:8c643bfe55b7 711 return NRF_SUCCESS;
jksoft 0:8c643bfe55b7 712 }
jksoft 0:8c643bfe55b7 713
jksoft 0:8c643bfe55b7 714
jksoft 0:8c643bfe55b7 715 /**
jksoft 0:8c643bfe55b7 716 * @brief API to store data persistently.
jksoft 0:8c643bfe55b7 717 */
jksoft 0:8c643bfe55b7 718 uint32_t pstorage_raw_store(pstorage_handle_t * p_dest,
jksoft 0:8c643bfe55b7 719 uint8_t * p_src,
jksoft 0:8c643bfe55b7 720 uint32_t size,
jksoft 0:8c643bfe55b7 721 uint32_t offset)
jksoft 0:8c643bfe55b7 722 {
jksoft 0:8c643bfe55b7 723 VERIFY_MODULE_INITIALIZED();
jksoft 0:8c643bfe55b7 724 NULL_PARAM_CHECK(p_src);
jksoft 0:8c643bfe55b7 725 NULL_PARAM_CHECK(p_dest);
jksoft 0:8c643bfe55b7 726 MODULE_RAW_ID_RANGE_CHECK(p_dest);
jksoft 0:8c643bfe55b7 727
jksoft 0:8c643bfe55b7 728 // Verify word alignment.
jksoft 0:8c643bfe55b7 729 if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset)))
jksoft 0:8c643bfe55b7 730 {
jksoft 0:8c643bfe55b7 731 return NRF_ERROR_INVALID_ADDR;
jksoft 0:8c643bfe55b7 732 }
jksoft 0:8c643bfe55b7 733
jksoft 0:8c643bfe55b7 734 return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
jksoft 0:8c643bfe55b7 735 }
jksoft 0:8c643bfe55b7 736
jksoft 0:8c643bfe55b7 737
jksoft 0:8c643bfe55b7 738 /**
jksoft 0:8c643bfe55b7 739 * @brief API to clear data in blocks of persistent memory.
jksoft 0:8c643bfe55b7 740 */
jksoft 0:8c643bfe55b7 741 uint32_t pstorage_raw_clear(pstorage_handle_t * p_dest, uint32_t size)
jksoft 0:8c643bfe55b7 742 {
jksoft 0:8c643bfe55b7 743 uint32_t retval;
jksoft 0:8c643bfe55b7 744 uint32_t pages;
jksoft 0:8c643bfe55b7 745
jksoft 0:8c643bfe55b7 746 VERIFY_MODULE_INITIALIZED();
jksoft 0:8c643bfe55b7 747 NULL_PARAM_CHECK(p_dest);
jksoft 0:8c643bfe55b7 748 MODULE_RAW_ID_RANGE_CHECK(p_dest);
jksoft 0:8c643bfe55b7 749
jksoft 0:8c643bfe55b7 750 retval = NRF_SUCCESS;
jksoft 0:8c643bfe55b7 751
jksoft 0:8c643bfe55b7 752 pages = CEIL_DIV(size, PSTORAGE_FLASH_PAGE_SIZE);
jksoft 0:8c643bfe55b7 753
jksoft 0:8c643bfe55b7 754 retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL , pages, 0);
jksoft 0:8c643bfe55b7 755
jksoft 0:8c643bfe55b7 756 return retval;
jksoft 0:8c643bfe55b7 757 }
jksoft 0:8c643bfe55b7 758
jksoft 0:8c643bfe55b7 759 #endif // PSTORAGE_RAW_MODE_ENABLE