Skip to content

Commit 2188110

Browse files
author
Cruz Monrreal
authored
Merge pull request #7479 from SiliconLabs/feature/crc
Silicon Labs: Add support for hardware CRC
2 parents 49ae504 + 8649162 commit 2188110

File tree

2 files changed

+153
-6
lines changed

2 files changed

+153
-6
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/***************************************************************************//**
2+
* @file crc_api.c
3+
*******************************************************************************
4+
* @section License
5+
* <b>(C) Copyright 2018 Silicon Labs, http://www.silabs.com</b>
6+
*******************************************************************************
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
11+
* not use this file except in compliance with the License.
12+
* You may obtain a copy of the License at
13+
*
14+
* http://www.apache.org/licenses/LICENSE-2.0
15+
*
16+
* Unless required by applicable law or agreed to in writing, software
17+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19+
* See the License for the specific language governing permissions and
20+
* limitations under the License.
21+
*
22+
******************************************************************************/
23+
24+
#include "device.h"
25+
#include "clocking.h"
26+
#include <stdio.h>
27+
28+
#if DEVICE_CRC
29+
#include "mbed_assert.h"
30+
#include "crc_api.h"
31+
#include "em_cmu.h"
32+
33+
#if defined(GPCRC_PRESENT) && (GPCRC_COUNT > 0)
34+
#include "em_gpcrc.h"
35+
36+
static bool revOutput = false;
37+
static uint32_t final_xor;
38+
39+
bool hal_crc_is_supported(const crc_mbed_config_t *config)
40+
{
41+
//GPCRC supports any 16-bit poly, but only the CCITT 32-bit poly
42+
if (config == NULL) {
43+
return false;
44+
}
45+
46+
if (config->width == 16) {
47+
return true;
48+
} else if (config->width == 32) {
49+
if (config->polynomial == POLY_32BIT_ANSI) {
50+
return true;
51+
} else {
52+
return false;
53+
}
54+
} else {
55+
return false;
56+
}
57+
}
58+
59+
void hal_crc_compute_partial_start(const crc_mbed_config_t *config)
60+
{
61+
if (!hal_crc_is_supported(config)) {
62+
return;
63+
}
64+
65+
CMU_ClockEnable(cmuClock_GPCRC, true);
66+
GPCRC_Reset(GPCRC);
67+
68+
GPCRC_Init_TypeDef crc_init;
69+
70+
crc_init.autoInit = false;
71+
crc_init.enable = true;
72+
crc_init.crcPoly = config->polynomial;
73+
74+
// GPCRC operates on bit-reversed inputs and outputs vs the standard
75+
// defined by the mbed API. Emlib does the reversal on the poly, but
76+
// not on the initial value.
77+
if (config->width == 16) {
78+
crc_init.initValue = __RBIT(config->initial_xor) >> 16;
79+
} else {
80+
crc_init.initValue = __RBIT(config->initial_xor);
81+
}
82+
83+
// GPCRC operates on bit-reversed inputs and outputs vs the standard
84+
// defined by the mbed API, so reflect_in/out needs to be negated.
85+
if (config->reflect_in) {
86+
crc_init.reverseByteOrder = false;
87+
crc_init.reverseBits = false;
88+
} else {
89+
crc_init.reverseByteOrder = true;
90+
crc_init.reverseBits = true;
91+
}
92+
93+
// Disable byte mode to be able to run a faster U32 input version
94+
crc_init.enableByteMode = false;
95+
96+
// GPCRC does not support hardware output bit-reversal, nor finalisation.
97+
// Since the mbed API does not pass the config struct when fetching the
98+
// CRC calculation result, we need to keep track of these locally.
99+
revOutput = config->reflect_out;
100+
final_xor = config->final_xor;
101+
102+
GPCRC_Init(GPCRC, &crc_init);
103+
GPCRC_Start(GPCRC);
104+
}
105+
106+
void hal_crc_compute_partial(const uint8_t *data, const size_t size)
107+
{
108+
if (data == NULL || size <= 0) {
109+
return;
110+
}
111+
112+
if (((uint32_t)data & 0x3) != 0 || size < 4) {
113+
// Unaligned or very small input, run a bytewise CRC
114+
for (size_t i = 0; i < size; i++) {
115+
GPCRC_InputU8(GPCRC, data[i]);
116+
}
117+
} else {
118+
// Aligned input, run 32-bit inputs as long as possible to make go faster.
119+
size_t i = 0;
120+
for (; i < (size & (~0x3)); i+=4) {
121+
GPCRC_InputU32(GPCRC, *((uint32_t*)(&data[i])));
122+
}
123+
for (; i < size; i++) {
124+
GPCRC_InputU8(GPCRC, data[i]);
125+
}
126+
}
127+
}
128+
129+
uint32_t hal_crc_get_result(void)
130+
{
131+
uint32_t result;
132+
133+
// GPCRC operates on bit-reversed inputs and outputs vs the standard
134+
// defined by the mbed API.
135+
if (!revOutput) {
136+
result = GPCRC_DataReadBitReversed(GPCRC);
137+
} else {
138+
result = GPCRC_DataRead(GPCRC);
139+
}
140+
141+
GPCRC_Enable(GPCRC, false);
142+
143+
return result ^ final_xor;
144+
}
145+
146+
#endif //GPCRC_PRESENT
147+
#endif //DEVICE_CRC

