AndroidのBLEラジコンプロポアプリ「BLEPropo」と接続し、RCサーボとDCモータを制御するプログラムです。 mbed HRM1017で動作を確認しています。 BLEPropo → https://github.com/lipoyang/BLEPropo

Dependencies:   BLE_API mbed

Fork of BLE_RCBController2 by Junichi Katsu

BLEを使ったAndroid用ラジコンプロポアプリ「BLEPropo」に対応するmbed HRM1017用ファームウェアです。
BLEPropoは、GitHubにて公開中。
https://github.com/lipoyang/BLEPropo
/media/uploads/lipoyang/blepropo_ui.png
ラジコンは、mbed HRM1017とRCサーボやDCモータを組み合わせて作ります。
/media/uploads/lipoyang/ble_wiring.png

Committer:
jksoft
Date:
Wed Aug 20 13:24:20 2014 +0000
Revision:
1:48f6e08a3ac2
2014.08.20?????BLE?????????????; ???mbed?????????????????; mbed HRM1017; Nordic nRF51822

Who changed what in which revision?

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