1 /*
2 * lfs utility functions
3 *
4 * Copyright (c) 2017, Arm Limited. All rights reserved.
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7 #ifndef LFS_UTIL_H
8 #define LFS_UTIL_H
9
10 // Users can override lfs_util.h with their own configuration by defining
11 // LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
12 //
13 // If LFS_CONFIG is used, none of the default utils will be emitted and must be
14 // provided by the config file. To start, I would suggest copying lfs_util.h
15 // and modifying as needed.
16 #ifdef LFS_CONFIG
17 #define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
18 #define LFS_STRINGIZE2(x) #x
19 #include LFS_STRINGIZE(LFS_CONFIG)
20 #else
21
22 // System includes
23 #include <stdint.h>
24 #include <stdbool.h>
25 #include <string.h>
26 #include <inttypes.h>
27
28 #ifndef LFS_NO_MALLOC
29 #include <stdlib.h>
30 #endif
31 #ifndef LFS_NO_ASSERT
32 #ifdef __ZEPHYR__
33 #include <sys/__assert.h>
34 #else /* __ZEPHYR__ */
35 #include <assert.h>
36 #endif /* __ZEPHYR__ */
37 #endif
38
39 #if !defined(LFS_NO_DEBUG) || \
40 !defined(LFS_NO_WARN) || \
41 !defined(LFS_NO_ERROR) || \
42 defined(LFS_YES_TRACE)
43
44 #ifdef __ZEPHYR__
45 #include <logging/log.h>
46
47 #ifdef LFS_LOG_REGISTER
48 LOG_MODULE_REGISTER(littlefs, CONFIG_FS_LOG_LEVEL);
49 #else
50 LOG_MODULE_DECLARE(littlefs, CONFIG_FS_LOG_LEVEL);
51 #endif
52
53 #endif /* __ZEPHYR__ */
54
55 #include <stdio.h>
56 #endif
57
58 #ifdef __cplusplus
59 extern "C"
60 {
61 #endif
62
63
64 // Macros, may be replaced by system specific wrappers. Arguments to these
65 // macros must not have side-effects as the macros can be removed for a smaller
66 // code footprint
67
68 // Logging functions
69 #ifdef LFS_YES_TRACE
70 #ifdef __ZEPHYR__
71 #define LFS_TRACE(fmt, ...) LOG_DBG("%s:%d:trace: " fmt, __FILE__, __LINE__, __VA_ARGS__)
72 #else /* __ZEPHYR__ */
73 #define LFS_TRACE_(fmt, ...) \
74 printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
75 #define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
76 #endif /* __ZEPHYR__ */
77 #else
78 #define LFS_TRACE(...)
79 #endif
80
81 #ifndef LFS_NO_DEBUG
82 #ifdef __ZEPHYR__
83 #define LFS_DEBUG(fmt, ...) LOG_DBG("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__)
84 #else /* __ZEPHYR__ */
85 #define LFS_DEBUG_(fmt, ...) \
86 printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
87 #define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, "")
88 #endif /* __ZEPHYR__ */
89 #else
90 #define LFS_DEBUG(...)
91 #endif
92
93 #ifndef LFS_NO_WARN
94 #ifdef __ZEPHYR__
95 #define LFS_WARN(fmt, ...) LOG_WRN("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__)
96 #else /* __ZEPHYR__ */
97 #define LFS_WARN_(fmt, ...) \
98 printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
99 #define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, "")
100 #endif /* __ZEPHYR__ */
101 #else
102 #define LFS_WARN(...)
103 #endif
104
105 #ifndef LFS_NO_ERROR
106 #ifdef __ZEPHYR__
107 #define LFS_ERROR(fmt, ...) LOG_ERR("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__)
108 #else /* __ZEPHYR__ */
109 #define LFS_ERROR_(fmt, ...) \
110 printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
111 #define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "")
112 #endif /* __ZEPHYR__ */
113 #else
114 #define LFS_ERROR(...)
115 #endif
116
117 // Runtime assertions
118 #ifndef LFS_NO_ASSERT
119 #ifdef __ZEPHYR__
120 #define LFS_ASSERT(test) __ASSERT_NO_MSG(test)
121 #else /* __ZEPHYR__ */
122 #define LFS_ASSERT(test) assert(test)
123 #endif /* __ZEPHYR__ */
124 #else
125 #define LFS_ASSERT(test)
126 #endif
127
128
129 // Builtin functions, these may be replaced by more efficient
130 // toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
131 // expensive basic C implementation for debugging purposes
132
133 // Min/max functions for unsigned 32-bit numbers
lfs_max(uint32_t a,uint32_t b)134 static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
135 return (a > b) ? a : b;
136 }
137
lfs_min(uint32_t a,uint32_t b)138 static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
139 return (a < b) ? a : b;
140 }
141
142 // Align to nearest multiple of a size
lfs_aligndown(uint32_t a,uint32_t alignment)143 static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
144 return a - (a % alignment);
145 }
146
lfs_alignup(uint32_t a,uint32_t alignment)147 static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
148 return lfs_aligndown(a + alignment-1, alignment);
149 }
150
151 // Find the smallest power of 2 greater than or equal to a
lfs_npw2(uint32_t a)152 static inline uint32_t lfs_npw2(uint32_t a) {
153 #if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
154 return 32 - __builtin_clz(a-1);
155 #else
156 uint32_t r = 0;
157 uint32_t s;
158 a -= 1;
159 s = (a > 0xffff) << 4; a >>= s; r |= s;
160 s = (a > 0xff ) << 3; a >>= s; r |= s;
161 s = (a > 0xf ) << 2; a >>= s; r |= s;
162 s = (a > 0x3 ) << 1; a >>= s; r |= s;
163 return (r | (a >> 1)) + 1;
164 #endif
165 }
166
167 // Count the number of trailing binary zeros in a
168 // lfs_ctz(0) may be undefined
lfs_ctz(uint32_t a)169 static inline uint32_t lfs_ctz(uint32_t a) {
170 #if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
171 return __builtin_ctz(a);
172 #else
173 return lfs_npw2((a & -a) + 1) - 1;
174 #endif
175 }
176
177 // Count the number of binary ones in a
lfs_popc(uint32_t a)178 static inline uint32_t lfs_popc(uint32_t a) {
179 #if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
180 return __builtin_popcount(a);
181 #else
182 a = a - ((a >> 1) & 0x55555555);
183 a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
184 return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
185 #endif
186 }
187
188 // Find the sequence comparison of a and b, this is the distance
189 // between a and b ignoring overflow
lfs_scmp(uint32_t a,uint32_t b)190 static inline int lfs_scmp(uint32_t a, uint32_t b) {
191 return (int)(unsigned)(a - b);
192 }
193
194 // Convert between 32-bit little-endian and native order
lfs_fromle32(uint32_t a)195 static inline uint32_t lfs_fromle32(uint32_t a) {
196 #if !defined(LFS_NO_INTRINSICS) && ( \
197 (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
198 (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
199 (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
200 return a;
201 #elif !defined(LFS_NO_INTRINSICS) && ( \
202 (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
203 (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
204 (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
205 return __builtin_bswap32(a);
206 #else
207 return (((uint8_t*)&a)[0] << 0) |
208 (((uint8_t*)&a)[1] << 8) |
209 (((uint8_t*)&a)[2] << 16) |
210 (((uint8_t*)&a)[3] << 24);
211 #endif
212 }
213
lfs_tole32(uint32_t a)214 static inline uint32_t lfs_tole32(uint32_t a) {
215 return lfs_fromle32(a);
216 }
217
218 // Convert between 32-bit big-endian and native order
lfs_frombe32(uint32_t a)219 static inline uint32_t lfs_frombe32(uint32_t a) {
220 #if !defined(LFS_NO_INTRINSICS) && ( \
221 (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
222 (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
223 (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
224 return __builtin_bswap32(a);
225 #elif !defined(LFS_NO_INTRINSICS) && ( \
226 (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
227 (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
228 (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
229 return a;
230 #else
231 return (((uint8_t*)&a)[0] << 24) |
232 (((uint8_t*)&a)[1] << 16) |
233 (((uint8_t*)&a)[2] << 8) |
234 (((uint8_t*)&a)[3] << 0);
235 #endif
236 }
237
lfs_tobe32(uint32_t a)238 static inline uint32_t lfs_tobe32(uint32_t a) {
239 return lfs_frombe32(a);
240 }
241
242 // Calculate CRC-32 with polynomial = 0x04c11db7
243 uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
244
245 // Allocate memory, only used if buffers are not provided to littlefs
246 // Note, memory must be 64-bit aligned
lfs_malloc(size_t size)247 static inline void *lfs_malloc(size_t size) {
248 #ifndef LFS_NO_MALLOC
249 return malloc(size);
250 #else
251 (void)size;
252 return NULL;
253 #endif
254 }
255
256 // Deallocate memory, only used if buffers are not provided to littlefs
lfs_free(void * p)257 static inline void lfs_free(void *p) {
258 #ifndef LFS_NO_MALLOC
259 free(p);
260 #else
261 (void)p;
262 #endif
263 }
264
265
266 #ifdef __cplusplus
267 } /* extern "C" */
268 #endif
269
270 #endif
271 #endif
272