| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /*
- * lfs utility functions
- *
- * Copyright (c) 2017 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #ifndef LFS_UTIL_H
- #define LFS_UTIL_H
- // Users can override lfs_util.h with their own configuration by defining
- // LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
- //
- // If LFS_CONFIG is used, none of the default utils will be emitted and must be
- // provided by the config file. To start I would suggest copying lfs_util.h and
- // modifying as needed.
- #ifdef LFS_CONFIG
- #define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
- #define LFS_STRINGIZE2(x) #x
- #include LFS_STRINGIZE(LFS_CONFIG)
- #else
- // System includes
- #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
- // 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;
- }
- // Find the next smallest power of 2 less 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)(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 ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
- (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
- (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
- return a;
- #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__))
- 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 16-bit little-endian and native order
- static inline uint16_t lfs_fromle16(uint16_t a) {
- #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 !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__))
- return __builtin_bswap16(a);
- #else
- return (((uint8_t*)&a)[0] << 0) |
- (((uint8_t*)&a)[1] << 8);
- #endif
- }
- static inline uint16_t lfs_tole16(uint16_t a) {
- return lfs_fromle16(a);
- }
- // Align to nearest multiple of a size
- static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
- return (a + alignment-1) - ((a + alignment-1) % alignment);
- }
- // 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
- }
- // 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
- #endif
|