diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/crc_api.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/crc_api.c
new file mode 100644
index 0000000000..4e7c71de0c
--- /dev/null
+++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/crc_api.c
@@ -0,0 +1,147 @@
+/***************************************************************************//**
+ * @file crc_api.c
+ *******************************************************************************
+ * @section License
+ * (C) Copyright 2018 Silicon Labs, http://www.silabs.com
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed 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.
+ *
+ ******************************************************************************/
+
+#include "device.h"
+#include "clocking.h"
+#include
+
+#if DEVICE_CRC
+#include "mbed_assert.h"
+#include "crc_api.h"
+#include "em_cmu.h"
+
+#if defined(GPCRC_PRESENT) && (GPCRC_COUNT > 0)
+#include "em_gpcrc.h"
+
+static bool revOutput = false;
+static uint32_t final_xor;
+
+bool hal_crc_is_supported(const crc_mbed_config_t *config)
+{
+ //GPCRC supports any 16-bit poly, but only the CCITT 32-bit poly
+ if (config == NULL) {
+ return false;
+ }
+
+ if (config->width == 16) {
+ return true;
+ } else if (config->width == 32) {
+ if (config->polynomial == POLY_32BIT_ANSI) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+}
+
+void hal_crc_compute_partial_start(const crc_mbed_config_t *config)
+{
+ if (!hal_crc_is_supported(config)) {
+ return;
+ }
+
+ CMU_ClockEnable(cmuClock_GPCRC, true);
+ GPCRC_Reset(GPCRC);
+
+ GPCRC_Init_TypeDef crc_init;
+
+ crc_init.autoInit = false;
+ crc_init.enable = true;
+ crc_init.crcPoly = config->polynomial;
+
+ // GPCRC operates on bit-reversed inputs and outputs vs the standard
+ // defined by the mbed API. Emlib does the reversal on the poly, but
+ // not on the initial value.
+ if (config->width == 16) {
+ crc_init.initValue = __RBIT(config->initial_xor) >> 16;
+ } else {
+ crc_init.initValue = __RBIT(config->initial_xor);
+ }
+
+ // GPCRC operates on bit-reversed inputs and outputs vs the standard
+ // defined by the mbed API, so reflect_in/out needs to be negated.
+ if (config->reflect_in) {
+ crc_init.reverseByteOrder = false;
+ crc_init.reverseBits = false;
+ } else {
+ crc_init.reverseByteOrder = true;
+ crc_init.reverseBits = true;
+ }
+
+ // Disable byte mode to be able to run a faster U32 input version
+ crc_init.enableByteMode = false;
+
+ // GPCRC does not support hardware output bit-reversal, nor finalisation.
+ // Since the mbed API does not pass the config struct when fetching the
+ // CRC calculation result, we need to keep track of these locally.
+ revOutput = config->reflect_out;
+ final_xor = config->final_xor;
+
+ GPCRC_Init(GPCRC, &crc_init);
+ GPCRC_Start(GPCRC);
+}
+
+void hal_crc_compute_partial(const uint8_t *data, const size_t size)
+{
+ if (data == NULL || size <= 0) {
+ return;
+ }
+
+ if (((uint32_t)data & 0x3) != 0 || size < 4) {
+ // Unaligned or very small input, run a bytewise CRC
+ for (size_t i = 0; i < size; i++) {
+ GPCRC_InputU8(GPCRC, data[i]);
+ }
+ } else {
+ // Aligned input, run 32-bit inputs as long as possible to make go faster.
+ size_t i = 0;
+ for (; i < (size & (~0x3)); i+=4) {
+ GPCRC_InputU32(GPCRC, *((uint32_t*)(&data[i])));
+ }
+ for (; i < size; i++) {
+ GPCRC_InputU8(GPCRC, data[i]);
+ }
+ }
+}
+
+uint32_t hal_crc_get_result(void)
+{
+ uint32_t result;
+
+ // GPCRC operates on bit-reversed inputs and outputs vs the standard
+ // defined by the mbed API.
+ if (!revOutput) {
+ result = GPCRC_DataReadBitReversed(GPCRC);
+ } else {
+ result = GPCRC_DataRead(GPCRC);
+ }
+
+ GPCRC_Enable(GPCRC, false);
+
+ return result ^ final_xor;
+}
+
+#endif //GPCRC_PRESENT
+#endif //DEVICE_CRC
diff --git a/targets/targets.json b/targets/targets.json
index 8d2d6c9dcc..7a13918744 100755
--- a/targets/targets.json
+++ b/targets/targets.json
@@ -3255,7 +3255,7 @@
},
"EFM32PG_STK3401": {
"inherits": ["EFM32PG1B100F256GM32"],
- "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"],
+ "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"],
"forced_reset_timeout": 2,
"config": {
"hf_clock_src": {
@@ -3318,7 +3318,7 @@
},
"EFR32MG1_BRD4150": {
"inherits": ["EFR32MG1P132F256GM48"],
- "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"],
+ "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"],
"forced_reset_timeout": 2,
"config": {
"hf_clock_src": {
@@ -3361,7 +3361,7 @@
},
"TB_SENSE_1": {
"inherits": ["EFR32MG1P233F256GM48"],
- "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"],
+ "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"],
"forced_reset_timeout": 5,
"config": {
"hf_clock_src": {
@@ -3409,7 +3409,7 @@
},
"EFM32PG12_STK3402": {
"inherits": ["EFM32PG12B500F1024GL125"],
- "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"],
+ "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"],
"forced_reset_timeout": 2,
"config": {
"hf_clock_src": {
@@ -3463,7 +3463,7 @@
"TB_SENSE_12": {
"inherits": ["EFR32MG12P332F1024GL125"],
"device_name": "EFR32MG12P332F1024GL125",
- "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"],
+ "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"],
"forced_reset_timeout": 5,
"config": {
"hf_clock_src": {
@@ -3512,7 +3512,7 @@
"EFM32GG11_STK3701": {
"inherits": ["EFM32GG11B820F2048GL192"],
"device_name": "EFM32GG11B820F2048GL192",
- "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"],
+ "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"],
"forced_reset_timeout": 5,
"config": {
"hf_clock_src": {