Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
Driver_Storage.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 __DRIVER_STORAGE_H 00019 #define __DRIVER_STORAGE_H 00020 00021 #include <stdint.h> 00022 00023 #ifdef __cplusplus 00024 extern "C" { 00025 #endif // __cplusplus 00026 00027 #include "Driver_Common.h" 00028 00029 #define ARM_STORAGE_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,00) /* API version */ 00030 00031 00032 #define _ARM_Driver_Storage_(n) Driver_Storage##n 00033 #define ARM_Driver_Storage_(n) _ARM_Driver_Storage_(n) 00034 00035 #define ARM_STORAGE_INVALID_OFFSET (0xFFFFFFFFFFFFFFFFULL) ///< Invalid address (relative to a storage controller's 00036 ///< address space). A storage block may never start at this address. 00037 00038 #define ARM_STORAGE_INVALID_ADDRESS (0xFFFFFFFFUL) ///< Invalid address within the processor's memory address space. 00039 ///< Refer to memory-mapped storage, i.e. < \ref ARM_DRIVER_STORAGE::ResolveAddress(). 00040 00041 /****** Storage specific error codes *****/ 00042 #define ARM_STORAGE_ERROR_NOT_ERASABLE (ARM_DRIVER_ERROR_SPECIFIC - 1) ///< Part (or all) of the range provided to Erase() isn't erasable. 00043 #define ARM_STORAGE_ERROR_NOT_PROGRAMMABLE (ARM_DRIVER_ERROR_SPECIFIC - 2) ///< Part (or all) of the range provided to ProgramData() isn't programmable. 00044 #define ARM_STORAGE_ERROR_PROTECTED (ARM_DRIVER_ERROR_SPECIFIC - 3) ///< Part (or all) of the range to Erase() or ProgramData() is protected. 00045 #define ARM_STORAGE_ERROR_RUNTIME_OR_INTEGRITY_FAILURE (ARM_DRIVER_ERROR_SPECIFIC - 4) ///< Runtime or sanity-check failure. 00046 00047 /** 00048 * \brief Attributes of the storage range within a storage block. 00049 */ 00050 typedef struct _ARM_STORAGE_BLOCK_ATTRIBUTES { 00051 uint32_t erasable : 1; ///< Erasing blocks is permitted with a minimum granularity of 'erase_unit'. 00052 ///< @note: if 'erasable' is 0--i.e. the 'erase' operation isn't available--then 00053 ///< 'erase_unit' (see below) is immaterial and should be 0. 00054 uint32_t programmable : 1; ///< Writing to ranges is permitted with a minimum granularity of 'program_unit'. 00055 ///< Writes are typically achieved through the ProgramData operation (following an erase); 00056 ///< if storage isn't erasable (see 'erasable' above) but is memory-mapped 00057 ///< (i.e. 'memory_mapped'), it can be written directly using memory-store operations. 00058 uint32_t executable : 1; ///< This storage block can hold program data; the processor can fetch and execute code 00059 ///< sourced from it. Often this is accompanied with the device being 'memory_mapped' (see \ref ARM_STORAGE_INFO). 00060 uint32_t protectable : 1; ///< The entire block can be protected from program and erase operations. Once protection 00061 ///< is enabled for a block, its 'erasable' and 'programmable' bits are turned off. 00062 uint32_t reserved : 28; 00063 uint32_t erase_unit; ///< Minimum erase size in bytes. 00064 ///< The offset of the start of the erase-range should also be aligned with this value. 00065 ///< Applicable if the 'erasable' attribute is set for the block. 00066 ///< @note: if 'erasable' (see above) is 0--i.e. the 'erase' operation isn't available--then 00067 ///< 'erase_unit' is immaterial and should be 0. 00068 uint32_t protection_unit; ///< Minimum protectable size in bytes. Applicable if the 'protectable' 00069 ///< attribute is set for the block. This should be a divisor of the block's size. A 00070 ///< block can be considered to be made up of consecutive, individually-protectable fragments. 00071 } ARM_STORAGE_BLOCK_ATTRIBUTES; 00072 00073 /** 00074 * \brief A storage block is a range of memory with uniform attributes. Storage blocks 00075 * combine to make up the address map of a storage controller. 00076 */ 00077 typedef struct _ARM_STORAGE_BLOCK { 00078 uint64_t addr; ///< This is the start address of the storage block. It is 00079 ///< expressed as an offset from the start of the storage map 00080 ///< maintained by the owning storage controller. 00081 uint64_t size; ///< This is the size of the storage block, in units of bytes. 00082 ///< Together with addr, it describes a range [addr, addr+size). 00083 ARM_STORAGE_BLOCK_ATTRIBUTES attributes; ///< Attributes for this block. 00084 } ARM_STORAGE_BLOCK; 00085 00086 /** 00087 * The check for a valid ARM_STORAGE_BLOCK. 00088 */ 00089 #define ARM_STORAGE_VALID_BLOCK(BLK) (((BLK)->addr != ARM_STORAGE_INVALID_OFFSET) && ((BLK)->size != 0)) 00090 00091 /** 00092 * \brief Values for encoding storage memory-types with respect to programmability. 00093 * 00094 * Please ensure that the maximum of the following memory types doesn't exceed 16; we 00095 * encode this in a 4-bit field within ARM_STORAGE_INFO::programmability. 00096 */ 00097 #define ARM_STORAGE_PROGRAMMABILITY_RAM (0x0) 00098 #define ARM_STORAGE_PROGRAMMABILITY_ROM (0x1) ///< Read-only memory. 00099 #define ARM_STORAGE_PROGRAMMABILITY_WORM (0x2) ///< write-once-read-only-memory (WORM). 00100 #define ARM_STORAGE_PROGRAMMABILITY_ERASABLE (0x3) ///< re-programmable based on erase. Supports multiple writes. 00101 00102 /** 00103 * Values for encoding data-retention levels for storage blocks. 00104 * 00105 * Please ensure that the maximum of the following retention types doesn't exceed 16; we 00106 * encode this in a 4-bit field within ARM_STORAGE_INFO::retention_level. 00107 */ 00108 #define ARM_RETENTION_WHILE_DEVICE_ACTIVE (0x0) ///< Data is retained only during device activity. 00109 #define ARM_RETENTION_ACROSS_SLEEP (0x1) ///< Data is retained across processor sleep. 00110 #define ARM_RETENTION_ACROSS_DEEP_SLEEP (0x2) ///< Data is retained across processor deep-sleep. 00111 #define ARM_RETENTION_BATTERY_BACKED (0x3) ///< Data is battery-backed. Device can be powered off. 00112 #define ARM_RETENTION_NVM (0x4) ///< Data is retained in non-volatile memory. 00113 00114 /** 00115 * Device Data Security Protection Features. Applicable mostly to EXTERNAL_NVM. 00116 */ 00117 typedef struct _ARM_STORAGE_SECURITY_FEATURES { 00118 uint32_t acls : 1; ///< Protection against internal software attacks using ACLs. 00119 uint32_t rollback_protection : 1; ///< Roll-back protection. Set to true if the creator of the storage 00120 ///< can ensure that an external attacker can't force an 00121 ///< older firmware to run or to revert back to a previous state. 00122 uint32_t tamper_proof : 1; ///< Tamper-proof memory (will be deleted on tamper-attempts using board level or chip level sensors). 00123 uint32_t internal_flash : 1; ///< Internal flash. 00124 uint32_t reserved1 : 12; 00125 00126 /** 00127 * Encode support for hardening against various classes of attacks. 00128 */ 00129 uint32_t software_attacks : 1; ///< device software (malware running on the device). 00130 uint32_t board_level_attacks : 1; ///< board level attacks (debug probes, copy protection fuses.) 00131 uint32_t chip_level_attacks : 1; ///< chip level attacks (tamper-protection). 00132 uint32_t side_channel_attacks : 1; ///< side channel attacks. 00133 uint32_t reserved2 : 12; 00134 } ARM_STORAGE_SECURITY_FEATURES; 00135 00136 #define ARM_STORAGE_PROGRAM_CYCLES_INFINITE (0UL) /**< Infinite or unknown endurance for reprogramming. */ 00137 00138 /** 00139 * \brief Storage information. This contains device-metadata. It is the return 00140 * value from calling GetInfo() on the storage driver. 00141 * 00142 * \details These fields serve a different purpose than the ones contained in 00143 * \ref ARM_STORAGE_CAPABILITIES, which is another structure containing 00144 * device-level metadata. ARM_STORAGE_CAPABILITIES describes the API 00145 * capabilities, whereas ARM_STORAGE_INFO describes the device. Furthermore 00146 * ARM_STORAGE_CAPABILITIES fits within a single word, and is designed to be 00147 * passed around by value; ARM_STORAGE_INFO, on the other hand, contains 00148 * metadata which doesn't fit into a single word and requires the use of 00149 * pointers to be moved around. 00150 */ 00151 typedef struct _ARM_STORAGE_INFO { 00152 uint64_t total_storage; ///< Total available storage, in bytes. 00153 uint32_t program_unit; ///< Minimum programming size in bytes. 00154 ///< The offset of the start of the program-range should also be aligned with this value. 00155 ///< Applicable only if the 'programmable' attribute is set for a block. 00156 ///< @note: setting program_unit to 0 has the effect of disabling the size and alignment 00157 ///< restrictions (setting it to 1 also has the same effect). 00158 uint32_t optimal_program_unit; ///< Optimal programming page-size in bytes. Some storage controllers 00159 ///< have internal buffers into which to receive data. Writing in chunks of 00160 ///< 'optimal_program_unit' would achieve maximum programming speed. 00161 ///< Applicable only if the 'programmable' attribute is set for the underlying block(s). 00162 uint32_t program_cycles; ///< A measure of endurance for reprogramming. 00163 ///< Use ARM_STORAGE_PROGRAM_CYCLES_INFINITE for infinite or unknown endurance. 00164 uint32_t erased_value : 1; ///< Contents of erased memory (usually 1 to indicate erased bytes with state 0xFF). 00165 uint32_t memory_mapped : 1; ///< This storage device has a mapping onto the processor's memory address space. 00166 ///< @note: For a memory-mapped block which isn't erasable but is programmable (i.e. if 00167 ///< 'erasable' is set to 0, but 'programmable' is 1), writes should be possible directly to 00168 ///< the memory-mapped storage without going through the ProgramData operation. 00169 uint32_t programmability : 4; ///< A value to indicate storage programmability. 00170 uint32_t retention_level : 4; 00171 uint32_t reserved : 22; 00172 ARM_STORAGE_SECURITY_FEATURES security; ///< \ref ARM_STORAGE_SECURITY_FEATURES 00173 } ARM_STORAGE_INFO; 00174 00175 /** 00176 \brief Operating status of the storage controller. 00177 */ 00178 typedef struct _ARM_STORAGE_STATUS { 00179 uint32_t busy : 1; ///< Controller busy flag 00180 uint32_t error : 1; ///< Read/Program/Erase error flag (cleared on start of next operation) 00181 } ARM_STORAGE_STATUS; 00182 00183 /** 00184 * \brief Storage Driver API Capabilities. 00185 * 00186 * This data structure is designed to fit within a single word so that it can be 00187 * fetched cheaply using a call to driver->GetCapabilities(). 00188 */ 00189 typedef struct _ARM_STORAGE_CAPABILITIES { 00190 uint32_t asynchronous_ops : 1; ///< Used to indicate if APIs like initialize, 00191 ///< read, erase, program, etc. can operate in asynchronous mode. 00192 ///< Setting this bit to 1 means that the driver is capable 00193 ///< of launching asynchronous operations; command completion is 00194 ///< signaled by the invocation of a completion callback. If 00195 ///< set to 1, drivers may still complete asynchronous 00196 ///< operations synchronously as necessary--in which case they 00197 ///< return a positive error code to indicate synchronous completion. 00198 uint32_t erase_all : 1; ///< Supports EraseAll operation. 00199 uint32_t reserved : 30; 00200 } ARM_STORAGE_CAPABILITIES; 00201 00202 /** 00203 * Command opcodes for Storage. Completion callbacks use these codes to refer to 00204 * completing commands. Refer to \ref ARM_Storage_Callback_t. 00205 */ 00206 typedef enum _ARM_STORAGE_OPERATION { 00207 ARM_STORAGE_OPERATION_GET_VERSION, 00208 ARM_STORAGE_OPERATION_GET_CAPABILITIES, 00209 ARM_STORAGE_OPERATION_INITIALIZE, 00210 ARM_STORAGE_OPERATION_UNINITIALIZE, 00211 ARM_STORAGE_OPERATION_POWER_CONTROL, 00212 ARM_STORAGE_OPERATION_READ_DATA, 00213 ARM_STORAGE_OPERATION_PROGRAM_DATA, 00214 ARM_STORAGE_OPERATION_ERASE, 00215 ARM_STORAGE_OPERATION_ERASE_ALL, 00216 ARM_STORAGE_OPERATION_GET_STATUS, 00217 ARM_STORAGE_OPERATION_GET_INFO, 00218 ARM_STORAGE_OPERATION_RESOLVE_ADDRESS, 00219 ARM_STORAGE_OPERATION_GET_NEXT_BLOCK, 00220 ARM_STORAGE_OPERATION_GET_BLOCK 00221 } ARM_STORAGE_OPERATION; 00222 00223 /** 00224 * Declaration of the callback-type for command completion. 00225 * 00226 * @param [in] status 00227 * A code to indicate the status of the completed operation. For data 00228 * transfer operations, the status field is overloaded in case of 00229 * success to return the count of items successfully transferred; this 00230 * can be done safely because error codes are negative values. 00231 * 00232 * @param [in] operation 00233 * The command op-code. This value isn't essential for the callback in 00234 * the presence of the command instance-id, but it is expected that 00235 * this information could be a quick and useful filter. 00236 */ 00237 typedef void (*ARM_Storage_Callback_t)(int32_t status, ARM_STORAGE_OPERATION operation); 00238 00239 /** 00240 * This is the set of operations constituting the Storage driver. Their 00241 * implementation is platform-specific, and needs to be supplied by the 00242 * porting effort. 00243 * 00244 * Some APIs within `ARM_DRIVER_STORAGE` will always operate synchronously: 00245 * GetVersion, GetCapabilities, GetStatus, GetInfo, ResolveAddress, 00246 * GetNextBlock, and GetBlock. This means that control returns to the caller 00247 * with a relevant status code only after the completion of the operation (or 00248 * the discovery of a failure condition). 00249 * 00250 * The remainder of the APIs: Initialize, Uninitialize, PowerControl, ReadData, 00251 * ProgramData, Erase, EraseAll, can function asynchronously if the underlying 00252 * controller supports it--i.e. if ARM_STORAGE_CAPABILITIES::asynchronous_ops is 00253 * set. In the case of asynchronous operation, the invocation returns early 00254 * (with ARM_DRIVER_OK) and results in a completion callback later. If 00255 * ARM_STORAGE_CAPABILITIES::asynchronous_ops is not set, then all such APIs 00256 * execute synchronously, and control returns to the caller with a status code 00257 * only after the completion of the operation (or the discovery of a failure 00258 * condition). 00259 * 00260 * If ARM_STORAGE_CAPABILITIES::asynchronous_ops is set, a storage driver may 00261 * still choose to execute asynchronous operations in a synchronous manner. If 00262 * so, the driver returns a positive value to indicate successful synchronous 00263 * completion (or an error code in case of failure) and no further invocation of 00264 * completion callback should be expected. The expected return value for 00265 * synchronous completion of such asynchronous operations varies depending on 00266 * the operation. For operations involving data access, it often equals the 00267 * amount of data transferred or affected. For non data-transfer operations, 00268 * such as EraseAll or Initialize, it is usually 1. 00269 * 00270 * Here's a code snippet to suggest how asynchronous APIs might be used by 00271 * callers to handle both synchronous and asynchronous execution by the 00272 * underlying storage driver: 00273 * \code 00274 * ASSERT(ARM_DRIVER_OK == 0); // this is a precondition; it doesn't need to be put in code 00275 * int32_t returnValue = drv->asynchronousAPI(...); 00276 * if (returnValue < ARM_DRIVER_OK) { 00277 * // handle error. 00278 * } else if (returnValue == ARM_DRIVER_OK) { 00279 * ASSERT(drv->GetCapabilities().asynchronous_ops == 1); 00280 * // handle early return from asynchronous execution; remainder of the work is done in the callback handler. 00281 * } else { 00282 * ASSERT(returnValue == EXPECTED_RETURN_VALUE_FOR_SYNCHRONOUS_COMPLETION); 00283 * // handle synchronous completion. 00284 * } 00285 * \endcode 00286 */ 00287 typedef struct _ARM_DRIVER_STORAGE { 00288 /** 00289 * \brief Get driver version. 00290 * 00291 * The function GetVersion() returns version information of the driver implementation in ARM_DRIVER_VERSION. 00292 * 00293 * - API version is the version of the CMSIS-Driver specification used to implement this driver. 00294 * - Driver version is source code version of the actual driver implementation. 00295 * 00296 * Example: 00297 * \code 00298 * extern ARM_DRIVER_STORAGE *drv_info; 00299 * 00300 * void read_version (void) { 00301 * ARM_DRIVER_VERSION version; 00302 * 00303 * version = drv_info->GetVersion (); 00304 * if (version.api < 0x10A) { // requires at minimum API version 1.10 or higher 00305 * // error handling 00306 * return; 00307 * } 00308 * } 00309 * \endcode 00310 * 00311 * @return \ref ARM_DRIVER_VERSION. 00312 * 00313 * @note This API returns synchronously--it does not result in an invocation 00314 * of a completion callback. 00315 * 00316 * @note The function GetVersion() can be called any time to obtain the 00317 * required information from the driver (even before initialization). It 00318 * always returns the same information. 00319 */ 00320 ARM_DRIVER_VERSION (*GetVersion)(void); 00321 00322 /** 00323 * \brief Get driver capabilities. 00324 * 00325 * \details The function GetCapabilities() returns information about 00326 * capabilities in this driver implementation. The data fields of the struct 00327 * ARM_STORAGE_CAPABILITIES encode various capabilities, for example if the device 00328 * is able to execute operations asynchronously. 00329 * 00330 * Example: 00331 * \code 00332 * extern ARM_DRIVER_STORAGE *drv_info; 00333 * 00334 * void read_capabilities (void) { 00335 * ARM_STORAGE_CAPABILITIES drv_capabilities; 00336 * 00337 * drv_capabilities = drv_info->GetCapabilities (); 00338 * // interrogate capabilities 00339 * 00340 * } 00341 * \endcode 00342 * 00343 * @return \ref ARM_STORAGE_CAPABILITIES. 00344 * 00345 * @note This API returns synchronously--it does not result in an invocation 00346 * of a completion callback. 00347 * 00348 * @note The function GetCapabilities() can be called any time to obtain the 00349 * required information from the driver (even before initialization). It 00350 * always returns the same information. 00351 */ 00352 ARM_STORAGE_CAPABILITIES (*GetCapabilities)(void); 00353 00354 /** 00355 * \brief Initialize the Storage Interface. 00356 * 00357 * The function Initialize is called when the middleware component starts 00358 * operation. In addition to bringing the controller to a ready state, 00359 * Initialize() receives a callback handler to be invoked upon completion of 00360 * asynchronous operations. 00361 * 00362 * Initialize() needs to be called explicitly before 00363 * powering the peripheral using PowerControl(), and before initiating other 00364 * accesses to the storage controller. 00365 * 00366 * The function performs the following operations: 00367 * - Initializes the resources needed for the Storage interface. 00368 * - Registers the \ref ARM_Storage_Callback_t callback function. 00369 * 00370 * To start working with a peripheral the functions Initialize and PowerControl need to be called in this order: 00371 * drv->Initialize (...); // Allocate I/O pins 00372 * drv->PowerControl (ARM_POWER_FULL); // Power up peripheral, setup IRQ/DMA 00373 * 00374 * - Initialize() typically allocates the I/O resources (pins) for the 00375 * peripheral. The function can be called multiple times; if the I/O resources 00376 * are already initialized it performs no operation and just returns with 00377 * ARM_DRIVER_OK. 00378 * 00379 * - PowerControl (ARM_POWER_FULL) sets the peripheral registers including 00380 * interrupt (NVIC) and optionally DMA. The function can be called multiple 00381 * times; if the registers are already set it performs no operation and just 00382 * returns with ARM_DRIVER_OK. 00383 * 00384 * To stop working with a peripheral the functions PowerControl and Uninitialize need to be called in this order: 00385 * drv->PowerControl (ARM_POWER_OFF); // Terminate any pending transfers, reset IRQ/DMA, power off peripheral 00386 * drv->Uninitialize (...); // Release I/O pins 00387 * 00388 * The functions PowerControl and Uninitialize always execute and can be used 00389 * to put the peripheral into a Safe State, for example after any data 00390 * transmission errors. To restart the peripheral in an error condition, 00391 * you should first execute the Stop Sequence and then the Start Sequence. 00392 * 00393 * @param [in] callback 00394 * Caller-defined callback to be invoked upon command completion 00395 * for asynchronous APIs (including the completion of 00396 * initialization). Use a NULL pointer when no callback 00397 * signals are required. 00398 * 00399 * @note This API may execute asynchronously if 00400 * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous 00401 * execution is optional even if 'asynchronous_ops' is set. 00402 * 00403 * @return If asynchronous activity is launched, an invocation returns 00404 * ARM_DRIVER_OK, and the caller can expect to receive a callback in the 00405 * future with a status value of ARM_DRIVER_OK or an error-code. In the 00406 * case of synchronous execution, control returns after completion with a 00407 * value of 1. Return values less than ARM_DRIVER_OK (0) signify errors. 00408 */ 00409 int32_t (*Initialize)(ARM_Storage_Callback_t callback); 00410 00411 /** 00412 * \brief De-initialize the Storage Interface. 00413 * 00414 * The function Uninitialize() de-initializes the resources of Storage interface. 00415 * 00416 * It is called when the middleware component stops operation, and wishes to 00417 * release the software resources used by the interface. 00418 * 00419 * @note This API may execute asynchronously if 00420 * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous 00421 * execution is optional even if 'asynchronous_ops' is set. 00422 * 00423 * @return If asynchronous activity is launched, an invocation returns 00424 * ARM_DRIVER_OK, and the caller can expect to receive a callback in the 00425 * future with a status value of ARM_DRIVER_OK or an error-code. In the 00426 * case of synchronous execution, control returns after completion with a 00427 * value of 1. Return values less than ARM_DRIVER_OK (0) signify errors. 00428 */ 00429 int32_t (*Uninitialize)(void); 00430 00431 /** 00432 * \brief Control the Storage interface power. 00433 * 00434 * The function \b ARM_Storage_PowerControl operates the power modes of the Storage interface. 00435 * 00436 * To start working with a peripheral the functions Initialize and PowerControl need to be called in this order: 00437 * drv->Initialize (...); // Allocate I/O pins 00438 * drv->PowerControl (ARM_POWER_FULL); // Power up peripheral, setup IRQ/DMA 00439 * 00440 * - Initialize() typically allocates the I/O resources (pins) for the 00441 * peripheral. The function can be called multiple times; if the I/O resources 00442 * are already initialized it performs no operation and just returns with 00443 * ARM_DRIVER_OK. 00444 * 00445 * - PowerControl (ARM_POWER_FULL) sets the peripheral registers including 00446 * interrupt (NVIC) and optionally DMA. The function can be called multiple 00447 * times; if the registers are already set it performs no operation and just 00448 * returns with ARM_DRIVER_OK. 00449 * 00450 * To stop working with a peripheral the functions PowerControl and Uninitialize need to be called in this order: 00451 * 00452 * drv->PowerControl (ARM_POWER_OFF); // Terminate any pending transfers, reset IRQ/DMA, power off peripheral 00453 * drv->Uninitialize (...); // Release I/O pins 00454 * 00455 * The functions PowerControl and Uninitialize always execute and can be used 00456 * to put the peripheral into a Safe State, for example after any data 00457 * transmission errors. To restart the peripheral in an error condition, 00458 * you should first execute the Stop Sequence and then the Start Sequence. 00459 * 00460 * @param state 00461 * \ref ARM_POWER_STATE. The target power-state for the storage controller. 00462 * The parameter state can have the following values: 00463 * - ARM_POWER_FULL : set-up peripheral for data transfers, enable interrupts 00464 * (NVIC) and optionally DMA. Can be called multiple times. If the peripheral 00465 * is already in this mode, then the function performs no operation and returns 00466 * with ARM_DRIVER_OK. 00467 * - ARM_POWER_LOW : may use power saving. Returns ARM_DRIVER_ERROR_UNSUPPORTED when not implemented. 00468 * - ARM_POWER_OFF : terminates any pending data transfers, disables peripheral, disables related interrupts and DMA. 00469 * 00470 * @note This API may execute asynchronously if 00471 * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous 00472 * execution is optional even if 'asynchronous_ops' is set. 00473 * 00474 * @return If asynchronous activity is launched, an invocation returns 00475 * ARM_DRIVER_OK, and the caller can expect to receive a callback in the 00476 * future with a status value of ARM_DRIVER_OK or an error-code. In the 00477 * case of synchronous execution, control returns after completion with a 00478 * value of 1. Return values less than ARM_DRIVER_OK (0) signify errors. 00479 */ 00480 int32_t (*PowerControl)(ARM_POWER_STATE state); 00481 00482 /** 00483 * \brief read the contents of a given address range from the storage device. 00484 * 00485 * \details Read the contents of a range of storage memory into a buffer 00486 * supplied by the caller. The buffer is owned by the caller and should 00487 * remain accessible for the lifetime of this command. 00488 * 00489 * @param [in] addr 00490 * This specifies the address from where to read data. 00491 * 00492 * @param [out] data 00493 * The destination of the read operation. The buffer 00494 * is owned by the caller and should remain accessible for the 00495 * lifetime of this command. 00496 * 00497 * @param [in] size 00498 * The number of bytes requested to read. The data buffer 00499 * should be at least as large as this size. 00500 * 00501 * @note This API may execute asynchronously if 00502 * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous 00503 * execution is optional even if 'asynchronous_ops' is set. 00504 * 00505 * @return If asynchronous activity is launched, an invocation returns 00506 * ARM_DRIVER_OK, and the caller can expect to receive a callback in the 00507 * future with the number of successfully transferred bytes passed in as 00508 * the 'status' parameter. In the case of synchronous execution, control 00509 * returns after completion with a positive transfer-count. Return values 00510 * less than ARM_DRIVER_OK (0) signify errors. 00511 */ 00512 int32_t (*ReadData)(uint64_t addr, void *data, uint32_t size); 00513 00514 /** 00515 * \brief program (write into) the contents of a given address range of the storage device. 00516 * 00517 * \details Write the contents of a given memory buffer into a range of 00518 * storage memory. In the case of flash memory, the destination range in 00519 * storage memory typically has its contents in an erased state from a 00520 * preceding erase operation. The source memory buffer is owned by the 00521 * caller and should remain accessible for the lifetime of this command. 00522 * 00523 * @param [in] addr 00524 * This is the start address of the range to be written into. It 00525 * needs to be aligned to the device's \em program_unit 00526 * specified in \ref ARM_STORAGE_INFO. 00527 * 00528 * @param [in] data 00529 * The source of the write operation. The buffer is owned by the 00530 * caller and should remain accessible for the lifetime of this 00531 * command. 00532 * 00533 * @param [in] size 00534 * The number of bytes requested to be written. The buffer 00535 * should be at least as large as this size. \note 'size' should 00536 * be a multiple of the device's 'program_unit' (see \ref 00537 * ARM_STORAGE_INFO). 00538 * 00539 * @note It is best for the middleware to write in units of 00540 * 'optimal_program_unit' (\ref ARM_STORAGE_INFO) of the device. 00541 * 00542 * @note This API may execute asynchronously if 00543 * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous 00544 * execution is optional even if 'asynchronous_ops' is set. 00545 * 00546 * @return If asynchronous activity is launched, an invocation returns 00547 * ARM_DRIVER_OK, and the caller can expect to receive a callback in the 00548 * future with the number of successfully transferred bytes passed in as 00549 * the 'status' parameter. In the case of synchronous execution, control 00550 * returns after completion with a positive transfer-count. Return values 00551 * less than ARM_DRIVER_OK (0) signify errors. 00552 */ 00553 int32_t (*ProgramData)(uint64_t addr, const void *data, uint32_t size); 00554 00555 /** 00556 * @brief Erase Storage range. 00557 * 00558 * @details This function erases a range of storage specified by [addr, addr + 00559 * size). Both 'addr' and 'addr + size' should align with the 00560 * 'erase_unit'(s) of the respective owning storage block(s) (see \ref 00561 * ARM_STORAGE_BLOCK and \ref ARM_STORAGE_BLOCK_ATTRIBUTES). The range to 00562 * be erased will have its contents returned to the un-programmed state-- 00563 * i.e. to 'erased_value' (see \ref ARM_STORAGE_BLOCK_ATTRIBUTES), which 00564 * is usually 1 to indicate the pattern of all ones: 0xFF. 00565 * 00566 * @param [in] addr 00567 * This is the start-address of the range to be erased. It must 00568 * start at an 'erase_unit' boundary of the underlying block. 00569 * 00570 * @param [in] size 00571 * Size (in bytes) of the range to be erased. 'addr + size' 00572 * must be aligned with the 'erase_unit' of the underlying 00573 * block. 00574 * 00575 * @note This API may execute asynchronously if 00576 * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous 00577 * execution is optional even if 'asynchronous_ops' is set. 00578 * 00579 * @return 00580 * If the range to be erased doesn't align with the erase_units of the 00581 * respective start and end blocks, ARM_DRIVER_ERROR_PARAMETER is returned. 00582 * If any part of the range is protected, ARM_STORAGE_ERROR_PROTECTED is 00583 * returned. If any part of the range is not erasable, 00584 * ARM_STORAGE_ERROR_NOT_ERASABLE is returned. All such sanity-check 00585 * failures result in the error code being returned synchronously and the 00586 * storage bytes within the range remain unaffected. 00587 * Otherwise the function executes in the following ways: 00588 * If asynchronous activity is launched, an invocation returns 00589 * ARM_DRIVER_OK, and the caller can expect to receive a callback in the 00590 * future with the number of successfully erased bytes passed in as 00591 * the 'status' parameter. In the case of synchronous execution, control 00592 * returns after completion with a positive erase-count. Return values 00593 * less than ARM_DRIVER_OK (0) signify errors. 00594 * 00595 * @note Erase() may return a smaller (positive) value than the size of the 00596 * requested range. The returned value indicates the actual number of bytes 00597 * erased. It is the caller's responsibility to follow up with an appropriate 00598 * request to complete the operation. 00599 * 00600 * @note in the case of a failed erase (except when 00601 * ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_ERROR_PROTECTED, or 00602 * ARM_STORAGE_ERROR_NOT_ERASABLE is returned synchronously), the 00603 * requested range should be assumed to be in an unknown state. The 00604 * previous contents may not be retained. 00605 */ 00606 int32_t (*Erase)(uint64_t addr, uint32_t size); 00607 00608 /** 00609 * @brief Erase complete storage. Optional function for faster erase of the complete device. 00610 * 00611 * This optional function erases the complete device. If the device does not 00612 * support global erase then the function returns the error value \ref 00613 * ARM_DRIVER_ERROR_UNSUPPORTED. The data field \em 'erase_all' = 00614 * \token{1} of the structure \ref ARM_STORAGE_CAPABILITIES encodes that 00615 * \ref ARM_STORAGE_EraseAll is supported. 00616 * 00617 * @note This API may execute asynchronously if 00618 * ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous 00619 * execution is optional even if 'asynchronous_ops' is set. 00620 * 00621 * @return 00622 * If any part of the storage range is protected, 00623 * ARM_STORAGE_ERROR_PROTECTED is returned. If any part of the storage 00624 * range is not erasable, ARM_STORAGE_ERROR_NOT_ERASABLE is returned. All 00625 * such sanity-check failures result in the error code being returned 00626 * synchronously and the storage bytes within the range remain unaffected. 00627 * Otherwise the function executes in the following ways: 00628 * If asynchronous activity is launched, an invocation returns 00629 * ARM_DRIVER_OK, and the caller can expect to receive a callback in the 00630 * future with ARM_DRIVER_OK passed in as the 'status' parameter. In the 00631 * case of synchronous execution, control returns after completion with a 00632 * value of 1. Return values less than ARM_DRIVER_OK (0) signify errors. 00633 */ 00634 int32_t (*EraseAll)(void); 00635 00636 /** 00637 * @brief Get the status of the current (or previous) command executed by the 00638 * storage controller; stored in the structure \ref ARM_STORAGE_STATUS. 00639 * 00640 * @return 00641 * The status of the underlying controller. 00642 * 00643 * @note This API returns synchronously--it does not result in an invocation 00644 * of a completion callback. 00645 */ 00646 ARM_STORAGE_STATUS (*GetStatus)(void); 00647 00648 /** 00649 * @brief Get information about the Storage device; stored in the structure \ref ARM_STORAGE_INFO. 00650 * 00651 * @param [out] info 00652 * A caller-supplied buffer capable of being filled in with an 00653 * \ref ARM_STORAGE_INFO. 00654 * 00655 * @return ARM_DRIVER_OK if a ARM_STORAGE_INFO structure containing top level 00656 * metadata about the storage controller is filled into the supplied 00657 * buffer, else an appropriate error value. 00658 * 00659 * @note It is the caller's responsibility to ensure that the buffer passed in 00660 * is able to be initialized with a \ref ARM_STORAGE_INFO. 00661 * 00662 * @note This API returns synchronously--it does not result in an invocation 00663 * of a completion callback. 00664 */ 00665 int32_t (*GetInfo)(ARM_STORAGE_INFO *info); 00666 00667 /** 00668 * \brief For memory-mapped storage, resolve an address relative to 00669 * the storage controller into a memory address. 00670 * 00671 * @param addr 00672 * This is the address for which we want a resolution to the 00673 * processor's physical address space. It is an offset from the 00674 * start of the storage map maintained by the owning storage 00675 * controller. 00676 * 00677 * @return 00678 * The resolved address in the processor's address space; else 00679 * ARM_STORAGE_INVALID_ADDRESS, if no resolution is possible. 00680 * 00681 * @note This API returns synchronously. The invocation should return quickly, 00682 * and result in a resolved address. 00683 */ 00684 uint32_t (*ResolveAddress)(uint64_t addr); 00685 00686 /** 00687 * @brief Advance to the successor of the current block (iterator), or fetch 00688 * the first block (if 'prev_block' is passed in as NULL). 00689 * 00690 * @details This helper function fetches (an iterator to) the next block (or 00691 * the first block if 'prev_block' is passed in as NULL). In the failure 00692 * case, a terminating, invalid block iterator is filled into the out 00693 * parameter: 'next_block'. In combination with \ref 00694 * ARM_STORAGE_VALID_BLOCK(), it can be used to iterate over the sequence 00695 * of blocks within the storage map: 00696 * 00697 * \code 00698 * ARM_STORAGE_BLOCK block; 00699 * for (drv->GetNextBlock(NULL, &block); ARM_STORAGE_VALID_BLOCK(&block); drv->GetNextBlock(&block, &block)) { 00700 * // make use of block 00701 * } 00702 * \endcode 00703 * 00704 * @param[in] prev_block 00705 * An existing block (iterator) within the same storage 00706 * controller. The memory buffer holding this block is owned 00707 * by the caller. This pointer may be NULL; if so, the 00708 * invocation fills in the first block into the out parameter: 00709 * 'next_block'. 00710 * 00711 * @param[out] next_block 00712 * A caller-owned buffer large enough to be filled in with 00713 * the following ARM_STORAGE_BLOCK. It is legal to provide the 00714 * same buffer using 'next_block' as was passed in with 'prev_block'. It 00715 * is also legal to pass a NULL into this parameter if the 00716 * caller isn't interested in populating a buffer with the next 00717 * block--i.e. if the caller only wishes to establish the 00718 * presence of a next block. 00719 * 00720 * @return ARM_DRIVER_OK if a valid next block is found (or first block, if 00721 * prev_block is passed as NULL); upon successful operation, the contents 00722 * of the next (or first) block are filled into the buffer pointed to by 00723 * the parameter 'next_block' and ARM_STORAGE_VALID_BLOCK(next_block) is 00724 * guaranteed to be true. Upon reaching the end of the sequence of blocks 00725 * (iterators), or in case the driver is unable to fetch information about 00726 * the next (or first) block, an error (negative) value is returned and an 00727 * invalid StorageBlock is populated into the supplied buffer. If 00728 * prev_block is NULL, the first block is returned. 00729 * 00730 * @note This API returns synchronously--it does not result in an invocation 00731 * of a completion callback. 00732 */ 00733 int32_t (*GetNextBlock)(const ARM_STORAGE_BLOCK* prev_block, ARM_STORAGE_BLOCK *next_block); 00734 00735 /** 00736 * @brief Find the storage block (iterator) encompassing a given storage address. 00737 * 00738 * @param[in] addr 00739 * Storage address in bytes. 00740 * 00741 * @param[out] block 00742 * A caller-owned buffer large enough to be filled in with the 00743 * ARM_STORAGE_BLOCK encapsulating the given address. This value 00744 * can also be passed in as NULL if the caller isn't interested 00745 * in populating a buffer with the block--if the caller only 00746 * wishes to establish the presence of a containing storage 00747 * block. 00748 * 00749 * @return ARM_DRIVER_OK if a containing storage-block is found. In this case, 00750 * if block is non-NULL, the buffer pointed to by it is populated with 00751 * the contents of the storage block--i.e. if block is valid and a block is 00752 * found, ARM_STORAGE_VALID_BLOCK(block) would return true following this 00753 * call. If there is no storage block containing the given offset, or in 00754 * case the driver is unable to resolve an address to a storage-block, an 00755 * error (negative) value is returned and an invalid StorageBlock is 00756 * populated into the supplied buffer. 00757 * 00758 * @note This API returns synchronously--it does not result in an invocation 00759 * of a completion callback. 00760 */ 00761 int32_t (*GetBlock)(uint64_t addr, ARM_STORAGE_BLOCK *block); 00762 } const ARM_DRIVER_STORAGE; 00763 00764 #ifdef __cplusplus 00765 } 00766 #endif // __cplusplus 00767 00768 #endif /* __DRIVER_STORAGE_H */
Generated on Tue Jul 12 2022 19:20:55 by
1.7.2
