Skip to content

Commit b5ee0c0

Browse files
authored
Merge pull request #8026 from SiliconLabs/bugfix/gpcrc
Fix for HW CRC calculations on Silicon Labs targets
2 parents f0c6a66 + 0f879ad commit b5ee0c0

File tree

1 file changed

+22
-7
lines changed
  • targets/TARGET_Silicon_Labs/TARGET_EFM32

1 file changed

+22
-7
lines changed

targets/TARGET_Silicon_Labs/TARGET_EFM32/crc_api.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "em_gpcrc.h"
3535

3636
static bool revOutput = false;
37+
static bool enableWordInput = false;
3738
static uint32_t final_xor;
3839

3940
bool hal_crc_is_supported(const crc_mbed_config_t *config)
@@ -75,21 +76,24 @@ void hal_crc_compute_partial_start(const crc_mbed_config_t *config)
7576
// defined by the mbed API. Emlib does the reversal on the poly, but
7677
// not on the initial value.
7778
if (config->width == 16) {
79+
enableWordInput = false;
7880
crc_init.initValue = __RBIT(config->initial_xor) >> 16;
7981
} else {
82+
enableWordInput = true;
8083
crc_init.initValue = __RBIT(config->initial_xor);
8184
}
8285

8386
// GPCRC operates on bit-reversed inputs and outputs vs the standard
8487
// defined by the mbed API, so reflect_in/out needs to be negated.
8588
if (config->reflect_in) {
86-
crc_init.reverseByteOrder = false;
8789
crc_init.reverseBits = false;
8890
} else {
89-
crc_init.reverseByteOrder = true;
9091
crc_init.reverseBits = true;
9192
}
9293

94+
// Input is little-endian
95+
crc_init.reverseByteOrder = false;
96+
9397
// Disable byte mode to be able to run a faster U32 input version
9498
crc_init.enableByteMode = false;
9599

@@ -109,19 +113,30 @@ void hal_crc_compute_partial(const uint8_t *data, const size_t size)
109113
return;
110114
}
111115

112-
if (((uint32_t)data & 0x3) != 0 || size < 4) {
113-
// Unaligned or very small input, run a bytewise CRC
116+
if (!enableWordInput || size < sizeof(uint32_t)) {
117+
// Input to a non-word-sized poly, or too small data size for a word input
114118
for (size_t i = 0; i < size; i++) {
115119
GPCRC_InputU8(GPCRC, data[i]);
116120
}
117121
} else {
118-
// Aligned input, run 32-bit inputs as long as possible to make go faster.
119122
size_t i = 0;
120-
for (; i < (size & (~0x3)); i+=4) {
123+
124+
// If input is unaligned, take off as many bytes as needed to align
125+
while (((uint32_t)(data + i) & 0x3) != 0) {
126+
GPCRC_InputU8(GPCRC, data[i]);
127+
i++;
128+
}
129+
130+
// If enough input remaining to do word-sized writes, do so
131+
while ((size - i) >= sizeof(uint32_t)) {
121132
GPCRC_InputU32(GPCRC, *((uint32_t*)(&data[i])));
133+
i += sizeof(uint32_t);
122134
}
123-
for (; i < size; i++) {
135+
136+
// Do byte input to pick off the last remaining bytes
137+
while (i < size) {
124138
GPCRC_InputU8(GPCRC, data[i]);
139+
i++;
125140
}
126141
}
127142
}

0 commit comments

Comments
 (0)