From e313c56e94397d541cb3932921e1b3db84dc787e Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Thu, 6 Oct 2022 17:43:20 +0200 Subject: [PATCH 1/2] sys/checksum: add CRC-16 implementation without lookup table --- makefiles/pseudomodules.inc.mk | 1 + sys/Makefile.dep | 4 ++++ sys/checksum/crc16_ccitt.c | 22 ++++++++++++++++++++-- sys/include/checksum/crc16_ccitt.h | 3 +++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index b3558a71cfd8..fefb6e45f698 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -45,6 +45,7 @@ PSEUDOMODULES += cortexm_fpu PSEUDOMODULES += cortexm_svc PSEUDOMODULES += cpp PSEUDOMODULES += cpu_check_address +PSEUDOMODULES += crc16_fast PSEUDOMODULES += crc32_fast PSEUDOMODULES += credman_load PSEUDOMODULES += dbgpin diff --git a/sys/Makefile.dep b/sys/Makefile.dep index f3e983777214..270b3816a5a2 100644 --- a/sys/Makefile.dep +++ b/sys/Makefile.dep @@ -49,6 +49,10 @@ ifneq (,$(filter congure_reno_methods,$(USEMODULE))) USEMODULE += seq endif +ifneq (,$(filter crc16_fast,$(USEMODULE))) + USEMODULE += checksum +endif + ifneq (,$(filter crc32_fast,$(USEMODULE))) USEMODULE += checksum endif diff --git a/sys/checksum/crc16_ccitt.c b/sys/checksum/crc16_ccitt.c index 5f8f30b9ce51..d6b3cdb6a7e4 100644 --- a/sys/checksum/crc16_ccitt.c +++ b/sys/checksum/crc16_ccitt.c @@ -21,6 +21,8 @@ #include #include +#include "byteorder.h" +#include "kernel_defines.h" #include "checksum/crc16_ccitt.h" static const uint16_t crc_ccitt_lookuptable[256] = { @@ -96,7 +98,16 @@ static const uint16_t _crc16_ccitt_false_lookuptable[256] = { uint16_t crc16_ccitt_kermit_update(uint16_t crc, const unsigned char *buf, size_t len) { while (len--) { - crc = (crc >> 8) ^ crc_ccitt_lookuptable[(crc ^ (*buf++)) & 0xff]; + uint8_t e = crc ^= *buf++; + if (IS_USED(MODULE_CRC16_FAST)) { + crc = (crc >> 8) ^ crc_ccitt_lookuptable[e]; + } else { + uint8_t f = e ^ (e << 4); + crc = (crc >> 8) + ^ ((uint16_t)f << 8) + ^ ((uint16_t)f << 3) + ^ ((uint16_t)f >> 4); + } } return crc; @@ -115,7 +126,14 @@ uint16_t crc16_ccitt_mcrf4xx_calc(const unsigned char *buf, size_t len) uint16_t crc16_ccitt_false_update(uint16_t crc, const unsigned char *buf, size_t len) { while (len--) { - crc = ((crc << 8) ^ _crc16_ccitt_false_lookuptable[((crc >> 8) ^ ((*buf++) & 0x00FF))]); + crc = byteorder_swaps(crc) ^ *buf++; + if (IS_USED(MODULE_CRC16_FAST)) { + crc = (crc & 0xFF00) ^ _crc16_ccitt_false_lookuptable[crc & 0xFF]; + } else { + crc ^= (uint8_t)(crc & 0xff) >> 4; + crc ^= (crc << 8) << 4; + crc ^= ((crc & 0xff) << 4) << 1; + } } return crc; diff --git a/sys/include/checksum/crc16_ccitt.h b/sys/include/checksum/crc16_ccitt.h index b884ed2bfaac..14ad802b2e8c 100644 --- a/sys/include/checksum/crc16_ccitt.h +++ b/sys/include/checksum/crc16_ccitt.h @@ -18,6 +18,9 @@ * do (and is thus also far more memory efficient). Its caveat * however is that it is slower by about factor 8 than these versions. * + * @note enable the `crc32_fast` module for a look-up table based + * implementation that trades code size for speed. + * * @{ * @file * @author Ludwig Knüpfer From 98e18edab34eafb2a2dd4568bb8ffb629a828996 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Thu, 6 Oct 2022 17:48:47 +0200 Subject: [PATCH 2/2] drivers/dose: make use of checksum module --- drivers/dose/Kconfig | 1 + drivers/dose/Makefile.dep | 1 + drivers/dose/dose.c | 20 +++----------------- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/dose/Kconfig b/drivers/dose/Kconfig index aab666ba92e2..081cbdb2c32c 100644 --- a/drivers/dose/Kconfig +++ b/drivers/dose/Kconfig @@ -28,6 +28,7 @@ menuconfig MODULE_DOSE depends on HAS_PERIPH_GPIO depends on HAS_PERIPH_GPIO_IRQ depends on HAS_PERIPH_UART + select MODULE_CHECKSUM select MODULE_CHUNKED_RINGBUFFER select MODULE_EUI_PROVIDER select MODULE_IOLIST diff --git a/drivers/dose/Makefile.dep b/drivers/dose/Makefile.dep index 9de44766c6b4..3805ddfd3949 100644 --- a/drivers/dose/Makefile.dep +++ b/drivers/dose/Makefile.dep @@ -7,6 +7,7 @@ ifneq (,$(filter dose_watchdog,$(USEMODULE))) FEATURES_REQUIRED += periph_timer_periodic endif +USEMODULE += checksum USEMODULE += chunked_ringbuffer USEMODULE += eui_provider USEMODULE += iolist diff --git a/drivers/dose/dose.c b/drivers/dose/dose.c index 2c1e8effef92..c641f0ad5d1d 100644 --- a/drivers/dose/dose.c +++ b/drivers/dose/dose.c @@ -27,6 +27,7 @@ #include "irq.h" #include "periph/timer.h" +#include "checksum/crc16_ccitt.h" #include "net/eui_provider.h" #include "net/netdev/eth.h" #include "timex.h" @@ -38,7 +39,6 @@ #error "DOSE_TIMER_DEV needs to be set by the board" #endif -static uint16_t crc16_update(uint16_t crc, uint8_t octet); static dose_signal_t state_transit_blocked(dose_t *ctx, dose_signal_t signal); static dose_signal_t state_transit_idle(dose_t *ctx, dose_signal_t signal); static dose_signal_t state_transit_recv(dose_t *ctx, dose_signal_t signal); @@ -59,22 +59,10 @@ static int _init(netdev_t *dev); static void _poweron(dose_t *dev); static void _poweroff(dose_t *dev, dose_state_t sleep_state); -static uint16_t crc16_update(uint16_t crc, uint8_t octet) -{ - crc = (uint8_t)(crc >> 8) | (crc << 8); - crc ^= octet; - crc ^= (uint8_t)(crc & 0xff) >> 4; - crc ^= (crc << 8) << 4; - crc ^= ((crc & 0xff) << 4) << 1; - return crc; -} - static void _crc_cb(void *ctx, uint8_t *data, size_t len) { uint16_t *crc = ctx; - for (uint8_t *end = data + len; data != end; ++data) { - *crc = crc16_update(*crc, *data); - } + *crc = crc16_ccitt_false_update(*crc, data, len); } static void _init_standby(dose_t *ctx, const dose_params_t *params) @@ -571,15 +559,13 @@ static int _send(netdev_t *dev, const iolist_t *iolist) size_t n = iol->iol_len; pktlen += n; uint8_t *ptr = iol->iol_base; + crc = crc16_ccitt_false_update(crc, ptr, n); while (n--) { /* Send data octet */ if (send_data_octet(ctx, *ptr)) { goto collision; } - /* Update CRC */ - crc = crc16_update(crc, *ptr); - ptr++; } }