Part 1
요약·해설
공식 Doxygen의 82개 macro와 19개 function, 예제 코드 34개를 원래 순서와 내용 그대로 연결한 한국어 reference입니다.
82 definitions
19 definitions
34 exact blocks
Part 2
접을 수 있는 영어 원문 전체
영어 원문 전체 펼치기
98623C34B5673F0774042C6A426924C918E954350B5FC583F6616E87F5DF860B
.. _util_api:
Utilities
#########
This page contains reference documentation for ``<sys/util.h>``, which provides
miscellaneous utility functions and macros.
.. doxygengroup:: sys-util
Part 3
한국어 전문 번역
이 페이지는
cast · mask · compile check
bounds · container · token
align · round · units · wait
mask · Kconfig conditional
map · list · index · paste
convert · UTF-8 · XOR
아래 101개 정의는 공식 Doxygen 렌더링 순서를 유지합니다.
Pointer·bitfield·compile-time 기본 매크로
POINTER_TO_UINT(x)Pointer x를 unsigned integer로 cast합니다.
UINT_TO_POINTER(x)Unsigned integer x를 void pointer로 cast합니다.
POINTER_TO_INT(x)Pointer x를 signed integer로 cast합니다.
INT_TO_POINTER(x)Signed integer x를 void pointer로 cast합니다.
BITS_PER_LONGlong int 한 개의 bit 수입니다.
BITS_PER_LONG_LONGlong long int 한 개의 bit 수입니다.
GENMASK(h, l)Bit position l에서 h까지 연속해서 1인 bitmask를 만듭니다.
GENMASK64(h, l)Bit position l에서 h까지 연속해서 1인 64-bit bitmask를 만듭니다.
LSB_GET(value)value에서 least-significant bit를 추출합니다.
FIELD_GET(mask, value)mask가 나타내는 field position과 width에 맞춰 value의 bitfield element를 추출합니다.
FIELD_PREP(mask, value)mask가 나타내는 field position과 width에 value를 배치합니다. 결과는 다른 field와 logical OR로 결합해야 합니다.
ZERO_OR_COMPILE_ERROR(cond)cond가 true로 평가되면 0이고, 그렇지 않으면 compile error를 발생시킵니다.
Array·type·container 매크로
IS_ARRAY(array)array가 array type이면 0이고 아니면 compile error입니다. C에서만 제공되며 C++에서는 사용할 수 없습니다.
ARRAY_SIZE(array)주어진 array의 element 수를 반환합니다. C에서 pointer를 넘기면 compile error입니다. C++에서는 language 제약 때문에 operator[]를 구현한 type도 array로 받아들일 수 있어 결과가 의미 없을 수 있습니다.
IS_ARRAY_ELEMENT(array, ptr)ptr이 array element인지 확인합니다. PART_OF_ARRAY보다 엄격해 array-element boundary alignment도 검사합니다. C에서 array 자리에 pointer를 넘기면 compile error이며, array에 속하면 1, 아니면 0을 반환합니다.
ARRAY_INDEX(array, ptr)array 안 element ptr의 index를 반환합니다. CONFIG_ASSERT=y에서는 ptr이 범위 밖이거나 element boundary에 align되지 않으면 runtime assertion이 발생합니다. C에서 array 자리에 pointer를 넘기면 compile error입니다.
PART_OF_ARRAY(array, ptr)ptr이 array 범위 안에 있는지 검사해 1 또는 0을 반환합니다. C에서는 array가 실제 array가 아니면 compile error를 내어 ptr과 array를 뒤바꾼 실수를 잡지만 C++에는 이 검사가 없습니다.
ARRAY_INDEX_FLOOR(array, ptr)array 범위 안의 임의 ptr을 바로 아래 element index로 내림합니다. ARRAY_INDEX와 달리 element boundary alignment를 요구하지 않으며 CONFIG_ASSERT=y에서는 범위 밖 ptr에 runtime assertion을 냅니다.
ARRAY_FOR_EACH(array, idx)idx라는 index variable로 array member를 순회합니다. array는 대상 array, idx는 사용할 index variable 이름입니다.
ARRAY_FOR_EACH_PTR(array, ptr)ptr을 각 element pointer로 두고 array member를 순회합니다.
SAME_TYPE(a, b)a와 b의 type이 compatible하면 1, 아니면 0을 반환합니다.
CONTAINER_OF_VALIDATE(ptr, type, field)CONTAINER_OF parameter를 검증합니다. C mode에만 적용됩니다.
CONTAINER_OF(ptr, type, field)Structure element ptr에서 그 element를 포함하는 structure의 pointer를 구합니다. ptr은 member pointer, type은 containing type, field는 member name이며 containing structure pointer를 반환합니다.
struct foo { int bar; }; struct foo my_foo; int *ptr = &my_foo.bar; struct foo *container = CONTAINER_OF(ptr, struct foo, bar);예제에서 container는 my_foo를 가리킵니다.
SIZEOF_FIELD(type, member)type structure의 member field 크기를 byte 단위로 반환합니다.
CONCAT(...)Preprocessor pass에서 입력 token을 하나의 token으로 연결합니다. Number, 다른 macro, macro argument 등을 조합해 identifier를 만들 수 있습니다. 가변 인자는 연결할 token이며 결합된 token을 반환합니다.
Alignment·산술·단위·대기 매크로
IS_ALIGNED(ptr, align)ptr이 align boundary에 맞춰 정렬됐는지 확인합니다.
ROUND_UP(x, align)x를 align의 다음 multiple로 올림합니다.
ROUND_DOWN(x, align)x를 align의 이전 multiple로 내림합니다.
WB_UP(x)x를 다음 word boundary로 올림합니다.
WB_DN(x)x를 이전 word boundary로 내림합니다.
DIV_ROUND_UP(n, d)Numerator n을 denominator d로 나눈 값을 올림해 반환합니다.
DIV_ROUND_UP(1, 2); // 1 DIV_ROUND_UP(3, 2); // 2DIV_ROUND_CLOSEST(n, d)n / d를 가장 가까운 integer로 반올림합니다. 음수 denominator도 예제와 같이 처리합니다.
DIV_ROUND_CLOSEST(5, 2); // 3 DIV_ROUND_CLOSEST(5, -2); // -3 DIV_ROUND_CLOSEST(5, 3); // 2ceiling_fraction(numerator, divider)numerator / divider fraction에 ceiling을 적용합니다. Deprecated API이므로 DIV_ROUND_UP()을 사용해야 합니다.
MAX(a, b)a와 b 중 maximum을 반환합니다. Argument가 두 번 평가되므로 side effect에 주의해야 하며 GCC-only single-evaluation variant는 Z_MAX입니다.
MIN(a, b)a와 b 중 minimum을 반환합니다. Argument가 두 번 평가되므로 side effect에 주의해야 하며 GCC-only single-evaluation variant는 Z_MIN입니다.
CLAMP(val, low, high)val을 inclusive range [low, high] 안으로 제한합니다. Argument가 여러 번 평가되며 GCC-only single-evaluation variant는 Z_CLAMP입니다.
IN_RANGE(val, min, max)val이 inclusive range [min, max] 안이면 true, 아니면 false입니다. val은 두 번 평가됩니다.
LOG2(x)Positive unsigned integral x의 log2를 계산합니다. 1 이상이면 log2(x), 1 미만이면 -1입니다. Constant expression 지원을 위해 argument를 여러 번 확장하므로 side effect가 없어야 합니다.
LOG2CEIL(x)Unsigned integral x에 ceil(log2(x))를 적용합니다. 1 미만이면 0입니다. Argument를 여러 번 확장하므로 side effect가 없어야 합니다.
NHPOT(x)x 이상인 다음 power of two, 즉 2^ceil(log2(x))를 계산합니다. 결과가 64-bit를 saturate하면 0입니다. Argument에 side effect가 없어야 합니다.
KB(x)x kibibyte에 해당하는 byte 수입니다.
MB(x)x mebibyte에 해당하는 byte 수입니다.
GB(x)x gibibyte에 해당하는 byte 수입니다.
KHZ(x)x kHz에 해당하는 Hz 수입니다.
MHZ(x)x MHz에 해당하는 Hz 수입니다.
WAIT_FOR(expr, timeout, delay_stmt)expr이 true가 될 때까지 timeout microsecond 동안 spin하고 iteration 사이에 optional delay_stmt를 실행합니다. Hardware read/write/initialize/reset 같은 asynchronous request 대기에 흔히 씁니다. delay_stmt에는 NULL, k_yield(), k_msleep(1), k_busy_wait(1) 등을 줄 수 있으며 timeout이면 boolean false를 반환합니다.
Bit·configuration 조건 매크로
BIT(n)Bit position n만 set된 unsigned integer를 만듭니다. Assembly language에서는 signed입니다.
BIT64(_n)Bit position _n만 set된 64-bit unsigned integer를 만듭니다.
WRITE_BIT(var, bit, set)Boolean set 값에 따라 variable var의 bit 번호 bit를 clear하거나 set합니다. set이 0이면 clear하고 그 외에는 set하며 var를 side effect로 변경합니다.
BIT_MASK(n)Bit 0부터 n-1까지 set된 mask를 만들며 n이 0이면 0입니다.
BIT64_MASK(n)Bit 0부터 n-1까지 set된 64-bit mask를 만들며 n이 0이면 0입니다.
IS_POWER_OF_TWO(x)x가 power of two인지 검사합니다.
IS_SHIFTED_BIT_MASK(m, s)m에서 s를 lowest bit로 하여 bit가 끊기지 않고 연속해서 set됐는지 검사합니다. Bit width에 의존하지 않습니다.
IS_BIT_MASK(m)m의 bit가 LSB부터 끊기지 않고 연속해서 set됐는지 검사합니다.
IS_ENABLED(config_macro)config_macro가 literal 1로 정의되면 1, 정의되지 않았거나 그 외이면 0입니다. Linux config_enabled() 기법처럼 Kconfig macro를 preprocessor 전용 조건이 아닌 C compiler가 볼 수 있는 expression으로 바꿉니다. CONFIG_FOO가 없어도 compiler가 branch 안 code의 error와 warning을 검사할 수 있습니다. #if 안에서는 plain #if defined()보다 이점이 없으므로 권장하지 않습니다.
if (IS_ENABLED(CONFIG_FOO)) { do_something_with_foo }COND_CODE_1(_flag, _if_1_code, _else_code)_flag가 integer literal 1로 확장되면 _if_1_code, 아니면 _else_code를 그 자리에서 확장합니다. Comma가 argument separator로 처리되지 않도록 두 code expression을 괄호로 감싸야 하며 확장 때 괄호는 제거됩니다. _flag는 macro expansion 결과여도 되지만 arithmetic 결과가 1인 expression은 안 되고 literal 1이어야 합니다.
COND_CODE_1(CONFIG_FLAG, (uint32_t x;), (there_is_no_flag();))uint32_t x;동일한 preprocessor 분기는 다음처럼 별도 macro를 정의하는 방식으로도 쓸 수 있지만 COND_CODE_1은 사용 위치에서 바로 해결돼 더 간결합니다.
#if defined(CONFIG_FLAG) && (CONFIG_FLAG == 1) #define MAYBE_DECLARE(x) uint32_t x #else #define MAYBE_DECLARE(x) there_is_no_flag() #endif MAYBE_DECLARE(x);COND_CODE_0(_flag, _if_0_code, _else_code)COND_CODE_1과 같지만 _flag가 integer literal 0인지 검사합니다. 0이면 괄호 안 _if_0_code, 아니면 _else_code를 확장합니다.
IF_ENABLED(_flag, _code)_flag가 정의돼 literal 1이면 괄호 안 _code를 넣고, 아니면 아무것도 넣지 않습니다. #if defined(CONFIG_FLAG) 분기의 compact alternative입니다.
IF_ENABLED(CONFIG_FLAG, (uint32_t foo;))uint32_t foo;#if defined(CONFIG_FLAG) && (CONFIG_FLAG == 1) uint32_t foo; #endifIF_DISABLED(_flag, _code)_flag가 정의되지 않았거나 1이 아니면 괄호 안 _code를 넣고, 1이면 아무것도 넣지 않습니다. IF_ENABLED의 반대입니다.
IF_DISABLED(CONFIG_FLAG, (uint32_t foo;))uint32_t foo;IS_EMPTY(...)Macro replacement expression이 비어 있는지 검사하며 __VA_ARGS__의 empty argument 처리에 COND_CODE_1·COND_CODE_0과 함께 사용할 수 있습니다. Defined macro만 지원하므로 경우에 따라 #ifdef가 추가로 필요합니다. 문서 예제에서 EMPTY, NON_EMPTY, UNDEFINED는 각각 true, false, true를 반환하고 조건부 code가 포함됩니다.
#define EMPTY #define NON_EMPTY 1 #undef UNDEFINED IS_EMPTY(EMPTY) IS_EMPTY(NON_EMPTY) IS_EMPTY(UNDEFINED) #if defined(EMPTY) && IS_EMPTY(EMPTY) == true some_conditional_code #endifIS_EQ(a, b)C preprocessor 단계에서 a == b처럼 평가하고 short-circuit합니다. Integer literal 0~4095에만 동작합니다.
LIST_DROP_EMPTY(...)__VA_ARGS__ 같은 preprocessor-generated list에서 empty element를 제거합니다. FOR_EACH가 empty element까지 처리하지 않게 만들 때 사용합니다.
#define LIST ,a,b,,d,LIST를 EMPTY 표기로 펼치면 다음과 같습니다.
EMPTY, a, b, EMPTY, dLIST_DROP_EMPTY을 적용하면 empty item이 사라집니다.
LIST_DROP_EMPTY(LIST)a, b, dEMPTY아무것도 확장하지 않는 macro입니다. Empty result가 필요할 때 의도를 드러내고 checkpatch warning을 피하는 데 사용합니다.
#define LIST_ITEM(n) , item##n앞에 EMPTY를 명시하면 같은 expansion을 유지하면서 의도를 표현합니다.
#define LIST_ITEM(n) EMPTY, item##nIDENTITY(V)Argument V를 그대로 확장합니다. FOR_EACH에서 list element transformation이 필요 없을 때 유용합니다.
Variadic list·mapping 매크로
GET_ARG_N(N, ...)1부터 세는 index N에 해당하는 variadic argument를 반환합니다.
GET_ARGS_LESS_N(N, ...)가변 argument list의 앞 N개를 버리고 나머지 list를 반환합니다.
UTIL_OR(a, b)C preprocessor 단계에서 a || b처럼 평가하고 short-circuit합니다. Binary ||와 달리 a는 literal 0 또는 1로 확장돼야 하지만 b는 어떤 값도 가능합니다. a가 1일 때 b를 확장하면 build error가 나는 경우를 피할 수 있습니다.
UTIL_AND(a, b)C preprocessor 단계에서 a && b처럼 평가하고 short-circuit합니다. a는 literal 0 또는 1이어야 하지만 b는 어떤 값도 가능하며, a가 0일 때 b expansion이 build error를 내는 경우를 피할 수 있습니다.
UTIL_INC(x)Integer literal x가 0~4095이면 x+1인 literal로 확장합니다. UTIL_DEC의 반대입니다.
UTIL_DEC(x)Integer literal x가 0~4095이면 x-1인 literal로 확장합니다. UTIL_INC의 반대입니다.
UTIL_X2(y)Integer literal y가 0~4095이면 2y인 literal로 확장합니다.
LISTIFY(LEN, F, sep, ...)Length LEN만큼 F(i, ...)를 반복 호출해 sep로 구분한 code sequence를 만듭니다. LEN은 4095 미만 integer literal이고 sep는 comma도 받을 수 있게 괄호로 감싸야 합니다. Undefined argument로 호출하면 undefined behavior입니다.
#define FOO(i, _) MY_PWM ## i { LISTIFY(PWM_COUNT, FOO, (,)) }예제는 PWM_COUNT가 2일 때
{ MY_PWM0 , MY_PWM1 }로 확장됩니다.FOR_EACH(F, sep, ...)가변 argument 각각에 F(element)를 호출하고 호출 사이에 괄호로 감싼 sep를 넣습니다.
#define F(x) int a##x FOR_EACH(F, (;), 4, 5, 6);확장 결과는 다음과 같습니다.
int a4; int a5; int a6;FOR_EACH_NONEMPTY_TERM(F, term, ...)FOR_EACH와 비슷하지만 separator 대신 각 F 호출 뒤 terminator를 붙이고 empty element는 버립니다. Empty argument list이면 아무것도 확장하지 않아, 비어 있을 수 있는 __VA_ARGS__ 결과를 더 큰 initializer에 넣기 편합니다.
FOR_EACH(F, (sep), a, b) // F(a) sep F(b) // ^^^ no sep here!FOR_EACH_NONEMPTY_TERM(F, (term), a, b) // F(a) term F(b) term // ^^^^FOR_EACH_NONEMPTY_TERM(F, (term), a, EMPTY, b) // F(a) term F(b) term여러 optional list를 initializer에 이어 붙이는 예시는 다음과 같습니다.
#define SQUARE(x) ((x)*(x)) int my_array[] = { FOR_EACH_NONEMPTY_TERM(SQUARE, (,), FOO(...)) FOR_EACH_NONEMPTY_TERM(SQUARE, (,), BAR(...)) FOR_EACH_NONEMPTY_TERM(SQUARE, (,), BAZ(...)) };FOR_EACH_IDX(F, sep, ...)각 argument에 F(index, element)를 호출하고 sep로 구분합니다. Index는 0부터 시작합니다.
#define F(idx, x) int a##idx = x FOR_EACH_IDX(F, (;), 4, 5, 6);확장 결과는 다음과 같습니다.
int a0 = 4; int a1 = 5; int a2 = 6;FOR_EACH_FIXED_ARG(F, sep, fixed_arg, ...)각 variable element에 같은 fixed_arg를 더해 F(element, fixed_arg)를 호출하고 sep로 구분합니다.
static void func(int val, void *dev); FOR_EACH_FIXED_ARG(func, (;), dev, 4, 5, 6);확장 결과는 다음과 같습니다.
func(4, dev); func(5, dev); func(6, dev);FOR_EACH_IDX_FIXED_ARG(F, sep, fixed_arg, ...)FOR_EACH_IDX와 FOR_EACH_FIXED_ARG를 결합해 각 element마다 F(index, element, fixed_arg)를 호출합니다.
#define F(idx, x, fixed_arg) int fixed_arg##idx = x FOR_EACH_IDX_FIXED_ARG(F, (;), a, 4, 5, 6);확장 결과는 다음과 같습니다.
int a0 = 4; int a1 = 5; int a2 = 6;REVERSE_ARGS(...)가변 argument list의 순서를 뒤집습니다.
NUM_VA_ARGS_LESS_1(...)Variadic argument 수에서 1을 뺀 값을 반환하며 최대 64개 argument를 지원합니다.
NUM_VA_ARGS(...)Variadic argument 수를 반환하며 최대 63개 argument를 지원합니다.
MACRO_MAP_CAT(...)첫 argument인 one-argument macro를 나머지 각 argument에 적용하고 결과를 하나의 token으로 paste합니다. FOR_EACH와 달리 separator 없이 단일 token을 만듭니다.
#define FOO(x) item_##x##_MACRO_MAP_CAT(FOO, a, b, c)의 결과는 다음 token입니다.item_a_item_b_item_c_MACRO_MAP_CAT_N(N, ...)MACRO_MAP_CAT과 같지만 mapping할 argument 수 N을 고정합니다. N보다 많은 argument는 무시하고 각 expansion 결과를 한 token으로 붙입니다.
Runtime utility 함수
static inline bool is_power_of_two(unsigned int x)Unsigned x가 power of two이면 true, 아니면 false를 반환합니다.
ALWAYS_INLINE static bool is_null_no_warn(void *p)Pointer p가 NULL이면 true입니다. Macro argument가 절대 NULL일 수 없는 context에서 직접 NULL check가 compiler warning을 만들 수 있으므로 이 inline function으로 검사합니다. CONFIG_COMPILER_SAVE_TEMPS=y 또는 -ftrack-macro-expansion=0에서도 warning을 피하면서 compiler는 후속 optimization에서 check를 제거할 수 있습니다.
static inline int64_t arithmetic_shift_right(int64_t value, uint8_t shift)Signed 64-bit value를 shift bit만큼 arithmetic right shift하며 새로 열린 bit position은 sign bit로 채웁니다.
static inline void bytecpy(void *dst, const void *src, size_t size)src에서 dst로 size byte를 반드시 byte-by-byte 방식으로 copy합니다.
static inline void byteswp(void *a, void *b, size_t size)Memory region a와 b 사이 size byte를 반드시 byte-by-byte 방식으로 swap합니다.
int char2hex(char c, uint8_t *x)문자 c 하나를 hexadecimal nibble로 변환해 x에 저장합니다. 성공하면 0, 실패하면 negative error code입니다.
int hex2char(uint8_t x, char *c)Hexadecimal nibble x 하나를 문자로 변환해 c에 저장합니다. 성공하면 0, 실패하면 negative error code입니다.
size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen)buflen byte binary array를 string representation으로 바꿔 size hexlen의 hex storage에 저장합니다. 변환 string 길이를 반환하고 error이면 0입니다.
size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen)길이 hexlen의 hexadecimal string을 binary array로 바꿔 size buflen의 buf에 저장합니다. Binary array 길이를 반환하고 error이면 0입니다.
static inline uint8_t bcd2bin(uint8_t bcd)BCD 8421 값을 binary representation으로 변환합니다.
static inline uint8_t bin2bcd(uint8_t bin)Binary value를 BCD 8421 representation으로 변환합니다.
uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value)uint8_t value를 ASCII decimal string으로 바꿔 size buflen의 buf에 저장합니다. 공간이 충분하면 NULL terminator를 붙입니다. Terminator를 제외한 변환 길이를 반환하고 error이면 0입니다.
static inline int32_t sign_extend(uint32_t value, uint8_t index)8·16·32-bit value에서 0-based index(0~31)를 sign bit로 사용해 int32_t로 sign extension합니다.
static inline int64_t sign_extend_64(uint64_t value, uint8_t index)64-bit value에서 0-based index(0~63)를 sign bit로 사용해 int64_t로 sign extension합니다.
char *utf8_trunc(char *utf8_str)이미 다른 방식으로 NULL terminator가 삽입돼 잘린 UTF-8 string이 올바른 1~4 byte UTF-8 character boundary에서 끝나도록 다시 truncate하고 원래 utf8_str pointer를 반환합니다.
char *utf8_lcpy(char *dst, const char *src, size_t n)UTF-8 src를 dst로 copy합니다. n이 0보다 크면 dst는 항상 NULL-terminated이고 올바른 UTF-8 boundary에서 잘립니다. 최대 n-1 character를 copy하며 n=0이면 아무 작업도 하지 않고 terminator도 쓰지 않습니다. dst를 반환합니다.
static inline void mem_xor_n(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, size_t len)길이 len byte인 src1과 src2를 byte-wise XOR해 길이 len byte의 dst에 저장합니다.
static inline void mem_xor_32(uint8_t dst[4], const uint8_t src1[4], const uint8_t src2[4])32-bit src1과 src2를 XOR해 32-bit dst에 저장합니다.
static inline void mem_xor_128(uint8_t dst[16], const uint8_t src1[16], const uint8_t src2[16])128-bit src1과 src2를 XOR해 128-bit dst에 저장합니다.
Source
출처
영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.