lib: utils: Add function for finding group of cleared bits in a bit mask
Add function which finds contiguous number of bits which are not set in the 32 bit mask. Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
committed by
Benjamin Cabé
parent
993b642f2e
commit
53c2d58ff8
@@ -434,6 +434,22 @@ extern "C" {
|
||||
*/
|
||||
#define IN_RANGE(val, min, max) ((val) >= (min) && (val) <= (max))
|
||||
|
||||
/**
|
||||
* Find number of contiguous bits which are not set in the bit mask (32 bits).
|
||||
*
|
||||
* It is possible to return immediately when requested number of bits is found or
|
||||
* iterate over whole mask and return the best fit (smallest from available options).
|
||||
*
|
||||
* @param[in] mask 32 bit mask.
|
||||
* @param[in] num_bits Number of bits to find.
|
||||
* @param[in] total_bits Total number of LSB bits that can be used in the mask.
|
||||
* @param[in] first_match If true returns when first match is found, else returns the best fit.
|
||||
*
|
||||
* @retval -1 Contiguous bits not found.
|
||||
* @retval non-negative Starting index of the bits group.
|
||||
*/
|
||||
int bitmask_find_gap(uint32_t mask, size_t num_bits, size_t total_bits, bool first_match);
|
||||
|
||||
/**
|
||||
* @brief Is @p x a power of two?
|
||||
* @param x value to check
|
||||
|
||||
@@ -8,6 +8,7 @@ zephyr_sources(
|
||||
rb.c
|
||||
timeutil.c
|
||||
bitarray.c
|
||||
bitmask.c
|
||||
)
|
||||
|
||||
zephyr_sources_ifdef(CONFIG_ONOFF onoff.c)
|
||||
|
||||
50
lib/utils/bitmask.c
Normal file
50
lib/utils/bitmask.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/sys/math_extras.h>
|
||||
|
||||
int bitmask_find_gap(uint32_t mask, size_t num_bits, size_t total_bits, bool first_match)
|
||||
{
|
||||
uint32_t max = UINT32_MAX;
|
||||
int max_loc = -1;
|
||||
|
||||
if (total_bits < 32) {
|
||||
mask |= ~BIT_MASK(total_bits);
|
||||
}
|
||||
|
||||
mask = ~mask;
|
||||
while (mask != 0U) {
|
||||
uint32_t block_size;
|
||||
uint32_t loc;
|
||||
int nidx;
|
||||
uint32_t idx = 31 - u32_count_leading_zeros(mask);
|
||||
uint32_t rmask = ~BIT_MASK(idx);
|
||||
|
||||
rmask |= mask;
|
||||
rmask = ~rmask;
|
||||
if (rmask != 0U) {
|
||||
nidx = 31 - u32_count_leading_zeros(rmask);
|
||||
block_size = idx - nidx;
|
||||
loc = nidx + 1;
|
||||
mask &= BIT_MASK(nidx);
|
||||
} else {
|
||||
mask = 0;
|
||||
block_size = idx + 1;
|
||||
loc = 0;
|
||||
}
|
||||
|
||||
if ((block_size == num_bits) || (first_match && block_size > num_bits)) {
|
||||
max_loc = loc;
|
||||
max = block_size;
|
||||
break;
|
||||
} else if (block_size >= num_bits && block_size < max) {
|
||||
max_loc = loc;
|
||||
max = block_size;
|
||||
}
|
||||
}
|
||||
|
||||
return max_loc;
|
||||
}
|
||||
Reference in New Issue
Block a user