This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit d10757afff546b3209f51313dc9de89f4c7aadf9 Author: mazhuang <[email protected]> AuthorDate: Tue Apr 7 10:12:53 2026 +0800 libs/libc: add xorsum16() Add xorsum16(), the XOR of the 16-bit little-endian words of a buffer, declared in nuttx/lib/xorsum.h. It reads the buffer as uint64_t once it is 8-byte aligned and folds the result down to 16 bits, so it is much cheaper than a table CRC on a frame-sized buffer. The head and tail bytes go into the lane of their address and the result is swapped for an odd start, so the same bytes give the same value at any alignment. It is not a CRC: it misses errors that flip the same bit in two words and swapped words. rpmsg_port uses it to check frames on its links. Signed-off-by: mazhuang <[email protected]> Signed-off-by: Bowen Wang <[email protected]> --- include/nuttx/lib/xorsum.h | 69 ++++++++++++++++++++++++++ libs/libc/misc/CMakeLists.txt | 1 + libs/libc/misc/Make.defs | 2 +- libs/libc/misc/lib_xorsum16.c | 113 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+), 1 deletion(-) diff --git a/include/nuttx/lib/xorsum.h b/include/nuttx/lib/xorsum.h new file mode 100644 index 00000000000..d89d1bb0c23 --- /dev/null +++ b/include/nuttx/lib/xorsum.h @@ -0,0 +1,69 @@ +/**************************************************************************** + * include/nuttx/lib/xorsum.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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 __INCLUDE_NUTTX_LIB_XORSUM_H +#define __INCLUDE_NUTTX_LIB_XORSUM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stddef.h> +#include <stdint.h> + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/**************************************************************************** + * Name: xorsum16 + * + * Description: + * Return the XOR of the 16-bit little-endian words of a buffer, taken by + * their offset from the start; an odd last byte is the low byte of a + * final word. The result does not depend on the buffer's alignment. + * This is a fast check for framing errors, not a CRC: it misses errors + * that flip the same bit in two words and words that are swapped. + * + * Input Parameters: + * buf - The buffer + * len - The buffer length in bytes + * + * Returned Value: + * The 16-bit XOR checksum. + * + ****************************************************************************/ + +uint16_t xorsum16(FAR const void *buf, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_LIB_XORSUM_H */ diff --git a/libs/libc/misc/CMakeLists.txt b/libs/libc/misc/CMakeLists.txt index ac67adcf594..0cf18eb3ec8 100644 --- a/libs/libc/misc/CMakeLists.txt +++ b/libs/libc/misc/CMakeLists.txt @@ -96,6 +96,7 @@ list( lib_crc16xmodem.c lib_crc16h1021.c lib_crc16h8005.c + lib_xorsum16.c lib_crc8.c lib_crc8ccitt.c lib_crc8h1d.c diff --git a/libs/libc/misc/Make.defs b/libs/libc/misc/Make.defs index 916325be4cf..fbcc6c8bdb3 100644 --- a/libs/libc/misc/Make.defs +++ b/libs/libc/misc/Make.defs @@ -54,7 +54,7 @@ CSRCS += lib_crc8.c lib_crc8ccitt.c lib_crc8table.c lib_crc8rohc.c CSRCS += lib_crc8h1d.c lib_crc8h2f.c lib_crc16h1021.c lib_crc16h8005.c CSRCS += lib_crc32h04c11db7.c lib_crc32hf4acfb13.c lib_crc64emac.c CSRCS += lib_backtrace.c lib_ftok.c lib_err.c lib_instrument.c lib_glob.c -CSRCS += lib_crc16ibm.c lib_crc16xmodem.c +CSRCS += lib_crc16ibm.c lib_crc16xmodem.c lib_xorsum16.c # Keyboard driver encoder/decoder diff --git a/libs/libc/misc/lib_xorsum16.c b/libs/libc/misc/lib_xorsum16.c new file mode 100644 index 00000000000..d325f48a8ff --- /dev/null +++ b/libs/libc/misc/lib_xorsum16.c @@ -0,0 +1,113 @@ +/**************************************************************************** + * libs/libc/misc/lib_xorsum16.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdbool.h> +#include <stdint.h> + +#include <nuttx/lib/xorsum.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Shift that puts the byte at address a in its lane of a native uint64_t + * read from the aligned word containing a. + */ + +#ifdef CONFIG_ENDIAN_BIG +# define XORSUM_LANE(a) ((7 - ((uintptr_t)(a) & 7)) * 8) +#else +# define XORSUM_LANE(a) (((uintptr_t)(a) & 7) * 8) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: xorsum16 + * + * Description: + * Return the XOR of the 16-bit little-endian words of a buffer, see + * include/nuttx/lib/xorsum.h. + * + ****************************************************************************/ + +uint16_t xorsum16(FAR const void *buf, size_t len) +{ + FAR const uint8_t *src = buf; + FAR const uint64_t *p; + uint64_t sum = 0; + uint16_t ret; + bool odd = (uintptr_t)src & 1; + + /* Every byte goes into the lane of its address, so the folded sum below + * depends only on address parity; the swap for an odd start makes it a + * function of the offset from buf alone. + */ + + while (((uintptr_t)src & 7) && len > 0) + { + sum ^= (uint64_t)*src << XORSUM_LANE(src); + src++; + len--; + } + + p = (FAR const uint64_t *)src; + while (len >= 64) + { + sum ^= p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4] ^ p[5] ^ p[6] ^ p[7]; + p += 8; + len -= 64; + } + + while (len >= 8) + { + sum ^= *p++; + len -= 8; + } + + src = (FAR const uint8_t *)p; + while (len-- > 0) + { + sum ^= (uint64_t)*src << XORSUM_LANE(src); + src++; + } + + sum ^= sum >> 32; + sum ^= sum >> 16; + ret = (uint16_t)sum; + +#ifdef CONFIG_ENDIAN_BIG + /* Lanes are mirrored: even addresses landed in the high byte */ + + odd = !odd; +#endif + + return odd ? (uint16_t)((ret << 8) | (ret >> 8)) : ret; +}
