1 /* -----------------------------------------------------------------------------
2 * Copyright (c) 2013-2016 ARM Limited. All rights reserved.
7 * Project: Storage Driver API
8 * -------------------------------------------------------------------------- */
12 \defgroup storage_interface_gr Storage Interface
13 \brief Driver API for Storage Device Interface (%Driver_Storage.h)
15 This is an abstraction for a storage controller. It offers an interface to
16 access an address space of storage locations, comprising APIs for
17 initialization, erase, access, program, and status-fetch operations. It also
18 offers APIs to iterate over the available Storage Blocks (\ref
19 ARM_STORAGE_BLOCK), allowing the discovery of block attributes such as
20 write/erase granularities. Using the Storage abstraction, it becomes possible to
21 write generic algorithms, such as block copy, to operate on any conforming
24 \note The storage abstraction layer is not responsible for storage management.
25 Algorithms such as block-allocation, wear-leveling, erase-before-write and other
26 storage-management policies are the responsibility of modules external to the
27 storage abstraction layer. In essence, the storage interface is the lowest
28 abstraction upon which block management policies can be implemented.
30 Here's a picture to help locate the storage abstraction in the software stack.
31 The part below the box labeled 'Storage abstraction layer' is implemented by a
34 +----------------------------------+
36 | or UBI (Unsorted Block Image) |
37 | (Block Management: alloc, erase) |
39 +--------------+-------------------+
41 +------------v--------------+
42 | Storage abstraction layer |
43 +--+--------------+----+----+
46 | | +-------------------------------------+
47 +---------v----------+ | |
48 | ARM_DRIVER_STORAGE | | |
49 | +----------------+ | | |
50 | (impl. specific) | +------+ |
51 | GetVersion | | Implemented |
52 | GetCapability | | Using a potentially Implemented | Using
53 | access operations | | dynamic table of | single
55 | Erase | +--------v---------------------+ +----------v----------------+
56 | Program | | ARM_STORAGE_BLOCK | | |
57 | ... | | +---------------+ | | ARM_STORAGE_CAPABILITIES |
58 | Resolve Address | | start_addr | | |
59 | Iteration ops | | size | +---------------------------+
60 | FirstSegment | | ARM_STORAGE_BLOCK_ATTRIBUTES|
62 | ... | +------------------------------+
63 +--------------------+
67 The following header files define the Application Programming Interface (API) for the Flash interface:
68 - \b %Driver_Storage.h : Driver API for Storage Device Interface
73 The driver functions are published in the access struct as explained in \ref DriverFunctions
74 - \ref ARM_DRIVER_STORAGE : access struct for Storage driver functions
76 A sample use for the driver can be found at: \ref SampleUseOfStorageDriver
77 *******************************************************************************************************************/
80 \defgroup SampleUseOfStorageDriver Sample Use of Storage Driver
84 The following is a generic algorithm to erase
85 and program one \ref ARM_STORAGE_BLOCK_ATTRIBUTES::erase_unit worth of storage
86 and then read it back to be verified. It handles both synchronous and
87 asynchronous driver implementations.
90 // Copyright (c) 2006-2016, ARM Limited, All Rights Reserved
91 // SPDX-License-Identifier: Apache-2.0
93 // Licensed under the Apache License, Version 2.0 (the "License"); you may
94 // not use this file except in compliance with the License.
95 // You may obtain a copy of the License at
97 // http:// www.apache.org/licenses/LICENSE-2.0
99 // Unless required by applicable law or agreed to in writing, software
100 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
101 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
102 // See the License for the specific language governing permissions and
103 // limitations under the License.
105 #include "Driver_Storage.h"
109 #define TEST_ASSERT(Expr) if (!(Expr)) { printf("%s:%u: assertion failure\n", __FUNCTION__, __LINE__); while (1) ;}
110 #define TEST_ASSERT_EQUAL(expected, actual) if ((expected) != (actual)) {printf("%s:%u: assertion failure\n", __FUNCTION__, __LINE__); while (1) ;}
111 #define TEST_ASSERT_NOT_EQUAL(expected, actual) if ((expected) == (actual)) {printf("%s:%u: assertion failure\n", __FUNCTION__, __LINE__); while (1) ;}
113 // forward declarations
114 void callbackHandler(int32_t status, ARM_STORAGE_OPERATION operation);
115 void progressStateMachine(void);
118 NEEDS_INITIALIZATION,
122 NEEDS_VERIFICATION_FOLLOWING_READ,
126 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_(0);
127 ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_(0);
129 static const unsigned BUFFER_SIZE = 16384;
130 static uint8_t buffer[BUFFER_SIZE];
132 void main(int argc __unused, char** argv __unused)
134 state = NEEDS_INITIALIZATION;
136 progressStateMachine();
138 // WFE(); // optional low-power sleep
142 void progressStateMachine(void)
146 static ARM_STORAGE_BLOCK firstBlock;
147 if (!ARM_STORAGE_VALID_BLOCK(&firstBlock)) {
148 // Get the first block. This block is entered only once.
149 rc = drv->GetNextBlock(NULL, &firstBlock); // get first block
150 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
152 TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
153 TEST_ASSERT(firstBlock.size > 0);
156 case NEEDS_INITIALIZATION:
157 rc = drv->Initialize(callbackHandler);
158 TEST_ASSERT(rc >= ARM_DRIVER_OK);
159 if (rc == ARM_DRIVER_OK) {
160 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
162 return; // there is pending asynchronous activity which will lead to a completion callback later.
164 TEST_ASSERT_EQUAL(1, rc); // synchronous completion
166 // intentional fall-through
169 TEST_ASSERT(firstBlock.attributes.erase_unit > 0);
170 rc = drv->Erase(firstBlock.addr, firstBlock.attributes.erase_unit);
171 TEST_ASSERT(rc >= ARM_DRIVER_OK);
172 if (rc == ARM_DRIVER_OK) {
173 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
174 state = NEEDS_PROGRAMMING;
175 return; // there is pending asynchronous activity which will lead to a completion callback later.
177 TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, (uint32_t)rc); // synchronous completion
179 // intentional fall-through
181 case NEEDS_PROGRAMMING:
182 TEST_ASSERT(BUFFER_SIZE >= firstBlock.attributes.erase_unit);
184 memset(buffer, PATTERN, firstBlock.attributes.erase_unit);
185 rc = drv->ProgramData(firstBlock.addr, buffer, firstBlock.attributes.erase_unit);
186 TEST_ASSERT(rc >= ARM_DRIVER_OK);
187 if (rc == ARM_DRIVER_OK) {
188 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
190 return; // there is pending asynchronous activity which will lead to a completion callback later.
192 TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, (uint32_t)rc); // synchronous completion
194 // intentional fall-through
197 rc = drv->ReadData(firstBlock.addr, buffer, firstBlock.attributes.erase_unit);
198 TEST_ASSERT(rc >= ARM_DRIVER_OK);
199 if (rc == ARM_DRIVER_OK) {
200 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
201 state = NEEDS_VERIFICATION_FOLLOWING_READ;
202 return; // there is pending asynchronous activity which will lead to a completion callback later.
204 TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, (uint32_t)rc);
206 // intentional fall-through
208 case NEEDS_VERIFICATION_FOLLOWING_READ:
209 printf("verifying data\r\n");
210 for (unsigned i = 0; i < firstBlock.attributes.erase_unit; i++) {
211 TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
222 void callbackHandler(int32_t status, ARM_STORAGE_OPERATION operation)
227 case ARM_STORAGE_OPERATION_INITIALIZE:
228 case ARM_STORAGE_OPERATION_READ_DATA:
229 case ARM_STORAGE_OPERATION_PROGRAM_DATA:
230 case ARM_STORAGE_OPERATION_ERASE:
231 progressStateMachine();
235 printf("callbackHandler: unexpected callback for opcode %u with status %ld\r\n", operation, status);
241 *******************************************************************************************************************/
244 \addtogroup storage_interface_gr
246 *******************************************************************************************************************/
249 \struct ARM_STORAGE_BLOCK_ATTRIBUTES
251 - \ref ARM_STORAGE_BLOCK
252 *******************************************************************************************************************/
255 \struct ARM_STORAGE_BLOCK
256 \details Storage blocks combine to make up the address map of a storage controller.
257 *******************************************************************************************************************/
260 \struct ARM_STORAGE_INFO
262 It describes the characteristics of a Storage device. This includes total
263 storage, programming size, a default value for erased memory etc. This
264 information can be obtained from the Storage device datasheet and is used by the
265 middleware in order to properly interact with the Storage device.
267 Total available storage (in bytes) is contained in \em total_storage. Minimum
268 programming size (in bytes) is described by \em program_unit (applicable only if
269 the \em programmable attribute is set for a block). It defines the granularity
270 for programming data. The offset of the start of a program-range and the size
271 should also be aligned with \em program_unit.
272 \note: setting \em program_unit to 0 has the effect of disabling the size and
273 alignment restrictions (setting it to 1 also has the same effect).
275 Optimal programming page-size (in bytes) is specified by \em
276 optimal_program_unit. Some storage controllers have internal buffers into which
277 to receive data. Writing in chunks of \em optimal_program_unit would achieve
278 maximum programming speed. Like with \em program_unit, this is applicable only
279 if the \em programmable attribute is set for the underlying storage block(s).
281 \em program_cycles is a measure of endurance for reprogramming.
282 A value of \em ARM_STORAGE_PROGRAM_CYCLES_INFINITE may be used to signify
283 infinite or unknown endurance.
285 Contents of erased memory is specified by the \em erased_value. It is usually
286 \token{1} to indicate erased bytes with state 0xFF.
288 \em memory_mapped can be set to \token{1} to indicate that the storage device
289 has a mapping onto the processor's memory address space.
290 \note: For a memory-mapped block which isn't erasable but is programmable,
291 writes should be possible directly to the memory-mapped storage without going
292 through the \ref ARM_Storage_ProgramData operation.
294 The field \em programmability holds a value to indicate storage programmability.
295 Similarly, \em retention_level holds a for encoding data-retention levels for
299 These fields serve a different purpose than the ones contained in
300 \ref ARM_STORAGE_CAPABILITIES, which is another structure containing device-level
301 metadata. ARM_STORAGE_CAPABILITIES describes the API capabilities, whereas
302 ARM_STORAGE_INFO describes the device. Furthermore ARM_STORAGE_CAPABILITIES fits
303 within a single word, and is designed to be passed around by value;
304 ARM_STORAGE_INFO, on the other hand, contains metadata which doesn't fit into a
305 single word and requires the use of pointers to be moved around.
308 - \ref ARM_Storage_GetInfo
309 *******************************************************************************************************************/
312 \struct ARM_DRIVER_STORAGE
314 This is the set of operations constituting the Storage driver. Their
315 implementation is platform-specific, and needs to be supplied by the porting
316 effort. The functions of the Storage driver are accessed by function pointers
317 exposed by this structure. Refer to \ref DriverFunctions for overview
320 Each instance of a Storage interface provides such an access structure.
321 The instance is identified by a postfix number in the symbol name of the access structure, for example:
322 - \b Driver_Storage0 is the name of the access struct of the first instance (no. 0).
323 - \b Driver_Storage1 is the name of the access struct of the second instance (no. 1).
325 A middleware configuration setting allows connecting the middleware to a specific driver instance \b %Driver_Flash<i>n</i>.
326 The default is \token{0}, which connects a middleware to the first instance of a driver.
327 *******************************************************************************************************************/
330 \defgroup DriverFunctions Use of Storage APIs
332 Function pointers within \ref ARM_DRIVER_STORAGE form the set of operations
333 constituting the Storage driver. Their implementation is platform-specific, and
334 needs to be supplied by the porting effort.
336 Some of these APIs will always operate synchronously:
337 \ref ARM_Storage_GetVersion, \ref ARM_Storage_GetCapabilities, \ref ARM_Storage_GetStatus,
338 \ref ARM_Storage_GetInfo, \ref ARM_Storage_ResolveAddress, \ref ARM_Storage_GetNextBlock,
339 and \ref ARM_Storage_GetBlock. This means that control returns to the caller
340 with a relevant status code only after the completion of the operation (or
341 the discovery of a failure condition).
343 The remainder of the APIs: \ref ARM_Storage_Initialize, \ref ARM_Storage_Uninitialize, \ref ARM_Storage_PowerControl, \ref ARM_Storage_ReadData,
344 \ref ARM_Storage_ProgramData, \ref ARM_Storage_Erase, and \ref ARM_Storage_EraseAll can function asynchronously if the underlying
345 controller supports it--i.e. if ARM_STORAGE_CAPABILITIES::asynchronous_ops is
346 set. In the case of asynchronous operation, the invocation returns early
347 (with ARM_DRIVER_OK) and results in a completion callback later. If
348 ARM_STORAGE_CAPABILITIES::asynchronous_ops is not set, then all such APIs
349 execute synchronously, and control returns to the caller with a status code
350 only after the completion of the operation (or the discovery of a failure
353 If ARM_STORAGE_CAPABILITIES::asynchronous_ops is set, a storage driver may
354 still choose to execute asynchronous operations in a synchronous manner. If
355 so, the driver returns a positive value to indicate successful synchronous
356 completion (or an error code in case of failure) and no further invocation of
357 completion callback should be expected. The expected return value for
358 synchronous completion of such asynchronous operations varies depending on
359 the operation. For operations involving data access, it often equals the
360 amount of data transferred or affected. For non data-transfer operations,
361 such as EraseAll or Initialize, it is usually 1.
363 Here's a code snippet to suggest how asynchronous APIs might be used by
364 callers to handle both synchronous and asynchronous execution by the
365 underlying storage driver:
367 ASSERT(ARM_DRIVER_OK == 0); // this is a precondition; it doesn't need to be put in code
368 int32_t returnValue = drv->asynchronousAPI(...);
369 if (returnValue < ARM_DRIVER_OK) {
371 } else if (returnValue == ARM_DRIVER_OK) {
372 ASSERT(drv->GetCapabilities().asynchronous_ops == 1);
373 // handle early return from asynchronous execution; remainder of the work is done in the callback handler.
375 ASSERT(returnValue == EXPECTED_RETURN_VALUE_FOR_SYNCHRONOUS_COMPLETION);
376 // handle synchronous completion.
380 Here's a sample use mixing synchronous and asynchronous APIs: \ref SampleUseOfStorageDriver
381 *******************************************************************************************************************/
384 \struct ARM_STORAGE_CAPABILITIES
386 A Storage driver can be implemented with different capabilities. The data fields
387 of this struct encode the API capabilities implemented by this driver.
389 The element \em asynchronous_ops indicates if APIs like initialize, read, erase,
390 program, etc. can operate in asynchronous mode. Having this bit set to 1 means
391 that the driver is capable of launching asynchronous operations; command
392 completion for asynchronous operations is signaled by the invocation of a
393 completion callback. If set to 1, drivers may still complete asynchronous
394 operations synchronously as necessary--in which case they return a positive
395 error code to indicate synchronous completion. If \em asynchronous_ops is not
396 set, then all such APIs execute synchronously, and control returns to the caller
397 with a status code only after the completion of the operation (or the discovery
398 of a failure condition).
400 The element \em erase_all specifies that the \ref ARM_Storage_EraseAll function
401 is supported. Typically full chip erase is much faster than erasing the whole
402 device using \em ARM_Storage_Erase.
405 - \ref ARM_Storage_GetCapabilities
408 This data structure is designed to fit within a single word so that it can be
409 fetched cheaply using a call to driver->GetCapabilities().
410 *******************************************************************************************************************/
413 \struct ARM_STORAGE_STATUS
415 Structure with information about the status of the Storage device.
417 The flag \em busy indicates that the driver is busy executing read/program/erase operation.
419 The flag \em error flag is cleared on start of read/program/erase operation and is set at the end of the current operation in case of error.
422 - \ref ARM_Storage_GetStatus
423 *****************************************************************************************************************/
426 \enum ARM_STORAGE_OPERATION
428 Command opcodes for the Storage interface. Completion callbacks use these codes
429 to refer to completing commands. Refer to \ref ARM_Storage_Callback_t.
430 *****************************************************************************************************************/
433 \typedef ARM_Storage_Callback_t
435 Provides the typedef for the callback function \ref ARM_Storage_Callback_t.
438 A code to indicate the status of the completed operation. For data
439 transfer operations, the status field is overloaded in case of
440 success to return the count of bytes successfully transferred; this
441 can be done safely because error codes are negative values.
443 \param [in] operation
444 The command op-code. This value isn't essential, but it is expected that
445 this information could be a quick and useful filter for the handler.
447 <b>Parameter for:</b>
448 - \ref ARM_Storage_Initialize
449 *******************************************************************************************************************/
456 ARM_DRIVER_VERSION ARM_Storage_GetVersion (void) {
460 \fn ARM_DRIVER_VERSION ARM_Storage_GetVersion (void)
462 The function \b ARM_Storage_GetVersion returns version information of the driver implementation in \ref ARM_DRIVER_VERSION.
463 - API version is the version of the CMSIS-Driver specification used to implement this driver.
464 - Driver version is source code version of the actual driver implementation.
468 extern ARM_DRIVER_STORAGE *drv_info;
470 void read_version (void) {
471 ARM_DRIVER_VERSION version;
473 version = drv_info->GetVersion ();
474 if (version.api < 0x10A) { // requires at minimum API version 1.10 or higher
481 \note This API returns synchronously--it does not result in an invocation
482 of a completion callback.
484 \note The function GetVersion() can be called any time to obtain the
485 required information from the driver (even before initialization). It
486 always returns the same information.
487 *******************************************************************************************************************/
489 ARM_STOR_CAPABILITIES ARM_Storage_GetCapabilities (void) {
493 \fn ARM_STORAGE_CAPABILITIES ARM_Storage_GetCapabilities (void)
496 The function \b ARM_Storage_GetCapabilities returns information about
497 capabilities in this driver implementation. The data fields of the struct
498 ARM_STORAGE_CAPABILITIES encode various capabilities, for example if the device
499 is able to execute operations asynchronously.
503 extern ARM_DRIVER_STORAGE *drv_info;
505 void read_capabilities (void) {
506 ARM_STORAGE_CAPABILITIES drv_capabilities;
508 drv_capabilities = drv_info->GetCapabilities ();
509 // interrogate capabilities
514 \note This API returns synchronously--it does not result in an invocation
515 of a completion callback.
517 \note The function GetCapabilities() can be called any time to obtain the
518 required information from the driver (even before initialization). It
519 always returns the same information.
520 *******************************************************************************************************************/
522 int32_t ARM_Storage_Initialize (ARM_Storage_Callback_t callback) {
526 \fn int32_t ARM_Storage_Initialize (ARM_Storage_Callback_t callback)
528 The function \b ARM_Storage_Initialize is called when the middleware component starts
529 operation. In addition to bringing the controller to a ready state,
530 Initialize() receives a callback handler to be invoked upon completion of
531 asynchronous operations.
533 ARM_Storage_Initialize() needs to be called explicitly before
534 powering the peripheral using ARM_Storage_PowerControl(), and before initiating other
535 accesses to the storage controller.
537 The function performs the following operations:
538 - Initializes the resources needed for the Storage interface.
539 - Registers the \ref ARM_Storage_Callback_t callback function.
541 To start working with a peripheral the functions ARM_Storage_Initialize and ARM_Storage_PowerControl() need to be called in this order:
543 drv->Initialize (...); // Allocate I/O pins
544 drv->PowerControl (ARM_POWER_FULL); // Power up peripheral, setup IRQ/DMA
547 - ARM_Storage_Initialize() typically allocates the I/O resources (pins) for the
548 peripheral. The function can be called multiple times; if the I/O resources
549 are already initialized it performs no operation and just returns with
552 - ARM_Storage_PowerControl (ARM_POWER_FULL) sets the peripheral registers including
553 interrupt (NVIC) and optionally DMA. The function can be called multiple
554 times; if the registers are already set it performs no operation and just
555 returns with ARM_DRIVER_OK.
557 To stop working with a peripheral the functions ARM_Storage_PowerControl() and ARM_Storage_Uninitialize() need to be called in this order:
559 drv->PowerControl (ARM_POWER_OFF); // Terminate any pending transfers, reset IRQ/DMA, power off peripheral
560 drv->Uninitialize (...); // Release I/O pins
563 The functions ARM_Storage_PowerControl() and ARM_Storage_Uninitialize() always execute and can be used
564 to put the peripheral into a Safe State, for example after any data
565 transmission errors. To restart the peripheral in an error condition,
566 you should first execute the Stop Sequence and then the Start Sequence.
568 \note This API may execute asynchronously if
569 ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
570 execution is optional even if 'asynchronous_ops' is set.
571 *******************************************************************************************************************/
573 int32_t ARM_Storage_Uninitialize (void) {
577 \fn int32_t ARM_Storage_Uninitialize (void)
579 It is called when the middleware component stops operation, and wishes to
580 release the software resources used by the interface.
582 \note This API may execute asynchronously if
583 ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
584 execution is optional even if 'asynchronous_ops' is set.
585 *******************************************************************************************************************/
587 int32_t ARM_Storage_PowerControl (ARM_POWER_STATE state) {
591 \fn int32_t ARM_Storage_PowerControl (ARM_POWER_STATE state)
593 The function \b ARM_Storage_PowerControl operates the power modes of the Storage interface.
595 To start working with a peripheral the functions Initialize and PowerControl need to be called in this order:
597 drv->Initialize (...); // Allocate I/O pins
598 drv->PowerControl (ARM_POWER_FULL); // Power up peripheral, setup IRQ/DMA
601 - ARM_Storage_Initialize() typically allocates the I/O resources (pins) for the
602 peripheral. The function can be called multiple times; if the I/O resources
603 are already initialized it performs no operation and just returns with
606 - PowerControl (ARM_POWER_FULL) sets the peripheral registers including
607 interrupt (NVIC) and optionally DMA. The function can be called multiple
608 times; if the registers are already set it performs no operation and just
609 returns with ARM_DRIVER_OK.
611 To stop working with a peripheral the functions PowerControl and Uninitialize need to be called in this order:
613 drv->PowerControl (ARM_POWER_OFF); // Terminate any pending transfers, reset IRQ/DMA, power off peripheral
614 drv->Uninitialize (...); // Release I/O pins
617 The functions ARM_Storage_PowerControl and ARM_Storage_Uninitialize always execute and can be used
618 to put the peripheral into a Safe State, for example after any data
619 transmission errors. To restart the peripheral in an error condition,
620 you should first execute the Stop Sequence and then the Start Sequence.
622 The parameter \em state can have the following values:
623 - \ref ARM_POWER_FULL : set-up the Storage device for data transfers, enable interrupts (NVIC) and optionally DMA. Can be called multiple times.
624 If the device is already in this mode, then the function performs no operation and returns with \ref ARM_DRIVER_OK.
625 - \ref ARM_POWER_LOW : may use power saving. Returns \ref ARM_DRIVER_ERROR_UNSUPPORTED when not implemented.
626 - \ref ARM_POWER_OFF : terminates any pending data transfers, disables peripheral, disables related interrupts and DMA.
628 \note This API may execute asynchronously if
629 ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
630 execution is optional even if 'asynchronous_ops' is set.
631 *******************************************************************************************************************/
633 int32_t ARM_Storage_ReadData (uint64_t addr, void *data, uint32_t size) {
637 \fn int32_t ARM_Storage_ReadData (uint64_t addr, void *data, uint32_t size)
639 Read the contents of a range of storage memory into a buffer
640 supplied by the caller. The buffer is owned by the caller and should
641 remain accessible for the lifetime of this command.
643 \note This API may execute asynchronously if
644 ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
645 execution is optional even if 'asynchronous_ops' is set.
646 *******************************************************************************************************************/
648 int32_t ARM_Storage_ProgramData (uint64_t addr, const void *data, uint32_t size) {
652 \fn int32_t ARM_Storage_ProgramData (uint64_t addr, const void *data, uint32_t size)
654 Write the contents of a given memory buffer into a range of
655 storage memory. In the case of flash memory, the destination range in
656 storage memory typically has its contents in an erased state from a
657 preceding erase operation. The source memory buffer is owned by the
658 caller and should remain accessible for the lifetime of this command.
660 \note It is best for the middleware to write in units of
661 'optimal_program_unit' (\ref ARM_STORAGE_INFO) of the device.
663 \note This API may execute asynchronously if
664 ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
665 execution is optional even if 'asynchronous_ops' is set.
666 *******************************************************************************************************************/
668 int32_t ARM_Storage_Erase (uint64_t addr, uint32_t size) {
672 \fn int32_t ARM_Storage_Erase (uint64_t addr, uint32_t size)
675 This function erases a range of storage specified by [addr, addr +
676 size). Both 'addr' and 'addr + size' should align with the
677 'erase_unit'(s) of the respective owning storage block(s) (see \ref
678 ARM_STORAGE_BLOCK and \ref ARM_STORAGE_BLOCK_ATTRIBUTES). The range to
679 be erased will have its contents returned to the un-programmed state--
680 i.e. to \ref ARM_STORAGE_INFO::erased_value, which
681 is usually 1 to indicate the pattern of all ones: 0xFF.
683 \note This API may execute asynchronously if
684 ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
685 execution is optional even if 'asynchronous_ops' is set.
687 \note Erase() may return a smaller (positive) value than the size of the
688 requested range. The returned value indicates the actual number of bytes
689 erased. It is the caller's responsibility to follow up with an appropriate
690 request to complete the operation.
692 \note in the case of a failed erase (except when
693 ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_ERROR_PROTECTED, or
694 ARM_STORAGE_ERROR_NOT_ERASABLE is returned synchronously), the
695 requested range should be assumed to be in an unknown state. The
696 previous contents may not be retained.
697 *******************************************************************************************************************/
699 int32_t ARM_Storage_EraseAll (void) {
703 \fn int32_t ARM_Storage_EraseAll (void)
705 This optional function erases the complete device. If the device does not
706 support global erase then the function returns the error value \ref
707 ARM_DRIVER_ERROR_UNSUPPORTED. The data field \em 'erase_all' =
708 \token{1} of the structure \ref ARM_STORAGE_CAPABILITIES encodes that
709 \ref ARM_Storage_EraseAll is supported.
711 \note This API may execute asynchronously if
712 ARM_STORAGE_CAPABILITIES::asynchronous_ops is set. Asynchronous
713 execution is optional even if 'asynchronous_ops' is set.
714 *******************************************************************************************************************/
716 ARM_Storage_STATUS ARM_Storage_GetStatus (void) {
720 \fn ARM_STORAGE_STATUS ARM_Storage_GetStatus (void)
722 Get the status of the current (or previous) command executed by the
723 storage controller; stored in the structure \ref ARM_STORAGE_STATUS.
725 \note This API returns synchronously--it does not result in an invocation
726 of a completion callback.
727 *******************************************************************************************************************/
729 int32_t ARM_Storage_GetInfo (ARM_STORAGE_INFO *info) {
733 \fn int32_t ARM_Storage_GetInfo (ARM_STORAGE_INFO *info)
735 Get information about the Storage device; stored in the structure \ref ARM_STORAGE_INFO.
737 \note It is the caller's responsibility to ensure that the buffer passed in
738 is able to be initialized with a \ref ARM_STORAGE_INFO.
740 \note This API returns synchronously--it does not result in an invocation
741 of a completion callback.
742 *******************************************************************************************************************/
744 uint32_t ARM_Storage_ResolveAddress(uint64_t addr) {
748 \fn uint32_t ARM_Storage_ResolveAddress(uint64_t addr)
750 Only applicable to devices with memory-mapped storage.
752 \note This API returns synchronously. The invocation should return quickly,
753 and result in a resolved address.
754 *******************************************************************************************************************/
756 int32_t ARM_Storage_GetNextBlock(const ARM_STORAGE_BLOCK* prev_block, ARM_STORAGE_BLOCK *next_block) {
760 \fn int32_t ARM_Storage_GetNextBlock(const ARM_STORAGE_BLOCK* prev_block, ARM_STORAGE_BLOCK *next_block);
762 This helper function fetches (an iterator to) the next block (or
763 the first block if 'prev_block' is passed in as NULL). In the failure
764 case, a terminating, invalid block iterator is filled into the out
765 parameter: 'next_block'. In combination with \ref
766 ARM_STORAGE_VALID_BLOCK, it can be used to iterate over the sequence
767 of blocks within the storage map:
770 ARM_STORAGE_BLOCK block;
771 for (drv->GetNextBlock(NULL, &block); ARM_STORAGE_VALID_BLOCK(&block); drv->GetNextBlock(&block, &block)) {
776 \note This API returns synchronously--it does not result in an invocation
777 of a completion callback.
778 *******************************************************************************************************************/
780 int32_t ARM_Storage_GetBlock(uint64_t addr, ARM_STORAGE_BLOCK *block) {
784 \fn int32_t ARM_Storage_GetBlock(uint64_t addr, ARM_STORAGE_BLOCK *block);
785 \note This API returns synchronously--it does not result in an invocation
786 of a completion callback.
787 *******************************************************************************************************************/
792 // End Flash Interface