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