mirror of
https://github.com/bouffalolab/bouffalo_sdk.git
synced 2025-05-09 03:11:58 +08:00
[update][littlefs] add easyflash porting for littlefs
This commit is contained in:
parent
f7a325f047
commit
0f6fe31094
@ -11,7 +11,15 @@ sdk_library_add_sources(port/lfs_xip_flash.c)
|
||||
sdk_add_include_directories(port)
|
||||
|
||||
sdk_add_compile_definitions(-DCONFIG_LITTLEFS)
|
||||
if(CONFIG_FREERTOS)
|
||||
sdk_add_compile_definitions(-DLFS_THREADSAFE)
|
||||
endif()
|
||||
|
||||
if(CONFIG_LITTLEFS_KV_EASYFLASH)
|
||||
sdk_library_add_sources(easyflash_port/lfs_easyflash.c)
|
||||
sdk_add_include_directories(easyflash_port)
|
||||
endif()
|
||||
|
||||
if(CONFIG_LITTLEFS_FLASH_ADDRESS)
|
||||
sdk_add_compile_definitions(-DCONFIG_LITTLEFS_FLASH_ADDRESS=${CONFIG_LITTLEFS_FLASH_ADDRESS})
|
||||
endif()
|
||||
endif()
|
||||
|
52
components/fs/littlefs/easyflash_port/easyflash.h
Normal file
52
components/fs/littlefs/easyflash_port/easyflash.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* This file is the header file that adapts LittleFS to EasyFlash4.
|
||||
*/
|
||||
|
||||
#ifndef EASYFLASH_H_
|
||||
#define EASYFLASH_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* EasyFlash error code */
|
||||
typedef enum {
|
||||
EF_NO_ERR,
|
||||
EF_ERASE_ERR,
|
||||
EF_READ_ERR,
|
||||
EF_WRITE_ERR,
|
||||
EF_ENV_NAME_ERR,
|
||||
EF_ENV_NAME_EXIST,
|
||||
EF_ENV_FULL,
|
||||
EF_ENV_INIT_FAILED,
|
||||
EF_ENV_ARG_ERR,
|
||||
} EfErrCode;
|
||||
|
||||
/* easyflash.c */
|
||||
EfErrCode easyflash_init(void);
|
||||
|
||||
/* only supported on ef_env.c */
|
||||
size_t ef_get_env_blob(const char *key, void *value_buf, size_t buf_len, size_t *saved_value_len);
|
||||
EfErrCode ef_set_env_blob(const char *key, const void *value_buf, size_t buf_len);
|
||||
|
||||
char *ef_get_env(const char *key) __attribute__((deprecated("Not recommended, use ef_get_env_blob instead")));
|
||||
EfErrCode ef_set_env(const char *key, const char *value);
|
||||
EfErrCode ef_del_env(const char *key);
|
||||
|
||||
EfErrCode ef_save_env(void);
|
||||
|
||||
/* clear all env */
|
||||
EfErrCode ef_env_set_default(void);
|
||||
|
||||
EfErrCode ef_set_and_save_env(const char *key, const char *value);
|
||||
EfErrCode ef_del_and_save_env(const char *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* EASYFLASH_H_ */
|
298
components/fs/littlefs/easyflash_port/lfs_easyflash.c
Normal file
298
components/fs/littlefs/easyflash_port/lfs_easyflash.c
Normal file
@ -0,0 +1,298 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#ifdef CONFIG_FREERTOS
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
#endif
|
||||
|
||||
#define DBG_TAG "LFS"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include "lfs.h"
|
||||
#include "lfs_port.h"
|
||||
#include "easyflash.h"
|
||||
|
||||
static lfs_t *lfs = NULL;
|
||||
static char key_buffer[64];
|
||||
|
||||
#ifndef LFS_EF_NAMESPACE
|
||||
#define LFS_EF_NAMESPACE "/_ef4_kvs_"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FREERTOS
|
||||
static SemaphoreHandle_t env_giant_lock = NULL;
|
||||
#endif
|
||||
|
||||
/* littlefs init */
|
||||
EfErrCode
|
||||
easyflash_init(void)
|
||||
{
|
||||
struct lfs_info stat;
|
||||
int32_t ret;
|
||||
|
||||
lfs = lfs_xip_init();
|
||||
if (lfs == NULL) {
|
||||
LOG_E("littlefs backend init failed.\r\n");
|
||||
return EF_ENV_INIT_FAILED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FREERTOS
|
||||
#if configUSE_RECURSIVE_MUTEXES
|
||||
env_giant_lock = xSemaphoreCreateRecursiveMutex();
|
||||
#else
|
||||
env_giant_lock = xSemaphoreCreateMutex();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* init namespace */
|
||||
ret = lfs_stat(lfs, LFS_EF_NAMESPACE, &stat);
|
||||
if (ret == LFS_ERR_OK) {
|
||||
if (stat.type == LFS_TYPE_DIR) {
|
||||
return EF_NO_ERR;
|
||||
} else if (stat.type == LFS_TYPE_REG) {
|
||||
LOG_E("namespace directory conflicts with standard file.\r\n");
|
||||
return EF_ENV_INIT_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
ret = lfs_mkdir(lfs, LFS_EF_NAMESPACE);
|
||||
if (ret != LFS_ERR_OK) {
|
||||
errno = -ret;
|
||||
LOG_E("create namespace directory failed.\r\n");
|
||||
return EF_ENV_INIT_FAILED;
|
||||
}
|
||||
|
||||
return EF_NO_ERR;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FREERTOS
|
||||
static void ef_giant_lock(void)
|
||||
{
|
||||
#if configUSE_RECURSIVE_MUTEXES
|
||||
xSemaphoreTakeRecursive(env_giant_lock, portMAX_DELAY);
|
||||
#else
|
||||
xSemaphoreTake(env_giant_lock, portMAX_DELAY);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ef_giant_unlock(void)
|
||||
{
|
||||
#if configUSE_RECURSIVE_MUTEXES
|
||||
xSemaphoreGiveRecursive(env_giant_lock);
|
||||
#else
|
||||
xSemaphoreGive(env_giant_lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define EF_GIANT_LOCK() ef_giant_lock()
|
||||
#define EF_GIANT_UNLOCK(ret) \
|
||||
ef_giant_unlock(); \
|
||||
return (ret)
|
||||
#else
|
||||
#define EF_GIANT_LOCK()
|
||||
#define EF_GIANT_UNLOCK(ret) return (ret)
|
||||
#endif
|
||||
|
||||
/* only supported on ef_env.c */
|
||||
size_t
|
||||
ef_get_env_blob(const char *key, void *value_buf, size_t buf_len, size_t *saved_value_len)
|
||||
{
|
||||
lfs_file_t file;
|
||||
int32_t ret, read_len;
|
||||
|
||||
if (lfs == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (key == NULL || value_buf == NULL || buf_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
EF_GIANT_LOCK();
|
||||
|
||||
ret = snprintf(key_buffer, sizeof(key_buffer), "%s/%s", LFS_EF_NAMESPACE, key);
|
||||
if (ret >= sizeof(key_buffer)) {
|
||||
LOG_E("key name is too long to truncated.\r\n");
|
||||
EF_GIANT_UNLOCK(0);
|
||||
}
|
||||
|
||||
ret = lfs_file_open(lfs, &file, key_buffer, LFS_O_RDONLY);
|
||||
if (ret != LFS_ERR_OK) {
|
||||
errno = -ret;
|
||||
EF_GIANT_UNLOCK(0);
|
||||
}
|
||||
|
||||
ret = lfs_file_read(lfs, &file, value_buf, buf_len);
|
||||
if (ret < 0) {
|
||||
LOG_E("lfs_file_read failed with errno:%d.\r\n", ret);
|
||||
errno = -ret;
|
||||
lfs_file_close(lfs, &file);
|
||||
EF_GIANT_UNLOCK(0);
|
||||
}
|
||||
|
||||
read_len = ret;
|
||||
|
||||
if (saved_value_len != NULL) {
|
||||
ret = lfs_file_size(lfs, &file);
|
||||
if (ret < 0) {
|
||||
LOG_E("lfs_file_size failed with errno:%d.\r\n", ret);
|
||||
lfs_file_close(lfs, &file);
|
||||
errno = -ret;
|
||||
EF_GIANT_UNLOCK(0);
|
||||
}
|
||||
*saved_value_len = ret;
|
||||
}
|
||||
|
||||
lfs_file_close(lfs, &file);
|
||||
|
||||
EF_GIANT_UNLOCK(read_len);
|
||||
}
|
||||
|
||||
EfErrCode
|
||||
ef_set_env_blob(const char *key, const void *value_buf, size_t buf_len)
|
||||
{
|
||||
lfs_file_t file;
|
||||
int32_t ret;
|
||||
|
||||
if (lfs == NULL) {
|
||||
return EF_ENV_INIT_FAILED;
|
||||
}
|
||||
|
||||
if (key == NULL || value_buf == NULL || buf_len == 0) {
|
||||
return EF_ENV_ARG_ERR;
|
||||
}
|
||||
|
||||
EF_GIANT_LOCK();
|
||||
|
||||
ret = snprintf(key_buffer, sizeof(key_buffer), "%s/%s", LFS_EF_NAMESPACE, key);
|
||||
if (ret >= sizeof(key_buffer)) {
|
||||
LOG_E("key name is too long to truncated.\r\n");
|
||||
EF_GIANT_UNLOCK(EF_ENV_NAME_ERR);
|
||||
}
|
||||
|
||||
ret = lfs_file_open(lfs, &file, key_buffer, LFS_O_RDWR | LFS_O_CREAT);
|
||||
if (ret != LFS_ERR_OK) {
|
||||
errno = -ret;
|
||||
LOG_E("lfs_file_open failed with errno:%d\r\n", ret);
|
||||
EF_GIANT_UNLOCK(EF_WRITE_ERR);
|
||||
}
|
||||
|
||||
ret = lfs_file_truncate(lfs, &file, buf_len);
|
||||
if (ret != LFS_ERR_OK) {
|
||||
errno = -ret;
|
||||
LOG_E("lfs_file_truncate failed with errno:%d\r\n", ret);
|
||||
lfs_file_close(lfs, &file);
|
||||
EF_GIANT_UNLOCK(EF_WRITE_ERR);
|
||||
}
|
||||
|
||||
ret = lfs_file_write(lfs, &file, value_buf, buf_len);
|
||||
if (ret != buf_len) {
|
||||
errno = -ret;
|
||||
LOG_E("lfs_file_write failed with errno:%d.\r\n", ret);
|
||||
lfs_file_close(lfs, &file);
|
||||
EF_GIANT_UNLOCK(EF_WRITE_ERR);
|
||||
}
|
||||
|
||||
lfs_file_close(lfs, &file);
|
||||
|
||||
EF_GIANT_UNLOCK(EF_NO_ERR);
|
||||
}
|
||||
|
||||
EfErrCode
|
||||
ef_del_env(const char *key)
|
||||
{
|
||||
int32_t ret;
|
||||
|
||||
if (lfs == NULL) {
|
||||
return EF_ENV_INIT_FAILED;
|
||||
}
|
||||
|
||||
if (key == NULL) {
|
||||
return EF_ENV_ARG_ERR;
|
||||
}
|
||||
|
||||
ret = snprintf(key_buffer, sizeof(key_buffer), "%s/%s", LFS_EF_NAMESPACE, key);
|
||||
if (ret >= sizeof(key_buffer)) {
|
||||
LOG_E("key name is too long to truncated.\r\n");
|
||||
EF_GIANT_UNLOCK(EF_ENV_NAME_ERR);
|
||||
}
|
||||
|
||||
lfs_remove(lfs, key_buffer);
|
||||
|
||||
return EF_ENV_ARG_ERR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DEPRECATED DEPRECATED-DEPRECATED-DEPRECATED-DEPRECATED-DEPRECATED
|
||||
***************************************************************************/
|
||||
static bool ef_is_str(uint8_t *value, size_t len)
|
||||
{
|
||||
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!__is_print(value[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DEPRECATED DEPRECATED-DEPRECATED-DEPRECATED-DEPRECATED-DEPRECATED
|
||||
***************************************************************************/
|
||||
char *
|
||||
ef_get_env(const char *key)
|
||||
{
|
||||
#ifndef EF_STR_ENV_VALUE_MAX_SIZE
|
||||
#define EF_STR_ENV_VALUE_MAX_SIZE (3979)
|
||||
#endif
|
||||
static char value[EF_STR_ENV_VALUE_MAX_SIZE + 1];
|
||||
size_t get_size;
|
||||
|
||||
printf("WARNING!!! ef_get_env is deprecated, use ef_get_env_blob instead.\r\n");
|
||||
|
||||
get_size = ef_get_env_blob(key, value, EF_STR_ENV_VALUE_MAX_SIZE, NULL);
|
||||
if (get_size > 0 && ef_is_str((uint8_t *)value, get_size)) {
|
||||
value[get_size] = '\0';
|
||||
return value;
|
||||
} else {
|
||||
LOG_W("The ENV value isn't string. Could not be returned\r\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
EfErrCode
|
||||
ef_set_env(const char *key, const char *value)
|
||||
{
|
||||
return ef_set_env_blob(key, value, strlen(value));
|
||||
}
|
||||
|
||||
EfErrCode
|
||||
ef_save_env(void)
|
||||
{
|
||||
return EF_NO_ERR;
|
||||
}
|
||||
|
||||
/* clear all env */
|
||||
EfErrCode
|
||||
ef_env_set_default(void)
|
||||
{
|
||||
return EF_ENV_ARG_ERR;
|
||||
}
|
||||
|
||||
EfErrCode
|
||||
ef_set_and_save_env(const char *key, const char *value)
|
||||
{
|
||||
return ef_set_env(key, value);
|
||||
}
|
||||
|
||||
EfErrCode
|
||||
ef_del_and_save_env(const char *key)
|
||||
{
|
||||
return ef_del_env(key);
|
||||
}
|
@ -3,11 +3,13 @@
|
||||
|
||||
#include "lfs.h"
|
||||
|
||||
extern int lfs_xip_flash_read(const struct lfs_config *c, lfs_block_t block,
|
||||
lfs_off_t off, void *buffer, lfs_size_t size);
|
||||
extern int lfs_xip_flash_prog(const struct lfs_config *c, lfs_block_t block,
|
||||
lfs_off_t off, const void *buffer, lfs_size_t size);
|
||||
extern int lfs_xip_flash_erase(const struct lfs_config *c, lfs_block_t block);
|
||||
extern int lfs_xip_flash_sync(const struct lfs_config *c);
|
||||
lfs_t *lfs_xip_init(void);
|
||||
|
||||
#endif
|
||||
int lfs_xip_flash_read(const struct lfs_config *c, lfs_block_t block,
|
||||
lfs_off_t off, void *buffer, lfs_size_t size);
|
||||
int lfs_xip_flash_prog(const struct lfs_config *c, lfs_block_t block,
|
||||
lfs_off_t off, const void *buffer, lfs_size_t size);
|
||||
int lfs_xip_flash_erase(const struct lfs_config *c, lfs_block_t block);
|
||||
int lfs_xip_flash_sync(const struct lfs_config *c);
|
||||
|
||||
#endif
|
||||
|
@ -1,26 +1,179 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "lfs.h"
|
||||
#include "bflb_flash.h"
|
||||
#include "bflb_l1c.h"
|
||||
#include "bflb_mtd.h"
|
||||
|
||||
#ifdef CONFIG_FREERTOS
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#endif
|
||||
#include "lfs_port.h"
|
||||
|
||||
#define DBG_TAG "LFS"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
/*!< use memory area after 512k */
|
||||
#ifdef CONFIG_LITTLEFS_FLASH_ADDRESS
|
||||
#define LITTLEFS_FLASH_SIZE (0x71000)
|
||||
#endif
|
||||
|
||||
#define LITTLEFS_FLASH_BLOCK_SIZE 4096
|
||||
#define LITTLEFS_FLASH_BLOCK_CYCLE 500
|
||||
|
||||
static lfs_t lfs;
|
||||
static char lfs_inited = 0;
|
||||
|
||||
#if defined(LFS_THREADSAFE) && defined(CONFIG_FREERTOS)
|
||||
static int lfs_xip_giant_lock(const struct lfs_config *c);
|
||||
static int lfs_xip_giant_unlock(const struct lfs_config *c);
|
||||
#endif
|
||||
|
||||
static struct lfs_context {
|
||||
uint32_t flash_addr;
|
||||
#ifdef CONFIG_FREERTOS
|
||||
SemaphoreHandle_t fs_giant_lock;
|
||||
#endif
|
||||
} lfs_xip_ctx;
|
||||
|
||||
/*!< configuration of the filesystem is provided by this struct */
|
||||
static struct lfs_config cfg = {
|
||||
.context = &lfs_xip_ctx,
|
||||
// block device operations
|
||||
.read = lfs_xip_flash_read,
|
||||
.prog = lfs_xip_flash_prog,
|
||||
.erase = lfs_xip_flash_erase,
|
||||
.sync = lfs_xip_flash_sync,
|
||||
#if defined(LFS_THREADSAFE) && defined(CONFIG_FREERTOS)
|
||||
.lock = lfs_xip_giant_lock,
|
||||
.unlock = lfs_xip_giant_unlock,
|
||||
#endif
|
||||
|
||||
// block device configuration
|
||||
.read_size = 256,
|
||||
.prog_size = 16,
|
||||
.lookahead_size = 256,
|
||||
.cache_size = 512,
|
||||
|
||||
.block_size = LITTLEFS_FLASH_BLOCK_SIZE,
|
||||
.block_cycles = LITTLEFS_FLASH_BLOCK_CYCLE,
|
||||
};
|
||||
|
||||
lfs_t *lfs_xip_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (lfs_inited) {
|
||||
return &lfs;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_LITTLEFS_FLASH_ADDRESS
|
||||
#error "must define CONFIG_LITTLEFS_FLASH_ADDRESS"
|
||||
bflb_mtd_info_t info;
|
||||
bflb_mtd_handle_t handle;
|
||||
|
||||
ret = bflb_mtd_open(BFLB_MTD_PARTITION_NAME_PSM, &handle, BFLB_MTD_OPEN_FLAG_BUSADDR);
|
||||
if (ret < 0) {
|
||||
LOG_E("no valid PSM partition found\r\n");
|
||||
errno = LFS_ERR_IO;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
bflb_mtd_info(handle, &info);
|
||||
LOG_I("Found valid PSM partition, XIP addr %08x, flash addr %08x, size %d\r\n",
|
||||
info.xip_addr,
|
||||
info.offset,
|
||||
info.size);
|
||||
lfs_xip_ctx.flash_addr = info.offset;
|
||||
cfg.block_count = info.size / LITTLEFS_FLASH_BLOCK_SIZE;
|
||||
bflb_mtd_close(handle);
|
||||
#else
|
||||
lfs_xip_ctx.flash_addr = CONFIG_LITTLEFS_FLASH_ADDRESS;
|
||||
cfg.block_count = LITTLEFS_FLASH_SIZE / LITTLEFS_FLASH_BLOCK_SIZE;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FREERTOS
|
||||
#if configUSE_RECURSIVE_MUTEXES
|
||||
lfs_xip_ctx.fs_giant_lock = xSemaphoreCreateRecursiveMutex();
|
||||
#else
|
||||
lfs_xip_ctx.fs_giant_lock = xSemaphoreCreateMutex();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// mount the filesystem
|
||||
ret = lfs_mount(&lfs, &cfg);
|
||||
|
||||
// reformat if we can't mount the filesystem
|
||||
// this should only happen on the first boot
|
||||
if (ret == LFS_ERR_CORRUPT) {
|
||||
LOG_W("try to reformat \r\n");
|
||||
ret = lfs_format(&lfs, &cfg);
|
||||
if (ret) {
|
||||
LOG_F("reformat fail\r\n");
|
||||
errno = LFS_ERR_CORRUPT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LOG_I("reformat success\r\n");
|
||||
ret = lfs_mount(&lfs, &cfg);
|
||||
if (ret) {
|
||||
errno = ret;
|
||||
return NULL;
|
||||
}
|
||||
} else if (ret != LFS_ERR_OK) {
|
||||
errno = ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LOG_I("mount success\r\n");
|
||||
lfs_inited = 1;
|
||||
|
||||
return &lfs;
|
||||
}
|
||||
|
||||
#if defined(LFS_THREADSAFE) && defined(CONFIG_FREERTOS)
|
||||
static int lfs_xip_giant_lock(const struct lfs_config *c)
|
||||
{
|
||||
struct lfs_context *ctx = c->context;
|
||||
#if configUSE_RECURSIVE_MUTEXES
|
||||
xSemaphoreTakeRecursive(ctx->fs_giant_lock, portMAX_DELAY);
|
||||
#else
|
||||
xSemaphoreTake(ctx->fs_giant_lock, portMAX_DELAY);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lfs_xip_giant_unlock(const struct lfs_config *c)
|
||||
{
|
||||
struct lfs_context *ctx = c->context;
|
||||
#if configUSE_RECURSIVE_MUTEXES
|
||||
xSemaphoreGiveRecursive(ctx->fs_giant_lock);
|
||||
#else
|
||||
xSemaphoreGive(ctx->fs_giant_lock);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief Read a region in a block. Negative error codes are propagated
|
||||
* to the user.
|
||||
* @param[in] c
|
||||
* @param[in] block
|
||||
* @param[in] off
|
||||
* @param[out] buffer
|
||||
* @param[in] size
|
||||
*
|
||||
* @retval int
|
||||
* @param[in] c
|
||||
* @param[in] block
|
||||
* @param[in] off
|
||||
* @param[out] buffer
|
||||
* @param[in] size
|
||||
*
|
||||
* @retval int
|
||||
*****************************************************************************/
|
||||
int lfs_xip_flash_read(const struct lfs_config *c, lfs_block_t block,
|
||||
lfs_off_t off, void *buffer, lfs_size_t size)
|
||||
{
|
||||
return bflb_flash_read(CONFIG_LITTLEFS_FLASH_ADDRESS + block * c->block_size + off,
|
||||
struct lfs_context *ctx = c->context;
|
||||
return bflb_flash_read(ctx->flash_addr + block * c->block_size + off,
|
||||
(uint8_t *)buffer, size);
|
||||
}
|
||||
|
||||
@ -28,18 +181,19 @@ int lfs_xip_flash_read(const struct lfs_config *c, lfs_block_t block,
|
||||
* @brief Program a region in a block. The block must have previously
|
||||
* been erased. Negative error codes are propagated to the user.
|
||||
* May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
* @param[in] c
|
||||
* @param[in] block
|
||||
* @param[in] off
|
||||
* @param[in] buffer
|
||||
* @param[in] size
|
||||
*
|
||||
* @retval int
|
||||
* @param[in] c
|
||||
* @param[in] block
|
||||
* @param[in] off
|
||||
* @param[in] buffer
|
||||
* @param[in] size
|
||||
*
|
||||
* @retval int
|
||||
*****************************************************************************/
|
||||
int lfs_xip_flash_prog(const struct lfs_config *c, lfs_block_t block,
|
||||
lfs_off_t off, const void *buffer, lfs_size_t size)
|
||||
{
|
||||
return bflb_flash_write(CONFIG_LITTLEFS_FLASH_ADDRESS + block * c->block_size + off,
|
||||
struct lfs_context *ctx = c->context;
|
||||
return bflb_flash_write(ctx->flash_addr + block * c->block_size + off,
|
||||
(uint8_t *)buffer, size);
|
||||
}
|
||||
|
||||
@ -48,25 +202,26 @@ int lfs_xip_flash_prog(const struct lfs_config *c, lfs_block_t block,
|
||||
* The state of an erased block is undefined. Negative error codes
|
||||
* are propagated to the user.
|
||||
* May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
* @param[in] c
|
||||
* @param[in] block
|
||||
*
|
||||
* @retval int
|
||||
* @param[in] c
|
||||
* @param[in] block
|
||||
*
|
||||
* @retval int
|
||||
*****************************************************************************/
|
||||
int lfs_xip_flash_erase(const struct lfs_config *c, lfs_block_t block)
|
||||
{
|
||||
return bflb_flash_erase(CONFIG_LITTLEFS_FLASH_ADDRESS + block * c->block_size, c->block_size);
|
||||
struct lfs_context *ctx = c->context;
|
||||
return bflb_flash_erase(ctx->flash_addr + block * c->block_size, c->block_size);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief Sync the state of the underlying block device. Negative error
|
||||
* @brief Sync the state of the underlying block device. Negative error
|
||||
* codes are propagated to the user.
|
||||
* @param[in] c
|
||||
*
|
||||
* @retval int
|
||||
* @param[in] c
|
||||
*
|
||||
* @retval int
|
||||
*****************************************************************************/
|
||||
int lfs_xip_flash_sync(const struct lfs_config *c)
|
||||
{
|
||||
/*!< if use xip, may need to clean cache */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
9
examples/easyflash/CMakeLists.txt
Normal file
9
examples/easyflash/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
include(proj.conf)
|
||||
|
||||
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
|
||||
|
||||
sdk_set_main_file(main.c)
|
||||
|
||||
project(easyflash)
|
13
examples/easyflash/Makefile
Normal file
13
examples/easyflash/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
SDK_DEMO_PATH ?= .
|
||||
BL_SDK_BASE ?= $(SDK_DEMO_PATH)/../..
|
||||
|
||||
export BL_SDK_BASE
|
||||
|
||||
CHIP ?= bl616
|
||||
BOARD ?= bl616dk
|
||||
CROSS_COMPILE ?= riscv64-unknown-elf-
|
||||
|
||||
# add custom cmake definition
|
||||
#cmake_definition+=-Dxxx=sss
|
||||
|
||||
include $(BL_SDK_BASE)/project.build
|
44
examples/easyflash/README.md
Normal file
44
examples/easyflash/README.md
Normal file
@ -0,0 +1,44 @@
|
||||
# easyflash
|
||||
|
||||
|
||||
## Support CHIP
|
||||
|
||||
| CHIP | Remark |
|
||||
|:----------------:|:------:|
|
||||
|BL602/BL604 | |
|
||||
|BL702/BL704/BL706 | |
|
||||
|BL616/BL618 | |
|
||||
|BL808 | |
|
||||
|
||||
## Compile
|
||||
|
||||
- BL602/BL604
|
||||
|
||||
```
|
||||
make CHIP=bl602 BOARD=bl602dk
|
||||
```
|
||||
|
||||
- BL702/BL704/BL706
|
||||
|
||||
```
|
||||
make CHIP=bl702 BOARD=bl702dk
|
||||
```
|
||||
|
||||
- BL616/BL618
|
||||
|
||||
```
|
||||
make CHIP=bl616 BOARD=bl616dk
|
||||
```
|
||||
|
||||
- BL808
|
||||
|
||||
```
|
||||
make CHIP=bl808 BOARD=bl808dk CPU_ID=m0
|
||||
make CHIP=bl808 BOARD=bl808dk CPU_ID=d0
|
||||
```
|
||||
|
||||
## Flash
|
||||
|
||||
```
|
||||
make flash CHIP=chip_name COMX=xxx # xxx is your com name
|
||||
```
|
20
examples/easyflash/flash_prog_cfg.ini
Normal file
20
examples/easyflash/flash_prog_cfg.ini
Normal file
@ -0,0 +1,20 @@
|
||||
[cfg]
|
||||
# 0: no erase, 1:programmed section erase, 2: chip erase
|
||||
erase = 1
|
||||
# skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
|
||||
skip_mode = 0x0, 0x0
|
||||
# 0: not use isp mode, #1: isp mode
|
||||
boot2_isp_mode = 0
|
||||
|
||||
[boot2]
|
||||
filedir = ./build/build_out/boot2_*.bin
|
||||
address = 0x000000
|
||||
|
||||
[partition]
|
||||
filedir = ./build/build_out/partition*.bin
|
||||
address = 0xE000
|
||||
|
||||
[FW]
|
||||
filedir = ./build/build_out/easyflash_$(CHIPNAME).bin
|
||||
address = @partition
|
||||
|
67
examples/easyflash/main.c
Normal file
67
examples/easyflash/main.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include "bflb_mtimer.h"
|
||||
#include "board.h"
|
||||
#include "bflb_mtd.h"
|
||||
#include "easyflash.h"
|
||||
|
||||
uint8_t test_data[] = { "1234567890" };
|
||||
uint8_t read_buffer[100];
|
||||
|
||||
#define WIFI_SSID_KEY "wifi.ssid"
|
||||
#define WIFI_PASSWD_KEY "wifi.passwd"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
|
||||
/* Partition and boot2 must be use, and we can only operate partition **psm** with easyflash
|
||||
*
|
||||
* partition_cfg with psm:
|
||||
*
|
||||
[[pt_entry]]
|
||||
type = 3
|
||||
name = "PSM"
|
||||
device = 0
|
||||
address0 = 0x3E9000
|
||||
size0 = 0x8000
|
||||
address1 = 0
|
||||
size1 = 0
|
||||
# compressed image must set len,normal image can left it to 0
|
||||
len = 0
|
||||
# If header is 1, it will add the header.
|
||||
header = 0
|
||||
# If header is 1 and security is 1, It will be encrypted.
|
||||
security= 0
|
||||
|
||||
*/
|
||||
bflb_mtd_init();
|
||||
easyflash_init();
|
||||
printf("errno: %d\r\n", errno);
|
||||
|
||||
memset(read_buffer, 0, sizeof(read_buffer));
|
||||
|
||||
printf("ef set env\r\n");
|
||||
ef_set_and_save_env(WIFI_SSID_KEY, (const char *)"helloworld");
|
||||
ef_set_and_save_env(WIFI_PASSWD_KEY, (const char *)"helloworld2023");
|
||||
|
||||
ef_save_env();
|
||||
|
||||
char ssid[33];
|
||||
char passwd[65];
|
||||
int ret;
|
||||
|
||||
printf("ef get env\r\n");
|
||||
if (ef_get_env(WIFI_SSID_KEY) != NULL) {
|
||||
ret = ef_get_env_blob(WIFI_SSID_KEY, ssid, sizeof(ssid), NULL);
|
||||
ssid[ret] = 0;
|
||||
printf("ssid:%s\r\n", ssid);
|
||||
}
|
||||
if (ef_get_env(WIFI_PASSWD_KEY) != NULL) {
|
||||
ret = ef_get_env_blob(WIFI_PASSWD_KEY, passwd, sizeof(passwd), NULL);
|
||||
passwd[ret] = 0;
|
||||
printf("passwd:%s\r\n", passwd);
|
||||
}
|
||||
|
||||
printf("easyflash case success\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
5
examples/easyflash/proj.conf
Normal file
5
examples/easyflash/proj.conf
Normal file
@ -0,0 +1,5 @@
|
||||
set(CONFIG_LITTLEFS 1)
|
||||
set(CONFIG_LITTLEFS_KV_EASYFLASH 1)
|
||||
|
||||
set(CONFIG_BFLB_MTD 1)
|
||||
set(CONFIG_PARTITION 1)
|
@ -6,6 +6,14 @@ skip_mode = 0x0, 0x0
|
||||
# 0: not use isp mode, #1: isp mode
|
||||
boot2_isp_mode = 0
|
||||
|
||||
[boot2]
|
||||
filedir = ./build/build_out/boot2_*.bin
|
||||
address = 0x000000
|
||||
|
||||
[partition]
|
||||
filedir = ./build/build_out/partition*.bin
|
||||
address = 0xE000
|
||||
|
||||
[FW]
|
||||
filedir = ./build/build_out/littlefs_$(CHIPNAME).bin
|
||||
address = 0x000000
|
||||
address = @partition
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include "arch_psm.h"
|
||||
|
||||
extern lfs_t lfs;
|
||||
extern lfs_t *lfs;
|
||||
|
||||
#ifndef CONFIG_KV_PSM_PATH
|
||||
#define CONFIG_KV_PSM_PATH ""
|
||||
@ -40,11 +40,11 @@ int arch_psm_get_value(const char *name_space, const char *key, void *value, siz
|
||||
|
||||
snprintf(name, CONFIG_KV_PSM_KEY_LEN, PSM_KV_FORMAT, CONFIG_KV_PSM_PATH, name_space, key);
|
||||
|
||||
fd = lfs_file_open(&lfs, &file, name, LFS_O_RDONLY);
|
||||
fd = lfs_file_open(lfs, &file, name, LFS_O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
ret = lfs_stat(&lfs, name, &info);
|
||||
ret = lfs_stat(lfs, name, &info);
|
||||
if (ret < 0)
|
||||
goto bail;
|
||||
|
||||
@ -53,11 +53,11 @@ int arch_psm_get_value(const char *name_space, const char *key, void *value, siz
|
||||
if (payload > length)
|
||||
goto bail;
|
||||
|
||||
ret = lfs_file_read(&lfs, &file, value, payload);
|
||||
ret = lfs_file_read(lfs, &file, value, payload);
|
||||
if (ret != payload)
|
||||
goto bail;
|
||||
|
||||
ret = lfs_file_read(&lfs, &file, &crc, sizeof(uint8_t));
|
||||
ret = lfs_file_read(lfs, &file, &crc, sizeof(uint8_t));
|
||||
if (ret != sizeof(uint8_t))
|
||||
goto bail;
|
||||
|
||||
@ -65,7 +65,7 @@ int arch_psm_get_value(const char *name_space, const char *key, void *value, siz
|
||||
ret = -1;
|
||||
|
||||
bail:
|
||||
lfs_file_close(&lfs, &file);
|
||||
lfs_file_close(lfs, &file);
|
||||
|
||||
return ret > 0 ? payload : ret;
|
||||
}
|
||||
@ -86,29 +86,29 @@ int arch_psm_set_value(const char *name_space, const char *key, const void *valu
|
||||
|
||||
snprintf(name, CONFIG_KV_PSM_KEY_LEN, PSM_KV_FORMAT, CONFIG_KV_PSM_PATH, name_space, key);
|
||||
|
||||
ret = lfs_stat(&lfs, name, &info);
|
||||
ret = lfs_stat(lfs, name, &info);
|
||||
if (ret < 0) {
|
||||
oflags = LFS_O_RDWR | LFS_O_CREAT;
|
||||
} else {
|
||||
oflags = LFS_O_RDWR | LFS_O_TRUNC;
|
||||
}
|
||||
|
||||
fd = lfs_file_open(&lfs, &file, name, oflags);
|
||||
fd = lfs_file_open(lfs, &file, name, oflags);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
ret = lfs_file_write(&lfs, &file, value, length);
|
||||
ret = lfs_file_write(lfs, &file, value, length);
|
||||
if (ret != length)
|
||||
goto bail;
|
||||
|
||||
crc = kvs_crc8((uint8_t *)value, length);
|
||||
|
||||
ret = lfs_file_write(&lfs, &file, &crc, sizeof(uint8_t));
|
||||
ret = lfs_file_write(lfs, &file, &crc, sizeof(uint8_t));
|
||||
|
||||
bail:
|
||||
ret_close = lfs_file_close(&lfs, &file);
|
||||
ret_close = lfs_file_close(lfs, &file);
|
||||
if ((ret_close < 0) && (oflags & LFS_O_CREAT)) {
|
||||
lfs_remove(&lfs, name);
|
||||
lfs_remove(lfs, name);
|
||||
}
|
||||
|
||||
return ret < 0 ? ret : (ret_close < 0 ? ret_close : length);
|
||||
@ -125,7 +125,7 @@ int arch_psm_erase_key(const char *name_space, const char *key)
|
||||
|
||||
snprintf(name, CONFIG_KV_PSM_KEY_LEN, PSM_KV_FORMAT, CONFIG_KV_PSM_PATH, name_space, key);
|
||||
|
||||
lfs_remove(&lfs, name);
|
||||
lfs_remove(lfs, name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "bflb_l1c.h"
|
||||
#include "bflb_uart.h"
|
||||
#include "board.h"
|
||||
#include "bflb_mtd.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "lfs.h"
|
||||
@ -39,40 +40,14 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/*!< use memory area after 512k */
|
||||
#define LITTLEFS_FLASH_SIZE (0x71000)
|
||||
#define LITTLEFS_FLASH_BLOCK_SIZE 4096
|
||||
#define LITTLEFS_FLASH_BLOCK_COUNT (LITTLEFS_FLASH_SIZE / LITTLEFS_FLASH_BLOCK_SIZE)
|
||||
#define LITTLEFS_FLASH_BLOCK_CYCLE 500
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct bflb_device_s *uart0;
|
||||
|
||||
lfs_t lfs;
|
||||
lfs_t *lfs;
|
||||
lfs_file_t file;
|
||||
|
||||
/*!< configuration of the filesystem is provided by this struct */
|
||||
const struct lfs_config cfg = {
|
||||
// block device operations
|
||||
.read = lfs_xip_flash_read,
|
||||
.prog = lfs_xip_flash_prog,
|
||||
.erase = lfs_xip_flash_erase,
|
||||
.sync = lfs_xip_flash_sync,
|
||||
|
||||
// block device configuration
|
||||
.read_size = 16,
|
||||
.prog_size = 16,
|
||||
.lookahead_size = 16,
|
||||
.cache_size = 16,
|
||||
|
||||
.block_size = LITTLEFS_FLASH_BLOCK_SIZE,
|
||||
.block_count = LITTLEFS_FLASH_BLOCK_COUNT,
|
||||
.block_cycles = LITTLEFS_FLASH_BLOCK_CYCLE,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
@ -88,45 +63,30 @@ SHELL_CMD_EXPORT_ALIAS(cmd_kv_test, kv_test, shell kv test);
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
bflb_mtd_init();
|
||||
|
||||
uart0 = bflb_device_get_by_name("uart0");
|
||||
shell_init_with_task(uart0);
|
||||
|
||||
// mount the filesystem
|
||||
int err = lfs_mount(&lfs, &cfg);
|
||||
|
||||
// reformat if we can't mount the filesystem
|
||||
// this should only happen on the first boot
|
||||
if (err) {
|
||||
LOG_W("try to reformat \r\n");
|
||||
err = lfs_format(&lfs, &cfg);
|
||||
if (err) {
|
||||
LOG_F("reformat fail\r\n");
|
||||
_CALL_ERROR();
|
||||
}
|
||||
|
||||
LOG_I("reformat success\r\n");
|
||||
err = lfs_mount(&lfs, &cfg);
|
||||
if (err) {
|
||||
LOG_F("mount fail\r\n");
|
||||
_CALL_ERROR();
|
||||
}
|
||||
lfs = lfs_xip_init();
|
||||
if (lfs == NULL) {
|
||||
LOG_F("lfs_xip_init failed. errno: %d\r\n", errno);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
LOG_I("mount success\r\n");
|
||||
|
||||
// read current count
|
||||
uint32_t boot_count = 0;
|
||||
lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
|
||||
lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));
|
||||
lfs_file_open(lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
|
||||
lfs_file_read(lfs, &file, &boot_count, sizeof(boot_count));
|
||||
|
||||
// update boot count
|
||||
boot_count += 1;
|
||||
lfs_file_rewind(&lfs, &file);
|
||||
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
|
||||
lfs_file_rewind(lfs, &file);
|
||||
lfs_file_write(lfs, &file, &boot_count, sizeof(boot_count));
|
||||
|
||||
// remember the storage is not updated until the file is closed successfully
|
||||
lfs_file_close(&lfs, &file);
|
||||
lfs_file_close(lfs, &file);
|
||||
|
||||
// release any resources we were using
|
||||
// lfs_unmount(&lfs);
|
||||
|
@ -4,7 +4,10 @@ set(CONFIG_MBEDTLS 1)
|
||||
set(CONFIG_SHELL 1)
|
||||
|
||||
set(CONFIG_LITTLEFS 1)
|
||||
set(CONFIG_LITTLEFS_FLASH_ADDRESS 0x378000)
|
||||
set(CONFIG_LITTLEFS_KV_EASYFLASH 1)
|
||||
|
||||
set(CONFIG_BFLB_MTD 1)
|
||||
set(CONFIG_PARTITION 1)
|
||||
|
||||
# Config
|
||||
## mbedtls
|
||||
@ -23,4 +26,3 @@ add_definitions(-DCONFIG_KV_TEST_FILE_OPER_SUM=20000)
|
||||
add_definitions(-DCONFIG_KV_TEST_FILE_OPER_PERIOD=1000)
|
||||
add_definitions(-DCONFIG_KV_PSM_KEY_LEN=64)
|
||||
# add_definitions(-DLFS_YES_TRACE)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user