Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkg/flashdb: enhance FAL config #20221

Merged
merged 6 commits into from
Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pkg/flashdb/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ config MODULE_FLASHDB_KVDB_AUTO_UPDATE
database. If the version changes, it will automatically trigger an upgrade action
and update the new default KV collection to the current database.

config FLASHDB_MIN_SECTOR_SIZE_DEFAULT_KiB
int "Minimal virtual sector size in KiB for FlashDB"
default 4
help
By default, KVDB will use 1 times the block size as the sector size, that is, 4096.
At this time, the KVDB cannot store a KV longer than 4096. If you want to save, for example,
a KV with a length of 10K, you can use the control function to set the sector size to 12K or
larger.

config MODULE_FLASHDB_MTD

endif # PACKAGE_FLASHDB
112 changes: 102 additions & 10 deletions pkg/flashdb/include/fal_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,40 @@
#define FAL_CFG_H

#include "board.h"
#include "macros/units.h"
#include "mtd_default.h"

#ifdef __cplusplus
extern "C" {
#endif

#if !defined(CONFIG_FLASHDB_MIN_SECTOR_SIZE_DEFAULT_KiB) || defined(DOXYGEN)
/**
* @brief Minimal virtual sector size in KiB for FlashDB
*
* This is just a reasonable default for an automatic partition configuration, hence "DEFAULT".
* The "MIN" stands for a required minimum to guarantee an expected size of key value pairs.
* The actually acceptable sector size must be a multiple of the physical sector size though.
* Thus, it can be larger than the minimum required size.
*
* The default is 4 (4096).
* FlashDB sector size is different from MTD sector size as it is a
* virtual measure of granularity and not a device property.
* The virtual sector size must be a multiple of the physical sector size.
*
* From the documentation of FLashDB:
* The internal storage structure of FlashDB is composed of N sectors, and each formatting takes
* sector as the smallest unit. A sector is usually N times the size of the Flash block.
* For example, the block size of Nor Flash is generally 4096.
*
* By default, KVDB will use 1 times the block size as the sector size, that is, 4096.
* At this time, the KVDB cannot store a KV longer than 4096. If you want to save, for example,
* a KV with a length of 10K, you can use the control function to set the sector size to 12K or larger.

Check warning on line 57 in pkg/flashdb/include/fal_cfg.h

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
*
*/
#define CONFIG_FLASHDB_MIN_SECTOR_SIZE_DEFAULT_KiB 4
#endif

/**
* @brief Partition table is defined at compile time (not read from flash)
*/
Expand All @@ -49,42 +78,105 @@
&mtd_flash0, \
}

#if !defined(FAL_MTD) || defined(DOXYGEN)
/**
* @brief Default MTD to use for flashdb
*/
#define FAL_MTD mtd_default_get_dev(0)
#endif

#if !defined(FAL_PART0_LABEL) || defined(DOXYGEN)
/**
* @brief Have at least the label of partition 0 defined
*/
#define FAL_PART0_LABEL "part0"
#endif

#if !defined(FAL_PART0_LENGTH) || defined(DOXYGEN)
/**
* @brief Have at least the length of partition 0 defined, which must be at least two sectors
* and a multiple of the virtual sector size.
*
* The virtual sector size is however bound to the physical sector size of @ref FAL_MTD.
* So make sure that @ref CONFIG_FLASHDB_MIN_SECTOR_SIZE_DEFAULT_KiB times 1024 is a multiple of the MTD sector size.

Check warning on line 101 in pkg/flashdb/include/fal_cfg.h

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
* For example if the MTD sector size is 4KiB, then @ref CONFIG_FLASHDB_MIN_SECTOR_SIZE_DEFAULT_KiB must be a multiple of 4.

Check warning on line 102 in pkg/flashdb/include/fal_cfg.h

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
* If the MTD sector size is 1KiB, then you have all options for @ref CONFIG_FLASHDB_MIN_SECTOR_SIZE_DEFAULT_KiB.

Check warning on line 103 in pkg/flashdb/include/fal_cfg.h

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
*/
#define FAL_PART0_LENGTH (2 * (CONFIG_FLASHDB_MIN_SECTOR_SIZE_DEFAULT_KiB * KiB(1)))

Check warning on line 105 in pkg/flashdb/include/fal_cfg.h

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
#endif

