joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers flash_journal.h Source File

flash_journal.h

00001 /*
00002  * Copyright (c) 2006-2016, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #ifndef __FLASH_JOURNAL_H__
00019 #define __FLASH_JOURNAL_H__
00020 
00021 #ifdef __cplusplus
00022 extern "C" {
00023 #endif // __cplusplus
00024 
00025 #include "storage_abstraction/Driver_Storage.h"
00026 #include <stdint.h>
00027 
00028 /**
00029  * General return codes. All Flash-Journal APIs return an int32_t to allow for
00030  * both error and success status returns. This enumeration contains all
00031  * possible error status values.
00032  */
00033 typedef enum _FlashJournal_Status
00034 {
00035     JOURNAL_STATUS_OK                =   0,
00036     JOURNAL_STATUS_ERROR             =  -1, ///< Unspecified error
00037     JOURNAL_STATUS_BUSY              =  -2, ///< Underlying storage is currently unavailable
00038     JOURNAL_STATUS_TIMEOUT           =  -3, ///< Timeout occurred
00039     JOURNAL_STATUS_UNSUPPORTED       =  -4, ///< Operation not supported
00040     JOURNAL_STATUS_PARAMETER         =  -5, ///< Parameter error
00041     JOURNAL_STATUS_BOUNDED_CAPACITY  =  -6, ///< Attempt to write larger than available capacity
00042     JOURNAL_STATUS_STORAGE_API_ERROR =  -7, ///< Failure from some Storage API
00043     JOURNAL_STATUS_STORAGE_IO_ERROR  =  -8, ///< Failure from underlying storage during an IO operation.
00044     JOURNAL_STATUS_NOT_INITIALIZED   =  -9, ///< journal not initialized
00045     JOURNAL_STATUS_EMPTY             = -10, ///< There is no further data to read
00046     JOURNAL_STATUS_SMALL_LOG_REQUEST = -11, ///< log request is smaller than the program_unit of the underlying MTD block.
00047 } FlashJournal_Status_t;
00048 
00049 /**
00050  * Command opcodes for flash. Completion callbacks use these codes to refer to
00051  * completing commands. Refer to \ref ARM_Flash_Callback_t.
00052  */
00053 typedef enum _FlashJournal_OpCode {
00054     FLASH_JOURNAL_OPCODE_INITIALIZE,
00055     FLASH_JOURNAL_OPCODE_GET_INFO,
00056     FLASH_JOURNAL_OPCODE_READ_BLOB,
00057     FLASH_JOURNAL_OPCODE_LOG_BLOB,
00058     FLASH_JOURNAL_OPCODE_COMMIT,
00059     FLASH_JOURNAL_OPCODE_RESET,
00060 } FlashJournal_OpCode_t;
00061 
00062 /**
00063  * @brief Flash Journal information. This contains journal-metadata, and is the
00064  *     return value from calling GetInfo() on the journal driver.
00065  */
00066 typedef struct _FlashJournal_Info {
00067     uint64_t capacity;             ///< Maximum capacity (in octets) of the flash journal--i.e. the largest 'blob' which can be contained as payload.
00068     uint64_t sizeofJournaledBlob;  ///< size (in octets) of the most recently logged blob.
00069     uint32_t program_unit;         ///< Minimum programming size (in units of octets) for
00070                                    ///<   the current storage block--the one which will be used
00071                                    ///<   for the next log() operation. This value may change as we
00072                                    ///<   cycle through the blocks of the underlying MTD.
00073                                    ///<   Callers of FlashJournal_log() should refer to this field
00074                                    ///<   upon receiving the error JOURNAL_STATUS_SMALL_LOG_REQUEST
00075                                    ///<   (of when the actual amount of data logged is smaller than
00076                                    ///<   the requested amount).
00077 } FlashJournal_Info_t;
00078 
00079 /**
00080  * This is the type of the command completion callback handler for the
00081  * asynchronous flash-journal APIs: initialize(), read(), log(), commit() and
00082  * reset() (which is nearly all APIs).
00083  *
00084  * @param status
00085  *          A code to indicate the status of the completed operation. For data
00086  *          transfer operations, the status field is overloaded in case of
00087  *          success to return the amount of data successfully transferred; this
00088  *          can be done safely because error codes are negative values.
00089  *
00090  * @param cmd_code
00091  *          The command op-code of type FlashJournal_OpCode_t. This value isn't
00092  *          essential for the callback, but it is expected that this information
00093  *          could be a quick and useful filter.
00094  */
00095 typedef void (*FlashJournal_Callback_t)(int32_t status, FlashJournal_OpCode_t cmd_code);
00096 
00097 /* forward declarations. */
00098 typedef struct _FlashJournal_t FlashJournal_t;
00099 typedef struct _FlashJournal_Ops_t FlashJournal_Ops_t;
00100 
00101 /**
00102  * @ref FlashJournal_t is an abstraction implemented by a table of generic
00103  * operations (i.e. strategy) together with an opaque, strategy-specific
00104  * data. Taken together, the FlashJournal_t is an opaque handle containing
00105  * such top-level metadata.
00106  *
00107  * Algorithms depending on the FlashJournal can be generic (i.e. independent of
00108  * the strategy) in their use of the Flash-Journal APIs. For the sake of being
00109  * able to allocate a FlashJournal_t for use in such generic algorithms, the
00110  * FlashJournal_t contains a MAX_SIZE to accommodate the largest of the
00111  * strategy-specific metadata. The value of this MAX_SIZE may need to be
00112  * increased if some future journal-strategy needs more metadata.
00113  */
00114 #define FLASH_JOURNAL_HANDLE_MAX_SIZE 140
00115 
00116 /**
00117  * This is the set of operations offered by the flash-journal abstraction. A set
00118  * of implementations for these operations defines a logging strategy.
00119  */
00120 typedef struct _FlashJournal_Ops_t {
00121     /**
00122      * \brief Initialize the flash journal. Refer to @ref FlashJournal_initialize.
00123      */
00124     int32_t               (*initialize)(FlashJournal_t *journal, ARM_DRIVER_STORAGE *mtd, const FlashJournal_Ops_t *ops, FlashJournal_Callback_t callback);
00125 
00126     /**
00127      * \brief fetch journal metadata. Refer to @ref FlashJournal_getInfo.
00128      */
00129     FlashJournal_Status_t (*getInfo)   (FlashJournal_t *journal, FlashJournal_Info_t *info);
00130 
00131     /**
00132      * @brief Read from the most recently logged blob. Refer to @ref FlashJournal_read.
00133      */
00134     int32_t               (*read)      (FlashJournal_t *journal, void *buffer, size_t size);
00135 
00136     /**
00137      * @brief Start logging a new blob or append to the one currently being logged. Refer to @ref FlashJournal_log.
00138      */
00139     int32_t               (*log)       (FlashJournal_t *journal, const void *blob, size_t size);
00140 
00141     /**
00142      * @brief commit a blob accumulated through a non-empty sequence of
00143      *     previously successful log() operations. Refer to @ref FlashJournal_commit.
00144      */
00145     int32_t               (*commit)    (FlashJournal_t *journal);
00146 
00147     /**
00148      * @brief Reset the journal. This has the effect of erasing all valid blobs.
00149      *     Refer to @ref FlashJournal_reset.
00150      */
00151     int32_t               (*reset)     (FlashJournal_t *journal);
00152 } FlashJournal_Ops_t;
00153 
00154 /**
00155  * @brief An opaque handle constituting the Flash Journal.
00156  *
00157  * @details This structure is intentionally opaque to avoid exposing data
00158  *     internal to an implementation strategy; this prevents accesses through any
00159  *     means other than through the defined API.
00160  *
00161  * Having a known size for the handle allows the caller to remain malloc-free.
00162  *
00163  * @note: There should be static asserts in the code to verify our assumption
00164  * that the real FlashJournal handle fits within FLASH_JOURNAL_HANDLE_MAX_SIZE
00165  * bytes.
00166  *
00167  * @note: there is a risk of overallocation in case an implementation doesn't
00168  * need FLASH_JOURNAL_HANDLE_MAX_SIZE bytes, but the impact should be small.
00169  */
00170 typedef struct _FlashJournal_t {
00171     FlashJournal_Ops_t       ops;
00172 
00173     union {
00174         ARM_DRIVER_STORAGE  *mtd;
00175         FlashJournal_Info_t  info;
00176         void                *pointer;
00177         uint8_t              octet;
00178         uint32_t             data[FLASH_JOURNAL_HANDLE_MAX_SIZE / sizeof(uint32_t)];
00179     } opaque;
00180 } FlashJournal_t;
00181 
00182 /**
00183  * @brief Initialize a flash journal.
00184  *
00185  * This is a front-end for @ref FlashJournal_Ops_t::initialize() of the
00186  * underlying strategy.
00187  *
00188  * This function must be called *before* the middle-ware component starts
00189  * using a journal. As a part of bringing the journal to a ready state, it
00190  * also discovers the most recently logged blob.
00191  *
00192  * Initialize() receives a callback handler to be invoked upon completion of
00193  * asynchronous operations.
00194  *
00195  * @param [out] journal
00196  *                A caller-supplied buffer large enough to hold an
00197  *                initialized journal. The internals of the actual journal
00198  *                are opaque to the caller and depend on the logging
00199  *                strategy (as defined by the parameter 'ops'). This memory
00200  *                should be at least as large as 'FLASH_JOURNAL_HANDLE_MAX_SIZE'.
00201  *                Upon successful return, the journal is setup in an
00202  *                initialized state.
00203  *
00204  * @param  [in] mtd
00205  *                The underlying Storage_Driver targeted by the journal. MTD
00206  *                stands for Memory-Technology-Device.
00207  *
00208  * @param  [in] ops
00209  *                This is the set of operations which define the logging strategy.
00210  *
00211  * @param  [in] callback
00212  *                Caller-defined callback to be invoked upon command completion of
00213  *                initialization; and also for all future invocations of
00214  *                asynchronous APIs. Use a NULL pointer when no
00215  *                callback signals are required.
00216  *
00217  * @note: this is an asynchronous operation, but it can finish
00218  * synchronously if the underlying MTD supports that.
00219  *
00220  * @return
00221  *   The function executes in the following ways:
00222  *   - When the operation is asynchronous, the function only starts the
00223  *     initialization and control returns to the caller with an
00224  *     JOURNAL_STATUS_OK before the actual completion of the operation (or
00225  *     with an appropriate error code in case of failure). When the
00226  *     operation is completed the command callback is invoked with
00227  *     JOURNAL_STATUS_OK passed in as the 'status' parameter of the
00228  *     callback. In case of errors, the completion callback is invoked with
00229  *     an error status.
00230  *   - When the operation is executed by the journal in a blocking (i.e.
00231  *     synchronous) manner, control returns to the caller only upon the actual
00232  *     completion of the operation or the discovery of a failure condition. In
00233  *     this case, the function returns 1 to signal successful synchronous
00234  *     completion or an appropriate error code, and no further
00235  *     invocation of the completion callback should be expected at a later time.
00236  *
00237  * Here's a code snippet to suggest how this API might be used by callers:
00238  * \code
00239  *     ASSERT(JOURNAL_STATUS_OK == 0); // this is a precondition; it doesn't need to be put in code
00240  *     int32_t returnValue = FlashJournal_initialize(&journal, MTD, &STRATEGY_SEQUENTIAL, callbackHandler);
00241  *     if (returnValue < JOURNAL_STATUS_OK) {
00242  *         // handle error
00243  *     } else if (returnValue == JOURNAL_STATUS_OK) {
00244  *         ASSERT(MTD->GetCapabilities().asynchronous_ops == 1);
00245  *         // handle early return from asynchronous execution
00246  *     } else {
00247  *         ASSERT(returnValue == 1);
00248  *         // handle synchronous completion
00249  *     }
00250  * \endcode
00251  */
00252 static inline int32_t FlashJournal_initialize(FlashJournal_t           *journal,
00253                                               ARM_DRIVER_STORAGE       *mtd,
00254                                               const FlashJournal_Ops_t *ops,
00255                                               FlashJournal_Callback_t   callback)
00256 {
00257     return ops->initialize(journal, mtd, ops, callback);
00258 }
00259 
00260 /**
00261  * @brief Fetch journal metadata. A front-end for @ref FlashJournal_Ops_t::getInfo().
00262  *
00263  * @param [in] journal
00264  *                A previously initialized journal.
00265  *
00266  * @param [out] info
00267  *                A caller-supplied buffer capable of being filled in with an
00268  *                FlashJournal_Info_t.
00269  *
00270  * @return JOURNAL_STATUS_OK if a FlashJournal_Info_t structure containing
00271  *         top level metadata about the journal is filled into the supplied
00272  *         buffer, else an appropriate error value.
00273  *
00274  * @note It is the caller's responsibility to ensure that the buffer passed in
00275  *         is able to be initialized with a FlashJournal_Info_t.
00276  *
00277  * @note getInfo()s can still be called during a sequence of
00278  *     log()s.
00279  *
00280  * @note This API returns synchronously--it does not result in an invocation
00281  *     of a completion callback.
00282  *
00283  * Here's a code snippet to suggest how this API might be used by callers:
00284  * \code
00285  *     ASSERT(JOURNAL_STATUS_OK == 0); // this is a precondition; it doesn't need to be put in code
00286  *     FlashJournal_Info_t info;
00287  *     int32_t returnValue = FlashJournal_getInfo(&journal, &info);
00288  *     if (returnValue < JOURNAL_STATUS_OK) {
00289  *         // handle error
00290  *     } else {
00291  *         ASSERT(returnValue == JOURNAL_STATUS_OK);
00292  *         // work with the 'info'.
00293  *     }
00294  * \endcode
00295  */
00296 static inline FlashJournal_Status_t FlashJournal_getInfo(FlashJournal_t *journal, FlashJournal_Info_t *info)
00297 {
00298     return journal->ops.getInfo(journal, info);
00299 }
00300 
00301 /**
00302  * @brief Read from the most recently logged blob. A front-end for @ref
00303  * FlashJournal_Ops_t::read().
00304  *
00305  * @details Read off a chunk of the logged blob sequentially. The blob may
00306  *     be larger than the size of the read (or even of available SRAM), so
00307  *     multiple calls to read() could be necessary before the entire blob is
00308  *     read off. The journal maintains a read-pointer internally to allow
00309  *     reads to continue where the previous one left off.
00310  *
00311  * @note: Once the entire blob is read, the final read() returns the error
00312  *     JOURNAL_STATUS_EMPTY (or passes that value as the status of a
00313  *     completion callback) and resets the read-pointer to allow re-reading
00314  *     the blob from the start.
00315  *
00316  * @param  [in] journal
00317  *                A previously initialized journal.
00318  *
00319  * @param [out] buffer
00320  *                The destination of the read operation. The memory is owned
00321  *                by the caller and should remain valid for the lifetime
00322  *                of this operation.
00323  *
00324  * @param  [in] size
00325  *                The maximum amount of data which can be read in this
00326  *                operation. The memory pointed to by 'buffer' should be as
00327  *                large as this amount.
00328  *
00329  * @return
00330  *    The function executes in the following ways:
00331  *   - When the operation is asynchronous--i.e. when the underlying MTD's
00332  *     ARM_STOR_CAPABILITIES::asynchronous_ops is set to 1--and the operation
00333  *     executed by the journal in a non-blocking (i.e. asynchronous) manner,
00334  *     control returns to the caller with JOURNAL_STATUS_OK before the actual
00335  *     completion of the operation (or with an appropriate error code in case of
00336  *     failure). When the operation completes, the command callback is
00337  *     invoked with the number of successfully transferred bytes passed in as
00338  *     the 'status' parameter of the callback. If any error is encountered
00339  *     after the launch of an asynchronous operation, the completion callback
00340  *     is invoked with an error status.
00341  *   - When the operation is executed by the journal in a blocking (i.e.
00342  *     synchronous) manner, control returns to the caller only upon the
00343  *     actual completion of the operation, or the discovery of a failure
00344  *     condition. In synchronous mode, the function returns the number
00345  *     of data items read or an appropriate error code.
00346  *
00347  * @note If the underlying MTD's ARM_STORAGE_CAPABILITIES::asynchronous_ops
00348  *     is set then this operation may execute asynchronously. In the case of
00349  *     asynchronous operation, the invocation returns early (with
00350  *     JOURNAL_STATUS_OK) and results in a completion callback later.
00351  *
00352  * @note If the underlying MTD's ARM_STORAGE_CAPABILITIES::asynchronous_ops
00353  *     is set, the journal is not required to operate asynchronously. A Read
00354  *     operation can be finished synchronously in spite of
00355  *     ARM_STORAGE_CAPABILITIES::asynchronous_ops being set, returning the
00356  *     number of data items read to indicate successful completion, or an
00357  *     appropriate error code. In this case no further invocation of a
00358  *     completion callback should be expected at a later time.
00359  *
00360  * Here's a code snippet to suggest how this API might be used by callers:
00361  * \code
00362  *     ASSERT(JOURNAL_STATUS_OK == 0); // this is a precondition; it doesn't need to be put in code
00363  *     int32_t returnValue = FlashJournal_read(&journal, buffer, size);
00364  *     if (returnValue < JOURNAL_STATUS_OK) {
00365  *         // handle error
00366  *     } else if (returnValue == JOURNAL_STATUS_OK) {
00367  *         ASSERT(MTD->GetCapabilities().asynchronous_ops == 1);
00368  *         // handle early return from asynchronous execution
00369  *     } else {
00370  *         ASSERT(returnValue == size);
00371  *         // handle synchronous completion
00372  *     }
00373  * \endcode
00374  */
00375 static inline int32_t FlashJournal_read(FlashJournal_t *journal, void *blob, size_t n)
00376 {
00377     return journal->ops.read(journal, blob, n);
00378 }
00379 
00380 /**
00381  * @brief Start logging a new blob or append to the one currently being logged.
00382  * A front-end for @ref FlashJournal_Ops_t::log().
00383  *
00384  * @details Extend (or start off) the currently logged blob sequentially.
00385  *     There could be several calls to log() before the entire blob is
00386  *     accumulated. A sequence of one or more log() must be terminated by a
00387  *     commit() before the state of the blob is sealed and made persistent.
00388  *     The journal maintains a log-pointer internally to allow
00389  *     log()s to continue where the previous one left off.
00390  *
00391  * @param [in] journal
00392  *               A previously initialized journal.
00393  *
00394  * @param [in] blob
00395  *               The source of the log operation. The memory is owned
00396  *               by the caller and should remain valid for the lifetime
00397  *               of this operation.
00398  *
00399  * @param [in] size
00400  *               The amount of data being logged in this operation. The
00401  *               buffer pointed to by 'blob' should be as large as this
00402  *               amount.
00403  *
00404  * @return [please be sure to read notes (below) regarding other return values]
00405  *   The function executes in the following ways:
00406  *   - When the operation is asynchronous--i.e. when the underlying MTD's
00407  *     ARM_STOR_CAPABILITIES::asynchronous_ops is set to 1--and the operation
00408  *     executed by the journal in a non-blocking (i.e. asynchronous) manner,
00409  *     control returns to the caller with JOURNAL_STATUS_OK before the actual
00410  *     completion of the operation (or with an appropriate error code in case of
00411  *     failure). When the operation completes, the command callback is
00412  *     invoked with the number of successfully transferred bytes passed in as
00413  *     the 'status' parameter of the callback. If any error is encountered
00414  *     after the launch of an asynchronous operation, the completion callback
00415  *     is invoked with an error status.
00416  *   - When the operation is executed by the journal in a blocking (i.e.
00417  *     synchronous) manner, control returns to the caller only upon the actual
00418  *     completion of the operation, or the discovery of a failure condition. In
00419  *     synchronous mode, the function returns the number of data items
00420  *     logged, or an appropriate error code.
00421  *
00422  * @note If the underlying MTD's ARM_STORAGE_CAPABILITIES::asynchronous_ops
00423  *     is set then this operation may execute asynchronously. In the case of
00424  *     asynchronous operation, the invocation returns early (with
00425  *     JOURNAL_STATUS_OK) and results in a completion callback later.
00426  *
00427  * @note If the underlying MTD's ARM_STORAGE_CAPABILITIES::asynchronous_ops
00428  *     is set, the journal is not required to operate asynchronously. A log
00429  *     operation can be finished synchronously in spite of
00430  *     ARM_STORAGE_CAPABILITIES::asynchronous_ops being set, returning the
00431  *     number of data items logged to indicate successful completion, or an
00432  *     appropriate error code. In this case no further invocation of a
00433  *     completion callback should be expected at a later time.
00434  *
00435  * @note If a log operation will exceed available capacity, it fails with the
00436  *     error JOURNAL_STATUS_BOUNDED_CAPACITY.
00437  *
00438  * @note The actual size of data transfer (as reported by the status
00439  *     parameter of the callback or the return value from log() in case of
00440  *     synchronous operation) may be smaller than the amount requested. This
00441  *     could be due to the 'program_unit' of the underlying storage block--
00442  *     i.e. the minimum programmable size. Refer to @ref
00443  *     FlashJournal_Info_t::program_unit. It is the caller's responsibility
00444  *     for resubmitting this left-over data in a subsequent call to log.
00445  *     When logging an arbitrary amount of data, the last of a sequence of
00446  *     logs may need to be padded in order to align with the
00447  *     programming unit.
00448  *
00449  * @note If the total size requested to be logged is smaller
00450  *     than the MTD's program_unit, log() fails with an error value of
00451  *     JOURNAL_STATUS_SMALL_LOG_REQUEST.
00452  *
00453  * @note the data being logged isn't made persistent (or available for read-
00454  *     backs) until a commit. A sequence of log() operations is expected to end
00455  *     in a commit(). A new sequence of log()s should be initiated by the caller
00456  *     only after a commit() has completed. If a sequence of logs() is followed
00457  *     by an operation other than a commit, that operation will very likely
00458  *     return an error code. getInfo()s can still be called during a sequence of
00459  *     log()s.
00460  *
00461  * Here's a code snippet to suggest how this API might be used by callers:
00462  * \code
00463  *     ASSERT(JOURNAL_STATUS_OK == 0); // this is a precondition; it doesn't need to be put in code
00464  *     int32_t returnValue = FlashJournal_log(&journal, buffer, size);
00465  *     if (returnValue < JOURNAL_STATUS_OK) {
00466  *         // handle error
00467  *     } else if (returnValue == JOURNAL_STATUS_OK) {
00468  *         ASSERT(MTD->GetCapabilities().asynchronous_ops == 1);
00469  *         // handle early return from asynchronous execution
00470  *     } else {
00471  *         ASSERT(returnValue <= size);
00472  *         // handle synchronous completion
00473  *
00474  *         if (returnValue < size) {
00475  *     #if DEBUG
00476  *             FlashJournal_Info_t info;
00477  *             int32_t rc = FlashJournal_getInfo(&journal, &info);
00478  *             ASSERT(rc == JOURNAL_STATUS_OK);
00479  *             ASSERT(returnValue == (size - (size % info.program_unit)));
00480  *     #endif
00481  *             // move the last (size - returnValue) bytes of the buffer to the
00482  *             // beginning of the buffer to be used for the successive request.
00483  *         }
00484  *     }
00485  * \endcode
00486  */
00487 static inline int32_t FlashJournal_log(FlashJournal_t *journal, const void *blob, size_t n)
00488 {
00489     return journal->ops.log(journal, blob, n);
00490 }
00491 
00492 /**
00493  * @brief Commit a blob accumulated through a (possibly empty) sequence of previously
00494  *     successful log() operations. A front-end for @ref FlashJournal_Ops_t::commit().
00495  *
00496  * @param  [in] journal
00497  *                A previously initialized journal.
00498  *
00499  * @return
00500  *   The function executes in the following ways:
00501  *   - When the operation is asynchronous--i.e. when the underlying MTD's
00502  *     ARM_STOR_CAPABILITIES::asynchronous_ops is set to 1--and the operation
00503  *     executed by the journal in a non-blocking (i.e. asynchronous) manner,
00504  *     control returns to the caller with JOURNAL_STATUS_OK before the actual
00505  *     completion of the operation (or with an appropriate error code in case of
00506  *     failure). When the operation completes, the command callback is invoked
00507  *     with 1 passed in as the 'status' parameter of the callback to indicate
00508  *     success. If any error is encountered after the launch of an asynchronous
00509  *     operation, the completion callback is invoked with an error status.
00510  *   - When the operation is executed by the journal in a blocking (i.e.
00511  *     synchronous) manner, control returns to the caller only upon the actual
00512  *     completion of the operation, or the discovery of a failure condition. In
00513  *     synchronous mode, the function returns 1 to indicate success, or an
00514  *     appropriate error code.
00515  *
00516  * @note If the underlying MTD's ARM_STORAGE_CAPABILITIES::asynchronous_ops
00517  *     is set then this operation may execute asynchronously. In the case of
00518  *     asynchronous operation, the invocation returns early (with
00519  *     JOURNAL_STATUS_OK) and results in a completion callback later.
00520  *
00521  * @note If the underlying MTD's ARM_STORAGE_CAPABILITIES::asynchronous_ops
00522  *     is set, the journal is not required to operate asynchronously. A
00523  *     commit operation can be finished synchronously in spite of
00524  *     ARM_STORAGE_CAPABILITIES::asynchronous_ops being set, returning the
00525  *     total size of the committed blob to indicate successful completion,
00526  *     or an appropriate error code. In this case no further invocation of a
00527  *     completion callback should be expected at a later time.
00528  *
00529  * Here's a code snippet to suggest how this API might be used by callers:
00530  * \code
00531  *     ASSERT(JOURNAL_STATUS_OK == 0); // this is a precondition; it doesn't need to be put in code
00532  *     int32_t returnValue = FlashJournal_commit(&journal);
00533  *     if (returnValue < JOURNAL_STATUS_OK) {
00534  *         // handle error
00535  *     } else if (returnValue == JOURNAL_STATUS_OK) {
00536  *         ASSERT(MTD->GetCapabilities().asynchronous_ops == 1);
00537  *         // handle early return from asynchronous execution
00538  *     } else {
00539  *         // handle synchronous completion
00540  *         ASSERT(returnValue == 1);
00541  *         ...
00542  *     }
00543  * \endcode
00544  *
00545  * @note A sequence of log() operations is expected to end in a commit(). A new
00546  *     sequence of log()s should be initiated by the caller only after a
00547  *     commit() has completed. If a sequence of logs() is followed
00548  *     by an operation other than a commit, that operation will very likely
00549  *     return an error code.
00550  */
00551 static inline int32_t FlashJournal_commit(FlashJournal_t *journal)
00552 {
00553     return journal->ops.commit(journal);
00554 }
00555 
00556 /**
00557  * @brief Reset the journal. This has the effect of erasing all valid blobs. A
00558  *     front-end for @ref FlashJournal_Ops_t::reset().
00559  *
00560  * @param [in] journal
00561  *               A previously initialized journal.
00562  *
00563  * @return
00564  *   The function executes in the following ways:
00565  *   - When the operation is asynchronous--i.e. when the underlying MTD's
00566  *     ARM_STOR_CAPABILITIES::asynchronous_ops is set to 1--and the
00567  *     operation executed by the journal in a non-blocking (i.e.
00568  *     asynchronous) manner, control returns to the caller with
00569  *     JOURNAL_STATUS_OK before the actual completion of the operation (or
00570  *     with an appropriate error code in case of failure). When the
00571  *     operation completes, the command callback is invoked with
00572  *     JOURNAL_STATUS_OK passed in as the 'status' parameter of the
00573  *     callback. If any error is encountered after the launch of an
00574  *     asynchronous operation, the completion callback is invoked with an
00575  *     error status.
00576  *   - When the operation is executed by the journal in a blocking (i.e.
00577  *     synchronous) manner, control returns to the caller only upon the
00578  *     actual completion of the operation, or the discovery of a failure
00579  *     condition. In synchronous mode, the function returns 1 to signal
00580  *     successful completion, or an appropriate error code.
00581  *
00582  * @note If the underlying MTD's ARM_STORAGE_CAPABILITIES::asynchronous_ops
00583  *     is set then this operation may execute asynchronously. In the case of
00584  *     asynchronous operation, the invocation returns early (with
00585  *     JOURNAL_STATUS_OK) and results in a completion callback later.
00586  *
00587  * @note If the underlying MTD's ARM_STORAGE_CAPABILITIES::asynchronous_ops
00588  *     is set, the journal is not required to operate asynchronously. A
00589  *     reset operation can be finished synchronously in spite of
00590  *     ARM_STORAGE_CAPABILITIES::asynchronous_ops being set, returning 1 to
00591  *     indicate successful completion, or an appropriate error code. In this
00592  *     case no further invocation of a completion callback should be
00593  *     expected at a later time.
00594  *
00595  * Here's a code snippet to suggest how this API might be used by callers:
00596  * \code
00597  *     ASSERT(JOURNAL_STATUS_OK == 0); // this is a precondition; it doesn't need to be put in code
00598  *     int32_t returnValue = FlashJournal_reset(&journal);
00599  *     if (returnValue < JOURNAL_STATUS_OK) {
00600  *         // handle error
00601  *     } else if (returnValue == JOURNAL_STATUS_OK) {
00602  *         ASSERT(MTD->GetCapabilities().asynchronous_ops == 1);
00603  *         // handle early return from asynchronous execution
00604  *     } else {
00605  *         ASSERT(returnValue == 1);
00606  *         // handle synchronous completion
00607  *     }
00608  * \endcode
00609  */
00610 static inline int32_t FlashJournal_reset(FlashJournal_t *journal)
00611 {
00612     return journal->ops.reset(journal);
00613 }
00614 
00615 #ifdef __cplusplus
00616 }
00617 #endif // __cplusplus
00618 
00619 #endif /* __FLASH_JOURNAL_H__ */