Mistake on this page?
Report an issue in GitHub or email us
lfs2_util.h
1 /*
2  * lfs2 utility functions
3  *
4  * Copyright (c) 2017, Arm Limited. All rights reserved.
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 #ifndef LFS2_UTIL_H
8 #define LFS2_UTIL_H
9 
10 // Users can override lfs2_util.h with their own configuration by defining
11 // LFS2_CONFIG as a header file to include (-DLFS2_CONFIG=lfs2_config.h).
12 //
13 // If LFS2_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 lfs2_util.h
15 // and modifying as needed.
16 #ifdef LFS2_CONFIG
17 #define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x)
18 #define LFS2_STRINGIZE2(x) #x
19 #include LFS2_STRINGIZE(LFS2_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 LFS2_NO_MALLOC
29 #include <stdlib.h>
30 #endif
31 #ifndef LFS2_NO_ASSERT
32 #include <assert.h>
33 #endif
34 #if !defined(LFS2_NO_DEBUG) || \
35  !defined(LFS2_NO_WARN) || \
36  !defined(LFS2_NO_ERROR) || \
37  defined(LFS2_YES_TRACE)
38 #include <stdio.h>
39 #endif
40 
41 #ifdef __cplusplus
42 extern "C"
43 {
44 #endif
45 
46 
47 // Macros, may be replaced by system specific wrappers. Arguments to these
48 // macros must not have side-effects as the macros can be removed for a smaller
49 // code footprint
50 
51 #ifdef __MBED__
52 #include "mbed_debug.h"
53 #include "mbed_assert.h"
54 #include "cmsis_compiler.h"
55 #else
56 #define MBED_LFS2_ENABLE_INFO false
57 #define MBED_LFS2_ENABLE_DEBUG true
58 #define MBED_LFS2_ENABLE_WARN true
59 #define MBED_LFS2_ENABLE_ERROR true
60 #define MBED_LFS2_ENABLE_ASSERT true
61 #define MBED_LFS2_INTRINSICS true
62 #endif
63 
64 // Logging functions
65 #if defined(LFS2_YES_TRACE) && MBED_LFS2_ENABLE_TRACE
66 #define LFS2_TRACE_(fmt, ...) \
67  printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
68 #define LFS2_TRACE(...) LFS2_TRACE_(__VA_ARGS__, "")
69 #elif defined(LFS2_YES_TRACE) && !defined(MBED_LFS2_ENABLE_TRACE)
70 #define LFS2_TRACE_(fmt, ...) \
71  debug("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
72 #define LFS2_TRACE(...) LFS2_TRACE_(__VA_ARGS__, "")
73 #else
74 #define LFS2_TRACE(...)
75 #endif
76 
77 #if !defined(LFS2_NO_DEBUG) && MBED_LFS2_ENABLE_DEBUG
78 #define LFS2_DEBUG_(fmt, ...) \
79  printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
80 #define LFS2_DEBUG(...) LFS2_DEBUG_(__VA_ARGS__, "")
81 #elif !defined(LFS2_NO_DEBUG) && !defined(MBED_LFS2_ENABLE_DEBUG)
82 #define LFS2_DEBUG_(fmt, ...) \
83  debug("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
84 #define LFS2_DEBUG(...) LFS2_DEBUG_(__VA_ARGS__, "")
85 #else
86 #define LFS2_DEBUG(...)
87 #endif
88 
89 #if !defined(LFS2_NO_WARN) && MBED_LFS2_ENABLE_WARN
90 #define LFS2_WARN_(fmt, ...) \
91  printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
92 #define LFS2_WARN(...) LFS2_WARN_(__VA_ARGS__, "")
93 #elif !defined(LFS2_NO_WARN) && !defined(MBED_LFS2_ENABLE_WARN)
94 #define LFS2_WARN_(fmt, ...) \
95  debug("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
96 #define LFS2_WARN(...) LFS2_WARN_(__VA_ARGS__, "")
97 #else
98 #define LFS2_WARN(...)
99 #endif
100 
101 #if !defined(LFS2_NO_ERROR) && MBED_LFS2_ENABLE_ERROR
102 #define LFS2_ERROR_(fmt, ...) \
103  printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
104 #define LFS2_ERROR(...) LFS2_ERROR_(__VA_ARGS__, "")
105 #elif !defined(LFS2_NO_ERROR) && !defined(MBED_LFS2_ENABLE_ERROR)
106 #define LFS2_ERROR_(fmt, ...) \
107  debug("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
108 #define LFS2_ERROR(...) LFS2_ERROR_(__VA_ARGS__, "")
109 #else
110 #define LFS2_ERROR(...)
111 #endif
112 
113 // Runtime assertions
114 #if !defined(LFS2_NO_ASSERT) && MBED_LFS2_ENABLE_ASSERT
115 #define LFS2_ASSERT(test) assert(test)
116 #elif !defined(LFS2_NO_ASSERT) && !defined(MBED_LFS2_ENABLE_ASSERT)
117 #define LFS2_ASSERT(test) MBED_ASSERT(test)
118 #else
119 #define LFS2_ASSERT(test)
120 #endif
121 
122 
123 // Builtin functions, these may be replaced by more efficient
124 // toolchain-specific implementations. LFS2_NO_INTRINSICS falls back to a more
125 // expensive basic C implementation for debugging purposes
126 
127 // Min/max functions for unsigned 32-bit numbers
128 static inline uint32_t lfs2_max(uint32_t a, uint32_t b) {
129  return (a > b) ? a : b;
130 }
131 
132 static inline uint32_t lfs2_min(uint32_t a, uint32_t b) {
133  return (a < b) ? a : b;
134 }
135 
136 // Align to nearest multiple of a size
137 static inline uint32_t lfs2_aligndown(uint32_t a, uint32_t alignment) {
138  return a - (a % alignment);
139 }
140 
141 static inline uint32_t lfs2_alignup(uint32_t a, uint32_t alignment) {
142  return lfs2_aligndown(a + alignment-1, alignment);
143 }
144 
145 // Find the smallest power of 2 greater than or equal to a
146 static inline uint32_t lfs2_npw2(uint32_t a) {
147 #if !defined(LFS2_NO_INTRINSICS) && MBED_LFS2_INTRINSICS && \
148  (defined(__GNUC__) || defined(__CC_ARM))
149  return 32 - __builtin_clz(a-1);
150 #else
151  uint32_t r = 0;
152  uint32_t s;
153  a -= 1;
154  s = (a > 0xffff) << 4; a >>= s; r |= s;
155  s = (a > 0xff ) << 3; a >>= s; r |= s;
156  s = (a > 0xf ) << 2; a >>= s; r |= s;
157  s = (a > 0x3 ) << 1; a >>= s; r |= s;
158  return (r | (a >> 1)) + 1;
159 #endif
160 }
161 
162 // Count the number of trailing binary zeros in a
163 // lfs2_ctz(0) may be undefined
164 static inline uint32_t lfs2_ctz(uint32_t a) {
165 #if !defined(LFS2_NO_INTRINSICS) && MBED_LFS2_INTRINSICS && \
166  defined(__GNUC__)
167  return __builtin_ctz(a);
168 #else
169  return lfs2_npw2((a & -a) + 1) - 1;
170 #endif
171 }
172 
173 // Count the number of binary ones in a
174 static inline uint32_t lfs2_popc(uint32_t a) {
175 #if !defined(LFS2_NO_INTRINSICS) && MBED_LFS2_INTRINSICS && \
176  (defined(__GNUC__) || defined(__CC_ARM))
177  return __builtin_popcount(a);
178 #else
179  a = a - ((a >> 1) & 0x55555555);
180  a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
181  return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
182 #endif
183 }
184 
185 // Find the sequence comparison of a and b, this is the distance
186 // between a and b ignoring overflow
187 static inline int lfs2_scmp(uint32_t a, uint32_t b) {
188  return (int)(unsigned)(a - b);
189 }
190 
191 // Convert between 32-bit little-endian and native order
192 static inline uint32_t lfs2_fromle32(uint32_t a) {
193 #if !defined(LFS2_NO_INTRINSICS) && MBED_LFS2_INTRINSICS && ( \
194  (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
195  (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
196  (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
197  return a;
198 #elif !defined(LFS2_NO_INTRINSICS) && MBED_LFS2_INTRINSICS && ( \
199  (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
200  (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
201  (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
202  return __builtin_bswap32(a);
203 #else
204  return (((uint8_t*)&a)[0] << 0) |
205  (((uint8_t*)&a)[1] << 8) |
206  (((uint8_t*)&a)[2] << 16) |
207  (((uint8_t*)&a)[3] << 24);
208 #endif
209 }
210 
211 static inline uint32_t lfs2_tole32(uint32_t a) {
212  return lfs2_fromle32(a);
213 }
214 
215 // Reverse the bits in a
216 static inline uint32_t lfs2_rbit(uint32_t a) {
217 #if !defined(LFS2_NO_INTRINSICS) && MBED_LFS2_INTRINSICS && \
218  defined(__MBED__)
219  return __RBIT(a);
220 #else
221  a = ((a & 0xaaaaaaaa) >> 1) | ((a & 0x55555555) << 1);
222  a = ((a & 0xcccccccc) >> 2) | ((a & 0x33333333) << 2);
223  a = ((a & 0xf0f0f0f0) >> 4) | ((a & 0x0f0f0f0f) << 4);
224  a = ((a & 0xff00ff00) >> 8) | ((a & 0x00ff00ff) << 8);
225  a = (a >> 16) | (a << 16);
226  return a;
227 #endif
228 }
229 
230 // Convert between 32-bit big-endian and native order
231 static inline uint32_t lfs2_frombe32(uint32_t a) {
232 #if !defined(LFS2_NO_INTRINSICS) && MBED_LFS2_INTRINSICS && ( \
233  (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
234  (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
235  (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
236  return __builtin_bswap32(a);
237 #elif !defined(LFS2_NO_INTRINSICS) && MBED_LFS2_INTRINSICS && ( \
238  (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
239  (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
240  (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
241  return a;
242 #else
243  return (((uint8_t*)&a)[0] << 24) |
244  (((uint8_t*)&a)[1] << 16) |
245  (((uint8_t*)&a)[2] << 8) |
246  (((uint8_t*)&a)[3] << 0);
247 #endif
248 }
249 
250 static inline uint32_t lfs2_tobe32(uint32_t a) {
251  return lfs2_frombe32(a);
252 }
253 
254 // Calculate CRC-32 with polynomial = 0x04c11db7
255 uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size);
256 
257 // Allocate memory, only used if buffers are not provided to littlefs
258 // Note, memory must be 64-bit aligned
259 static inline void *lfs2_malloc(size_t size) {
260 #ifndef LFS2_NO_MALLOC
261  return malloc(size);
262 #else
263  (void)size;
264  return NULL;
265 #endif
266 }
267 
268 // Deallocate memory, only used if buffers are not provided to littlefs
269 static inline void lfs2_free(void *p) {
270 #ifndef LFS2_NO_MALLOC
271  free(p);
272 #else
273  (void)p;
274 #endif
275 }
276 
277 
278 #ifdef __cplusplus
279 } /* extern "C" */
280 #endif
281 
282 #endif
283 #endif
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.