Mistake on this page?
Report an issue in GitHub or email us
Driver_Storage.h
1 
2 /** \addtogroup hal */
3 /** @{*/
4 /*
5  * Copyright (c) 2006-2016, ARM Limited, All Rights Reserved
6  * SPDX-License-Identifier: Apache-2.0
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License"); you may
9  * not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef __DRIVER_STORAGE_H
22 #define __DRIVER_STORAGE_H
23 
24 #include <stdint.h>
25 
26 /****** This file has been deprecated since mbed-os-5.5 *****/
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif // __cplusplus
31 
32 #include "Driver_Common.h"
33 
34 #define ARM_STORAGE_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,00) /* API version */
35 
36 
37 #define _ARM_Driver_Storage_(n) Driver_Storage##n
38 #define ARM_Driver_Storage_(n) _ARM_Driver_Storage_(n)
39 
40 #define ARM_STORAGE_INVALID_OFFSET (0xFFFFFFFFFFFFFFFFULL) ///< Invalid address (relative to a storage controller's
41  ///< address space). A storage block may never start at this address.
42 
43 #define ARM_STORAGE_INVALID_ADDRESS (0xFFFFFFFFUL) ///< Invalid address within the processor's memory address space.
44  ///< Refer to memory-mapped storage, i.e. < \ref ARM_DRIVER_STORAGE::ResolveAddress().
45 
46 /****** Storage specific error codes *****/
47 #define ARM_STORAGE_ERROR_NOT_ERASABLE (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< Part (or all) of the range provided to Erase() isn't erasable.
48 #define ARM_STORAGE_ERROR_NOT_PROGRAMMABLE (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Part (or all) of the range provided to ProgramData() isn't programmable.
49 #define ARM_STORAGE_ERROR_PROTECTED (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Part (or all) of the range to Erase() or ProgramData() is protected.
50 #define ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< Runtime or sanity-check failure.
51 
52 /**
53  * \brief Attributes of the storage range within a storage block.
54  */
56  uint32_t erasable : 1; ///< Erasing blocks is permitted with a minimum granularity of 'erase_unit'.
57  ///< @note: if 'erasable' is 0--i.e. the 'erase' operation isn't available--then
58  ///< 'erase_unit' (see below) is immaterial and should be 0.
59  uint32_t programmable : 1; ///< Writing to ranges is permitted with a minimum granularity of 'program_unit'.
60  ///< Writes are typically achieved through the ProgramData operation (following an erase);
61  ///< if storage isn't erasable (see 'erasable' above) but is memory-mapped
62  ///< (i.e. 'memory_mapped'), it can be written directly using memory-store operations.
63  uint32_t executable : 1; ///< This storage block can hold program data; the processor can fetch and execute code
64  ///< sourced from it. Often this is accompanied with the device being 'memory_mapped' (see \ref ARM_STORAGE_INFO).
65  uint32_t protectable : 1; ///< The entire block can be protected from program and erase operations. Once protection
66  ///< is enabled for a block, its 'erasable' and 'programmable' bits are turned off.
67  uint32_t reserved : 28;
68  uint32_t erase_unit; ///< Minimum erase size in bytes.
69  ///< The offset of the start of the erase-range should also be aligned with this value.
70  ///< Applicable if the 'erasable' attribute is set for the block.
71  ///< @note: if 'erasable' (see above) is 0--i.e. the 'erase' operation isn't available--then
72  ///< 'erase_unit' is immaterial and should be 0.
73  uint32_t protection_unit; ///< Minimum protectable size in bytes. Applicable if the 'protectable'
74  ///< attribute is set for the block. This should be a divisor of the block's size. A
75  ///< block can be considered to be made up of consecutive, individually-protectable fragments.
77 
78 /**
79  * \brief A storage block is a range of memory with uniform attributes. Storage blocks
80  * combine to make up the address map of a storage controller.
81  */
82 typedef struct _ARM_STORAGE_BLOCK {
83  uint64_t addr; ///< This is the start address of the storage block. It is
84  ///< expressed as an offset from the start of the storage map
85  ///< maintained by the owning storage controller.
86  uint64_t size; ///< This is the size of the storage block, in units of bytes.
87  ///< Together with addr, it describes a range [addr, addr+size).
88  ARM_STORAGE_BLOCK_ATTRIBUTES attributes; ///< Attributes for this block.
90 
91 /**
92  * The check for a valid ARM_STORAGE_BLOCK.
93  */
94 #define ARM_STORAGE_VALID_BLOCK(BLK) (((BLK)->addr != ARM_STORAGE_INVALID_OFFSET) && ((BLK)->size != 0))
95 
96 /**
97  * \brief Values for encoding storage memory-types with respect to programmability.
98  *
99  * Please ensure that the maximum of the following memory types doesn't exceed 16; we
100  * encode this in a 4-bit field within ARM_STORAGE_INFO::programmability.
101  */
102 #define ARM_STORAGE_PROGRAMMABILITY_RAM (0x0)
103 #define ARM_STORAGE_PROGRAMMABILITY_ROM (0x1) ///< Read-only memory.
104 #define ARM_STORAGE_PROGRAMMABILITY_WORM (0x2) ///< write-once-read-only-memory (WORM).
105 #define ARM_STORAGE_PROGRAMMABILITY_ERASABLE (0x3) ///< re-programmable based on erase. Supports multiple writes.
106 
107 /**
108  * Values for encoding data-retention levels for storage blocks.
109  *
110  * Please ensure that the maximum of the following retention types doesn't exceed 16; we
111  * encode this in a 4-bit field within ARM_STORAGE_INFO::retention_level.
112  */
113 #define ARM_RETENTION_WHILE_DEVICE_ACTIVE (0x0) ///< Data is retained only during device activity.
114 #define ARM_RETENTION_ACROSS_SLEEP (0x1) ///< Data is retained across processor sleep.
115 #define ARM_RETENTION_ACROSS_DEEP_SLEEP (0x2) ///< Data is retained across processor deep-sleep.
116 #define ARM_RETENTION_BATTERY_BACKED (0x3) ///< Data is battery-backed. Device can be powered off.
117 #define ARM_RETENTION_NVM (0x4) ///< Data is retained in non-volatile memory.
118 
119 /**
120  * Device Data Security Protection Features. Applicable mostly to EXTERNAL_NVM.
121  */
123  uint32_t acls : 1; ///< Protection against internal software attacks using ACLs.
124  uint32_t rollback_protection : 1; ///< Roll-back protection. Set to true if the creator of the storage
125  ///< can ensure that an external attacker can't force an
126  ///< older firmware to run or to revert back to a previous state.
127  uint32_t tamper_proof : 1; ///< Tamper-proof memory (will be deleted on tamper-attempts using board level or chip level sensors).
128  uint32_t internal_flash : 1; ///< Internal flash.
129  uint32_t reserved1 : 12;
130 
131  /**
132  * Encode support for hardening against various classes of attacks.
133  */
134  uint32_t software_attacks : 1; ///< device software (malware running on the device).
135  uint32_t board_level_attacks : 1; ///< board level attacks (debug probes, copy protection fuses.)
136  uint32_t chip_level_attacks : 1; ///< chip level attacks (tamper-protection).
137  uint32_t side_channel_attacks : 1; ///< side channel attacks.
138  uint32_t reserved2 : 12;
140 
141 #define ARM_STORAGE_PROGRAM_CYCLES_INFINITE (0UL) /**< Infinite or unknown endurance for reprogramming. */
142 
143 /**
144  * \brief Storage information. This contains device-metadata. It is the return
145  * value from calling GetInfo() on the storage driver.
146  *
147  * \details These fields serve a different purpose than the ones contained in
148  * \ref ARM_STORAGE_CAPABILITIES, which is another structure containing
149  * device-level metadata. ARM_STORAGE_CAPABILITIES describes the API
150  * capabilities, whereas ARM_STORAGE_INFO describes the device. Furthermore
151  * ARM_STORAGE_CAPABILITIES fits within a single word, and is designed to be
152  * passed around by value; ARM_STORAGE_INFO, on the other hand, contains
153  * metadata which doesn't fit into a single word and requires the use of
154  * pointers to be moved around.
155  */
156 typedef struct _ARM_STORAGE_INFO {
157  uint64_t total_storage; ///< Total available storage, in bytes.
158  uint32_t program_unit; ///< Minimum programming size in bytes.
159  ///< The offset of the start of the program-range should also be aligned with this value.
160  ///< Applicable only if the 'programmable' attribute is set for a block.
161  ///< @note: setting program_unit to 0 has the effect of disabling the size and alignment
162  ///< restrictions (setting it to 1 also has the same effect).
163  uint32_t optimal_program_unit; ///< Optimal programming page-size in bytes. Some storage controllers
164  ///< have internal buffers into which to receive data. Writing in chunks of
165  ///< 'optimal_program_unit' would achieve maximum programming speed.
166  ///< Applicable only if the 'programmable' attribute is set for the underlying block(s).
167  uint32_t program_cycles; ///< A measure of endurance for reprogramming.
168  ///< Use ARM_STORAGE_PROGRAM_CYCLES_INFINITE for infinite or unknown endurance.
169  uint32_t erased_value : 1; ///< Contents of erased memory (usually 1 to indicate erased bytes with state 0xFF).
170  uint32_t memory_mapped : 1; ///< This storage device has a mapping onto the processor's memory address space.
171  ///< @note: For a memory-mapped block which isn't erasable but is programmable (i.e. if
172  ///< 'erasable' is set to 0, but 'programmable' is 1), writes should be possible directly to
173  ///< the memory-mapped storage without going through the ProgramData operation.
174  uint32_t programmability : 4; ///< A value to indicate storage programmability.
175  uint32_t retention_level : 4;
176  uint32_t reserved : 22;
177  ARM_STORAGE_SECURITY_FEATURES security; ///< \ref ARM_STORAGE_SECURITY_FEATURES
179 
180 /**
181 \brief Operating status of the storage controller.
182 */
183 typedef struct _ARM_STORAGE_STATUS {
184  uint32_t busy : 1; ///< Controller busy flag
185  uint32_t error : 1; ///< Read/Program/Erase error flag (cleared on start of next operation)
187 
188 /**
189  * \brief Storage Driver API Capabilities.
190  *
191  * This data structure is designed to fit within a single word so that it can be
192  * fetched cheaply using a call to driver->GetCapabilities().
193  */
195  uint32_t asynchronous_ops : 1; ///< Used to indicate if APIs like initialize,
196  ///< read, erase, program, etc. can operate in asynchronous mode.
197  ///< Setting this bit to 1 means that the driver is capable
198  ///< of launching asynchronous operations; command completion is
199  ///< signaled by the invocation of a completion callback. If
200  ///< set to 1, drivers may still complete asynchronous
201  ///< operations synchronously as necessary--in which case they
202  ///< return a positive error code to indicate synchronous completion.
203  uint32_t erase_all : 1; ///< Supports EraseAll operation.
204  uint32_t reserved : 30;
206 
207 /**
208  * Command opcodes for Storage. Completion callbacks use these codes to refer to
209  * completing commands. Refer to \ref ARM_Storage_Callback_t.
210  */
212  ARM_STORAGE_OPERATION_GET_VERSION,
213  ARM_STORAGE_OPERATION_GET_CAPABILITIES,
214  ARM_STORAGE_OPERATION_INITIALIZE,
215  ARM_STORAGE_OPERATION_UNINITIALIZE,
216  ARM_STORAGE_OPERATION_POWER_CONTROL,
217  ARM_STORAGE_OPERATION_READ_DATA,
218  ARM_STORAGE_OPERATION_PROGRAM_DATA,
219  ARM_STORAGE_OPERATION_ERASE,
220  ARM_STORAGE_OPERATION_ERASE_ALL,
221  ARM_STORAGE_OPERATION_GET_STATUS,
222  ARM_STORAGE_OPERATION_GET_INFO,
223  ARM_STORAGE_OPERATION_RESOLVE_ADDRESS,
224  ARM_STORAGE_OPERATION_GET_NEXT_BLOCK,
225  ARM_STORAGE_OPERATION_GET_BLOCK
227 
228 /**
229  * Declaration of the callback-type for command completion.
230  *
231  * @param [in] status
232  * A code to indicate the status of the completed operation. For data
233  * transfer operations, the status field is overloaded in case of
234  * success to return the count of items successfully transferred; this
235  * can be done safely because error codes are negative values.
236  *
237  * @param [in] operation
238  * The command op-code. This value isn't essential for the callback in
239  * the presence of the command instance-id, but it is expected that
240  * this information could be a quick and useful filter.
241  */
242 typedef void (*ARM_Storage_Callback_t)(int32_t status, ARM_STORAGE_OPERATION operation);
243 
244 /**
245  * This is the set of operations constituting the Storage driver. Their
246  * implementation is platform-specific, and needs to be supplied by the
247  * porting effort.
248  *
249  * Some APIs within `ARM_DRIVER_STORAGE` will always operate synchronously:
250  * GetVersion, GetCapabilities, GetStatus, GetInfo, ResolveAddress,
251  * GetNextBlock, and GetBlock. This means that control returns to the caller
252  * with a relevant status code only after the completion of the operation (or
253  * the discovery of a failure condition).
254  *
255  * The remainder of the APIs: Initialize, Uninitialize, PowerControl, ReadData,
256  * ProgramData, Erase, EraseAll, can function asynchronously if the underlying
257  * controller supports it--i.e. if ARM_STORAGE_CAPABILITIES::asynchronous_ops is
258  * set. In the case of asynchronous operation, the invocation returns early
259  * (with ARM_DRIVER_OK) and results in a completion callback later. If
260  * ARM_STORAGE_CAPABILITIES::asynchronous_ops is not set, then all such APIs
261  * execute synchronously, and control returns to the caller with a status code
262  * only after the completion of the operation (or the discovery of a failure
263  * condition).
264  *
265  * If ARM_STORAGE_CAPABILITIES::asynchronous_ops is set, a storage driver may
266  * still choose to execute asynchronous operations in a synchronous manner. If
267  * so, the driver returns a positive value to indicate successful synchronous
268  * completion (or an error code in case of failure) and no further invocation of
269  * completion callback should be expected. The expected return value for
270  * synchronous completion of such asynchronous operations varies depending on
271  * the operation. For operations involving data access, it often equals the
272  * amount of data transferred or affected. For non data-transfer operations,
273  * such as EraseAll or Initialize, it is usually 1.
274  *
275  * Here's a code snippet to suggest how asynchronous APIs might be used by
276  * callers to handle both synchronous and asynchronous execution by the
277  * underlying storage driver:
278  * \code
279  * ASSERT(ARM_DRIVER_OK == 0); // this is a precondition; it doesn't need to be put in code
280  * int32_t returnValue = drv->asynchronousAPI(...);
281  * if (returnValue < ARM_DRIVER_OK) {
282  * // handle error.
283  * } else if (returnValue == ARM_DRIVER_OK) {
284  * ASSERT(drv->GetCapabilities().asynchronous_ops == 1);
285  * // handle early return from asynchronous execution; remainder of the work is done in the callback handler.
286  * } else {
287  * ASSERT(returnValue == EXPECTED_RETURN_VALUE_FOR_SYNCHRONOUS_COMPLETION);
288  * // handle synchronous completion.
289  * }
290  * \endcode
291  */
292 typedef struct _ARM_DRIVER_STORAGE {
293  /**
294  * \brief Get driver version.
295  *
296  * The function GetVersion() returns version information of the driver implementation in ARM_DRIVER_VERSION.
297  *
298  * - API version is the version of the CMSIS-Driver specification used to implement this driver.
299  * - Driver version is source code version of the actual driver implementation.
300  *
301  * Example:
302  * \code
303  * extern ARM_DRIVER_STORAGE *drv_info;
304  *
305  * void read_version (void) {
306  * ARM_DRIVER_VERSION version;
307  *
308  * version = drv_info->GetVersion ();
309  * if (version.api < 0x10A) { // requires at minimum API version 1.10 or higher
310  * // error handling
311  * return;
312  * }
313  * }
314  * \endcode
315  *
316  * @return \ref ARM_DRIVER_VERSION.
317  *
318  * @note This API returns synchronously--it does not result in an invocation
319  * of a completion callback.
320  *
321  * @note The function GetVersion() can be called any time to obtain the
322  * required information from the driver (even before initialization). It
323  * always returns the same information.
324  */
325  ARM_DRIVER_VERSION (*GetVersion)(void);
326 
327  /**
328  * \brief Get driver capabilities.
329  *
330  * \details The function GetCapabilities() returns information about
331  * capabilities in this driver implementation. The data fields of the struct
332  * ARM_STORAGE_CAPABILITIES encode various capabilities, for example if the device
333  * is able to execute operations asynchronously.
334  *
335  * Example:
336  * \code
337  * extern ARM_DRIVER_STORAGE *drv_info;
338  *
339  * void read_capabilities (void) {
340  * ARM_STORAGE_CAPABILITIES drv_capabilities;
341  *
342  * drv_capabilities = drv_info->GetCapabilities ();
343  * // interrogate capabilities
344  *
345  * }
346  * \endcode
347  *
348  * @return \ref ARM_STORAGE_CAPABILITIES.
349  *
350  * @note This API returns synchronously--it does not result in an invocation
351  * of a completion callback.
352  *
353  * @note The function GetCapabilities() can be called any time to obtain the
354  * required information from the driver (even before initialization). It
355  * always returns the same information.
356  */
357  ARM_STORAGE_CAPABILITIES (*GetCapabilities)(void);
358 
359  /**
360  * \brief Initialize the Storage Interface.
361  *
362  * The function Initialize is called when the middleware component starts
363  * operation. In addition to bringing the controller to a ready state,
364  * Initialize() receives a callback handler to be invoked upon completion of
365  * asynchronous operations.
366  *
367  * Initialize() needs to be called explicitly before
368  * powering the peripheral using PowerControl(), and before initiating other
369  * accesses to the storage controller.
370  *
371  * The function performs the following operations:
372  * - Initializes the resources needed for the Storage interface.
373  * - Registers the \ref ARM_Storage_Callback_t callback function.
374  *
375  * To start working with a peripheral the functions Initialize and PowerControl need to be called in this order:
376  * drv->Initialize (...); // Allocate I/O pins
377  * drv->PowerControl (ARM_POWER_FULL); // Power up peripheral, setup IRQ/DMA
378  *
379  * - Initialize() typically allocates the I/O resources (pins) for the
380  * peripheral. The function can be called multiple times; if the I/O resources
381  * are already initialized it performs no operation and just returns with
382  * ARM_DRIVER_OK.
383  *
384  * - PowerControl (ARM_POWER_FULL) sets the peripheral registers including
385  * interrupt (NVIC) and optionally DMA. The function can be called multiple
386  * times; if the registers are already set it performs no operation and just
387  * returns with ARM_DRIVER_OK.
388  *
389  * To stop working with a peripheral the functions PowerControl and Uninitialize need to be called in this order:
390  * drv->PowerControl (ARM_POWER_OFF); // Terminate any pending transfers, reset IRQ/DMA, power off peripheral
391  * drv->Uninitialize (...); // Release I/O pins
392  *
393  * The functions PowerControl and Uninitialize always execute and can be used
394  * to put the peripheral into a Safe State, for example after any data
395  * transmission errors. To restart the peripheral in an error condition,
396  * you should first execute the Stop Sequence and then the Start Sequence.
397  *
398  * @param [in] callback
399  * Caller-defined callback to be invoked upon command completion
400  * for asynchronous APIs (including the completion of
401  * initialization). Use a NULL pointer when no callback
402  * signals are required.
403  *
404  * @note This API may execute asynchronously if
405  * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
406  * execution is optional even if 'asynchronous_ops' is set.
407  *
408  * @return If asynchronous activity is launched, an invocation returns
409  * ARM_DRIVER_OK, and the caller can expect to receive a callback in the
410  * future with a status value of ARM_DRIVER_OK or an error-code. In the
411  * case of synchronous execution, control returns after completion with a
412  * value of 1. Return values less than ARM_DRIVER_OK (0) signify errors.
413  */
414  int32_t (*Initialize)(ARM_Storage_Callback_t callback);
415 
416  /**
417  * \brief De-initialize the Storage Interface.
418  *
419  * The function Uninitialize() de-initializes the resources of Storage interface.
420  *
421  * It is called when the middleware component stops operation, and wishes to
422  * release the software resources used by the interface.
423  *
424  * @note This API may execute asynchronously if
425  * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
426  * execution is optional even if 'asynchronous_ops' is set.
427  *
428  * @return If asynchronous activity is launched, an invocation returns
429  * ARM_DRIVER_OK, and the caller can expect to receive a callback in the
430  * future with a status value of ARM_DRIVER_OK or an error-code. In the
431  * case of synchronous execution, control returns after completion with a
432  * value of 1. Return values less than ARM_DRIVER_OK (0) signify errors.
433  */
434  int32_t (*Uninitialize)(void);
435 
436  /**
437  * \brief Control the Storage interface power.
438  *
439  * The function \b ARM_Storage_PowerControl operates the power modes of the Storage interface.
440  *
441  * To start working with a peripheral the functions Initialize and PowerControl need to be called in this order:
442  * drv->Initialize (...); // Allocate I/O pins
443  * drv->PowerControl (ARM_POWER_FULL); // Power up peripheral, setup IRQ/DMA
444  *
445  * - Initialize() typically allocates the I/O resources (pins) for the
446  * peripheral. The function can be called multiple times; if the I/O resources
447  * are already initialized it performs no operation and just returns with
448  * ARM_DRIVER_OK.
449  *
450  * - PowerControl (ARM_POWER_FULL) sets the peripheral registers including
451  * interrupt (NVIC) and optionally DMA. The function can be called multiple
452  * times; if the registers are already set it performs no operation and just
453  * returns with ARM_DRIVER_OK.
454  *
455  * To stop working with a peripheral the functions PowerControl and Uninitialize need to be called in this order:
456  *
457  * drv->PowerControl (ARM_POWER_OFF); // Terminate any pending transfers, reset IRQ/DMA, power off peripheral
458  * drv->Uninitialize (...); // Release I/O pins
459  *
460  * The functions PowerControl and Uninitialize always execute and can be used
461  * to put the peripheral into a Safe State, for example after any data
462  * transmission errors. To restart the peripheral in an error condition,
463  * you should first execute the Stop Sequence and then the Start Sequence.
464  *
465  * @param state
466  * \ref ARM_POWER_STATE. The target power-state for the storage controller.
467  * The parameter state can have the following values:
468  * - ARM_POWER_FULL : set-up peripheral for data transfers, enable interrupts
469  * (NVIC) and optionally DMA. Can be called multiple times. If the peripheral
470  * is already in this mode, then the function performs no operation and returns
471  * with ARM_DRIVER_OK.
472  * - ARM_POWER_LOW : may use power saving. Returns ARM_DRIVER_ERROR_UNSUPPORTED when not implemented.
473  * - ARM_POWER_OFF : terminates any pending data transfers, disables peripheral, disables related interrupts and DMA.
474  *
475  * @note This API may execute asynchronously if
476  * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
477  * execution is optional even if 'asynchronous_ops' is set.
478  *
479  * @return If asynchronous activity is launched, an invocation returns
480  * ARM_DRIVER_OK, and the caller can expect to receive a callback in the
481  * future with a status value of ARM_DRIVER_OK or an error-code. In the
482  * case of synchronous execution, control returns after completion with a
483  * value of 1. Return values less than ARM_DRIVER_OK (0) signify errors.
484  */
485  int32_t (*PowerControl)(ARM_POWER_STATE state);
486 
487  /**
488  * \brief read the contents of a given address range from the storage device.
489  *
490  * \details Read the contents of a range of storage memory into a buffer
491  * supplied by the caller. The buffer is owned by the caller and should
492  * remain accessible for the lifetime of this command.
493  *
494  * @param [in] addr
495  * This specifies the address from where to read data.
496  *
497  * @param [out] data
498  * The destination of the read operation. The buffer
499  * is owned by the caller and should remain accessible for the
500  * lifetime of this command.
501  *
502  * @param [in] size
503  * The number of bytes requested to read. The data buffer
504  * should be at least as large as this size.
505  *
506  * @note This API may execute asynchronously if
507  * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
508  * execution is optional even if 'asynchronous_ops' is set.
509  *
510  * @return If asynchronous activity is launched, an invocation returns
511  * ARM_DRIVER_OK, and the caller can expect to receive a callback in the
512  * future with the number of successfully transferred bytes passed in as
513  * the 'status' parameter. In the case of synchronous execution, control
514  * returns after completion with a positive transfer-count. Return values
515  * less than ARM_DRIVER_OK (0) signify errors.
516  */
517  int32_t (*ReadData)(uint64_t addr, void *data, uint32_t size);
518 
519  /**
520  * \brief program (write into) the contents of a given address range of the storage device.
521  *
522  * \details Write the contents of a given memory buffer into a range of
523  * storage memory. In the case of flash memory, the destination range in
524  * storage memory typically has its contents in an erased state from a
525  * preceding erase operation. The source memory buffer is owned by the
526  * caller and should remain accessible for the lifetime of this command.
527  *
528  * @param [in] addr
529  * This is the start address of the range to be written into. It
530  * needs to be aligned to the device's \em program_unit
531  * specified in \ref ARM_STORAGE_INFO.
532  *
533  * @param [in] data
534  * The source of the write operation. The buffer is owned by the
535  * caller and should remain accessible for the lifetime of this
536  * command.
537  *
538  * @param [in] size
539  * The number of bytes requested to be written. The buffer
540  * should be at least as large as this size. \note 'size' should
541  * be a multiple of the device's 'program_unit' (see \ref
542  * ARM_STORAGE_INFO).
543  *
544  * @note It is best for the middleware to write in units of
545  * 'optimal_program_unit' (\ref ARM_STORAGE_INFO) of the device.
546  *
547  * @note This API may execute asynchronously if
548  * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
549  * execution is optional even if 'asynchronous_ops' is set.
550  *
551  * @return If asynchronous activity is launched, an invocation returns
552  * ARM_DRIVER_OK, and the caller can expect to receive a callback in the
553  * future with the number of successfully transferred bytes passed in as
554  * the 'status' parameter. In the case of synchronous execution, control
555  * returns after completion with a positive transfer-count. Return values
556  * less than ARM_DRIVER_OK (0) signify errors.
557  */
558  int32_t (*ProgramData)(uint64_t addr, const void *data, uint32_t size);
559 
560  /**
561  * @brief Erase Storage range.
562  *
563  * @details This function erases a range of storage specified by [addr, addr +
564  * size). Both 'addr' and 'addr + size' should align with the
565  * 'erase_unit'(s) of the respective owning storage block(s) (see \ref
566  * ARM_STORAGE_BLOCK and \ref ARM_STORAGE_BLOCK_ATTRIBUTES). The range to
567  * be erased will have its contents returned to the un-programmed state--
568  * i.e. to 'erased_value' (see \ref ARM_STORAGE_BLOCK_ATTRIBUTES), which
569  * is usually 1 to indicate the pattern of all ones: 0xFF.
570  *
571  * @param [in] addr
572  * This is the start-address of the range to be erased. It must
573  * start at an 'erase_unit' boundary of the underlying block.
574  *
575  * @param [in] size
576  * Size (in bytes) of the range to be erased. 'addr + size'
577  * must be aligned with the 'erase_unit' of the underlying
578  * block.
579  *
580  * @note This API may execute asynchronously if
581  * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
582  * execution is optional even if 'asynchronous_ops' is set.
583  *
584  * @return
585  * If the range to be erased doesn't align with the erase_units of the
586  * respective start and end blocks, ARM_DRIVER_ERROR_PARAMETER is returned.
587  * If any part of the range is protected, ARM_STORAGE_ERROR_PROTECTED is
588  * returned. If any part of the range is not erasable,
589  * ARM_STORAGE_ERROR_NOT_ERASABLE is returned. All such sanity-check
590  * failures result in the error code being returned synchronously and the
591  * storage bytes within the range remain unaffected.
592  * Otherwise the function executes in the following ways:
593  * If asynchronous activity is launched, an invocation returns
594  * ARM_DRIVER_OK, and the caller can expect to receive a callback in the
595  * future with the number of successfully erased bytes passed in as
596  * the 'status' parameter. In the case of synchronous execution, control
597  * returns after completion with a positive erase-count. Return values
598  * less than ARM_DRIVER_OK (0) signify errors.
599  *
600  * @note Erase() may return a smaller (positive) value than the size of the
601  * requested range. The returned value indicates the actual number of bytes
602  * erased. It is the caller's responsibility to follow up with an appropriate
603  * request to complete the operation.
604  *
605  * @note in the case of a failed erase (except when
606  * ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_ERROR_PROTECTED, or
607  * ARM_STORAGE_ERROR_NOT_ERASABLE is returned synchronously), the
608  * requested range should be assumed to be in an unknown state. The
609  * previous contents may not be retained.
610  */
611  int32_t (*Erase)(uint64_t addr, uint32_t size);
612 
613  /**
614  * @brief Erase complete storage. Optional function for faster erase of the complete device.
615  *
616  * This optional function erases the complete device. If the device does not
617  * support global erase then the function returns the error value \ref
618  * ARM_DRIVER_ERROR_UNSUPPORTED. The data field \em 'erase_all' = 1
619  * of the structure \ref ARM_STORAGE_CAPABILITIES encodes that
620  * ARM_STORAGE_EraseAll is supported.
621  *
622  * @note This API may execute asynchronously if
623  * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
624  * execution is optional even if 'asynchronous_ops' is set.
625  *
626  * @return
627  * If any part of the storage range is protected,
628  * ARM_STORAGE_ERROR_PROTECTED is returned. If any part of the storage
629  * range is not erasable, ARM_STORAGE_ERROR_NOT_ERASABLE is returned. All
630  * such sanity-check failures result in the error code being returned
631  * synchronously and the storage bytes within the range remain unaffected.
632  * Otherwise the function executes in the following ways:
633  * If asynchronous activity is launched, an invocation returns
634  * ARM_DRIVER_OK, and the caller can expect to receive a callback in the
635  * future with ARM_DRIVER_OK passed in as the 'status' parameter. In the
636  * case of synchronous execution, control returns after completion with a
637  * value of 1. Return values less than ARM_DRIVER_OK (0) signify errors.
638  */
639  int32_t (*EraseAll)(void);
640 
641  /**
642  * @brief Get the status of the current (or previous) command executed by the
643  * storage controller; stored in the structure \ref ARM_STORAGE_STATUS.
644  *
645  * @return
646  * The status of the underlying controller.
647  *
648  * @note This API returns synchronously--it does not result in an invocation
649  * of a completion callback.
650  */
651  ARM_STORAGE_STATUS (*GetStatus)(void);
652 
653  /**
654  * @brief Get information about the Storage device; stored in the structure \ref ARM_STORAGE_INFO.
655  *
656  * @param [out] info
657  * A caller-supplied buffer capable of being filled in with an
658  * \ref ARM_STORAGE_INFO.
659  *
660  * @return ARM_DRIVER_OK if a ARM_STORAGE_INFO structure containing top level
661  * metadata about the storage controller is filled into the supplied
662  * buffer, else an appropriate error value.
663  *
664  * @note It is the caller's responsibility to ensure that the buffer passed in
665  * is able to be initialized with a \ref ARM_STORAGE_INFO.
666  *
667  * @note This API returns synchronously--it does not result in an invocation
668  * of a completion callback.
669  */
670  int32_t (*GetInfo)(ARM_STORAGE_INFO *info);
671 
672  /**
673  * \brief For memory-mapped storage, resolve an address relative to
674  * the storage controller into a memory address.
675  *
676  * @param addr
677  * This is the address for which we want a resolution to the
678  * processor's physical address space. It is an offset from the
679  * start of the storage map maintained by the owning storage
680  * controller.
681  *
682  * @return
683  * The resolved address in the processor's address space; else
684  * ARM_STORAGE_INVALID_ADDRESS, if no resolution is possible.
685  *
686  * @note This API returns synchronously. The invocation should return quickly,
687  * and result in a resolved address.
688  */
689  uint32_t (*ResolveAddress)(uint64_t addr);
690 
691  /**
692  * @brief Advance to the successor of the current block (iterator), or fetch
693  * the first block (if 'prev_block' is passed in as NULL).
694  *
695  * @details This helper function fetches (an iterator to) the next block (or
696  * the first block if 'prev_block' is passed in as NULL). In the failure
697  * case, a terminating, invalid block iterator is filled into the out
698  * parameter: 'next_block'. In combination with \ref
699  * ARM_STORAGE_VALID_BLOCK(), it can be used to iterate over the sequence
700  * of blocks within the storage map:
701  *
702  * \code
703  * ARM_STORAGE_BLOCK block;
704  * for (drv->GetNextBlock(NULL, &block); ARM_STORAGE_VALID_BLOCK(&block); drv->GetNextBlock(&block, &block)) {
705  * // make use of block
706  * }
707  * \endcode
708  *
709  * @param[in] prev_block
710  * An existing block (iterator) within the same storage
711  * controller. The memory buffer holding this block is owned
712  * by the caller. This pointer may be NULL; if so, the
713  * invocation fills in the first block into the out parameter:
714  * 'next_block'.
715  *
716  * @param[out] next_block
717  * A caller-owned buffer large enough to be filled in with
718  * the following ARM_STORAGE_BLOCK. It is legal to provide the
719  * same buffer using 'next_block' as was passed in with 'prev_block'. It
720  * is also legal to pass a NULL into this parameter if the
721  * caller isn't interested in populating a buffer with the next
722  * block--i.e. if the caller only wishes to establish the
723  * presence of a next block.
724  *
725  * @return ARM_DRIVER_OK if a valid next block is found (or first block, if
726  * prev_block is passed as NULL); upon successful operation, the contents
727  * of the next (or first) block are filled into the buffer pointed to by
728  * the parameter 'next_block' and ARM_STORAGE_VALID_BLOCK(next_block) is
729  * guaranteed to be true. Upon reaching the end of the sequence of blocks
730  * (iterators), or in case the driver is unable to fetch information about
731  * the next (or first) block, an error (negative) value is returned and an
732  * invalid StorageBlock is populated into the supplied buffer. If
733  * prev_block is NULL, the first block is returned.
734  *
735  * @note This API returns synchronously--it does not result in an invocation
736  * of a completion callback.
737  */
738  int32_t (*GetNextBlock)(const ARM_STORAGE_BLOCK* prev_block, ARM_STORAGE_BLOCK *next_block);
739 
740  /**
741  * @brief Find the storage block (iterator) encompassing a given storage address.
742  *
743  * @param[in] addr
744  * Storage address in bytes.
745  *
746  * @param[out] block
747  * A caller-owned buffer large enough to be filled in with the
748  * ARM_STORAGE_BLOCK encapsulating the given address. This value
749  * can also be passed in as NULL if the caller isn't interested
750  * in populating a buffer with the block--if the caller only
751  * wishes to establish the presence of a containing storage
752  * block.
753  *
754  * @return ARM_DRIVER_OK if a containing storage-block is found. In this case,
755  * if block is non-NULL, the buffer pointed to by it is populated with
756  * the contents of the storage block--i.e. if block is valid and a block is
757  * found, ARM_STORAGE_VALID_BLOCK(block) would return true following this
758  * call. If there is no storage block containing the given offset, or in
759  * case the driver is unable to resolve an address to a storage-block, an
760  * error (negative) value is returned and an invalid StorageBlock is
761  * populated into the supplied buffer.
762  *
763  * @note This API returns synchronously--it does not result in an invocation
764  * of a completion callback.
765  */
766  int32_t (*GetBlock)(uint64_t addr, ARM_STORAGE_BLOCK *block);
767 } const ARM_DRIVER_STORAGE;
768 
769 #ifdef __cplusplus
770 }
771 #endif // __cplusplus
772 
773 #endif /* __DRIVER_STORAGE_H */
774 
775 /** @}*/
struct _ARM_STORAGE_SECURITY_FEATURES ARM_STORAGE_SECURITY_FEATURES
Device Data Security Protection Features.
struct _ARM_DRIVER_STORAGE ARM_DRIVER_STORAGE
This is the set of operations constituting the Storage driver.
uint32_t optimal_program_unit
Optimal programming page-size in bytes.
MBED_NORETURN void error(const char *format,...) MBED_PRINTF(1
To generate a fatal compile-time error, you can use the pre-processor error directive.
void(* ARM_Storage_Callback_t)(int32_t status, ARM_STORAGE_OPERATION operation)
Declaration of the callback-type for command completion.
struct _ARM_DRIVER_VERSION ARM_DRIVER_VERSION
Driver Version.
struct _ARM_STORAGE_INFO ARM_STORAGE_INFO
Storage information.
ARM_STORAGE_SECURITY_FEATURES security
ARM_STORAGE_SECURITY_FEATURES
Storage information.
Operating status of the storage controller.
The key size.
uint64_t addr
This is the start address of the storage block.
uint32_t erase_unit
Minimum erase size in bytes.
Storage Driver API Capabilities.
Attributes of the storage range within a storage block.
ARM_STORAGE_BLOCK_ATTRIBUTES attributes
Attributes for this block.
Device Data Security Protection Features.
uint32_t program_cycles
A measure of endurance for reprogramming.
uint32_t executable
This storage block can hold program data; the processor can fetch and execute code sourced from it...
uint32_t erasable
Erasing blocks is permitted with a minimum granularity of &#39;erase_unit&#39;.
uint32_t program_unit
Minimum programming size in bytes.
uint64_t size
This is the size of the storage block, in units of bytes.
uint32_t protectable
The entire block can be protected from program and erase operations.
A storage block is a range of memory with uniform attributes.
This is the set of operations constituting the Storage driver.
Callback< R(ArgTs...)> callback(R(*func)(ArgTs...)=0)
Create a callback class with type inferred from the arguments.
Definition: Callback.h:709
struct _ARM_STORAGE_CAPABILITIES ARM_STORAGE_CAPABILITIES
Storage Driver API Capabilities.
struct _ARM_STORAGE_STATUS ARM_STORAGE_STATUS
Operating status of the storage controller.
struct _ARM_STORAGE_BLOCK ARM_STORAGE_BLOCK
A storage block is a range of memory with uniform attributes.
uint64_t total_storage
Total available storage, in bytes.
enum _ARM_POWER_STATE ARM_POWER_STATE
General power states.
_ARM_STORAGE_OPERATION
Command opcodes for Storage.
enum _ARM_STORAGE_OPERATION ARM_STORAGE_OPERATION
Command opcodes for Storage.
struct _ARM_STORAGE_BLOCK_ATTRIBUTES ARM_STORAGE_BLOCK_ATTRIBUTES
Attributes of the storage range within a storage block.
uint32_t programmable
Writing to ranges is permitted with a minimum granularity of &#39;program_unit&#39;.
uint32_t protection_unit
Minimum protectable size in bytes.
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.