/**
* @brief Partition 0
*/
#ifdef FAL_PART0_LABEL
#if defined(FAL_PART0_LABEL) || defined(DOXYGEN)
#if !defined(FAL_PART0_OFFSET) || defined(DOXYGEN)
/**
* @brief Offset of partition 0
*/
#define FAL_PART0_OFFSET 0
#endif
/**
* @brief Partition 0 compound definition
*/
#define FAL_ROW_PART0 { FAL_PART_MAGIC_WORD, FAL_PART0_LABEL, "fal_mtd", \
0, FAL_PART0_LENGTH, 0 },
FAL_PART0_OFFSET, FAL_PART0_LENGTH, 0 },
#else
#define FAL_ROW_PART0
#endif

/**
* @brief Partition 1
*/
#ifdef FAL_PART1_LABEL
#if defined(FAL_PART1_LABEL) || defined(DOXYGEN)
#if !defined(FAL_PART1_OFFSET) || defined(DOXYGEN)
/**
* @brief Offset of partition 1
*/
#define FAL_PART1_OFFSET (FAL_PART0_OFFSET + FAL_PART0_LENGTH)
#endif
/**
* @brief Partition 1 compound definition
*/
#define FAL_ROW_PART1 { FAL_PART_MAGIC_WORD, FAL_PART1_LABEL, "fal_mtd", \
FAL_PART0_LENGTH, FAL_PART1_LENGTH, 0 },
FAL_PART1_OFFSET, FAL_PART1_LENGTH, 0 },
#else
#define FAL_ROW_PART1
#endif

/**
* @brief Partition 2
*/
#ifdef FAL_PART2_LABEL
#define FAL_ROW_PART2 { FAL_PART_MAGIC_WORD, FAL_PART2_LABEL, "fal_mtd",
FAL_PART1_LENGTH, FAL_PART2_LENGTH, 0 },
#if defined(FAL_PART2_LABEL) || defined(DOXYGEN)
#if !defined(FAL_PART2_OFFSET) || defined(DOXYGEN)
/**
* @brief Offset of partition 2
*/
#define FAL_PART2_OFFSET (FAL_PART1_OFFSET + FAL_PART1_LENGTH)
#endif
/**
* @brief Partition 2 compound definition
*/
#define FAL_ROW_PART2 { FAL_PART_MAGIC_WORD, FAL_PART2_LABEL, "fal_mtd", \
FAL_PART2_OFFSET, FAL_PART2_LENGTH, 0 },
#else
#define FAL_ROW_PART2
#endif

