Flipper Zero Firmware
Loading...
Searching...
No Matches
lfs_config.h
1#pragma once
2
3#include <furi.h>
4
5#ifdef FURI_NDEBUG
6#define LFS_NO_ASSERT
7#define LFS_ASSERT(x)
8#else
9#define LFS_ASSERT furi_assert
10#endif
11
12#define LFS_TAG "Lfs"
13
14#ifdef FURI_LFS_DEBUG
15#define LFS_TRACE(...) FURI_LOG_T(LFS_TAG, __VA_ARGS__);
16
17#define LFS_DEBUG(...) FURI_LOG_D(LFS_TAG, __VA_ARGS__);
18#else
19#define LFS_TRACE(...)
20
21#define LFS_DEBUG(...)
22#endif // FURI_LFS_DEBUG
23
24#define LFS_WARN(...) FURI_LOG_W(LFS_TAG, __VA_ARGS__);
25
26#define LFS_ERROR(...) FURI_LOG_E(LFS_TAG, __VA_ARGS__);
27
28// Because crc
29#undef LFS_CONFIG
30
31// System includes
32#include <stdint.h>
33#include <stdbool.h>
34#include <string.h>
35#include <inttypes.h>
36
37#ifndef LFS_NO_MALLOC
38#include <stdlib.h>
39#endif
40#ifndef LFS_NO_ASSERT
41#include <assert.h>
42#endif
43#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR) || \
44 defined(LFS_YES_TRACE)
45#include <stdio.h>
46#endif
47
48#ifdef __cplusplus
49extern "C" {
50#endif
51
52// Builtin functions, these may be replaced by more efficient
53// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
54// expensive basic C implementation for debugging purposes
55
56// Min/max functions for unsigned 32-bit numbers
57static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
58 return (a > b) ? a : b;
59}
60
61static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
62 return (a < b) ? a : b;
63}
64
65// Align to nearest multiple of a size
66static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
67 return a - (a % alignment);
68}
69
70static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
71 return lfs_aligndown(a + alignment - 1, alignment);
72}
73
74// Find the smallest power of 2 greater than or equal to a
75static inline uint32_t lfs_npw2(uint32_t a) {
76#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
77 return 32 - __builtin_clz(a - 1);
78#else
79 uint32_t r = 0;
80 uint32_t s;
81 a -= 1;
82 s = (a > 0xffff) << 4;
83 a >>= s;
84 r |= s;
85 s = (a > 0xff) << 3;
86 a >>= s;
87 r |= s;
88 s = (a > 0xf) << 2;
89 a >>= s;
90 r |= s;
91 s = (a > 0x3) << 1;
92 a >>= s;
93 r |= s;
94 return (r | (a >> 1)) + 1;
95#endif
96}
97
98// Count the number of trailing binary zeros in a
99// lfs_ctz(0) may be undefined
100static inline uint32_t lfs_ctz(uint32_t a) {
101#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
102 return __builtin_ctz(a);
103#else
104 return lfs_npw2((a & -a) + 1) - 1;
105#endif
106}
107
108// Count the number of binary ones in a
109static inline uint32_t lfs_popc(uint32_t a) {
110#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
111 return __builtin_popcount(a);
112#else
113 a = a - ((a >> 1) & 0x55555555);
114 a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
115 return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
116#endif
117}
118
119// Find the sequence comparison of a and b, this is the distance
120// between a and b ignoring overflow
121static inline int lfs_scmp(uint32_t a, uint32_t b) {
122 return (int)(unsigned)(a - b);
123}
124
125// Convert between 32-bit little-endian and native order
126static inline uint32_t lfs_fromle32(uint32_t a) {
127#if !defined(LFS_NO_INTRINSICS) && \
128 ((defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \
129 BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \
130 (defined(__BYTE_ORDER) && defined(__ORDER_LITTLE_ENDIAN) && \
131 __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \
132 (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
133 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
134 return a;
135#elif !defined(LFS_NO_INTRINSICS) && \
136 ((defined(BYTE_ORDER) && defined(ORDER_BIG_ENDIAN) && BYTE_ORDER == ORDER_BIG_ENDIAN) || \
137 (defined(__BYTE_ORDER) && defined(__ORDER_BIG_ENDIAN) && \
138 __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \
139 (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
140 __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
141 return __builtin_bswap32(a);
142#else
143 return (((uint8_t*)&a)[0] << 0) | (((uint8_t*)&a)[1] << 8) | (((uint8_t*)&a)[2] << 16) |
144 (((uint8_t*)&a)[3] << 24);
145#endif
146}
147
148static inline uint32_t lfs_tole32(uint32_t a) {
149 return lfs_fromle32(a);
150}
151
152// Convert between 32-bit big-endian and native order
153static inline uint32_t lfs_frombe32(uint32_t a) {
154#if !defined(LFS_NO_INTRINSICS) && \
155 ((defined(BYTE_ORDER) && defined(ORDER_LITTLE_ENDIAN) && \
156 BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \
157 (defined(__BYTE_ORDER) && defined(__ORDER_LITTLE_ENDIAN) && \
158 __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \
159 (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
160 __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
161 return __builtin_bswap32(a);
162#elif !defined(LFS_NO_INTRINSICS) && \
163 ((defined(BYTE_ORDER) && defined(ORDER_BIG_ENDIAN) && BYTE_ORDER == ORDER_BIG_ENDIAN) || \
164 (defined(__BYTE_ORDER) && defined(__ORDER_BIG_ENDIAN) && \
165 __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \
166 (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
167 __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
168 return a;
169#else
170 return (((uint8_t*)&a)[0] << 24) | (((uint8_t*)&a)[1] << 16) | (((uint8_t*)&a)[2] << 8) |
171 (((uint8_t*)&a)[3] << 0);
172#endif
173}
174
175static inline uint32_t lfs_tobe32(uint32_t a) {
176 return lfs_frombe32(a);
177}
178
179// Calculate CRC-32 with polynomial = 0x04c11db7
180uint32_t lfs_crc(uint32_t crc, const void* buffer, size_t size);
181
182// Allocate memory, only used if buffers are not provided to littlefs
183// Note, memory must be 64-bit aligned
184static inline void* lfs_malloc(size_t size) {
185#ifndef LFS_NO_MALLOC
186 return malloc(size);
187#else
188 (void)size;
189 return NULL;
190#endif
191}
192
193// Deallocate memory, only used if buffers are not provided to littlefs
194static inline void lfs_free(void* p) {
195#ifndef LFS_NO_MALLOC
196 free(p);
197#else
198 (void)p;
199#endif
200}
201
202#ifdef __cplusplus
203} /* extern "C" */
204#endif
Furi string primitive.