targets/targets.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3236,7 +3236,7 @@
32363236
},
32373237
"EFM32PG_STK3401": {
32383238
"inherits": ["EFM32PG1B100F256GM32"],
3239-
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
3239+
"device_has": ["ANALOGIN", "CRC", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
32403240
"forced_reset_timeout": 2,
32413241
"config": {
32423242
"hf_clock_src": {
@@ -3299,7 +3299,7 @@
32993299
},
33003300
"EFR32MG1_BRD4150": {
33013301
"inherits": ["EFR32MG1P132F256GM48"],
3302-
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
3302+
"device_has": ["ANALOGIN", "CRC", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
33033303
"forced_reset_timeout": 2,
33043304
"config": {
33053305
"hf_clock_src": {
@@ -3342,7 +3342,7 @@
33423342
},
33433343
"TB_SENSE_1": {
33443344
"inherits": ["EFR32MG1P233F256GM48"],
3345-
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
3345+
"device_has": ["ANALOGIN", "CRC", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "FLASH"],
33463346
"forced_reset_timeout": 5,
33473347
"config": {
33483348
"hf_clock_src": {
@@ -3390,7 +3390,7 @@
33903390
},
33913391
"EFM32PG12_STK3402": {
33923392
"inherits": ["EFM32PG12B500F1024GL125"],
3393-
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", "FLASH"],
3393+
"device_has": ["ANALOGIN", "CRC", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", "FLASH"],
33943394
"forced_reset_timeout": 2,
33953395
"config": {
33963396
"hf_clock_src": {
@@ -3444,7 +3444,7 @@
34443444
"TB_SENSE_12": {
34453445
"inherits": ["EFR32MG12P332F1024GL125"],
34463446
"device_name": "EFR32MG12P332F1024GL125",
3447-
"device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", "FLASH"],
3447+
"device_has": ["ANALOGIN", "CRC", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", "FLASH"],
34483448
"forced_reset_timeout": 5,
34493449
"config": {
34503450
"hf_clock_src": {
@@ -3493,7 +3493,7 @@
34933493
"EFM32GG11_STK3701": {
34943494
"inherits": ["EFM32GG11B820F2048GL192"],
34953495
"device_name": "EFM32GG11B820F2048GL192",
3496-
"device_has": ["ANALOGIN", "EMAC", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", "FLASH"],
3496+
"device_has": ["ANALOGIN", "CRC", "EMAC", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LPTICKER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "USTICKER", "TRNG", "FLASH"],
34973497
"forced_reset_timeout": 5,
34983498
"config": {
34993499
"hf_clock_src": {

0 commit comments

Comments
 (0)