Flash (索引式儲存空間)
開發應用程式的過程,有時開發者會需要斷電後也能保存資料的非揮發性儲存空間。LinkIt 7697 Arduino BSP 提供了 Arduino 開發者 LFlash 類別,以索引式存取的方式,將 LinkIt SDK 原生的 NVDM (NVDM: Non-Volatile Data Management) 資料儲存功能開放出來。藉由使用 LFlash APIs,可透過以字串為索引的方式將使用者資料儲存在開發板內建的 flash 記憶空間之中。在 Files / Examples / LFlash / ClickCount 裡,提供了利用 LFlash 來記錄 USR 按鈕按壓次數的範例,透過這個例子便可了解 LFlash 類別的使用方式。當執行這個範例時,開啟 Serial Monitor 並按下 USR 按鈕,即可看到 "USR button has been pressed for XXX times." 顯示按鈕被按了幾次的資訊;每當 USR 按鈕被按下時,顯示的按壓次數就會增加。
接下來將說明使用 LFlash 類別的方法:
NVDM 所管理的總空間為 64KB,而這個空間由 LFlash 與 EEPROM 兩個函式庫共同分享使用。也就是說,如果開發者將 EEPROM 的 1KB 空間都使用完畢,那麼 LFlash 就只剩下 64 - 1 = 63KB 可以使用。反之,若開發者完全不使用 EEPROM,那麼 LFlash 就可以使用 NVDM 完整的 64KB 儲存空間。
初始化
在程式的一開始要加入 "LFlash.h" 的 header file。由於 LFlash 類別預設在系統起始時即會產生物件實體,所以開發者可直接呼叫 LFlash.begin() 進行初始化動作。
讀寫操作
透過 LFlash.write() 和 LFlash.read() API 來存取使用者的資料。函式的宣告原型如下:
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);
對應的參數說明:
[IN] sectionName:存放資料的資料區名稱。
[IN] propertyName:資料區裡的屬性名稱。
[IN] dataType:資料類型。寫入的資料類型可為字串型別或是 raw 資料格式,這兩者對應到的 enum 名稱分別為 LFLASH_STRING_DATA 與 LFLASH_RAW_DATA。
[IN] buffer:儲存使用者資料的記憶體起始位址。
[IN] dataSize:輸入資料量的大小。
[IN/OUT] size:此參數一開始為輸入值,表示 buffer 參數所指到的空間大小。函式呼叫返回後,它則為輸出值,表示實際讀回來的資料量。
以一開始提到的 ClickCount 範例來說,要把按鈕按壓次數寫入 flash,需要呼叫 write() 函式如下:
LFlash.write(
SECTION_NAME,
PROPERTY_NAME,
LFLASH_RAW_DATA,
(const uint8_t *)&_count,
sizeof(_count));
這個函式呼叫會以 raw 格式把資料以屬性名 PROPERTY_NAME 寫入到資料區 SECTION_NAME。
而在範例的 setup() 函式裡,透過下列方式將按鈕按壓次數讀出來以顯示至 Serial Monitor:
LFlash.read(
SECTION_NAME,
PROPERTY_NAME,
(uint8_t *)&_count,
&size);
函式中的 size 參數一開始被設定為 _count 這塊記憶體空間的大小,等到讀取完成後,它的值會被更新為在 SECTION_NAME 區裡 PROPERTY_NAME 屬性所存的資料量大小。
範例程式
#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);
}
Last updated