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