Merge pull request #146 from kaans/feature/esp32_spi_flash_demo
Add demo project for esp32
This commit is contained in:
commit
a7b33d810a
|
@ -0,0 +1,4 @@
|
|||
/build
|
||||
|
||||
sdkconfig*
|
||||
!sdkconfig.defaults
|
|
@ -0,0 +1,10 @@
|
|||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
list(APPEND EXTRA_COMPONENT_DIRS
|
||||
"${CMAKE_CURRENT_LIST_DIR}/components")
|
||||
|
||||
project(esp32_spi_flash)
|
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := flashDB_demo
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# flashDB demo esp32 Example
|
||||
|
||||
built with ESP IDF version 4.4.1 (v4.4.1-64-g4b2098bc58) using cmake.
|
||||
|
||||
run `idf.py build` in this directory and then flash with `idf.py flash` and monitor
|
||||
the output with `idf.py monitor`.
|
||||
|
||||
A custom partition table is required so that a partition can be created for the FlashDB.
|
||||
The size in the demo is set to 32K, see file `partitions.csv`. Custom partitions are
|
||||
enabled by default in `sdkconfig.defaults`.
|
||||
|
||||
The file `sdkconfig.defaults` contains by default all values required for the demo to work,
|
||||
i.e. the custom partitions are configured. By default the SPI flash is configured to
|
||||
be 4MB.
|
|
@ -0,0 +1,3 @@
|
|||
idf_component_register(SRCS "porting/fal_flash_esp32_port.c"
|
||||
INCLUDE_DIRS "inc" "../../../../port/fal/inc"
|
||||
REQUIRES "spi_flash")
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Component Makefile
|
||||
#
|
||||
COMPONENT_ADD_INCLUDEDIRS += \
|
||||
inc \
|
||||
../../../../inc \
|
||||
../../../../port/fal/inc
|
||||
|
||||
COMPONENT_SRCDIRS += \
|
||||
../../../../src \
|
||||
../../../../samples \
|
||||
../../../../port/fal/src \
|
||||
porting
|
||||
|
||||
|
||||
# COMPONENT_PRIV_INCLUDEDIRS +=
|
||||
|
||||
# COMPONENT_ADD_LDFLAGS += -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2022, kaans, <https://github.com/kaans>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _FAL_CFG_H_
|
||||
#define _FAL_CFG_H_
|
||||
|
||||
//#define FAL_DEBUG 1
|
||||
#define FAL_PART_HAS_TABLE_CFG
|
||||
#define NOR_FLASH_DEV_NAME "norflash0"
|
||||
|
||||
//#define FAL_PART_TABLE_FLASH_DEV_NAME NOR_FLASH_DEV_NAME
|
||||
//#define FAL_PART_TABLE_END_OFFSET 65536
|
||||
|
||||
/* ===================== Flash device Configuration ========================= */
|
||||
extern const struct fal_flash_dev nor_flash0;
|
||||
|
||||
/* flash device table */
|
||||
#define FAL_FLASH_DEV_TABLE \
|
||||
{ \
|
||||
&nor_flash0, \
|
||||
}
|
||||
/* ====================== Partition Configuration ========================== */
|
||||
#ifdef FAL_PART_HAS_TABLE_CFG
|
||||
/* partition table */
|
||||
#define FAL_PART_TABLE \
|
||||
{ \
|
||||
{FAL_PART_MAGIC_WORD, "fdb_kvdb1", NOR_FLASH_DEV_NAME, 0, 16 * 1024, 0}, \
|
||||
{FAL_PART_MAGIC_WORD, "fdb_tsdb1", NOR_FLASH_DEV_NAME, 16 * 1024, 16 * 1024, 0}, \
|
||||
}
|
||||
#endif /* FAL_PART_HAS_TABLE_CFG */
|
||||
|
||||
#endif /* _FAL_CFG_H_ */
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2022, kaans, <https://github.com/kaans>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief configuration file
|
||||
*/
|
||||
|
||||
#ifndef _FDB_CFG_H_
|
||||
#define _FDB_CFG_H_
|
||||
|
||||
/* using KVDB feature */
|
||||
#define FDB_USING_KVDB
|
||||
|
||||
#ifdef FDB_USING_KVDB
|
||||
/* Auto update KV to latest default when current KVDB version number is changed. @see fdb_kvdb.ver_num */
|
||||
/* #define FDB_KV_AUTO_UPDATE */
|
||||
#endif
|
||||
|
||||
/* using TSDB (Time series database) feature */
|
||||
#define FDB_USING_TSDB
|
||||
|
||||
/* Using FAL storage mode */
|
||||
#define FDB_USING_FAL_MODE
|
||||
|
||||
/* the flash write granularity, unit: bit
|
||||
* only support 1(nor flash)/ 8(stm32f2/f4)/ 32(stm32f1) */
|
||||
#define FDB_WRITE_GRAN 1 /* @note you must define it for a value */
|
||||
|
||||
/* MCU Endian Configuration, default is Little Endian Order. */
|
||||
/* #define FDB_BIG_ENDIAN */
|
||||
|
||||
/* log print macro using ESP_LOG.
|
||||
* Need to include esp_log.h when setting FDB_PRINT to ESP_LOGI().
|
||||
* default EF_PRINT macro is printf() */
|
||||
//#include <esp_log.h>
|
||||
//#define FDB_PRINT(...) ESP_LOGI("fdb", __VA_ARGS__)
|
||||
|
||||
/* print debug information */
|
||||
#define FDB_DEBUG_ENABLE
|
||||
|
||||
#endif /* _FDB_CFG_H_ */
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2022, kaans, <https://github.com/kaans>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_log.h"
|
||||
#include <esp_partition.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <fal.h>
|
||||
|
||||
#define FLASH_ERASE_MIN_SIZE (4 * 1024)
|
||||
|
||||
#define LOCKER_ENABLE
|
||||
#ifdef LOCKER_ENABLE
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
static SemaphoreHandle_t s_lock = NULL;
|
||||
|
||||
const static esp_partition_t *partition;
|
||||
|
||||
#define LOCK() \
|
||||
do \
|
||||
{ \
|
||||
xSemaphoreTake(s_lock, portMAX_DELAY); \
|
||||
} while (0)
|
||||
|
||||
#define UNLOCK() \
|
||||
do \
|
||||
{ \
|
||||
xSemaphoreGive(s_lock); \
|
||||
} while (0)
|
||||
#else
|
||||
#define LOCK()
|
||||
#define UNLOCK()
|
||||
#endif
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
#ifdef LOCKER_ENABLE
|
||||
if (s_lock == NULL)
|
||||
{
|
||||
s_lock = xSemaphoreCreateCounting(1, 1);
|
||||
assert(s_lock != NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
// the values passed to esp_partition_find_first() must correspond to the
|
||||
// values set in partitions.csv for the partition named "flashdb".
|
||||
partition = esp_partition_find_first(0x40, 0x00, "flashdb");
|
||||
|
||||
assert(partition != NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read(long offset, uint8_t *buf, size_t size)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
LOCK();
|
||||
ret = esp_partition_read(partition, offset, buf, size);
|
||||
UNLOCK();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int write(long offset, const uint8_t *buf, size_t size)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
LOCK();
|
||||
ret = esp_partition_write(partition, offset, buf, size);
|
||||
UNLOCK();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int erase(long offset, size_t size)
|
||||
{
|
||||
esp_err_t ret;
|
||||
int32_t erase_size = ((size - 1) / FLASH_ERASE_MIN_SIZE) + 1;
|
||||
|
||||
LOCK();
|
||||
ret = esp_partition_erase_range(partition, offset, erase_size * FLASH_ERASE_MIN_SIZE);
|
||||
UNLOCK();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct fal_flash_dev nor_flash0 =
|
||||
{
|
||||
.name = NOR_FLASH_DEV_NAME,
|
||||
.addr = 0x0, // address is relative to beginning of partition; 0x0 is start of the partition
|
||||
.len = 32 * 1024, // size of the partition as specified in partitions.csv
|
||||
.blk_size = FLASH_ERASE_MIN_SIZE, // must be 4096 bytes
|
||||
.ops = {init, read, write, erase},
|
||||
.write_gran = 1, // 1 byte write granularity
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
set (SOURCES)
|
||||
|
||||
list (APPEND SOURCES "main.c")
|
||||
|
||||
list (APPEND SOURCES "../../../src/fdb.c" "../../../src/fdb_file.c" "../../../src/fdb_kvdb.c" "../../../src/fdb_tsdb.c" "../../../src/fdb_utils.c")
|
||||
|
||||
list (APPEND SOURCES "../../../port/fal/src/fal_flash.c" "../../../port/fal/src/fal_partition.c" "../../../port/fal/src/fal_rtt.c" "../../../port/fal/src/fal.c")
|
||||
|
||||
list (APPEND SOURCES "../../../samples/kvdb_basic_sample.c" "../../../samples/kvdb_type_blob_sample.c" "../../../samples/kvdb_type_string_sample.c" "../../../samples/tsdb_sample.c")
|
||||
|
||||
idf_component_register(SRCS "${SOURCES}"
|
||||
INCLUDE_DIRS "../components/FlashDB/inc" "../../../inc" "../../../port/fal/inc"
|
||||
REQUIRES "spi_flash")
|
|
@ -0,0 +1,4 @@
|
|||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
|
@ -0,0 +1,161 @@
|
|||
/* FlashDB ESP32 SPI Flash Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_spi_flash.h"
|
||||
|
||||
#include <flashdb.h>
|
||||
|
||||
#define FDB_LOG_TAG "[main]"
|
||||
|
||||
static uint32_t boot_count = 0;
|
||||
static time_t boot_time[10] = {0, 1, 2, 3};
|
||||
/* default KV nodes */
|
||||
static struct fdb_default_kv_node default_kv_table[] = {
|
||||
{"username", "armink", 0}, /* string KV */
|
||||
{"password", "123456", 0}, /* string KV */
|
||||
{"boot_count", &boot_count, sizeof(boot_count)}, /* int type KV */
|
||||
{"boot_time", &boot_time, sizeof(boot_time)}, /* int array type KV */
|
||||
};
|
||||
/* KVDB object */
|
||||
static struct fdb_kvdb kvdb = {0};
|
||||
/* TSDB object */
|
||||
struct fdb_tsdb tsdb = {0};
|
||||
/* counts for simulated timestamp */
|
||||
static int counts = 0;
|
||||
static SemaphoreHandle_t s_lock = NULL;
|
||||
|
||||
extern void kvdb_basic_sample(fdb_kvdb_t kvdb);
|
||||
extern void kvdb_type_string_sample(fdb_kvdb_t kvdb);
|
||||
extern void kvdb_type_blob_sample(fdb_kvdb_t kvdb);
|
||||
extern void tsdb_sample(fdb_tsdb_t tsdb);
|
||||
|
||||
static void lock(fdb_db_t db)
|
||||
{
|
||||
xSemaphoreTake(s_lock, portMAX_DELAY);
|
||||
}
|
||||
|
||||
static void unlock(fdb_db_t db)
|
||||
{
|
||||
xSemaphoreGive(s_lock);
|
||||
}
|
||||
|
||||
static fdb_time_t get_time(void)
|
||||
{
|
||||
/* Using the counts instead of timestamp.
|
||||
* Please change this function to return RTC time.
|
||||
*/
|
||||
return ++counts;
|
||||
}
|
||||
|
||||
int flashdb_demo(void)
|
||||
{
|
||||
fdb_err_t result;
|
||||
|
||||
if (s_lock == NULL)
|
||||
{
|
||||
s_lock = xSemaphoreCreateCounting(1, 1);
|
||||
assert(s_lock != NULL);
|
||||
}
|
||||
|
||||
#ifdef FDB_USING_KVDB
|
||||
{ /* KVDB Sample */
|
||||
struct fdb_default_kv default_kv;
|
||||
|
||||
default_kv.kvs = default_kv_table;
|
||||
default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]);
|
||||
/* set the lock and unlock function if you want */
|
||||
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, lock);
|
||||
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, unlock);
|
||||
/* Key-Value database initialization
|
||||
*
|
||||
* &kvdb: database object
|
||||
* "env": database name
|
||||
* "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
|
||||
* Please change to YOUR partition name.
|
||||
* &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully.
|
||||
* NULL: The user data if you need, now is empty.
|
||||
*/
|
||||
result = fdb_kvdb_init(&kvdb, "env", "fdb_kvdb1", &default_kv, NULL);
|
||||
|
||||
if (result != FDB_NO_ERR)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* run basic KV samples */
|
||||
kvdb_basic_sample(&kvdb);
|
||||
/* run string KV samples */
|
||||
kvdb_type_string_sample(&kvdb);
|
||||
/* run blob KV samples */
|
||||
kvdb_type_blob_sample(&kvdb);
|
||||
}
|
||||
#endif /* FDB_USING_KVDB */
|
||||
|
||||
#ifdef FDB_USING_TSDB
|
||||
{ /* TSDB Sample */
|
||||
/* set the lock and unlock function if you want */
|
||||
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_LOCK, lock);
|
||||
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_UNLOCK, unlock);
|
||||
/* Time series database initialization
|
||||
*
|
||||
* &tsdb: database object
|
||||
* "log": database name
|
||||
* "fdb_tsdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
|
||||
* Please change to YOUR partition name.
|
||||
* get_time: The get current timestamp function.
|
||||
* 128: maximum length of each log
|
||||
* NULL: The user data if you need, now is empty.
|
||||
*/
|
||||
result = fdb_tsdb_init(&tsdb, "log", "fdb_tsdb1", get_time, 128, NULL);
|
||||
/* read last saved time for simulated timestamp */
|
||||
fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_GET_LAST_TIME, &counts);
|
||||
|
||||
if (result != FDB_NO_ERR)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* run TSDB sample */
|
||||
tsdb_sample(&tsdb);
|
||||
}
|
||||
#endif /* FDB_USING_TSDB */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
printf("FlashDB ESP32 SPI Flash Demo\n");
|
||||
|
||||
/* Print chip information */
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
printf("This is ESP32 chip with %d CPU cores, WiFi, ",
|
||||
chip_info.cores);
|
||||
|
||||
printf("silicon revision %d, ", chip_info.revision);
|
||||
|
||||
printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
|
||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
||||
|
||||
flashdb_demo();
|
||||
|
||||
for (int i = 1000; i >= 0; i--)
|
||||
{
|
||||
printf("Restarting in %d seconds...\n", i);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
printf("Restarting now.\n");
|
||||
fflush(stdout);
|
||||
esp_restart();
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
# The partition named "flashdb" will contain the partitions for the kvdb and tsdb.
|
||||
# Note that this partition must be at least as large as the sum of all partitions as
|
||||
# defined in FAL_PART_TABLE in fal_cfg.h.
|
||||
# The offsets are left blank intentionally so that the partitions will be arranged
|
||||
# automatically.
|
||||
# The partition type for the partition "flashdb" was set to 0x40, a custom type.
|
||||
# The subtype was set to 0x0. These values must correspond to the settings in the
|
||||
# init() function in fal_flash_esp32_port.c.
|
||||
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, , 16k,
|
||||
phy_init, data, phy, , 4k,
|
||||
flashdb, 0x40, 0x00, , 32k,
|
||||
factory, app, factory, , 1M,
|
Can't render this file because it contains an unexpected character in line 1 and column 23.
|
File diff suppressed because it is too large
Load Diff
|
@ -20,6 +20,12 @@
|
|||
|
||||
#define FDB_LOG_TAG "[sample][tsdb]"
|
||||
|
||||
#ifdef FDB_USING_TIMESTAMP_64BIT
|
||||
#define __PRITS "ld"
|
||||
#else
|
||||
#define __PRITS "d"
|
||||
#endif
|
||||
|
||||
struct env_status {
|
||||
int temp;
|
||||
int humi;
|
||||
|
@ -90,7 +96,7 @@ static bool query_cb(fdb_tsl_t tsl, void *arg)
|
|||
fdb_tsdb_t db = arg;
|
||||
|
||||
fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status))));
|
||||
FDB_INFO("[query_cb] queried a TSL: time: %ld, temp: %d, humi: %d\n", tsl->time, status.temp, status.humi);
|
||||
FDB_INFO("[query_cb] queried a TSL: time: %" __PRITS ", temp: %d, humi: %d\n", tsl->time, status.temp, status.humi);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -102,7 +108,7 @@ static bool query_by_time_cb(fdb_tsl_t tsl, void *arg)
|
|||
fdb_tsdb_t db = arg;
|
||||
|
||||
fdb_blob_read((fdb_db_t) db, fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &status, sizeof(status))));
|
||||
FDB_INFO("[query_by_time_cb] queried a TSL: time: %ld, temp: %d, humi: %d\n", tsl->time, status.temp, status.humi);
|
||||
FDB_INFO("[query_by_time_cb] queried a TSL: time: %" __PRITS ", temp: %d, humi: %d\n", tsl->time, status.temp, status.humi);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -111,7 +117,7 @@ static bool set_status_cb(fdb_tsl_t tsl, void *arg)
|
|||
{
|
||||
fdb_tsdb_t db = arg;
|
||||
|
||||
FDB_INFO("set the TSL (time %ld) status from %d to %d\n", tsl->time, tsl->status, FDB_TSL_USER_STATUS1);
|
||||
FDB_INFO("set the TSL (time %" __PRITS ") status from %d to %d\n", tsl->time, tsl->status, FDB_TSL_USER_STATUS1);
|
||||
fdb_tsl_set_status(db, tsl, FDB_TSL_USER_STATUS1);
|
||||
|
||||
return false;
|
||||
|
|
Loading…
Reference in New Issue