]> begriffs open source - cmsis/blob - CMSIS/DoxyGen/Driver/src/Driver_Storage.c
Introduce Storage driver
[cmsis] / CMSIS / DoxyGen / Driver / src / Driver_Storage.c
1 /* -----------------------------------------------------------------------------
2  * Copyright (c) 2013-2016 ARM Limited. All rights reserved.
3  *
4  * $Date:        7. March 2016
5  * $Revision:    V1.00
6  *
7  * Project:      Storage Driver API
8  * -------------------------------------------------------------------------- */
9
10
11 /**
12 \defgroup storage_interface_gr Storage Interface
13 \brief    Driver API for Storage Device Interface (%Driver_Storage.h)
14 \details
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
22 storage device.
23
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.
29
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
32 storage driver.
33
34          +----------------------------------+
35          |            Volume                |
36          |  or UBI (Unsorted Block Image)   |
37          | (Block Management: alloc, erase) |
38          |                                  |
39          +--------------+-------------------+
40                         |
41            +------------v--------------+
42            | Storage abstraction layer |
43            +--+--------------+----+----+
44               |              |    |
45      operates | upon         |    |
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
54     |   Init             |          |                                   |
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|
61     |   NextSegment      | |                              |
62     |   ...              | +------------------------------+
63     +--------------------+
64
65 **Storage API**
66
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
69
70
71 **Driver Functions**
72
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
75
76 A sample use for the driver can be found at: \ref SampleUseOfStorageDriver
77 *******************************************************************************************************************/
78
79 /**
80 \defgroup SampleUseOfStorageDriver Sample Use of Storage Driver
81 @{
82 <b>Example Code:</b>
83
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.
88
89 \code
90 // Copyright (c) 2006-2016, ARM Limited, All Rights Reserved
91 // SPDX-License-Identifier: Apache-2.0
92 //
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
96 //
97 // http:// www.apache.org/licenses/LICENSE-2.0
98 //
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.
104
105 #include "Driver_Storage.h"
106 #include <stdio.h>
107 #include <string.h>
108
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) ;}
112
113 // forward declarations
114 void callbackHandler(int32_t status, ARM_STORAGE_OPERATION operation);
115 void progressStateMachine(void);
116
117 static enum {
118     NEEDS_INITIALIZATION,
119     NEEDS_ERASE,
120     NEEDS_PROGRAMMING,
121     NEEDS_READ,
122     NEEDS_VERIFICATION_FOLLOWING_READ,
123     FINISHED
124 } state;
125
126 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_(0);
127 ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_(0);
128
129 static const unsigned BUFFER_SIZE = 16384;
130 static uint8_t buffer[BUFFER_SIZE];
131
132 void main(int argc __unused, char** argv __unused)
133 {
134     state = NEEDS_INITIALIZATION;
135
136     progressStateMachine();
137     while (true) {
138         // WFE(); // optional low-power sleep
139     }
140 }
141
142 void progressStateMachine(void)
143 {
144     int32_t rc;
145
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);
151     }
152     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
153     TEST_ASSERT(firstBlock.size > 0);
154
155     switch (state) {
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);
161                 state = NEEDS_ERASE;
162                 return; // there is pending asynchronous activity which will lead to a completion callback later.
163             }
164             TEST_ASSERT_EQUAL(1, rc); // synchronous completion
165
166             // intentional fall-through
167
168         case NEEDS_ERASE:
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.
176             }
177             TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, (uint32_t)rc); // synchronous completion
178
179             // intentional fall-through
180
181         case NEEDS_PROGRAMMING:
182             TEST_ASSERT(BUFFER_SIZE >= firstBlock.attributes.erase_unit);
183             #define PATTERN 0xAA
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);
189                 state = NEEDS_READ;
190                 return;  // there is pending asynchronous activity which will lead to a completion callback later.
191             }
192             TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, (uint32_t)rc); // synchronous completion
193
194             // intentional fall-through
195
196         case NEEDS_READ:
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.
203             }
204             TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, (uint32_t)rc);
205
206             // intentional fall-through
207
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]);
212             }
213             state = FINISHED;
214             printf("done\r\n");
215             break;
216
217         case FINISHED:
218             break;
219     } // switch (state)
220 }
221
222 void callbackHandler(int32_t status, ARM_STORAGE_OPERATION operation)
223 {
224     (void)status;
225     (void)operation;
226     switch (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();
232             break;
233
234         default:
235             printf("callbackHandler: unexpected callback for opcode %u with status %ld\r\n", operation, status);
236             break;
237     }
238 }
239 \endcode
240 @}
241 *******************************************************************************************************************/
242
243 /**
244 \addtogroup storage_interface_gr
245 @{
246 *******************************************************************************************************************/
247
248 /**
249 \struct     ARM_STORAGE_BLOCK_ATTRIBUTES
250 <b>Contained in:</b>
251   - \ref ARM_STORAGE_BLOCK
252 *******************************************************************************************************************/
253
254 /**
255 \struct     ARM_STORAGE_BLOCK
256 \details Storage blocks combine to make up the address map of a storage controller.
257 *******************************************************************************************************************/
258
259 /**
260 \struct     ARM_STORAGE_INFO
261 \details
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.
266
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).
274
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).
280
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.
284
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.
287
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.
293
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
296 all storage blocks.
297
298 \note
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.
306
307 <b>Returned by:</b>
308   - \ref ARM_Storage_GetInfo
309 *******************************************************************************************************************/
310
311 /**
312 \struct ARM_DRIVER_STORAGE
313 \details
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
318 information.
319
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).
324
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 *******************************************************************************************************************/
328
329 /**
330 \defgroup DriverFunctions Use of Storage APIs
331
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.
335
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).
342
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
351 condition).
352
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.
362
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:
366 \code
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) {
370         // handle error.
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.
374     } else {
375         ASSERT(returnValue == EXPECTED_RETURN_VALUE_FOR_SYNCHRONOUS_COMPLETION);
376         // handle synchronous completion.
377     }
378 \endcode
379
380 Here's a sample use mixing synchronous and asynchronous APIs: \ref SampleUseOfStorageDriver
381 *******************************************************************************************************************/
382
383 /**
384 \struct     ARM_STORAGE_CAPABILITIES
385 \details
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.
388
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).
399
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.
403
404 <b>Returned by:</b>
405   - \ref ARM_Storage_GetCapabilities
406
407 \note
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 *******************************************************************************************************************/
411
412 /**
413 \struct     ARM_STORAGE_STATUS
414 \details
415 Structure with information about the status of the Storage device.
416
417 The flag \em busy indicates that the driver is busy executing read/program/erase operation.
418
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.
420
421 <b>Returned by:</b>
422   - \ref ARM_Storage_GetStatus
423 *****************************************************************************************************************/
424
425 /**
426 \enum       ARM_STORAGE_OPERATION
427 \details
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 *****************************************************************************************************************/
431
432 /**
433 \typedef    ARM_Storage_Callback_t
434 \details
435 Provides the typedef for the callback function \ref ARM_Storage_Callback_t.
436
437 \param [in] status
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.
442
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.
446
447 <b>Parameter for:</b>
448   - \ref ARM_Storage_Initialize
449 *******************************************************************************************************************/
450
451
452 //
453 // Functions
454 //
455
456 ARM_DRIVER_VERSION ARM_Storage_GetVersion (void)  {
457   return { 0, 0 };
458 }
459 /**
460 \fn ARM_DRIVER_VERSION ARM_Storage_GetVersion (void)
461 \details
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.
465
466 Example:
467 \code
468 extern ARM_DRIVER_STORAGE *drv_info;
469
470 void read_version (void)  {
471   ARM_DRIVER_VERSION  version;
472
473   version = drv_info->GetVersion ();
474   if (version.api < 0x10A)   {      // requires at minimum API version 1.10 or higher
475     // error handling
476     return;
477   }
478 }
479 \endcode
480
481 \note This API returns synchronously--it does not result in an invocation
482    of a completion callback.
483
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 *******************************************************************************************************************/
488
489 ARM_STOR_CAPABILITIES ARM_Storage_GetCapabilities (void)  {
490   return { 0 };
491 }
492 /**
493 \fn ARM_STORAGE_CAPABILITIES ARM_Storage_GetCapabilities (void)
494
495 \details
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.
500
501 Example:
502 \code
503 extern ARM_DRIVER_STORAGE *drv_info;
504
505 void read_capabilities (void)  {
506   ARM_STORAGE_CAPABILITIES drv_capabilities;
507
508   drv_capabilities = drv_info->GetCapabilities ();
509   // interrogate capabilities
510
511 }
512 \endcode
513
514 \note This API returns synchronously--it does not result in an invocation
515    of a completion callback.
516
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 *******************************************************************************************************************/
521
522 int32_t ARM_Storage_Initialize (ARM_Storage_Callback_t callback)  {
523   return 0;
524 }
525 /**
526 \fn int32_t ARM_Storage_Initialize (ARM_Storage_Callback_t callback)
527 \details
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.
532
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.
536
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.
540
541 To start working with a peripheral the functions ARM_Storage_Initialize and ARM_Storage_PowerControl() need to be called in this order:
542 \code
543    drv->Initialize (...);              // Allocate I/O pins
544    drv->PowerControl (ARM_POWER_FULL); // Power up peripheral, setup IRQ/DMA
545 \endcode
546
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
550  ARM_DRIVER_OK.
551
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.
556
557 To stop working with a peripheral the functions ARM_Storage_PowerControl() and ARM_Storage_Uninitialize() need to be called in this order:
558 \code
559    drv->PowerControl (ARM_POWER_OFF); // Terminate any pending transfers, reset IRQ/DMA, power off peripheral
560    drv->Uninitialize (...);           // Release I/O pins
561 \endcode
562
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.
567
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 *******************************************************************************************************************/
572
573 int32_t ARM_Storage_Uninitialize (void)  {
574   return 0;
575 }
576 /**
577 \fn int32_t ARM_Storage_Uninitialize (void)
578 \details
579 It is called when the middleware component stops operation, and wishes to
580 release the software resources used by the interface.
581
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 *******************************************************************************************************************/
586
587 int32_t ARM_Storage_PowerControl (ARM_POWER_STATE state)  {
588   return 0;
589 }
590 /**
591 \fn int32_t ARM_Storage_PowerControl (ARM_POWER_STATE state)
592 \details
593 The function \b ARM_Storage_PowerControl operates the power modes of the Storage interface.
594
595 To start working with a peripheral the functions Initialize and PowerControl need to be called in this order:
596 \code
597    drv->Initialize (...);                 // Allocate I/O pins
598    drv->PowerControl (ARM_POWER_FULL);    // Power up peripheral, setup IRQ/DMA
599 \endcode
600
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
604  ARM_DRIVER_OK.
605
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.
610
611 To stop working with a peripheral the functions PowerControl and Uninitialize need to be called in this order:
612 \code
613    drv->PowerControl (ARM_POWER_OFF);     // Terminate any pending transfers, reset IRQ/DMA, power off peripheral
614    drv->Uninitialize (...);               // Release I/O pins
615 \endcode
616
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.
621
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.
627
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 *******************************************************************************************************************/
632
633 int32_t ARM_Storage_ReadData (uint64_t addr, void *data, uint32_t size)  {
634   return 0;
635 }
636 /**
637 \fn int32_t ARM_Storage_ReadData (uint64_t addr, void *data, uint32_t size)
638 \details
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.
642
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 *******************************************************************************************************************/
647
648 int32_t ARM_Storage_ProgramData (uint64_t addr, const void *data, uint32_t size)  {
649   return 0;
650 }
651 /**
652 \fn int32_t ARM_Storage_ProgramData (uint64_t addr, const void *data, uint32_t size)
653 \details
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.
659
660 \note It is best for the middleware to write in units of
661    'optimal_program_unit' (\ref ARM_STORAGE_INFO) of the device.
662
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 *******************************************************************************************************************/
667
668 int32_t ARM_Storage_Erase (uint64_t addr, uint32_t size)  {
669   return 0;
670 }
671 /**
672 \fn int32_t ARM_Storage_Erase (uint64_t addr, uint32_t size)
673
674 \details
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.
682
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.
686
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.
691
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 *******************************************************************************************************************/
698
699 int32_t ARM_Storage_EraseAll (void)  {
700   return 0;
701 }
702 /**
703 \fn int32_t ARM_Storage_EraseAll (void)
704 \details
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.
710
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 *******************************************************************************************************************/
715
716 ARM_Storage_STATUS ARM_Storage_GetStatus (void)  {
717   return 0;
718 }
719 /**
720 \fn ARM_STORAGE_STATUS ARM_Storage_GetStatus (void)
721 \details
722 Get the status of the current (or previous) command executed by the
723 storage controller; stored in the structure \ref ARM_STORAGE_STATUS.
724
725 \note This API returns synchronously--it does not result in an invocation
726    of a completion callback.
727 *******************************************************************************************************************/
728
729 int32_t ARM_Storage_GetInfo (ARM_STORAGE_INFO *info)  {
730   return 0;
731 }
732 /**
733 \fn int32_t ARM_Storage_GetInfo (ARM_STORAGE_INFO *info)
734 \details
735 Get information about the Storage device; stored in the structure \ref ARM_STORAGE_INFO.
736
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.
739
740 \note This API returns synchronously--it does not result in an invocation
741    of a completion callback.
742 *******************************************************************************************************************/
743
744 uint32_t ARM_Storage_ResolveAddress(uint64_t addr) {
745   return 0;
746 }
747 /**
748 \fn uint32_t ARM_Storage_ResolveAddress(uint64_t addr)
749 \details
750 Only applicable to devices with memory-mapped storage.
751
752 \note This API returns synchronously. The invocation should return quickly,
753    and result in a resolved address.
754 *******************************************************************************************************************/
755
756 int32_t ARM_Storage_GetNextBlock(const ARM_STORAGE_BLOCK* prev_block, ARM_STORAGE_BLOCK *next_block) {
757   return 0;
758 }
759 /**
760 \fn int32_t ARM_Storage_GetNextBlock(const ARM_STORAGE_BLOCK* prev_block, ARM_STORAGE_BLOCK *next_block);
761 \details
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:
768
769 \code
770   ARM_STORAGE_BLOCK block;
771   for (drv->GetNextBlock(NULL, &block); ARM_STORAGE_VALID_BLOCK(&block); drv->GetNextBlock(&block, &block)) {
772       // make use of block
773   }
774 \endcode
775
776 \note This API returns synchronously--it does not result in an invocation
777     of a completion callback.
778 *******************************************************************************************************************/
779
780 int32_t ARM_Storage_GetBlock(uint64_t addr, ARM_STORAGE_BLOCK *block) {
781   return 0;
782 }
783 /**
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 *******************************************************************************************************************/
788
789 /**
790 @}
791 */
792 // End Flash Interface