mbed HRM11017を使ってkonashi.jsでナイトライダー

Dependencies:   BLE_API_Native_IRC mbed

Fork of BLE_RCBController by Junichi Katsu

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pstorage.cpp Source File

pstorage.cpp

00001 /* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
00002  *
00003  * The information contained herein is property of Nordic Semiconductor ASA.
00004  * Terms and conditions of usage are described in detail in NORDIC
00005  * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
00006  *
00007  * Licensees are granted free, non-transferable use of the information. NO
00008  * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
00009  * the file.
00010  *
00011  */
00012 
00013 #include <stdlib.h>
00014 #include <stdint.h>
00015 #include <string.h>
00016 #include "nordic_common.h"
00017 #include "nrf_error.h"
00018 #include "nrf_assert.h"
00019 //#include "nrf.h"
00020 #include "nrf_soc.h"
00021 #include "app_util.h "
00022 #include "pstorage.h "
00023 
00024 
00025 #define INVALID_OPCODE              0x00                       /**< Invalid op code identifier. */
00026 #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. */
00027 
00028 /**
00029  * @defgroup api_param_check API Parameters check macros.
00030  *
00031  * @details Macros that verify parameters passed to the module in the APIs. These macros
00032  *          could be mapped to nothing in final versions of code to save execution and size.
00033  *
00034  * @{
00035  */
00036 /**
00037  * @brief Check if the input pointer is NULL, if it is returns NRF_ERROR_NULL.
00038  */
00039 #define NULL_PARAM_CHECK(PARAM)                                                                   \
00040         if ((PARAM) == NULL)                                                                      \
00041         {                                                                                         \
00042             return NRF_ERROR_NULL;                                                                \
00043         }
00044 
00045 /**
00046  * @brief Verifies the module identifier supplied by the application is within permissible
00047  *        range.
00048  */
00049 #define MODULE_ID_RANGE_CHECK(ID)                                                                 \
00050         if ((((ID)->module_id) >= PSTORAGE_MAX_APPLICATIONS) ||                                   \
00051             (m_app_table[(ID)->module_id].cb == NULL))                                            \
00052         {                                                                                         \
00053             return NRF_ERROR_INVALID_PARAM;                                                       \
00054         }
00055 
00056 /**
00057  * @brief Verifies the block identifier supplied by the application is within the permissible
00058  *        range.
00059  */
00060 #define BLOCK_ID_RANGE_CHECK(ID)                                                                  \
00061         if (((ID)->block_id) >= (m_app_table[(ID)->module_id].base_id +                           \
00062             (m_app_table[(ID)->module_id].block_count * MODULE_BLOCK_SIZE(ID))))                  \
00063         {                                                                                         \
00064             return NRF_ERROR_INVALID_PARAM;                                                       \
00065         }
00066 
00067 
00068 /**
00069  * @brief Verifies the block size requested by the application can be supported by the module. 
00070  */
00071 #define BLOCK_SIZE_CHECK(X)                                                                       \
00072         if (((X) > PSTORAGE_MAX_BLOCK_SIZE) || ((X) < PSTORAGE_MIN_BLOCK_SIZE))                   \
00073         {                                                                                         \
00074             return NRF_ERROR_INVALID_PARAM;                                                       \
00075         }
00076 
00077 /**
00078  * @brief Verifies block size requested by Application in registration API.
00079  */
00080 #define BLOCK_COUNT_CHECK(COUNT, SIZE)                                                            \
00081         if (((COUNT) == 0) || ((m_next_page_addr + ((COUNT) *(SIZE)) > PSTORAGE_DATA_END_ADDR)))  \
00082         {                                                                                         \
00083             return NRF_ERROR_INVALID_PARAM;                                                       \
00084         }
00085 
00086 /**
00087  * @brief Verifies size parameter provided by application in API.
00088  */
00089 #define SIZE_CHECK(ID, SIZE)                                                                      \
00090         if(((SIZE) == 0) || ((SIZE) > MODULE_BLOCK_SIZE(ID)))                                     \
00091         {                                                                                         \
00092             return NRF_ERROR_INVALID_PARAM;                                                       \
00093         }
00094 
00095 /**
00096  * @brief Verifies offset parameter provided by application in API.
00097  */
00098 #define OFFSET_CHECK(ID, OFFSET, SIZE)                                                            \
00099         if(((SIZE) + (OFFSET)) > MODULE_BLOCK_SIZE(ID))                                           \
00100         {                                                                                         \
00101             return NRF_ERROR_INVALID_PARAM;                                                       \
00102         }
00103 
00104 #ifdef PSTORAGE_RAW_MODE_ENABLE
00105 
00106 /**
00107  * @brief Verifies the module identifier supplied by the application is registered for raw mode.
00108  */
00109 #define MODULE_RAW_ID_RANGE_CHECK(ID)                                                             \
00110         if ((PSTORAGE_MAX_APPLICATIONS+1 != ((ID)->module_id)) ||                                 \
00111             (m_raw_app_table.cb == NULL))                                                         \
00112         {                                                                                         \
00113             return NRF_ERROR_INVALID_PARAM;                                                       \
00114         }
00115 
00116 #endif // PSTORAGE_RAW_MODE_ENABLE
00117 
00118 /**@} */
00119 
00120 /**@brief    Verify module's initialization status.
00121  *
00122  * @details   Verify module's initialization status. Returns NRF_ERROR_INVALID_STATE in case a
00123  *            module API is called without initializing the module.
00124  */
00125 #define VERIFY_MODULE_INITIALIZED()                                                               \
00126         do                                                                                        \
00127         {                                                                                         \
00128             if (!m_module_initialized)                                                            \
00129             {                                                                                     \
00130                  return NRF_ERROR_INVALID_STATE;                                                  \
00131             }                                                                                     \
00132         } while(0)
00133 
00134 /**@brief Macro to fetch the block size registered for the module. */
00135 #define MODULE_BLOCK_SIZE(ID) (m_app_table[(ID)->module_id].block_size)
00136 
00137 /**@} */
00138 
00139 /**
00140  * @brief Application registration information.
00141  *
00142  * @details Define application specific information that application needs to maintain to be able
00143  *          to process requests from each one of them.
00144  */
00145 typedef struct
00146 {
00147     pstorage_ntf_cb_t      cb;             /**< Callback registered with the module to be notified of result of flash access.  */
00148     pstorage_block_t       base_id;        /**< Base block id assigned to the module */
00149     pstorage_size_t        block_size;     /**< Size of block for the module */
00150     pstorage_size_t        block_count;    /**< Number of block requested by application */
00151     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. */    
00152 } pstorage_module_table_t;
00153 
00154 #ifdef PSTORAGE_RAW_MODE_ENABLE
00155 /**
00156  * @brief Application registration information.
00157  *
00158  * @details Define application specific information that application registered for raw mode.
00159  */
00160 typedef struct
00161 {
00162     pstorage_ntf_cb_t      cb;             /**< Callback registered with the module to be notified of result of flash access.  */
00163     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. */
00164 } pstorage_raw_module_table_t;
00165 #endif // PSTORAGE_RAW_MODE_ENABLE
00166 
00167 
00168 
00169 
00170 /**
00171  * @brief Defines command queue element.
00172  *
00173  * @details Defines command queue element. Each element encapsulates needed information to process
00174  *          a flash access command.
00175  */
00176 typedef struct
00177 {
00178     uint8_t              op_code;          /**< Identifies flash access operation being queued. Element is free is op-code is INVALID_OPCODE */
00179     pstorage_size_t      size;             /**< Identifies size in bytes requested for the operation. */
00180     pstorage_size_t      offset;           /**< Offset requested by the application for access operation. */    
00181     pstorage_handle_t    storage_addr;     /**< Address/Identifier for persistent memory. */
00182     uint8_t              * p_data_addr;    /**< Address/Identifier for data memory. This is assumed to be resident memory. */    
00183 } cmd_queue_element_t;
00184 
00185 
00186 /**
00187  * @brief Defines command queue, an element is free is op_code field is not invalid.
00188  *
00189  * @details Defines commands enqueued for flash access. At any point of time, this queue has one or
00190  *          more flash access operation pending if the count field is not zero. When the queue is
00191  *          not empty, the rp (read pointer) field points to the flash access command in progress
00192  *          or to requested next. The queue implements a simple first in first out algorithm.
00193  *          Data addresses are assumed to be resident.
00194  */
00195 typedef struct
00196 {
00197     uint8_t              rp;                              /**< Read pointer, pointing to flash access that is ongoing or to be requested next. */
00198     uint8_t              count;                           /**< Number of elements in the queue.  */
00199     bool                 flash_access;                    /**< Flag to ensure an flash event received is for an request issued by the module. */
00200     cmd_queue_element_t  cmd[PSTORAGE_CMD_QUEUE_SIZE];    /**< Array to maintain flash access operation details */
00201 }cmd_queue_t;
00202 
00203 static cmd_queue_t             m_cmd_queue;                               /**< Flash operation request queue. */
00204 static pstorage_module_table_t m_app_table[PSTORAGE_MAX_APPLICATIONS];    /**< Registered application information table. */
00205 
00206 #ifdef PSTORAGE_RAW_MODE_ENABLE
00207 static pstorage_raw_module_table_t m_raw_app_table;      /**< Registered application information table for raw mode. */
00208 #endif // PSTORAGE_RAW_MODE_ENABLE
00209 
00210 static pstorage_size_t  m_next_app_instance;             /**< Points to the application module instance that can be allocated next */
00211 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. */
00212 static bool             m_module_initialized = false;    /**< Flag for checking if module has been initialized. */
00213 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. */
00214 
00215 static uint32_t process_cmd(void);
00216 static void app_notify (uint32_t reason);
00217 
00218 /**
00219  * @defgroup utility_functions Utility internal functions.
00220  * @{
00221  * @details Utility functions needed for interfacing with flash through SoC APIs.
00222  * SoC APIs are non blocking and provide the result of flash access through an event.
00223  *
00224  * @note Only one flash access operation is permitted at a time by SoC. Hence a queue is
00225  * maintained by this module.
00226  */
00227  
00228 /**
00229  * @brief Initializes command queue element.
00230  */
00231 static void cmd_queue_init_element(uint32_t index)
00232 {
00233     // Internal function and checks on range of index can be avoided
00234     m_cmd_queue.cmd[index].op_code                = INVALID_OPCODE;
00235     m_cmd_queue.cmd[index].size                   = 0;
00236     m_cmd_queue.cmd[index].storage_addr.module_id = PSTORAGE_MAX_APPLICATIONS;
00237     m_cmd_queue.cmd[index].storage_addr.block_id  = 0;
00238     m_cmd_queue.cmd[index].p_data_addr            = NULL;
00239     m_cmd_queue.cmd[index].offset                 = 0;
00240 }
00241 
00242 
00243 /**
00244  * @brief Initializes command queue.
00245  */
00246 static void cmd_queue_init (void)
00247 {
00248     uint32_t cmd_index;
00249 
00250     m_round_val              = 0;
00251     m_cmd_queue.rp           = 0;
00252     m_cmd_queue.count        = 0;
00253     m_cmd_queue.flash_access = false;
00254 
00255     for(cmd_index = 0; cmd_index < PSTORAGE_CMD_QUEUE_SIZE; cmd_index++)
00256     {
00257         cmd_queue_init_element(cmd_index);
00258     }
00259 }
00260 
00261 
00262 /**
00263  * @brief Routine to enqueue a flash access operation.
00264  */
00265 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)
00266 {
00267     uint32_t retval;
00268     uint8_t  write_index = 0;
00269     retval = NRF_ERROR_NO_MEM;
00270 
00271     // Check if flash access is ongoing.
00272     if ((m_cmd_queue.flash_access == false) && (m_cmd_queue.count == 0))
00273     {
00274         m_cmd_queue.rp = 0;
00275         m_cmd_queue.cmd[m_cmd_queue.rp].op_code      = opcode;
00276         m_cmd_queue.cmd[m_cmd_queue.rp].p_data_addr  = p_data_addr;
00277         m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr = (*p_storage_addr);
00278         m_cmd_queue.cmd[m_cmd_queue.rp].size         = size;
00279         m_cmd_queue.cmd[m_cmd_queue.rp].offset       = offset;
00280         m_cmd_queue.count++;
00281         retval = process_cmd();
00282         if ((retval == NRF_SUCCESS) || (retval == NRF_ERROR_BUSY))
00283         {
00284             // In case of busy error code, it is possible to attempt to access flash
00285             retval = NRF_SUCCESS;
00286         }
00287     }
00288     else if (m_cmd_queue.count != PSTORAGE_CMD_QUEUE_SIZE)
00289     {
00290         // Enqueue the command if it is queue is not full
00291         write_index = m_cmd_queue.rp + m_cmd_queue.count;
00292 
00293         if (write_index >= PSTORAGE_CMD_QUEUE_SIZE)
00294         {
00295             write_index -= PSTORAGE_CMD_QUEUE_SIZE;
00296         }
00297 
00298         m_cmd_queue.cmd[write_index].op_code      = opcode;
00299         m_cmd_queue.cmd[write_index].p_data_addr  = p_data_addr;
00300         m_cmd_queue.cmd[write_index].storage_addr = (*p_storage_addr);
00301         m_cmd_queue.cmd[write_index].size         = size;
00302         m_cmd_queue.cmd[write_index].offset       = offset;
00303         m_cmd_queue.count++;
00304 
00305         retval = NRF_SUCCESS;
00306 
00307     }
00308 
00309     return retval;
00310 }
00311 
00312 
00313 /**
00314  * @brief Dequeues a command element.
00315  */
00316 static uint32_t cmd_queue_dequeue(void)
00317 {
00318     uint32_t retval;    
00319 
00320     cmd_queue_element_t * p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
00321     // Update count and read pointer to process any queued requests
00322     if(m_round_val >= p_cmd->size)
00323     {
00324         // Initialize/free the element as it is now processed.
00325         cmd_queue_init_element(m_cmd_queue.rp);
00326         m_round_val = 0;
00327         m_cmd_queue.count--;
00328         m_cmd_queue.rp++;
00329     }
00330 
00331     retval = NRF_SUCCESS;
00332 
00333     // If any flash operation is enqueued, schedule
00334     if (m_cmd_queue.count)
00335     {
00336         retval = process_cmd();
00337 
00338         if (retval != NRF_SUCCESS)
00339         {
00340             // Flash could be accessed by modules other than Bond Manager, hence a busy error is
00341             // acceptable, but any other error needs to be indicated to the bond manager
00342             if (retval != NRF_ERROR_BUSY)
00343             {
00344                 app_notify (retval);
00345             }
00346             else
00347             {
00348                 // In case of busy next trigger will be a success or a failure event
00349             }
00350         }
00351     }
00352     else
00353     {
00354         // No flash access request pending
00355     }
00356 
00357     return retval;
00358 }
00359 
00360 
00361 /**
00362  * @brief Routine to notify application of any errors.
00363  */
00364 static void app_notify (uint32_t result)
00365 {
00366     pstorage_ntf_cb_t  ntf_cb;
00367     uint8_t            op_code = m_cmd_queue.cmd[m_cmd_queue.rp].op_code;
00368     
00369 #ifdef PSTORAGE_RAW_MODE_ENABLE
00370     if(m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr.module_id == (PSTORAGE_MAX_APPLICATIONS + 1))
00371     {
00372         ntf_cb = m_raw_app_table.cb;
00373     }
00374     else
00375 #endif // PSTORAGE_RAW_MODE_ENABLE
00376     {
00377         ntf_cb = m_app_table[m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr.module_id].cb;
00378     }
00379 
00380     // Indicate result to client.
00381     // For PSTORAGE_CLEAR_OP_CODE no size is returned as the size field is used only internally 
00382     // for clients registering multiple pages.
00383     ntf_cb(&m_cmd_queue.cmd[m_cmd_queue.rp].storage_addr,
00384            op_code,
00385            result,
00386            m_cmd_queue.cmd[m_cmd_queue.rp].p_data_addr,
00387            op_code == PSTORAGE_CLEAR_OP_CODE ? 0 : m_cmd_queue.cmd[m_cmd_queue.rp].size);
00388 }
00389 
00390 
00391 /**
00392  * @brief Handles Flash Access Result Events.
00393  */
00394 void pstorage_sys_event_handler (uint32_t sys_evt)
00395 {
00396     uint32_t retval;
00397 
00398     retval = NRF_SUCCESS;
00399 
00400     // Its possible the flash access was not initiated by bond manager, hence
00401     // event is processed only if the event triggered was for an operation requested by the
00402     // bond manager.
00403     if (m_cmd_queue.flash_access == true)
00404     {
00405         cmd_queue_element_t * p_cmd;
00406         m_cmd_queue.flash_access = false;
00407         switch (sys_evt)
00408         {
00409             case NRF_EVT_FLASH_OPERATION_SUCCESS:
00410                 p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
00411                 if ((p_cmd->op_code != PSTORAGE_CLEAR_OP_CODE) || (m_round_val >= p_cmd->size))
00412                 {
00413                     app_notify(retval);
00414                 }
00415                 // Schedule any queued flash access operations
00416                 retval = cmd_queue_dequeue ();
00417                 if (retval != NRF_SUCCESS)
00418                 {
00419                     app_notify(retval);
00420                 }
00421 
00422                 break;
00423             case NRF_EVT_FLASH_OPERATION_ERROR:
00424                 app_notify(NRF_ERROR_TIMEOUT);
00425                 break;
00426             default:
00427                 // No implementation needed.
00428                 break;
00429         }
00430     }
00431 }
00432 
00433 
00434 /**
00435  * @brief Routine called to actually issue the flash access request to the SoftDevice.
00436  */
00437 static uint32_t process_cmd(void)
00438 {
00439     uint32_t             retval;
00440     uint32_t             storage_addr;
00441     cmd_queue_element_t * p_cmd;
00442 
00443     retval = NRF_ERROR_FORBIDDEN;
00444 
00445     p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
00446 
00447     storage_addr = p_cmd->storage_addr.block_id;
00448 
00449     if (p_cmd->op_code == PSTORAGE_CLEAR_OP_CODE)
00450     {
00451         // Calculate page number before copy.
00452         uint32_t page_number;
00453 
00454         page_number =  ((storage_addr / PSTORAGE_FLASH_PAGE_SIZE) +
00455                         m_round_val);
00456 
00457         retval = sd_flash_page_erase(page_number);
00458 
00459         if (NRF_SUCCESS == retval)
00460         {
00461             m_round_val++;
00462         }
00463     }
00464     else if (p_cmd->op_code == PSTORAGE_STORE_OP_CODE)
00465     {
00466         uint32_t size;
00467         uint8_t * p_data_addr = p_cmd->p_data_addr;
00468     
00469         p_data_addr += m_round_val;
00470         
00471         storage_addr += (p_cmd->offset + m_round_val);
00472         
00473         size = p_cmd->size - m_round_val;
00474         
00475         if (size < SOC_MAX_WRITE_SIZE)
00476         {
00477             retval = sd_flash_write(((uint32_t *)storage_addr),
00478                                      (uint32_t *)p_data_addr,
00479                                      size / sizeof(uint32_t));
00480         }
00481         else
00482         {
00483             retval = sd_flash_write(((uint32_t *)storage_addr),
00484                                      (uint32_t *)p_data_addr,
00485                                      SOC_MAX_WRITE_SIZE / sizeof(uint32_t));
00486         }
00487         
00488 
00489         if (retval == NRF_SUCCESS)
00490         {
00491             m_round_val += SOC_MAX_WRITE_SIZE;
00492         }
00493     }
00494     else
00495     {
00496         // Should never reach here.
00497     }
00498     
00499     if (retval == NRF_SUCCESS)
00500     {
00501        m_cmd_queue.flash_access = true;
00502     }
00503 
00504     return retval;
00505 }
00506 /** @} */
00507 
00508 
00509 /**
00510  * @brief Module initialization routine to be called once by the application.
00511  */
00512 uint32_t pstorage_init(void)
00513 {
00514     unsigned int index;
00515     cmd_queue_init();
00516     
00517     m_next_app_instance = 0;
00518     m_next_page_addr    = PSTORAGE_DATA_START_ADDR;    
00519     m_round_val         = 0;
00520 
00521     for(index = 0; index < PSTORAGE_MAX_APPLICATIONS; index++)
00522     {
00523         m_app_table[index].cb          = NULL;
00524         m_app_table[index].block_size  = 0;
00525         m_app_table[index].no_of_pages = 0;
00526         m_app_table[index].block_count = 0;
00527     }
00528 
00529 #ifdef PSTORAGE_RAW_MODE_ENABLE
00530     m_raw_app_table.cb          = NULL;
00531     m_raw_app_table.no_of_pages = 0;
00532 #endif //PSTORAGE_RAW_MODE_ENABLE
00533     
00534     m_module_initialized = true;
00535     return NRF_SUCCESS;
00536 }
00537 
00538 /**
00539  * @brief Registration routine to request persistent memory of certain sizes based on
00540  *        application module requirements.
00541  */
00542 uint32_t pstorage_register(pstorage_module_param_t * p_module_param,
00543                            pstorage_handle_t       * p_block_id)
00544 {
00545     uint16_t page_count;
00546     uint32_t total_size;
00547 
00548     VERIFY_MODULE_INITIALIZED();
00549     NULL_PARAM_CHECK(p_module_param);
00550     NULL_PARAM_CHECK(p_block_id);
00551     NULL_PARAM_CHECK(p_module_param->cb);
00552     BLOCK_SIZE_CHECK(p_module_param->block_size);
00553     BLOCK_COUNT_CHECK(p_module_param->block_count, p_module_param->block_size);
00554 
00555     if (m_next_app_instance == PSTORAGE_MAX_APPLICATIONS)
00556     {
00557         return NRF_ERROR_NO_MEM;
00558     }
00559 
00560     p_block_id->module_id = m_next_app_instance;
00561     p_block_id->block_id = m_next_page_addr;
00562     m_app_table[m_next_app_instance].base_id = p_block_id->block_id;
00563     m_app_table[m_next_app_instance].cb = p_module_param->cb;
00564     m_app_table[m_next_app_instance].block_size = p_module_param->block_size;
00565     m_app_table[m_next_app_instance].block_count = p_module_param->block_count;
00566 
00567     // Calculate number of flash pages allocated for the device.
00568     page_count = 0;
00569     total_size = p_module_param->block_size * p_module_param->block_count;
00570     do
00571     {
00572         page_count++;
00573         if (total_size > PSTORAGE_FLASH_PAGE_SIZE)
00574         {
00575             total_size -= PSTORAGE_FLASH_PAGE_SIZE;
00576         }
00577         else
00578         {
00579             total_size = 0;
00580         }
00581         m_next_page_addr += PSTORAGE_FLASH_PAGE_SIZE;
00582     }while(total_size >= PSTORAGE_FLASH_PAGE_SIZE);
00583 
00584     m_app_table[m_next_app_instance].no_of_pages = page_count;
00585     m_next_app_instance++;
00586 
00587     return NRF_SUCCESS;
00588 }
00589 
00590 
00591 /**
00592  * @brief API to get the next block identifier.
00593  */
00594 uint32_t pstorage_block_identifier_get(pstorage_handle_t * p_base_id,
00595                                        pstorage_size_t   block_num,
00596                                        pstorage_handle_t * p_block_id)
00597 {
00598     pstorage_handle_t temp_id;
00599 
00600     VERIFY_MODULE_INITIALIZED();
00601     NULL_PARAM_CHECK(p_base_id);
00602     NULL_PARAM_CHECK(p_block_id);
00603     MODULE_ID_RANGE_CHECK(p_base_id);
00604 
00605     temp_id = (*p_base_id);
00606     temp_id.block_id += (block_num * MODULE_BLOCK_SIZE(p_base_id));
00607     BLOCK_ID_RANGE_CHECK(&temp_id);
00608     (*p_block_id) = temp_id;
00609 
00610     return NRF_SUCCESS;
00611 }
00612 
00613 
00614 /**
00615  * @brief API to store data persistently.
00616  */
00617 uint32_t pstorage_store(pstorage_handle_t * p_dest,
00618                         uint8_t           * p_src,
00619                         pstorage_size_t     size,
00620                         pstorage_size_t     offset)
00621 {
00622     VERIFY_MODULE_INITIALIZED();
00623     NULL_PARAM_CHECK(p_src);
00624     NULL_PARAM_CHECK(p_dest);
00625     MODULE_ID_RANGE_CHECK (p_dest);
00626     BLOCK_ID_RANGE_CHECK(p_dest);
00627     SIZE_CHECK(p_dest,size);
00628     OFFSET_CHECK(p_dest,offset,size);
00629 
00630     // Verify word alignment.
00631     if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset)))
00632     {
00633         return NRF_ERROR_INVALID_ADDR;
00634     }
00635 
00636     return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
00637 }
00638 
00639 
00640 /**
00641  * @brief API to load data from persistent memory.
00642  */
00643 uint32_t pstorage_load(uint8_t           * p_dest,
00644                        pstorage_handle_t * p_src,
00645                        pstorage_size_t     size,
00646                        pstorage_size_t     offset)
00647 {
00648     VERIFY_MODULE_INITIALIZED();
00649     NULL_PARAM_CHECK(p_src);
00650     NULL_PARAM_CHECK(p_dest);
00651     MODULE_ID_RANGE_CHECK (p_src);
00652     BLOCK_ID_RANGE_CHECK(p_src);
00653     SIZE_CHECK(p_src,size);
00654     OFFSET_CHECK(p_src,offset,size);
00655 
00656     // Verify word alignment.
00657     if ((!is_word_aligned (p_dest)) || (!is_word_aligned (p_dest + offset)))
00658     {
00659         return NRF_ERROR_INVALID_ADDR;
00660     }
00661 
00662     memcpy (p_dest, (((uint8_t *)p_src->block_id) + offset), size);
00663 
00664     return NRF_SUCCESS;
00665 }
00666 
00667 
00668 /**
00669  * @brief API to clear data in blocks of persistent memory.
00670  */
00671 uint32_t pstorage_clear(pstorage_handle_t * p_dest, pstorage_size_t size)
00672 {
00673     uint32_t retval;
00674     uint32_t pages;
00675 
00676     VERIFY_MODULE_INITIALIZED();
00677     NULL_PARAM_CHECK(p_dest);
00678     MODULE_ID_RANGE_CHECK(p_dest);
00679     BLOCK_ID_RANGE_CHECK(p_dest);
00680 
00681     pages = m_app_table[p_dest->module_id].no_of_pages;
00682 
00683     retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL , pages , 0);
00684 
00685     return retval;
00686 }
00687 
00688 
00689 #ifdef PSTORAGE_RAW_MODE_ENABLE
00690 
00691 /**
00692  * @brief Registration routine to request persistent memory of certain sizes based on 
00693  *        application module requirements.
00694  */
00695 uint32_t pstorage_raw_register(pstorage_module_param_t * p_module_param,
00696                                pstorage_handle_t       * p_block_id)
00697 {
00698     VERIFY_MODULE_INITIALIZED();
00699     NULL_PARAM_CHECK(p_module_param);
00700     NULL_PARAM_CHECK(p_block_id);
00701     NULL_PARAM_CHECK(p_module_param->cb);
00702 
00703     if (m_raw_app_table.cb != NULL)
00704     {
00705         return NRF_ERROR_NO_MEM;
00706     }
00707 
00708     p_block_id->module_id = PSTORAGE_MAX_APPLICATIONS + 1;
00709     m_raw_app_table.cb    = p_module_param->cb;
00710 
00711     return NRF_SUCCESS;
00712 }
00713 
00714 
00715 /**
00716  * @brief API to store data persistently.
00717  */
00718 uint32_t pstorage_raw_store(pstorage_handle_t * p_dest,
00719                             uint8_t           * p_src,
00720                             uint32_t            size,
00721                             uint32_t            offset)
00722 {
00723     VERIFY_MODULE_INITIALIZED();
00724     NULL_PARAM_CHECK(p_src);
00725     NULL_PARAM_CHECK(p_dest);
00726     MODULE_RAW_ID_RANGE_CHECK(p_dest);
00727 
00728     // Verify word alignment.
00729     if ((!is_word_aligned(p_src)) || (!is_word_aligned(p_src+offset)))
00730     {
00731         return NRF_ERROR_INVALID_ADDR;
00732     }
00733 
00734     return cmd_queue_enqueue(PSTORAGE_STORE_OP_CODE, p_dest, p_src, size, offset);
00735 }
00736 
00737 
00738 /**
00739  * @brief API to clear data in blocks of persistent memory.
00740  */
00741 uint32_t pstorage_raw_clear(pstorage_handle_t * p_dest, uint32_t size)
00742 {
00743     uint32_t retval;
00744     uint32_t pages;
00745 
00746     VERIFY_MODULE_INITIALIZED();
00747     NULL_PARAM_CHECK(p_dest);
00748     MODULE_RAW_ID_RANGE_CHECK(p_dest);
00749 
00750     retval = NRF_SUCCESS;
00751 
00752     pages = CEIL_DIV(size, PSTORAGE_FLASH_PAGE_SIZE);
00753     
00754     retval = cmd_queue_enqueue(PSTORAGE_CLEAR_OP_CODE, p_dest, NULL , pages, 0);
00755 
00756     return retval;
00757 }
00758 
00759 #endif // PSTORAGE_RAW_MODE_ENABLE