119ea8026Sopenharmony_ci/* 219ea8026Sopenharmony_ci * lfs utility functions 319ea8026Sopenharmony_ci * 419ea8026Sopenharmony_ci * Copyright (c) 2022, The littlefs authors. 519ea8026Sopenharmony_ci * Copyright (c) 2017, Arm Limited. All rights reserved. 619ea8026Sopenharmony_ci * SPDX-License-Identifier: BSD-3-Clause 719ea8026Sopenharmony_ci */ 819ea8026Sopenharmony_ci#ifndef LFS_UTIL_H 919ea8026Sopenharmony_ci#define LFS_UTIL_H 1019ea8026Sopenharmony_ci 1119ea8026Sopenharmony_ci// Users can override lfs_util.h with their own configuration by defining 1219ea8026Sopenharmony_ci// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h). 1319ea8026Sopenharmony_ci// 1419ea8026Sopenharmony_ci// If LFS_CONFIG is used, none of the default utils will be emitted and must be 1519ea8026Sopenharmony_ci// provided by the config file. To start, I would suggest copying lfs_util.h 1619ea8026Sopenharmony_ci// and modifying as needed. 1719ea8026Sopenharmony_ci#ifdef LFS_CONFIG 1819ea8026Sopenharmony_ci#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x) 1919ea8026Sopenharmony_ci#define LFS_STRINGIZE2(x) #x 2019ea8026Sopenharmony_ci#include LFS_STRINGIZE(LFS_CONFIG) 2119ea8026Sopenharmony_ci#else 2219ea8026Sopenharmony_ci 2319ea8026Sopenharmony_ci// System includes 2419ea8026Sopenharmony_ci#include <stdint.h> 2519ea8026Sopenharmony_ci#include <stdbool.h> 2619ea8026Sopenharmony_ci#include <string.h> 2719ea8026Sopenharmony_ci#include <inttypes.h> 2819ea8026Sopenharmony_ci 2919ea8026Sopenharmony_ci#ifndef LFS_NO_MALLOC 3019ea8026Sopenharmony_ci#include <stdlib.h> 3119ea8026Sopenharmony_ci#endif 3219ea8026Sopenharmony_ci#ifndef LFS_NO_ASSERT 3319ea8026Sopenharmony_ci#include <assert.h> 3419ea8026Sopenharmony_ci#endif 3519ea8026Sopenharmony_ci#if !defined(LFS_NO_DEBUG) || \ 3619ea8026Sopenharmony_ci !defined(LFS_NO_WARN) || \ 3719ea8026Sopenharmony_ci !defined(LFS_NO_ERROR) || \ 3819ea8026Sopenharmony_ci defined(LFS_YES_TRACE) 3919ea8026Sopenharmony_ci#include <stdio.h> 4019ea8026Sopenharmony_ci#endif 4119ea8026Sopenharmony_ci 4219ea8026Sopenharmony_ci#ifdef __cplusplus 4319ea8026Sopenharmony_ciextern "C" 4419ea8026Sopenharmony_ci{ 4519ea8026Sopenharmony_ci#endif 4619ea8026Sopenharmony_ci 4719ea8026Sopenharmony_ci 4819ea8026Sopenharmony_ci// Macros, may be replaced by system specific wrappers. Arguments to these 4919ea8026Sopenharmony_ci// macros must not have side-effects as the macros can be removed for a smaller 5019ea8026Sopenharmony_ci// code footprint 5119ea8026Sopenharmony_ci 5219ea8026Sopenharmony_ci// Logging functions 5319ea8026Sopenharmony_ci#ifndef LFS_TRACE 5419ea8026Sopenharmony_ci#ifdef LFS_YES_TRACE 5519ea8026Sopenharmony_ci#define LFS_TRACE_(fmt, ...) \ 5619ea8026Sopenharmony_ci printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) 5719ea8026Sopenharmony_ci#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "") 5819ea8026Sopenharmony_ci#else 5919ea8026Sopenharmony_ci#define LFS_TRACE(...) 6019ea8026Sopenharmony_ci#endif 6119ea8026Sopenharmony_ci#endif 6219ea8026Sopenharmony_ci 6319ea8026Sopenharmony_ci#ifndef LFS_DEBUG 6419ea8026Sopenharmony_ci#ifndef LFS_NO_DEBUG 6519ea8026Sopenharmony_ci#define LFS_DEBUG_(fmt, ...) \ 6619ea8026Sopenharmony_ci printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) 6719ea8026Sopenharmony_ci#define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, "") 6819ea8026Sopenharmony_ci#else 6919ea8026Sopenharmony_ci#define LFS_DEBUG(...) 7019ea8026Sopenharmony_ci#endif 7119ea8026Sopenharmony_ci#endif 7219ea8026Sopenharmony_ci 7319ea8026Sopenharmony_ci#ifndef LFS_WARN 7419ea8026Sopenharmony_ci#ifndef LFS_NO_WARN 7519ea8026Sopenharmony_ci#define LFS_WARN_(fmt, ...) \ 7619ea8026Sopenharmony_ci printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) 7719ea8026Sopenharmony_ci#define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, "") 7819ea8026Sopenharmony_ci#else 7919ea8026Sopenharmony_ci#define LFS_WARN(...) 8019ea8026Sopenharmony_ci#endif 8119ea8026Sopenharmony_ci#endif 8219ea8026Sopenharmony_ci 8319ea8026Sopenharmony_ci#ifndef LFS_ERROR 8419ea8026Sopenharmony_ci#ifndef LFS_NO_ERROR 8519ea8026Sopenharmony_ci#define LFS_ERROR_(fmt, ...) \ 8619ea8026Sopenharmony_ci printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) 8719ea8026Sopenharmony_ci#define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "") 8819ea8026Sopenharmony_ci#else 8919ea8026Sopenharmony_ci#define LFS_ERROR(...) 9019ea8026Sopenharmony_ci#endif 9119ea8026Sopenharmony_ci#endif 9219ea8026Sopenharmony_ci 9319ea8026Sopenharmony_ci// Runtime assertions 9419ea8026Sopenharmony_ci#ifndef LFS_ASSERT 9519ea8026Sopenharmony_ci#ifndef LFS_NO_ASSERT 9619ea8026Sopenharmony_ci#define LFS_ASSERT(test) assert(test) 9719ea8026Sopenharmony_ci#else 9819ea8026Sopenharmony_ci#define LFS_ASSERT(test) 9919ea8026Sopenharmony_ci#endif 10019ea8026Sopenharmony_ci#endif 10119ea8026Sopenharmony_ci 10219ea8026Sopenharmony_ci 10319ea8026Sopenharmony_ci// Builtin functions, these may be replaced by more efficient 10419ea8026Sopenharmony_ci// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more 10519ea8026Sopenharmony_ci// expensive basic C implementation for debugging purposes 10619ea8026Sopenharmony_ci 10719ea8026Sopenharmony_ci// Min/max functions for unsigned 32-bit numbers 10819ea8026Sopenharmony_cistatic inline uint32_t lfs_max(uint32_t a, uint32_t b) { 10919ea8026Sopenharmony_ci return (a > b) ? a : b; 11019ea8026Sopenharmony_ci} 11119ea8026Sopenharmony_ci 11219ea8026Sopenharmony_cistatic inline uint32_t lfs_min(uint32_t a, uint32_t b) { 11319ea8026Sopenharmony_ci return (a < b) ? a : b; 11419ea8026Sopenharmony_ci} 11519ea8026Sopenharmony_ci 11619ea8026Sopenharmony_ci// Align to nearest multiple of a size 11719ea8026Sopenharmony_cistatic inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) { 11819ea8026Sopenharmony_ci return a - (a % alignment); 11919ea8026Sopenharmony_ci} 12019ea8026Sopenharmony_ci 12119ea8026Sopenharmony_cistatic inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) { 12219ea8026Sopenharmony_ci return lfs_aligndown(a + alignment-1, alignment); 12319ea8026Sopenharmony_ci} 12419ea8026Sopenharmony_ci 12519ea8026Sopenharmony_ci// Find the smallest power of 2 greater than or equal to a 12619ea8026Sopenharmony_cistatic inline uint32_t lfs_npw2(uint32_t a) { 12719ea8026Sopenharmony_ci#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) 12819ea8026Sopenharmony_ci return 32 - __builtin_clz(a-1); 12919ea8026Sopenharmony_ci#else 13019ea8026Sopenharmony_ci uint32_t r = 0; 13119ea8026Sopenharmony_ci uint32_t s; 13219ea8026Sopenharmony_ci a -= 1; 13319ea8026Sopenharmony_ci s = (a > 0xffff) << 4; a >>= s; r |= s; 13419ea8026Sopenharmony_ci s = (a > 0xff ) << 3; a >>= s; r |= s; 13519ea8026Sopenharmony_ci s = (a > 0xf ) << 2; a >>= s; r |= s; 13619ea8026Sopenharmony_ci s = (a > 0x3 ) << 1; a >>= s; r |= s; 13719ea8026Sopenharmony_ci return (r | (a >> 1)) + 1; 13819ea8026Sopenharmony_ci#endif 13919ea8026Sopenharmony_ci} 14019ea8026Sopenharmony_ci 14119ea8026Sopenharmony_ci// Count the number of trailing binary zeros in a 14219ea8026Sopenharmony_ci// lfs_ctz(0) may be undefined 14319ea8026Sopenharmony_cistatic inline uint32_t lfs_ctz(uint32_t a) { 14419ea8026Sopenharmony_ci#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__) 14519ea8026Sopenharmony_ci return __builtin_ctz(a); 14619ea8026Sopenharmony_ci#else 14719ea8026Sopenharmony_ci return lfs_npw2((a & -a) + 1) - 1; 14819ea8026Sopenharmony_ci#endif 14919ea8026Sopenharmony_ci} 15019ea8026Sopenharmony_ci 15119ea8026Sopenharmony_ci// Count the number of binary ones in a 15219ea8026Sopenharmony_cistatic inline uint32_t lfs_popc(uint32_t a) { 15319ea8026Sopenharmony_ci#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM)) 15419ea8026Sopenharmony_ci return __builtin_popcount(a); 15519ea8026Sopenharmony_ci#else 15619ea8026Sopenharmony_ci a = a - ((a >> 1) & 0x55555555); 15719ea8026Sopenharmony_ci a = (a & 0x33333333) + ((a >> 2) & 0x33333333); 15819ea8026Sopenharmony_ci return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24; 15919ea8026Sopenharmony_ci#endif 16019ea8026Sopenharmony_ci} 16119ea8026Sopenharmony_ci 16219ea8026Sopenharmony_ci// Find the sequence comparison of a and b, this is the distance 16319ea8026Sopenharmony_ci// between a and b ignoring overflow 16419ea8026Sopenharmony_cistatic inline int lfs_scmp(uint32_t a, uint32_t b) { 16519ea8026Sopenharmony_ci return (int)(unsigned)(a - b); 16619ea8026Sopenharmony_ci} 16719ea8026Sopenharmony_ci 16819ea8026Sopenharmony_ci// Convert between 32-bit little-endian and native order 16919ea8026Sopenharmony_cistatic inline uint32_t lfs_fromle32(uint32_t a) { 17019ea8026Sopenharmony_ci#if (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ 17119ea8026Sopenharmony_ci (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ 17219ea8026Sopenharmony_ci (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 17319ea8026Sopenharmony_ci return a; 17419ea8026Sopenharmony_ci#elif !defined(LFS_NO_INTRINSICS) && ( \ 17519ea8026Sopenharmony_ci (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ 17619ea8026Sopenharmony_ci (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ 17719ea8026Sopenharmony_ci (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) 17819ea8026Sopenharmony_ci return __builtin_bswap32(a); 17919ea8026Sopenharmony_ci#else 18019ea8026Sopenharmony_ci return (((uint8_t*)&a)[0] << 0) | 18119ea8026Sopenharmony_ci (((uint8_t*)&a)[1] << 8) | 18219ea8026Sopenharmony_ci (((uint8_t*)&a)[2] << 16) | 18319ea8026Sopenharmony_ci (((uint8_t*)&a)[3] << 24); 18419ea8026Sopenharmony_ci#endif 18519ea8026Sopenharmony_ci} 18619ea8026Sopenharmony_ci 18719ea8026Sopenharmony_cistatic inline uint32_t lfs_tole32(uint32_t a) { 18819ea8026Sopenharmony_ci return lfs_fromle32(a); 18919ea8026Sopenharmony_ci} 19019ea8026Sopenharmony_ci 19119ea8026Sopenharmony_ci// Convert between 32-bit big-endian and native order 19219ea8026Sopenharmony_cistatic inline uint32_t lfs_frombe32(uint32_t a) { 19319ea8026Sopenharmony_ci#if !defined(LFS_NO_INTRINSICS) && ( \ 19419ea8026Sopenharmony_ci (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ 19519ea8026Sopenharmony_ci (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ 19619ea8026Sopenharmony_ci (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) 19719ea8026Sopenharmony_ci return __builtin_bswap32(a); 19819ea8026Sopenharmony_ci#elif (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ 19919ea8026Sopenharmony_ci (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ 20019ea8026Sopenharmony_ci (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 20119ea8026Sopenharmony_ci return a; 20219ea8026Sopenharmony_ci#else 20319ea8026Sopenharmony_ci return (((uint8_t*)&a)[0] << 24) | 20419ea8026Sopenharmony_ci (((uint8_t*)&a)[1] << 16) | 20519ea8026Sopenharmony_ci (((uint8_t*)&a)[2] << 8) | 20619ea8026Sopenharmony_ci (((uint8_t*)&a)[3] << 0); 20719ea8026Sopenharmony_ci#endif 20819ea8026Sopenharmony_ci} 20919ea8026Sopenharmony_ci 21019ea8026Sopenharmony_cistatic inline uint32_t lfs_tobe32(uint32_t a) { 21119ea8026Sopenharmony_ci return lfs_frombe32(a); 21219ea8026Sopenharmony_ci} 21319ea8026Sopenharmony_ci 21419ea8026Sopenharmony_ci// Calculate CRC-32 with polynomial = 0x04c11db7 21519ea8026Sopenharmony_ciuint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size); 21619ea8026Sopenharmony_ci 21719ea8026Sopenharmony_ci// Allocate memory, only used if buffers are not provided to littlefs 21819ea8026Sopenharmony_ci// Note, memory must be 64-bit aligned 21919ea8026Sopenharmony_cistatic inline void *lfs_malloc(size_t size) { 22019ea8026Sopenharmony_ci#ifndef LFS_NO_MALLOC 22119ea8026Sopenharmony_ci return malloc(size); 22219ea8026Sopenharmony_ci#else 22319ea8026Sopenharmony_ci (void)size; 22419ea8026Sopenharmony_ci return NULL; 22519ea8026Sopenharmony_ci#endif 22619ea8026Sopenharmony_ci} 22719ea8026Sopenharmony_ci 22819ea8026Sopenharmony_ci// Deallocate memory, only used if buffers are not provided to littlefs 22919ea8026Sopenharmony_cistatic inline void lfs_free(void *p) { 23019ea8026Sopenharmony_ci#ifndef LFS_NO_MALLOC 23119ea8026Sopenharmony_ci free(p); 23219ea8026Sopenharmony_ci#else 23319ea8026Sopenharmony_ci (void)p; 23419ea8026Sopenharmony_ci#endif 23519ea8026Sopenharmony_ci} 23619ea8026Sopenharmony_ci 23719ea8026Sopenharmony_ci 23819ea8026Sopenharmony_ci#ifdef __cplusplus 23919ea8026Sopenharmony_ci} /* extern "C" */ 24019ea8026Sopenharmony_ci#endif 24119ea8026Sopenharmony_ci 24219ea8026Sopenharmony_ci#endif 24319ea8026Sopenharmony_ci#endif 244