| CMSIS-Driver Peripheral Interface for Middleware and Application Code |

Loading...
Searching...
No Matches
Sample Use of Storage Driver
Storage Interface

Example Code:

The following is a generic algorithm to erase and program one ARM_STORAGE_BLOCK_ATTRIBUTES::erase_unit worth of storage and then read it back to be verified. It handles both synchronous and asynchronous driver implementations.

// Copyright (c) 2006-2016, Arm Limited, All Rights Reserved
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "Driver_Storage.h"
#include <stdio.h>
#include <string.h>
#define TEST_ASSERT(Expr) if (!(Expr)) { printf("%s:%u: assertion failure\n", __FUNCTION__, __LINE__); while (1) ;}
#define TEST_ASSERT_EQUAL(expected, actual) if ((expected) != (actual)) {printf("%s:%u: assertion failure\n", __FUNCTION__, __LINE__); while (1) ;}
#define TEST_ASSERT_NOT_EQUAL(expected, actual) if ((expected) == (actual)) {printf("%s:%u: assertion failure\n", __FUNCTION__, __LINE__); while (1) ;}
// forward declarations
void callbackHandler(int32_t status, ARM_STORAGE_OPERATION operation);
void progressStateMachine(void);
static enum {
NEEDS_INITIALIZATION,
NEEDS_ERASE,
NEEDS_PROGRAMMING,
NEEDS_READ,
NEEDS_VERIFICATION_FOLLOWING_READ,
FINISHED
} state;
extern ARM_DRIVER_STORAGE ARM_Driver_Storage_(0);
ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_(0);
static const unsigned BUFFER_SIZE = 16384;
static uint8_t buffer[BUFFER_SIZE];
void main(int argc __unused, char** argv __unused)
{
state = NEEDS_INITIALIZATION;
progressStateMachine();
while (true) {
// WFE(); // optional low-power sleep
}
}
void progressStateMachine(void)
{
int32_t rc;
static ARM_STORAGE_BLOCK firstBlock;
if (!ARM_STORAGE_VALID_BLOCK(&firstBlock)) {
// Get the first block. This block is entered only once.
rc = drv->GetNextBlock(NULL, &firstBlock); // get first block
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
}
TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
TEST_ASSERT(firstBlock.size > 0);
switch (state) {
case NEEDS_INITIALIZATION:
rc = drv->Initialize(callbackHandler);
TEST_ASSERT(rc >= ARM_DRIVER_OK);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
state = NEEDS_ERASE;
return; // there is pending asynchronous activity which will lead to a completion callback later.
}
TEST_ASSERT_EQUAL(1, rc); // synchronous completion
// intentional fall-through
case NEEDS_ERASE:
TEST_ASSERT(firstBlock.attributes.erase_unit > 0);
rc = drv->Erase(firstBlock.addr, firstBlock.attributes.erase_unit);
TEST_ASSERT(rc >= ARM_DRIVER_OK);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
state = NEEDS_PROGRAMMING;
return; // there is pending asynchronous activity which will lead to a completion callback later.
}
TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, (uint32_t)rc); // synchronous completion
// intentional fall-through
case NEEDS_PROGRAMMING:
TEST_ASSERT(BUFFER_SIZE >= firstBlock.attributes.erase_unit);
#define PATTERN 0xAA
memset(buffer, PATTERN, firstBlock.attributes.erase_unit);
rc = drv->ProgramData(firstBlock.addr, buffer, firstBlock.attributes.erase_unit);
TEST_ASSERT(rc >= ARM_DRIVER_OK);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
state = NEEDS_READ;
return; // there is pending asynchronous activity which will lead to a completion callback later.
}
TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, (uint32_t)rc); // synchronous completion
// intentional fall-through
case NEEDS_READ:
rc = drv->ReadData(firstBlock.addr, buffer, firstBlock.attributes.erase_unit);
TEST_ASSERT(rc >= ARM_DRIVER_OK);
if (rc == ARM_DRIVER_OK) {
TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
state = NEEDS_VERIFICATION_FOLLOWING_READ;
return; // there is pending asynchronous activity which will lead to a completion callback later.
}
TEST_ASSERT_EQUAL(firstBlock.attributes.erase_unit, (uint32_t)rc);
// intentional fall-through
case NEEDS_VERIFICATION_FOLLOWING_READ:
printf("verifying data\r\n");
for (unsigned i = 0; i < firstBlock.attributes.erase_unit; i++) {
TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
}
state = FINISHED;
printf("done\r\n");
break;
case FINISHED:
break;
} // switch (state)
}
void callbackHandler(int32_t status, ARM_STORAGE_OPERATION operation)
{
(void)status;
(void)operation;
switch (operation) {
case ARM_STORAGE_OPERATION_INITIALIZE:
case ARM_STORAGE_OPERATION_READ_DATA:
case ARM_STORAGE_OPERATION_PROGRAM_DATA:
case ARM_STORAGE_OPERATION_ERASE:
progressStateMachine();
break;
default:
printf("callbackHandler: unexpected callback for opcode %u with status %ld\r\n", operation, status);
break;
}
}
Driver_Storage.h
ARM_STORAGE_VALID_BLOCK
#define ARM_STORAGE_VALID_BLOCK(BLK)
Definition: Driver_Storage.h:100
ARM_Driver_Storage_
#define ARM_Driver_Storage_(n)
Definition: Driver_Storage.h:46
ARM_STORAGE_OPERATION_READ_DATA
@ ARM_STORAGE_OPERATION_READ_DATA
Definition: Driver_Storage.h:210
ARM_STORAGE_OPERATION_PROGRAM_DATA
@ ARM_STORAGE_OPERATION_PROGRAM_DATA
Definition: Driver_Storage.h:211
ARM_STORAGE_OPERATION_ERASE
@ ARM_STORAGE_OPERATION_ERASE
Definition: Driver_Storage.h:212
ARM_STORAGE_OPERATION_INITIALIZE
@ ARM_STORAGE_OPERATION_INITIALIZE
Definition: Driver_Storage.h:207
ARM_DRIVER_OK
#define ARM_DRIVER_OK
Operation succeeded.
ARM_DRIVER_STORAGE::Erase
int32_t(* Erase)(uint64_t addr, uint32_t size)
Pointer to ARM_Storage_Erase : Erase Storage range.
Definition: Driver_Storage.h:421
ARM_STORAGE_BLOCK::addr
uint64_t addr
This is the start address of the storage block. It is expressed as an offset from the start of the st...
Definition: Driver_Storage.h:89
ARM_STORAGE_CAPABILITIES::asynchronous_ops
uint32_t asynchronous_ops
Used to indicate if APIs like initialize, read, erase, program, etc. can operate in asynchronous mode...
Definition: Driver_Storage.h:189
ARM_DRIVER_STORAGE::ProgramData
int32_t(* ProgramData)(uint64_t addr, const void *data, uint32_t size)
Pointer to ARM_Storage_ProgramData : Program data to Storage.
Definition: Driver_Storage.h:420
ARM_DRIVER_STORAGE::GetNextBlock
int32_t(* GetNextBlock)(const ARM_STORAGE_BLOCK *prev, ARM_STORAGE_BLOCK *next)
Pointer to ARM_Storage_GetNextBlock : fetch successor for current block.
Definition: Driver_Storage.h:426
ARM_DRIVER_STORAGE::Initialize
int32_t(* Initialize)(ARM_Storage_Callback_t callback)
Pointer to ARM_Storage_Initialize : Initialize the Storage Interface.
Definition: Driver_Storage.h:416
ARM_STORAGE_BLOCK_ATTRIBUTES::erase_unit
uint32_t erase_unit
Minimum erase size in bytes. The offset of the start of the erase-range should also be aligned with t...
Definition: Driver_Storage.h:75
ARM_DRIVER_STORAGE::ReadData
int32_t(* ReadData)(uint64_t addr, void *data, uint32_t size)
Pointer to ARM_Storage_ReadData : Read data from Storage.
Definition: Driver_Storage.h:419
ARM_DRIVER_STORAGE::GetCapabilities
ARM_STORAGE_CAPABILITIES(* GetCapabilities)(void)
Pointer to ARM_Storage_GetCapabilities : Get driver capabilities.
Definition: Driver_Storage.h:415
ARM_STORAGE_BLOCK::attributes
ARM_STORAGE_BLOCK_ATTRIBUTES attributes
Attributes for this block.
Definition: Driver_Storage.h:94
ARM_STORAGE_BLOCK::size
uint64_t size
This is the size of the storage block, in units of bytes. Together with addr, it describes a range [a...
Definition: Driver_Storage.h:92
ARM_STORAGE_OPERATION
ARM_STORAGE_OPERATION
Definition: Driver_Storage.h:204
ARM_DRIVER_STORAGE
Definition: Driver_Storage.h:413
ARM_STORAGE_BLOCK
A storage block is a range of memory with uniform attributes.
Definition: Driver_Storage.h:88