diff options
author | Christopher Haster <chaster@utexas.edu> | 2018-01-30 00:20:12 +0300 |
---|---|---|
committer | Christopher Haster <chaster@utexas.edu> | 2018-02-19 10:40:23 +0300 |
commit | a3fd2d4d6d5e125f878177931a8bd52e5d114f7a (patch) | |
tree | b28db28611d9dd9a97bacbdf10426421386b0782 /lfs_util.h | |
parent | a0a55fb9e5942b51331947b855756abcac42a3c5 (diff) |
Added more configurable utils
Note: It's still expected to modify lfs_utils.h when porting littlefs
to a new target/system. There's just too much room for system-specific
improvements, such as taking advantage of CRC hardware.
Rather, encouraging modification of lfs_util.h and making it easy to
modify and debug should result in better integration with the consuming
systems.
This just adds a bunch of quality-of-life improvements that should help
development and integration in littlefs.
- Macros that require no side-effects are all-caps
- System includes are only brought in when needed
- Malloc/free wrappers
- LFS_NO_* checks for quickly disabling things at the command line
- At least a little-bit more docs
Diffstat (limited to 'lfs_util.h')
-rw-r--r-- | lfs_util.h | 92 |
1 files changed, 78 insertions, 14 deletions
@@ -18,13 +18,60 @@ #ifndef LFS_UTIL_H #define LFS_UTIL_H -#include <stdlib.h> #include <stdint.h> +#include <stdbool.h> +#include <string.h> + +#ifndef LFS_NO_MALLOC +#include <stdlib.h> +#endif +#ifndef LFS_NO_ASSERT +#include <assert.h> +#endif +#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR) #include <stdio.h> +#endif + + +// Macros, may be replaced by system specific wrappers. Arguments to these +// macros must not have side-effects as the macros can be removed for a smaller +// code footprint + +// Logging functions +#ifndef LFS_NO_DEBUG +#define LFS_DEBUG(fmt, ...) \ + printf("lfs debug:%d: " fmt "\n", __LINE__, __VA_ARGS__) +#else +#define LFS_DEBUG(fmt, ...) +#endif + +#ifndef LFS_NO_WARN +#define LFS_WARN(fmt, ...) \ + printf("lfs warn:%d: " fmt "\n", __LINE__, __VA_ARGS__) +#else +#define LFS_WARN(fmt, ...) +#endif + +#ifndef LFS_NO_ERROR +#define LFS_ERROR(fmt, ...) \ + printf("lfs error:%d: " fmt "\n", __LINE__, __VA_ARGS__) +#else +#define LFS_ERROR(fmt, ...) +#endif + +// Runtime assertions +#ifndef LFS_NO_ASSERT +#define LFS_ASSERT(test) assert(test) +#else +#define LFS_ASSERT(test) +#endif -// Builtin functions, these may be replaced by more -// efficient implementations in the system +// 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; } @@ -33,8 +80,9 @@ static inline uint32_t lfs_min(uint32_t a, uint32_t b) { return (a < b) ? a : b; } +// Find the next smallest power of 2 less than or equal to a static inline uint32_t lfs_npw2(uint32_t a) { -#if defined(__GNUC__) || defined(__CC_ARM) +#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) return 32 - __builtin_clz(a-1); #else uint32_t r = 0; @@ -48,16 +96,19 @@ static inline uint32_t lfs_npw2(uint32_t a) { #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(__GNUC__) +#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(__GNUC__) || defined(__CC_ARM) +#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) return __builtin_popcount(a); #else a = a - ((a >> 1) & 0x55555555); @@ -66,17 +117,20 @@ static inline uint32_t lfs_popc(uint32_t a) { #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)(a - b); } +// Convert from 32-bit little-endian to native order static inline uint32_t lfs_fromle32(uint32_t a) { -#if ( \ +#if !defined(LFS_NO_INTRINSICS) && ( \ (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) return a; -#elif ( \ +#elif !defined(LFS_NO_INTRINSICS) && ( \ (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) @@ -89,19 +143,29 @@ static inline uint32_t lfs_fromle32(uint32_t a) { #endif } +// Convert to 32-bit little-endian from native order static inline uint32_t lfs_tole32(uint32_t a) { return lfs_fromle32(a); } -// CRC-32 with polynomial = 0x04c11db7 +// Calculate CRC-32 with polynomial = 0x04c11db7 void lfs_crc(uint32_t *crc, const void *buffer, size_t size); +// Allocate memory, only used if buffers are not provided to littlefs +static inline void *lfs_malloc(size_t size) { +#ifndef LFS_NO_MALLOC + return malloc(size); +#else + return NULL; +#endif +} -// Logging functions, these may be replaced by system-specific -// logging functions -#define LFS_DEBUG(fmt, ...) printf("lfs debug: " fmt "\n", __VA_ARGS__) -#define LFS_WARN(fmt, ...) printf("lfs warn: " fmt "\n", __VA_ARGS__) -#define LFS_ERROR(fmt, ...) printf("lfs error: " fmt "\n", __VA_ARGS__) +// Deallocate memory, only used if buffers are not provided to littlefs +static inline void lfs_free(void *p) { +#ifndef LFS_NO_MALLOC + free(p); +#endif +} #endif |