diff --git a/modules/Kconfig b/modules/Kconfig index 08aa3aa26a..6033be2c7c 100644 --- a/modules/Kconfig +++ b/modules/Kconfig @@ -53,6 +53,9 @@ comment "hal_gigadevice module not available." comment "hal_nordic module not available." depends on !ZEPHYR_HAL_NORDIC_MODULE +comment "LittleFS module not available." + depends on !ZEPHYR_LITTLEFS_MODULE + comment "mbedtls module not available." depends on !ZEPHYR_MBEDTLS_MODULE diff --git a/modules/littlefs/CMakeLists.txt b/modules/littlefs/CMakeLists.txt new file mode 100644 index 0000000000..c73f810095 --- /dev/null +++ b/modules/littlefs/CMakeLists.txt @@ -0,0 +1,18 @@ +if(CONFIG_FILE_SYSTEM_LITTLEFS) + add_library(LITTLEFS INTERFACE) + + target_include_directories(LITTLEFS INTERFACE + ${ZEPHYR_LITTLEFS_MODULE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ) + target_link_libraries(LITTLEFS INTERFACE zephyr_interface) + target_compile_definitions(LITTLEFS INTERFACE LFS_CONFIG=zephyr_lfs_config.h) + + zephyr_library() + zephyr_library_sources( + ${ZEPHYR_LITTLEFS_MODULE_DIR}/lfs.c + ${ZEPHYR_LITTLEFS_MODULE_DIR}/lfs_util.c + zephyr_lfs_crc.c + ) + zephyr_library_link_libraries(LITTLEFS) +endif() diff --git a/modules/littlefs/Kconfig b/modules/littlefs/Kconfig new file mode 100644 index 0000000000..7c0f86ed58 --- /dev/null +++ b/modules/littlefs/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2022 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config ZEPHYR_LITTLEFS_MODULE + bool + +# Configuration of LittleFS is found in subsys/fs/Kconfig.littlefs for historic +# reasons. diff --git a/modules/littlefs/zephyr_lfs_config.h b/modules/littlefs/zephyr_lfs_config.h new file mode 100644 index 0000000000..af7be9ad93 --- /dev/null +++ b/modules/littlefs/zephyr_lfs_config.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2017, Arm Limited. All rights reserved. + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Origin of this file is the LittleFS lfs_util.h file adjusted for Zephyr + * specific needs. + */ + +#ifndef ZEPHYR_LFS_CONFIG_H +#define ZEPHYR_LFS_CONFIG_H + +/* System includes */ +#include +#include +#include +#include + +#ifndef LFS_NO_MALLOC +#include +#endif +#ifndef LFS_NO_ASSERT +#include +#endif + +#if !defined(LFS_NO_DEBUG) || \ + !defined(LFS_NO_WARN) || \ + !defined(LFS_NO_ERROR) || \ + defined(LFS_YES_TRACE) + +#include + +#ifdef LFS_LOG_REGISTER +LOG_MODULE_REGISTER(littlefs, CONFIG_FS_LOG_LEVEL); +#endif + +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Logging functions when using LittleFS with Zephyr. */ +#ifndef LFS_TRACE +#ifdef LFS_YES_TRACE +#define LFS_TRACE(fmt, ...) LOG_DBG("%s:%d:trace: " fmt, __FILE__, __LINE__, __VA_ARGS__) +#else +#define LFS_TRACE(...) +#endif +#endif + +#ifndef LFS_DEBUG +#define LFS_DEBUG(fmt, ...) LOG_DBG("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__) +#endif + +#ifndef LFS_WARN +#define LFS_WARN(fmt, ...) LOG_WRN("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__) +#endif + +#ifndef LFS_ERROR +#define LFS_ERROR(fmt, ...) LOG_ERR("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__) +#endif + +/* Runtime assertions */ +#ifndef LFS_ASSERT +#define LFS_ASSERT(test) __ASSERT_NO_MSG(test) +#endif + + +/* Builtin functions, these may be replaced by more efficient */ +/* toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more */ +/* expensive basic C implementation for debugging purposes */ + +/* Min/max functions for unsigned 32-bit numbers */ +static inline uint32_t lfs_max(uint32_t a, uint32_t b) +{ + return (a > b) ? a : b; +} + +static inline uint32_t lfs_min(uint32_t a, uint32_t b) +{ + return (a < b) ? a : b; +} + +/* Align to nearest multiple of a size */ +static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) +{ + return a - (a % alignment); +} + +static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) +{ + return lfs_aligndown(a + alignment-1, alignment); +} + +/* Find the smallest power of 2 greater than or equal to a */ +static inline uint32_t lfs_npw2(uint32_t a) +{ +#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) + return 32 - __builtin_clz(a-1); +#else + uint32_t r = 0; + uint32_t s; + + a -= 1; + s = (a > 0xffff) << 4; a >>= s; r |= s; + s = (a > 0xff) << 3; a >>= s; r |= s; + s = (a > 0xf) << 2; a >>= s; r |= s; + s = (a > 0x3) << 1; a >>= s; r |= s; + return (r | (a >> 1)) + 1; +#endif +} + +/* Count the number of trailing binary zeros in a */ +/* lfs_ctz(0) may be undefined */ +static inline uint32_t lfs_ctz(uint32_t a) +{ +#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__) + return __builtin_ctz(a); +#else + return lfs_npw2((a & -a) + 1) - 1; +#endif +} + +/* Count the number of binary ones in a */ +static inline uint32_t lfs_popc(uint32_t a) +{ +#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) + return __builtin_popcount(a); +#else + a = a - ((a >> 1) & 0x55555555); + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); + return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24; +#endif +} + +/* Find the sequence comparison of a and b, this is the distance */ +/* between a and b ignoring overflow */ +static inline int lfs_scmp(uint32_t a, uint32_t b) +{ + return (int)(unsigned int)(a - b); +} + +/* Convert between 32-bit little-endian and native order */ +static inline uint32_t lfs_fromle32(uint32_t a) +{ +#if !defined(LFS_NO_INTRINSICS) && ( \ + (defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \ + BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \ + (defined(__BYTE_ORDER) && defined(__ORDER_LITTLE_ENDIAN) && \ + __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) + return a; +#elif !defined(LFS_NO_INTRINSICS) && ( \ + (defined(BYTE_ORDER) && defined(ORDER_BIG_ENDIAN) && \ + BYTE_ORDER == ORDER_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER) && defined(__ORDER_BIG_ENDIAN) && \ + __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + return __builtin_bswap32(a); +#else + return (((uint8_t *)&a)[0] << 0) | + (((uint8_t *)&a)[1] << 8) | + (((uint8_t *)&a)[2] << 16) | + (((uint8_t *)&a)[3] << 24); +#endif +} + +static inline uint32_t lfs_tole32(uint32_t a) +{ + return lfs_fromle32(a); +} + +/* Convert between 32-bit big-endian and native order */ +static inline uint32_t lfs_frombe32(uint32_t a) +{ +#if !defined(LFS_NO_INTRINSICS) && ( \ + (defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \ + BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \ + (defined(__BYTE_ORDER) && defined(__ORDER_LITTLE_ENDIAN) && \ + __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) + return __builtin_bswap32(a); +#elif !defined(LFS_NO_INTRINSICS) && ( \ + (defined(BYTE_ORDER) && defined(ORDER_BIG_ENDIAN) && \ + BYTE_ORDER == ORDER_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER) && defined(__ORDER_BIG_ENDIAN) && \ + __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \ + (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ + __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + return a; +#else + return (((uint8_t *)&a)[0] << 24) | + (((uint8_t *)&a)[1] << 16) | + (((uint8_t *)&a)[2] << 8) | + (((uint8_t *)&a)[3] << 0); +#endif +} + +static inline uint32_t lfs_tobe32(uint32_t a) +{ + return lfs_frombe32(a); +} + +/* Calculate CRC-32 with polynomial = 0x04c11db7 */ +uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size); + +/* Allocate memory, only used if buffers are not provided to littlefs */ +/* Note, memory must be 64-bit aligned */ +static inline void *lfs_malloc(size_t size) +{ +#ifndef LFS_NO_MALLOC + return malloc(size); +#else + (void)size; + return NULL; +#endif +} + +/* Deallocate memory, only used if buffers are not provided to littlefs */ +static inline void lfs_free(void *p) +{ +#ifndef LFS_NO_MALLOC + free(p); +#else + (void)p; +#endif +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ZEPHYR_LFS_CONFIG_H */ diff --git a/subsys/fs/CMakeLists.txt b/subsys/fs/CMakeLists.txt index 66e01e4df7..f8a7a51c5c 100644 --- a/subsys/fs/CMakeLists.txt +++ b/subsys/fs/CMakeLists.txt @@ -10,6 +10,10 @@ if(CONFIG_FILE_SYSTEM) zephyr_library_sources_ifdef(CONFIG_FILE_SYSTEM_LITTLEFS littlefs_fs.c) zephyr_library_sources_ifdef(CONFIG_FILE_SYSTEM_SHELL shell.c) + zephyr_library_compile_definitions_ifdef(CONFIG_FILE_SYSTEM_LITTLEFS + LFS_CONFIG=zephyr_lfs_config.h + ) + zephyr_library_link_libraries(FS) target_link_libraries_ifdef(CONFIG_FAT_FILESYSTEM_ELM FS INTERFACE ELMFAT) diff --git a/subsys/fs/Kconfig.littlefs b/subsys/fs/Kconfig.littlefs index 86cd1d5a98..f714bb159a 100644 --- a/subsys/fs/Kconfig.littlefs +++ b/subsys/fs/Kconfig.littlefs @@ -8,6 +8,7 @@ config FILE_SYSTEM_LITTLEFS depends on FILE_SYSTEM depends on FLASH_MAP depends on FLASH_PAGE_LAYOUT + depends on ZEPHYR_LITTLEFS_MODULE help Enables LittleFS file system support. diff --git a/west.yml b/west.yml index 401a46aac1..3abbadc201 100644 --- a/west.yml +++ b/west.yml @@ -157,7 +157,7 @@ manifest: path: modules/fs/littlefs groups: - fs - revision: 33509ed9c3d369cdb9d909cd40c5eea8f64a902c + revision: pull/9/head - name: loramac-node revision: 12019623bbad9eb54fe51066847a7cbd4b4eac57 path: modules/lib/loramac-node