/**
* @brief Partition 3
*/
#ifdef FAL_PART3_LABEL
#define FAL_ROW_PART3 { FAL_PART_MAGIC_WORD, FAL_PART2_LABEL, "fal_mtd",
FAL_PART2_LENGTH, FAL_PART3_LENGTH, 0 },
#if defined(FAL_PART3_LABEL) || defined(DOXYGEN)
#if !defined(FAL_PART3_OFFSET) || defined(DOXYGEN)
/**
* @brief Offset of partition 3
*/
#define FAL_PART3_OFFSET (FAL_PART2_OFFSET + FAL_PART2_LENGTH)
#endif
/**
* @brief Partition 3 compound definition
*/
#define FAL_ROW_PART3 { FAL_PART_MAGIC_WORD, FAL_PART3_LABEL, "fal_mtd", \
FAL_PART3_OFFSET, FAL_PART3_LENGTH, 0 },
#else
#define FAL_ROW_PART3
#endif
Expand Down
4 changes: 3 additions & 1 deletion pkg/flashdb/mtd/fal_mtd_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ struct fal_flash_dev mtd_flash0 = {
void fdb_mtd_init(mtd_dev_t *mtd)
{
unsigned sector_size;

if (_mtd) {
return;
}
mtd_init(mtd);
_mtd = mtd;

Expand Down
29 changes: 29 additions & 0 deletions tests/pkg/flashdb_fal_cfg/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
include ../Makefile.pkg_common

# select the MTD backend
USEMODULE += flashdb_mtd
# enable key-value database
USEMODULE += flashdb_kvdb
# enable time series database
USEMODULE += flashdb_tsdb
# rtc_localtime()
USEMODULE += rtc_utils

# prefer periph_rtc over periph_rtt
FEATURES_OPTIONAL += periph_rtc
FEATURES_REQUIRED_ANY += periph_rtc|periph_rtt

CFLAGS += -DFAL_PART1_LABEL=\"part1\"
CFLAGS += -DFAL_PART1_LENGTH=FAL_PART0_LENGTH
CFLAGS += -DFAL_PART2_LABEL=\"part2\"
CFLAGS += -DFAL_PART2_LENGTH=FAL_PART0_LENGTH
CFLAGS += -DFAL_PART3_LABEL=\"part3\"
CFLAGS += -DFAL_PART3_LENGTH=FAL_PART0_LENGTH

include $(RIOTBASE)/Makefile.include

# handle RTC backend after inclusion of $(RIOTBASE)/Makefile.include
ifeq (,$(filter periph_rtc,$(FEATURES_USED)))
USEMODULE += rtt_rtc
USEMODULE += ztimer_no_periph_rtt
endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work? I would expect that doing this after the dependency resolution won't have any effect.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don´t know the magic behind it but I assume it works. When I remove FEATURES_PROVIDED += periph_rtc from boards/same54-xpro/Makefile.features and do an info-modules I see that rtt_rtc and ztimer_no_periph_rtt are in. When I try to build after I remove USEMODULE += rtt_rtc linking fails, as expected.

Copy link
Contributor Author

@fabian18 fabian18 Jan 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests/pkg/flashdb_fal_cfg/main.c:99: undefined reference to 'rtc_get_time'

7 changes: 7 additions & 0 deletions tests/pkg/flashdb_fal_cfg/Makefile.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
BOARD_INSUFFICIENT_MEMORY := \
nucleo-f031k6 \
nucleo-l011k4 \
samd10-xmini \
stk3200 \
stm32f030f4-demo \
#
149 changes: 149 additions & 0 deletions tests/pkg/flashdb_fal_cfg/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright (C) 2023 ML!PA Consulting Gmbh
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/

/**
* @ingroup tests
* @{
*
* @file
* @brief Short test for the FlashDB FAL configuration initialization
*
* @author Fabian Hüßler <fabian.huessler@ml-pa.com>
*
* @}
*/

#include <stdio.h>

#include "container.h"
#include "fal.h"
#include "macros/math.h"
#include "mutex.h"
#include "periph/rtc.h"

#include <flashdb.h>

/**
* @brief FlashDB Magic Word
*
* The value here is not relevant but it must be defined.
*/
#define FAL_PART_MAGIC_WORD 0x45503130

/**
* @brief Number of FAL partitions
*/
#define FAL_PART_TABLE_NUMOF ARRAY_SIZE(((const struct fal_partition[])FAL_PART_TABLE))

#if !defined(FAL_TSDB_MAX) || defined(DOXYGEN)
/**
* @brief Maximum length of a TSDB entry
*/
#define FAL_TSDB_MAX 128
#endif

#if !defined(FAL_PART_TABLE_KVDB) || defined(DOXYGEN)
/**
* @brief Indices of partitions in @ref FAL_PART_TABLE that can be initialized as a Key-Value-DB
*/
#define FAL_PART_TABLE_KVDB \
{ \
0, \
1, \
}
#endif

#if !defined(FAL_PART_TABLE_TSDB) || defined(DOXYGEN)
/**
* @brief Indices of partitions in @ref FAL_PART_TABLE that can be initialized as a Time-Series-DB
*/
#define FAL_PART_TABLE_TSDB \
{ \
2, \
3, \
}
#endif

extern void fdb_mtd_init(mtd_dev_t *mtd);

static mutex_t _locker = MUTEX_INIT;
static const unsigned _fdb_part_kvdb[] = FAL_PART_TABLE_KVDB;
static const unsigned _fdb_part_tsdb[] = FAL_PART_TABLE_TSDB;
static struct fdb_kvdb _kvdb[ARRAY_SIZE(_fdb_part_kvdb)];
static struct fdb_tsdb _tsdb[ARRAY_SIZE(_fdb_part_tsdb)];

/**
* @brief Select MTD device to use for FlashDB
*/
#if !defined(FDB_MTD)
#define FDB_MTD FAL_MTD
#endif

static void _lock(fdb_db_t db)
{
mutex_lock(db->user_data);
}

static void _unlock(fdb_db_t db)
{
mutex_unlock(db->user_data);
}

static fdb_time_t _get_time(void)
{
struct tm now;
rtc_get_time(&now);
return mktime(&now);
}

int main(void)
{
int init_failed;
fdb_mtd_init(FDB_MTD);
size_t size = FDB_MTD->pages_per_sector * FDB_MTD->page_size;
/* scale hardware sector size to minimum required virtual sector size */
size = DIV_ROUND_UP((CONFIG_FLASHDB_MIN_SECTOR_SIZE_DEFAULT_KiB * KiB(1)), size) * size;
printf("Informational: Make sure the following requirements are fulfilled for a successful initialization:\n");

Check warning on line 111 in tests/pkg/flashdb_fal_cfg/main.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
printf("The virtual sector size is a multiple of the physical sector size: %lu %% %lu == 0\n",
(unsigned long)size, (unsigned long)FDB_MTD->pages_per_sector * FDB_MTD->page_size);
printf("The maximum partition size is a multiple of the virtual sector size: %lu %% %lu == 0\n",
(unsigned long)FAL_PART0_LENGTH, (unsigned long)size);

for (unsigned i = 0; i < ARRAY_SIZE(_fdb_part_kvdb); i++) {
unsigned part = _fdb_part_kvdb[i];
if (part >= FAL_PART_TABLE_NUMOF) {
continue;
}
fdb_kvdb_control(&_kvdb[i], FDB_KVDB_CTRL_SET_SEC_SIZE, &size);
fdb_kvdb_control(&_kvdb[i], FDB_KVDB_CTRL_SET_LOCK, (void *)(uintptr_t)_lock);
fdb_kvdb_control(&_kvdb[i], FDB_KVDB_CTRL_SET_UNLOCK, (void *)(uintptr_t)_unlock);
const char *spart = ((const struct fal_partition[])FAL_PART_TABLE)[part].name;
printf("Initializing FlashDB KVDB partition %s\n", spart);
if ((init_failed = fdb_kvdb_init(&_kvdb[i], "kvdb", spart, NULL, &_locker)) != FDB_NO_ERR) {
printf("Failed to initialize FlashDB KVDB partition %s (%d)\n", spart, init_failed);
return 1;
}
}
for (unsigned i = 0; i < ARRAY_SIZE(_fdb_part_tsdb); i++) {
unsigned part = _fdb_part_tsdb[i];
if (part >= FAL_PART_TABLE_NUMOF) {
continue;
}
fdb_tsdb_control(&_tsdb[i], FDB_TSDB_CTRL_SET_LOCK, (void *)(uintptr_t)_lock);
fdb_tsdb_control(&_tsdb[i], FDB_TSDB_CTRL_SET_UNLOCK, (void *)(uintptr_t)_unlock);
fdb_tsdb_control(&_tsdb[i], FDB_TSDB_CTRL_SET_SEC_SIZE, &size);
const char *spart = ((const struct fal_partition[])FAL_PART_TABLE)[part].name;
printf("Initializing FlashDB TSDB partition %s\n", spart);
if ((init_failed = fdb_tsdb_init(&_tsdb[i], "tsdb", spart, _get_time, FAL_TSDB_MAX, &_locker)) != FDB_NO_ERR) {

Check warning on line 142 in tests/pkg/flashdb_fal_cfg/main.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
printf("Failed to initialize FlashDB TSDB partition %s (%d)\n", spart, init_failed);
return 1;
}
}
puts("SUCCESS");
return 0;
}
7 changes: 7 additions & 0 deletions tests/pkg/flashdb_mtd/Makefile.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
BOARD_INSUFFICIENT_MEMORY := \
nucleo-f031k6 \
nucleo-l011k4 \
samd10-xmini \
stk3200 \
stm32f030f4-demo \
#
5 changes: 3 additions & 2 deletions tests/pkg/flashdb_vfs/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <sys/types.h>
#include <flashdb.h>

#include "fal_cfg.h"
#include "board.h"
#include "mutex.h"
#ifdef MODULE_VFS
Expand All @@ -20,8 +21,8 @@
/**
* @brief Select MTD device to use for FlashDB
*/
#if !defined(FDB_MTD) && defined(MTD_0)
#define FDB_MTD MTD_0
#if !defined(FDB_MTD)
#define FDB_MTD FAL_MTD
#endif

#define FDB_LOG_TAG "[main]"
Expand Down Expand Up @@ -110,9 +111,9 @@
*
* &kvdb: database object
* "env": database name
* "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.

Check warning on line 114 in tests/pkg/flashdb_vfs/main.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
* Please change to YOUR partition name.
* &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully.

Check warning on line 116 in tests/pkg/flashdb_vfs/main.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
* &kv_locker: The locker object.
*/
result = fdb_kvdb_init(&kvdb, "env", FDB_DIR "/fdb_kvdb1", &default_kv, &kv_locker);
Expand Down Expand Up @@ -150,7 +151,7 @@
*
* &tsdb: database object
* "log": database name
* "fdb_tsdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.

Check warning on line 154 in tests/pkg/flashdb_vfs/main.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
* Please change to YOUR partition name.
* get_time: The get current timestamp function.
* 128: maximum length of each log
Expand Down
Loading