Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sys/checksum: add CRC-16 implementation without lookup table #18701

Merged
merged 2 commits into from
Oct 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/dose/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/dose/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 3 additions & 17 deletions drivers/dose/dose.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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++;
}
}
Expand Down
1 change: 1 addition & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions sys/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 20 additions & 2 deletions sys/checksum/crc16_ccitt.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <stdint.h>
#include <stdlib.h>

#include "byteorder.h"
#include "kernel_defines.h"
#include "checksum/crc16_ccitt.h"

static const uint16_t crc_ccitt_lookuptable[256] = {
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions sys/include/checksum/crc16_ccitt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
Expand Down