# Flash (Key-Pair Storage)

When developing an application, sometimes developers need to store data values in a local non-volatile storage. The *LFlash* class exports a key-pair storage function ([**NVDM**](http://labs.mediatek.com/api/mt7697/group___n_v_d_m.html): **N**on-**V**olatile **D**ata **M**anagement) from the native LinkIt SDK to Arduino users. By using LFlash APIs, user data can be stored in the on-board flash and indexed by a string-based key. In **Files / Examples / LFlash / ClickCount**, an example counts the number of times that the USR button is clicked. You can check the example code for an application of the LFlash class. After running this example, open the Serial Monitor and click the USR button on LinkIt 7697, you'll see a message like "*USR button has been pressed for XXX times.*" being shown. Every time you click the USR button, the displayed counting value will increase.

Next, we describe the basics about using the LFlash class.

{% hint style="danger" %}
The total accessible storage size for NVDM on LinkIt 7697 is 64KB. And this storage partition is shared between the LFlash class and the EEPROM class, which are both implemented by NVDM. Therefore, if you consume all the 1KB storage provided by the EEPROM class, you'll have 63KB left for LFlash. If you don't need any storage for EEPROM, then LFlash can use all the 64KB storage allocated to NVDM.

In short, size(LFlash + EEPROM) := 64KB and max\_size(EEPROM) := 1KB.
{% endhint %}

### Initialization <a href="#flash-key-pairstorage-initialization" id="flash-key-pairstorage-initialization"></a>

Include the header file *"LFlash.h"* in the beginning of your code. An instance of the LFlash class is by default instantiated when the system is up, so developers can call *LFlash.begin()* directly to initialize the flash module for doing key-pair storing.

### Write and Read <a href="#flash-key-pairstorage-writeandread" id="flash-key-pairstorage-writeandread"></a>

*LFlash.write()* and *LFlash.read()* are used to access the user stored data. The function prototypes are:

```
LFlashStatus write(
  const char *sectionName,
  const char *propertyName,
  LFlashDataType dataType,
  const uint8_t *buffer,
  uint32_t dataSize);
 
LFlashStatus read(
  const char *sectionName, 
  const char *propertyName, 
  uint8_t *buffer, 
  uint32_t *size);
```

The definitions of corresponding parameters are:

* **\[IN]** *sectionName*: the name of the data section.
* **\[IN]** *propertyName*: the name of the property inside the data section specified above.
* **\[IN]** *dataType*: the data type to be stored. The data type can be string data or raw data. The valid enumeration for this parameter is *LFLASH\_STRING\_DATA* or *LFLASH\_RAW\_DATA*.
* **\[IN]** *buffer*: the buffer which contains the data.
* **\[IN]** *dataSize*: the size of the input data.
* **\[IN/OUT]** *size*: as the input, it's the size of the buffer. As the output, it's the size of the read-out data.

Take the *ClickCount* example as an instance, when writing the number of click counts into the flash, a call like:

```
LFlash.write(
  SECTION_NAME,
  PROPERTY_NAME,
  LFLASH_RAW_DATA,
  (const uint8_t *)&_count,
  sizeof(_count));
```

is issued to store the raw data of *\_count* variable into the flash with a section name *SECTION\_NAME* and a property name *PROPERTY\_NAME*.

And in the *setup()* routine of the example, it would read back the current click count and show it to the Serial Monitor. It's done by calling:

```
LFlash.read(
  SECTION_NAME, 
  PROPERTY_NAME, 
  (uint8_t *)&_count, 
  &size);
```

where the *size* is initially set to the length of the *\_count* buffer and it will be updated to the length of the data pointed by the SECTION\_NAME and PROPERTY\_NAME keys.

### Example Code <a href="#flash-key-pairstorage-examplecode" id="flash-key-pairstorage-examplecode"></a>

```
#include "Arduino.h"
#include "LFlash.h"
#include <string.h>

#define BUFFER_LENGTH (4)

#define SECTION_NAME "MONITOR"
#define PROPERTY_NAME "BTN_CLICK"

#define LED_PIN (7)
#define BUTTON_PIN (6)

static uint32_t _count = 0;

void show_message(uint32_t times)
{
  Serial.print("USR button has been pressed for ");
  Serial.print(times);
  Serial.print(" time");
  
  if (times < 2)
  {
    Serial.println(".");
  }
  else
  {
    Serial.println("s.");
  }
}

void button_press(void)
{
  _count++;
  
  // write the count into the flash
  LFlash.write(
    SECTION_NAME,
    PROPERTY_NAME,
    LFLASH_RAW_DATA,
    (const uint8_t *)&_count,
    sizeof(_count));

  show_message(_count);
}

void setup() {
  uint32_t size = BUFFER_LENGTH;

  Serial.begin(115200);
  
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);

  if (LFlash.begin() != LFLASH_OK)
  {
    Serial.println("Flash init failed.");
    return;
  }

  // flash init done and okay
  digitalWrite(LED_PIN, LOW);

  attachInterrupt(BUTTON_PIN, button_press, RISING);

  // read back the current click count
  LFlash.read(SECTION_NAME, PROPERTY_NAME, (uint8_t *)&_count, &size);

  show_message(_count);
}

void loop() {
  delay(1000);
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cavedu.gitbook.io/linkit-7697/linkit-7697-development-guide-for-arduino-ide/developer-guide/flash-key-pair-storage.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
