Module map

Module map 

Source
Expand description

A module for storing key-value pairs in flash with minimal erase cycles.

When a key-value is stored, it overwrites the any old items with the same key.

§Basic API:


// Initialize the flash. This can be internal or external
let mut flash = init_flash();
// These are the flash addresses in which the crate will operate.
// The crate will not read, write or erase outside of this range.
let flash_range = 0x1000..0x3000;
// We need to give the crate a buffer to work with.
// It must be big enough to serialize the biggest value of your storage type in,
// rounded up to to word alignment of the flash. Some kinds of internal flash may require
// this buffer to be aligned in RAM as well.
let mut data_buffer = [0; 128];

// We can fetch an item from the flash. We're using `u8` as our key type and `u32` as our value type.
// Nothing is stored in it yet, so it will return None.

assert_eq!(
    fetch_item::<u8, u32, _>(
        &mut flash,
        flash_range.clone(),
        &mut NoCache::new(),
        &mut data_buffer,
        &42,
    ).await.unwrap(),
    None
);

// Now we store an item the flash with key 42.
// Again we make sure we pass the correct key and value types, u8 and u32.
// It is important to do this consistently.

store_item(
    &mut flash,
    flash_range.clone(),
    &mut NoCache::new(),
    &mut data_buffer,
    &42u8,
    &104729u32,
).await.unwrap();

// When we ask for key 42, we now get back a Some with the correct value

assert_eq!(
    fetch_item::<u8, u32, _>(
        &mut flash,
        flash_range.clone(),
        &mut NoCache::new(),
        &mut data_buffer,
        &42,
    ).await.unwrap(),
    Some(104729)
);

§Key and value traits

In the previous example we saw we used one key and one value type. It is crucial we use the same key type every time on the same range of flash. This is because the internal items are serialized as [key|value]. A different key type will have a different length and will make all data nonsense.

However, if we have special knowledge about what we store for each key, we are allowed to use different value types.

For example, we can do the following:

  1. Store a u32 with key 0
  2. Store a custom type ‘Foo’ with key 1
  3. Fetch a u32 with key 0
  4. Fetch a custom type ‘Foo’ with key 1

It is up to the user to make sure this is done correctly. If done incorrectly, the deserialize function of requested value type will see data it doesn’t expect. In the best case it’ll return an error, in a bad case it’ll give bad invalid data and in the worst case the deserialization code panics. It is worth mentioning that fetch_all_items also requires that all items have the same type. So be careful.

For your convenience there are premade implementations for the Key and Value traits.

Structs§

MapItemIter
Iterator which iterates all non-erased & non-corrupted items in the map.

Enums§

SerializationError
Error for map value (de)serialization.

Traits§

Key
Anything implementing this trait can be used as a key in the map functions.
Value
The trait that defines how map values are serialized and deserialized.

Functions§

fetch_all_items
Get an iterator that iterates over all non-erased & non-corrupted items in the map.
fetch_item
Get the last stored value from the flash that is associated with the given key. If no value with the key is found, None is returned.
remove_all_items
Fully remove all stored items. Additional calls to fetch with any key will return None until new items are stored again.
remove_item
Fully remove an item. Additional calls to fetch with the same key will return None until a new one is stored again.
store_item
Store a key-value pair into flash memory. It will overwrite the last value that has the same key. The flash needs to be at least 2 pages long.