Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
Child:
1:9db0e321a9f4
mbed-os5 only for TYBLE16

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /* mbed Microcontroller Library
kenjiArai 0:5b88d5760320 2 * Copyright (c) 2018 ARM Limited
kenjiArai 0:5b88d5760320 3 * SPDX-License-Identifier: Apache-2.0
kenjiArai 0:5b88d5760320 4 *
kenjiArai 0:5b88d5760320 5 * Licensed under the Apache License, Version 2.0 (the "License");
kenjiArai 0:5b88d5760320 6 * you may not use this file except in compliance with the License.
kenjiArai 0:5b88d5760320 7 * You may obtain a copy of the License at
kenjiArai 0:5b88d5760320 8 *
kenjiArai 0:5b88d5760320 9 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 0:5b88d5760320 10 *
kenjiArai 0:5b88d5760320 11 * Unless required by applicable law or agreed to in writing, software
kenjiArai 0:5b88d5760320 12 * distributed under the License is distributed on an "AS IS" BASIS,
kenjiArai 0:5b88d5760320 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 0:5b88d5760320 14 * See the License for the specific language governing permissions and
kenjiArai 0:5b88d5760320 15 * limitations under the License.
kenjiArai 0:5b88d5760320 16 */
kenjiArai 0:5b88d5760320 17 #ifndef MBED_CRC_API_H
kenjiArai 0:5b88d5760320 18 #define MBED_CRC_API_H
kenjiArai 0:5b88d5760320 19
kenjiArai 0:5b88d5760320 20 #include "drivers/TableCRC.h"
kenjiArai 0:5b88d5760320 21 #include "hal/crc_api.h"
kenjiArai 0:5b88d5760320 22 #include "platform/mbed_assert.h"
kenjiArai 0:5b88d5760320 23 #include "platform/SingletonPtr.h"
kenjiArai 0:5b88d5760320 24 #include "platform/PlatformMutex.h"
kenjiArai 0:5b88d5760320 25
kenjiArai 0:5b88d5760320 26 /* This is an invalid warning from the compiler for the below section of code
kenjiArai 0:5b88d5760320 27 if ((width < 8) && (NULL == _crc_table)) {
kenjiArai 0:5b88d5760320 28 p_crc = (uint32_t)(p_crc << (8 - width));
kenjiArai 0:5b88d5760320 29 }
kenjiArai 0:5b88d5760320 30 Compiler warns of the shift operation with width as it is width=(std::uint8_t),
kenjiArai 0:5b88d5760320 31 but we check for ( width < 8) before performing shift, so it should not be an issue.
kenjiArai 0:5b88d5760320 32 */
kenjiArai 0:5b88d5760320 33 #if defined ( __CC_ARM )
kenjiArai 0:5b88d5760320 34 #pragma diag_suppress 62 // Shift count is negative
kenjiArai 0:5b88d5760320 35 #elif defined ( __GNUC__ )
kenjiArai 0:5b88d5760320 36 #pragma GCC diagnostic push
kenjiArai 0:5b88d5760320 37 #pragma GCC diagnostic ignored "-Wshift-count-negative"
kenjiArai 0:5b88d5760320 38 #elif defined (__ICCARM__)
kenjiArai 0:5b88d5760320 39 #pragma diag_suppress=Pe062 // Shift count is negative
kenjiArai 0:5b88d5760320 40 #endif
kenjiArai 0:5b88d5760320 41
kenjiArai 0:5b88d5760320 42 namespace mbed {
kenjiArai 0:5b88d5760320 43 /** \addtogroup drivers */
kenjiArai 0:5b88d5760320 44 /** @{*/
kenjiArai 0:5b88d5760320 45
kenjiArai 0:5b88d5760320 46 extern SingletonPtr<PlatformMutex> mbed_crc_mutex;
kenjiArai 0:5b88d5760320 47
kenjiArai 0:5b88d5760320 48 /** CRC object provides CRC generation through hardware or software
kenjiArai 0:5b88d5760320 49 *
kenjiArai 0:5b88d5760320 50 * CRC sums can be generated using three different methods: hardware, software ROM tables
kenjiArai 0:5b88d5760320 51 * and bitwise computation. The mode used is selected automatically based on required
kenjiArai 0:5b88d5760320 52 * polynomial and hardware capabilities. Any polynomial in standard form (`x^3 + x + 1`)
kenjiArai 0:5b88d5760320 53 * can be used for computation, but custom ones can affect the performance.
kenjiArai 0:5b88d5760320 54 *
kenjiArai 0:5b88d5760320 55 * First choice is the hardware mode. The supported polynomials are hardware specific, and
kenjiArai 0:5b88d5760320 56 * you need to consult your MCU manual to discover them. Next, ROM polynomial tables
kenjiArai 0:5b88d5760320 57 * are tried (you can find list of supported polynomials here ::crc_polynomial). If the selected
kenjiArai 0:5b88d5760320 58 * configuration is supported, it will accelerate the software computations. If ROM tables
kenjiArai 0:5b88d5760320 59 * are not available for the selected polynomial, then CRC is computed at run time bit by bit
kenjiArai 0:5b88d5760320 60 * for all data input.
kenjiArai 0:5b88d5760320 61 * @note Synchronization level: Thread safe
kenjiArai 0:5b88d5760320 62 *
kenjiArai 0:5b88d5760320 63 * @tparam polynomial CRC polynomial value in hex
kenjiArai 0:5b88d5760320 64 * @tparam width CRC polynomial width
kenjiArai 0:5b88d5760320 65 *
kenjiArai 0:5b88d5760320 66 * Example: Compute CRC data
kenjiArai 0:5b88d5760320 67 * @code
kenjiArai 0:5b88d5760320 68 *
kenjiArai 0:5b88d5760320 69 * #include "mbed.h"
kenjiArai 0:5b88d5760320 70 *
kenjiArai 0:5b88d5760320 71 * int main() {
kenjiArai 0:5b88d5760320 72 * MbedCRC<POLY_32BIT_ANSI, 32> ct;
kenjiArai 0:5b88d5760320 73 *
kenjiArai 0:5b88d5760320 74 * char test[] = "123456789";
kenjiArai 0:5b88d5760320 75 * uint32_t crc = 0;
kenjiArai 0:5b88d5760320 76 *
kenjiArai 0:5b88d5760320 77 * printf("\nPolynomial = 0x%lx Width = %d \n", ct.get_polynomial(), ct.get_width());
kenjiArai 0:5b88d5760320 78 *
kenjiArai 0:5b88d5760320 79 * ct.compute((void *)test, strlen((const char*)test), &crc);
kenjiArai 0:5b88d5760320 80 *
kenjiArai 0:5b88d5760320 81 * printf("The CRC of data \"123456789\" is : 0x%lx\n", crc);
kenjiArai 0:5b88d5760320 82 * return 0;
kenjiArai 0:5b88d5760320 83 * }
kenjiArai 0:5b88d5760320 84 * @endcode
kenjiArai 0:5b88d5760320 85 * Example: Compute CRC with data available in parts
kenjiArai 0:5b88d5760320 86 * @code
kenjiArai 0:5b88d5760320 87 *
kenjiArai 0:5b88d5760320 88 * #include "mbed.h"
kenjiArai 0:5b88d5760320 89 * int main() {
kenjiArai 0:5b88d5760320 90 * MbedCRC<POLY_32BIT_ANSI, 32> ct;
kenjiArai 0:5b88d5760320 91 *
kenjiArai 0:5b88d5760320 92 * char test[] = "123456789";
kenjiArai 0:5b88d5760320 93 * uint32_t crc = 0;
kenjiArai 0:5b88d5760320 94 *
kenjiArai 0:5b88d5760320 95 * printf("\nPolynomial = 0x%lx Width = %d \n", ct.get_polynomial(), ct.get_width());
kenjiArai 0:5b88d5760320 96 * ct.compute_partial_start(&crc);
kenjiArai 0:5b88d5760320 97 * ct.compute_partial((void *)&test, 4, &crc);
kenjiArai 0:5b88d5760320 98 * ct.compute_partial((void *)&test[4], 5, &crc);
kenjiArai 0:5b88d5760320 99 * ct.compute_partial_stop(&crc);
kenjiArai 0:5b88d5760320 100 * printf("The CRC of data \"123456789\" is : 0x%lx\n", crc);
kenjiArai 0:5b88d5760320 101 * return 0;
kenjiArai 0:5b88d5760320 102 * }
kenjiArai 0:5b88d5760320 103 * @endcode
kenjiArai 0:5b88d5760320 104 * @ingroup drivers
kenjiArai 0:5b88d5760320 105 */
kenjiArai 0:5b88d5760320 106 template <uint32_t polynomial = POLY_32BIT_ANSI, uint8_t width = 32>
kenjiArai 0:5b88d5760320 107 class MbedCRC {
kenjiArai 0:5b88d5760320 108
kenjiArai 0:5b88d5760320 109 public:
kenjiArai 0:5b88d5760320 110 enum CrcMode {
kenjiArai 0:5b88d5760320 111 #if DEVICE_CRC
kenjiArai 0:5b88d5760320 112 HARDWARE = 0,
kenjiArai 0:5b88d5760320 113 #endif
kenjiArai 0:5b88d5760320 114 TABLE = 1,
kenjiArai 0:5b88d5760320 115 BITWISE
kenjiArai 0:5b88d5760320 116 };
kenjiArai 0:5b88d5760320 117
kenjiArai 0:5b88d5760320 118 typedef uint64_t crc_data_size_t;
kenjiArai 0:5b88d5760320 119
kenjiArai 0:5b88d5760320 120 /** Lifetime of CRC object
kenjiArai 0:5b88d5760320 121 *
kenjiArai 0:5b88d5760320 122 * @param initial_xor Inital value/seed to Xor
kenjiArai 0:5b88d5760320 123 * @param final_xor Final Xor value
kenjiArai 0:5b88d5760320 124 * @param reflect_data
kenjiArai 0:5b88d5760320 125 * @param reflect_remainder
kenjiArai 0:5b88d5760320 126 * @note Default constructor without any arguments is valid only for supported CRC polynomials. :: crc_polynomial_t
kenjiArai 0:5b88d5760320 127 * MbedCRC <POLY_7BIT_SD, 7> ct; --- Valid POLY_7BIT_SD
kenjiArai 0:5b88d5760320 128 * MbedCRC <0x1021, 16> ct; --- Valid POLY_16BIT_CCITT
kenjiArai 0:5b88d5760320 129 * MbedCRC <POLY_16BIT_CCITT, 32> ct; --- Invalid, compilation error
kenjiArai 0:5b88d5760320 130 * MbedCRC <POLY_16BIT_CCITT, 32> ct (i,f,rd,rr) Constructor can be used for not supported polynomials
kenjiArai 0:5b88d5760320 131 * MbedCRC<POLY_16BIT_CCITT, 16> sd(0, 0, false, false); Constructor can also be used for supported
kenjiArai 0:5b88d5760320 132 * polynomials with different intial/final/reflect values
kenjiArai 0:5b88d5760320 133 *
kenjiArai 0:5b88d5760320 134 */
kenjiArai 0:5b88d5760320 135 MbedCRC(uint32_t initial_xor, uint32_t final_xor, bool reflect_data, bool reflect_remainder) :
kenjiArai 0:5b88d5760320 136 _initial_value(initial_xor), _final_xor(final_xor), _reflect_data(reflect_data),
kenjiArai 0:5b88d5760320 137 _reflect_remainder(reflect_remainder)
kenjiArai 0:5b88d5760320 138 {
kenjiArai 0:5b88d5760320 139 mbed_crc_ctor();
kenjiArai 0:5b88d5760320 140 }
kenjiArai 0:5b88d5760320 141 MbedCRC();
kenjiArai 0:5b88d5760320 142 virtual ~MbedCRC()
kenjiArai 0:5b88d5760320 143 {
kenjiArai 0:5b88d5760320 144 // Do nothing
kenjiArai 0:5b88d5760320 145 }
kenjiArai 0:5b88d5760320 146
kenjiArai 0:5b88d5760320 147 /** Compute CRC for the data input
kenjiArai 0:5b88d5760320 148 * Compute CRC performs the initialization, computation and collection of
kenjiArai 0:5b88d5760320 149 * final CRC.
kenjiArai 0:5b88d5760320 150 *
kenjiArai 0:5b88d5760320 151 * @param buffer Data bytes
kenjiArai 0:5b88d5760320 152 * @param size Size of data
kenjiArai 0:5b88d5760320 153 * @param crc CRC is the output value
kenjiArai 0:5b88d5760320 154 * @return 0 on success, negative error code on failure
kenjiArai 0:5b88d5760320 155 */
kenjiArai 0:5b88d5760320 156 int32_t compute(const void *buffer, crc_data_size_t size, uint32_t *crc)
kenjiArai 0:5b88d5760320 157 {
kenjiArai 0:5b88d5760320 158 MBED_ASSERT(crc != NULL);
kenjiArai 0:5b88d5760320 159 int32_t status = 0;
kenjiArai 0:5b88d5760320 160
kenjiArai 0:5b88d5760320 161 status = compute_partial_start(crc);
kenjiArai 0:5b88d5760320 162 if (0 != status) {
kenjiArai 0:5b88d5760320 163 unlock();
kenjiArai 0:5b88d5760320 164 return status;
kenjiArai 0:5b88d5760320 165 }
kenjiArai 0:5b88d5760320 166
kenjiArai 0:5b88d5760320 167 status = compute_partial(buffer, size, crc);
kenjiArai 0:5b88d5760320 168 if (0 != status) {
kenjiArai 0:5b88d5760320 169 unlock();
kenjiArai 0:5b88d5760320 170 return status;
kenjiArai 0:5b88d5760320 171 }
kenjiArai 0:5b88d5760320 172
kenjiArai 0:5b88d5760320 173 status = compute_partial_stop(crc);
kenjiArai 0:5b88d5760320 174 if (0 != status) {
kenjiArai 0:5b88d5760320 175 *crc = 0;
kenjiArai 0:5b88d5760320 176 }
kenjiArai 0:5b88d5760320 177
kenjiArai 0:5b88d5760320 178 return status;
kenjiArai 0:5b88d5760320 179
kenjiArai 0:5b88d5760320 180 }
kenjiArai 0:5b88d5760320 181
kenjiArai 0:5b88d5760320 182 /** Compute partial CRC for the data input.
kenjiArai 0:5b88d5760320 183 *
kenjiArai 0:5b88d5760320 184 * CRC data if not available fully, CRC can be computed in parts with available data.
kenjiArai 0:5b88d5760320 185 *
kenjiArai 0:5b88d5760320 186 * In case of hardware, intermediate values and states are saved by hardware. Mutex
kenjiArai 0:5b88d5760320 187 * locking is used to serialize access to hardware CRC.
kenjiArai 0:5b88d5760320 188 *
kenjiArai 0:5b88d5760320 189 * In case of software CRC, previous CRC output should be passed as argument to the
kenjiArai 0:5b88d5760320 190 * current compute_partial call. Please note the intermediate CRC value is maintained by
kenjiArai 0:5b88d5760320 191 * application and not the driver.
kenjiArai 0:5b88d5760320 192 *
kenjiArai 0:5b88d5760320 193 * @pre: Call `compute_partial_start` to start the partial CRC calculation.
kenjiArai 0:5b88d5760320 194 * @post: Call `compute_partial_stop` to get the final CRC value.
kenjiArai 0:5b88d5760320 195 *
kenjiArai 0:5b88d5760320 196 * @param buffer Data bytes
kenjiArai 0:5b88d5760320 197 * @param size Size of data
kenjiArai 0:5b88d5760320 198 * @param crc CRC value is intermediate CRC value filled by API.
kenjiArai 0:5b88d5760320 199 * @return 0 on success or a negative error code on failure
kenjiArai 0:5b88d5760320 200 * @note: CRC as output in compute_partial is not final CRC value, call `compute_partial_stop`
kenjiArai 0:5b88d5760320 201 * to get final correct CRC value.
kenjiArai 0:5b88d5760320 202 */
kenjiArai 0:5b88d5760320 203 int32_t compute_partial(const void *buffer, crc_data_size_t size, uint32_t *crc)
kenjiArai 0:5b88d5760320 204 {
kenjiArai 0:5b88d5760320 205 int32_t status = 0;
kenjiArai 0:5b88d5760320 206
kenjiArai 0:5b88d5760320 207 switch (_mode) {
kenjiArai 0:5b88d5760320 208 #if DEVICE_CRC
kenjiArai 0:5b88d5760320 209 case HARDWARE:
kenjiArai 0:5b88d5760320 210 hal_crc_compute_partial(static_cast<const uint8_t *>(buffer), size);
kenjiArai 0:5b88d5760320 211 *crc = 0;
kenjiArai 0:5b88d5760320 212 break;
kenjiArai 0:5b88d5760320 213 #endif
kenjiArai 0:5b88d5760320 214 case TABLE:
kenjiArai 0:5b88d5760320 215 status = table_compute_partial(buffer, size, crc);
kenjiArai 0:5b88d5760320 216 break;
kenjiArai 0:5b88d5760320 217 case BITWISE:
kenjiArai 0:5b88d5760320 218 status = bitwise_compute_partial(buffer, size, crc);
kenjiArai 0:5b88d5760320 219 break;
kenjiArai 0:5b88d5760320 220 default:
kenjiArai 0:5b88d5760320 221 status = -1;
kenjiArai 0:5b88d5760320 222 break;
kenjiArai 0:5b88d5760320 223 }
kenjiArai 0:5b88d5760320 224
kenjiArai 0:5b88d5760320 225 return status;
kenjiArai 0:5b88d5760320 226 }
kenjiArai 0:5b88d5760320 227
kenjiArai 0:5b88d5760320 228 /** Compute partial start, indicate start of partial computation.
kenjiArai 0:5b88d5760320 229 *
kenjiArai 0:5b88d5760320 230 * This API should be called before performing any partial computation
kenjiArai 0:5b88d5760320 231 * with compute_partial API.
kenjiArai 0:5b88d5760320 232 *
kenjiArai 0:5b88d5760320 233 * @param crc Initial CRC value set by the API
kenjiArai 0:5b88d5760320 234 * @return 0 on success or a negative in case of failure
kenjiArai 0:5b88d5760320 235 * @note: CRC is an out parameter and must be reused with compute_partial
kenjiArai 0:5b88d5760320 236 * and `compute_partial_stop` without any modifications in application.
kenjiArai 0:5b88d5760320 237 */
kenjiArai 0:5b88d5760320 238 int32_t compute_partial_start(uint32_t *crc)
kenjiArai 0:5b88d5760320 239 {
kenjiArai 0:5b88d5760320 240 MBED_ASSERT(crc != NULL);
kenjiArai 0:5b88d5760320 241
kenjiArai 0:5b88d5760320 242 #if DEVICE_CRC
kenjiArai 0:5b88d5760320 243 if (_mode == HARDWARE) {
kenjiArai 0:5b88d5760320 244 lock();
kenjiArai 0:5b88d5760320 245 crc_mbed_config_t config;
kenjiArai 0:5b88d5760320 246 config.polynomial = polynomial;
kenjiArai 0:5b88d5760320 247 config.width = width;
kenjiArai 0:5b88d5760320 248 config.initial_xor = _initial_value;
kenjiArai 0:5b88d5760320 249 config.final_xor = _final_xor;
kenjiArai 0:5b88d5760320 250 config.reflect_in = _reflect_data;
kenjiArai 0:5b88d5760320 251 config.reflect_out = _reflect_remainder;
kenjiArai 0:5b88d5760320 252
kenjiArai 0:5b88d5760320 253 hal_crc_compute_partial_start(&config);
kenjiArai 0:5b88d5760320 254 }
kenjiArai 0:5b88d5760320 255 #endif
kenjiArai 0:5b88d5760320 256
kenjiArai 0:5b88d5760320 257 *crc = _initial_value;
kenjiArai 0:5b88d5760320 258 return 0;
kenjiArai 0:5b88d5760320 259 }
kenjiArai 0:5b88d5760320 260
kenjiArai 0:5b88d5760320 261 /** Get the final CRC value of partial computation.
kenjiArai 0:5b88d5760320 262 *
kenjiArai 0:5b88d5760320 263 * CRC value available in partial computation is not correct CRC, as some
kenjiArai 0:5b88d5760320 264 * algorithms require remainder to be reflected and final value to be XORed
kenjiArai 0:5b88d5760320 265 * This API is used to perform final computation to get correct CRC value.
kenjiArai 0:5b88d5760320 266 *
kenjiArai 0:5b88d5760320 267 * @param crc CRC result
kenjiArai 0:5b88d5760320 268 * @return 0 on success or a negative in case of failure.
kenjiArai 0:5b88d5760320 269 */
kenjiArai 0:5b88d5760320 270 int32_t compute_partial_stop(uint32_t *crc)
kenjiArai 0:5b88d5760320 271 {
kenjiArai 0:5b88d5760320 272 MBED_ASSERT(crc != NULL);
kenjiArai 0:5b88d5760320 273
kenjiArai 0:5b88d5760320 274 #if DEVICE_CRC
kenjiArai 0:5b88d5760320 275 if (_mode == HARDWARE) {
kenjiArai 0:5b88d5760320 276 *crc = hal_crc_get_result();
kenjiArai 0:5b88d5760320 277 unlock();
kenjiArai 0:5b88d5760320 278 return 0;
kenjiArai 0:5b88d5760320 279 }
kenjiArai 0:5b88d5760320 280 #endif
kenjiArai 0:5b88d5760320 281 uint32_t p_crc = *crc;
kenjiArai 0:5b88d5760320 282 if ((width < 8) && (NULL == _crc_table)) {
kenjiArai 0:5b88d5760320 283 p_crc = (uint32_t)(p_crc << (8 - width));
kenjiArai 0:5b88d5760320 284 }
kenjiArai 0:5b88d5760320 285 // Optimized algorithm for 32BitANSI does not need additional reflect_remainder
kenjiArai 0:5b88d5760320 286 if ((TABLE == _mode) && (POLY_32BIT_REV_ANSI == polynomial)) {
kenjiArai 0:5b88d5760320 287 *crc = (p_crc ^ _final_xor) & get_crc_mask();
kenjiArai 0:5b88d5760320 288 } else {
kenjiArai 0:5b88d5760320 289 *crc = (reflect_remainder(p_crc) ^ _final_xor) & get_crc_mask();
kenjiArai 0:5b88d5760320 290 }
kenjiArai 0:5b88d5760320 291 unlock();
kenjiArai 0:5b88d5760320 292 return 0;
kenjiArai 0:5b88d5760320 293 }
kenjiArai 0:5b88d5760320 294
kenjiArai 0:5b88d5760320 295 /** Get the current CRC polynomial.
kenjiArai 0:5b88d5760320 296 *
kenjiArai 0:5b88d5760320 297 * @return Polynomial value
kenjiArai 0:5b88d5760320 298 */
kenjiArai 0:5b88d5760320 299 uint32_t get_polynomial(void) const
kenjiArai 0:5b88d5760320 300 {
kenjiArai 0:5b88d5760320 301 return polynomial;
kenjiArai 0:5b88d5760320 302 }
kenjiArai 0:5b88d5760320 303
kenjiArai 0:5b88d5760320 304 /** Get the current CRC width
kenjiArai 0:5b88d5760320 305 *
kenjiArai 0:5b88d5760320 306 * @return CRC width
kenjiArai 0:5b88d5760320 307 */
kenjiArai 0:5b88d5760320 308 uint8_t get_width(void) const
kenjiArai 0:5b88d5760320 309 {
kenjiArai 0:5b88d5760320 310 return width;
kenjiArai 0:5b88d5760320 311 }
kenjiArai 0:5b88d5760320 312
kenjiArai 0:5b88d5760320 313 #if !defined(DOXYGEN_ONLY)
kenjiArai 0:5b88d5760320 314 private:
kenjiArai 0:5b88d5760320 315 uint32_t _initial_value;
kenjiArai 0:5b88d5760320 316 uint32_t _final_xor;
kenjiArai 0:5b88d5760320 317 bool _reflect_data;
kenjiArai 0:5b88d5760320 318 bool _reflect_remainder;
kenjiArai 0:5b88d5760320 319 uint32_t *_crc_table;
kenjiArai 0:5b88d5760320 320 CrcMode _mode;
kenjiArai 0:5b88d5760320 321
kenjiArai 0:5b88d5760320 322 /** Acquire exclusive access to CRC hardware/software.
kenjiArai 0:5b88d5760320 323 */
kenjiArai 0:5b88d5760320 324 void lock()
kenjiArai 0:5b88d5760320 325 {
kenjiArai 0:5b88d5760320 326 #if DEVICE_CRC
kenjiArai 0:5b88d5760320 327 if (_mode == HARDWARE) {
kenjiArai 0:5b88d5760320 328 mbed_crc_mutex->lock();
kenjiArai 0:5b88d5760320 329 }
kenjiArai 0:5b88d5760320 330 #endif
kenjiArai 0:5b88d5760320 331 }
kenjiArai 0:5b88d5760320 332
kenjiArai 0:5b88d5760320 333 /** Release exclusive access to CRC hardware/software.
kenjiArai 0:5b88d5760320 334 */
kenjiArai 0:5b88d5760320 335 virtual void unlock()
kenjiArai 0:5b88d5760320 336 {
kenjiArai 0:5b88d5760320 337 #if DEVICE_CRC
kenjiArai 0:5b88d5760320 338 if (_mode == HARDWARE) {
kenjiArai 0:5b88d5760320 339 mbed_crc_mutex->unlock();
kenjiArai 0:5b88d5760320 340 }
kenjiArai 0:5b88d5760320 341 #endif
kenjiArai 0:5b88d5760320 342 }
kenjiArai 0:5b88d5760320 343
kenjiArai 0:5b88d5760320 344 /** Get the current CRC data size.
kenjiArai 0:5b88d5760320 345 *
kenjiArai 0:5b88d5760320 346 * @return CRC data size in bytes
kenjiArai 0:5b88d5760320 347 */
kenjiArai 0:5b88d5760320 348 uint8_t get_data_size(void) const
kenjiArai 0:5b88d5760320 349 {
kenjiArai 0:5b88d5760320 350 return (width <= 8 ? 1 : (width <= 16 ? 2 : 4));
kenjiArai 0:5b88d5760320 351 }
kenjiArai 0:5b88d5760320 352
kenjiArai 0:5b88d5760320 353 /** Get the top bit of current CRC.
kenjiArai 0:5b88d5760320 354 *
kenjiArai 0:5b88d5760320 355 * @return Top bit is set high for respective data width of current CRC
kenjiArai 0:5b88d5760320 356 * Top bit for CRC width less then 8 bits will be set as 8th bit.
kenjiArai 0:5b88d5760320 357 */
kenjiArai 0:5b88d5760320 358 uint32_t get_top_bit(void) const
kenjiArai 0:5b88d5760320 359 {
kenjiArai 0:5b88d5760320 360 return (width < 8 ? (1u << 7) : (uint32_t)(1ul << (width - 1)));
kenjiArai 0:5b88d5760320 361 }
kenjiArai 0:5b88d5760320 362
kenjiArai 0:5b88d5760320 363 /** Get the CRC data mask.
kenjiArai 0:5b88d5760320 364 *
kenjiArai 0:5b88d5760320 365 * @return CRC data mask is generated based on current CRC width
kenjiArai 0:5b88d5760320 366 */
kenjiArai 0:5b88d5760320 367 uint32_t get_crc_mask(void) const
kenjiArai 0:5b88d5760320 368 {
kenjiArai 0:5b88d5760320 369 return (width < 8 ? ((1u << 8) - 1) : (uint32_t)((uint64_t)(1ull << width) - 1));
kenjiArai 0:5b88d5760320 370 }
kenjiArai 0:5b88d5760320 371
kenjiArai 0:5b88d5760320 372 /** Final value of CRC is reflected.
kenjiArai 0:5b88d5760320 373 *
kenjiArai 0:5b88d5760320 374 * @param data final crc value, which should be reflected
kenjiArai 0:5b88d5760320 375 * @return Reflected CRC value
kenjiArai 0:5b88d5760320 376 */
kenjiArai 0:5b88d5760320 377 uint32_t reflect_remainder(uint32_t data) const
kenjiArai 0:5b88d5760320 378 {
kenjiArai 0:5b88d5760320 379 if (_reflect_remainder) {
kenjiArai 0:5b88d5760320 380 uint32_t reflection = 0x0;
kenjiArai 0:5b88d5760320 381 uint8_t const nBits = (width < 8 ? 8 : width);
kenjiArai 0:5b88d5760320 382
kenjiArai 0:5b88d5760320 383 for (uint8_t bit = 0; bit < nBits; ++bit) {
kenjiArai 0:5b88d5760320 384 if (data & 0x01) {
kenjiArai 0:5b88d5760320 385 reflection |= (1 << ((nBits - 1) - bit));
kenjiArai 0:5b88d5760320 386 }
kenjiArai 0:5b88d5760320 387 data = (data >> 1);
kenjiArai 0:5b88d5760320 388 }
kenjiArai 0:5b88d5760320 389 return (reflection);
kenjiArai 0:5b88d5760320 390 } else {
kenjiArai 0:5b88d5760320 391 return data;
kenjiArai 0:5b88d5760320 392 }
kenjiArai 0:5b88d5760320 393 }
kenjiArai 0:5b88d5760320 394
kenjiArai 0:5b88d5760320 395 /** Data bytes are reflected.
kenjiArai 0:5b88d5760320 396 *
kenjiArai 0:5b88d5760320 397 * @param data value to be reflected
kenjiArai 0:5b88d5760320 398 * @return Reflected data value
kenjiArai 0:5b88d5760320 399 */
kenjiArai 0:5b88d5760320 400 uint32_t reflect_bytes(uint32_t data) const
kenjiArai 0:5b88d5760320 401 {
kenjiArai 0:5b88d5760320 402 if (_reflect_data) {
kenjiArai 0:5b88d5760320 403 uint32_t reflection = 0x0;
kenjiArai 0:5b88d5760320 404
kenjiArai 0:5b88d5760320 405 for (uint8_t bit = 0; bit < 8; ++bit) {
kenjiArai 0:5b88d5760320 406 if (data & 0x01) {
kenjiArai 0:5b88d5760320 407 reflection |= (1 << (7 - bit));
kenjiArai 0:5b88d5760320 408 }
kenjiArai 0:5b88d5760320 409 data = (data >> 1);
kenjiArai 0:5b88d5760320 410 }
kenjiArai 0:5b88d5760320 411 return (reflection);
kenjiArai 0:5b88d5760320 412 } else {
kenjiArai 0:5b88d5760320 413 return data;
kenjiArai 0:5b88d5760320 414 }
kenjiArai 0:5b88d5760320 415 }
kenjiArai 0:5b88d5760320 416
kenjiArai 0:5b88d5760320 417 /** Bitwise CRC computation.
kenjiArai 0:5b88d5760320 418 *
kenjiArai 0:5b88d5760320 419 * @param buffer data buffer
kenjiArai 0:5b88d5760320 420 * @param size size of the data
kenjiArai 0:5b88d5760320 421 * @param crc CRC value is filled in, but the value is not the final
kenjiArai 0:5b88d5760320 422 * @return 0 on success or a negative error code on failure
kenjiArai 0:5b88d5760320 423 */
kenjiArai 0:5b88d5760320 424 int32_t bitwise_compute_partial(const void *buffer, crc_data_size_t size, uint32_t *crc) const
kenjiArai 0:5b88d5760320 425 {
kenjiArai 0:5b88d5760320 426 MBED_ASSERT(crc != NULL);
kenjiArai 0:5b88d5760320 427
kenjiArai 0:5b88d5760320 428 const uint8_t *data = static_cast<const uint8_t *>(buffer);
kenjiArai 0:5b88d5760320 429 uint32_t p_crc = *crc;
kenjiArai 0:5b88d5760320 430
kenjiArai 0:5b88d5760320 431 if (width < 8) {
kenjiArai 0:5b88d5760320 432 uint8_t data_byte;
kenjiArai 0:5b88d5760320 433 for (crc_data_size_t byte = 0; byte < size; byte++) {
kenjiArai 0:5b88d5760320 434 data_byte = reflect_bytes(data[byte]);
kenjiArai 0:5b88d5760320 435 for (uint8_t bit = 8; bit > 0; --bit) {
kenjiArai 0:5b88d5760320 436 p_crc <<= 1;
kenjiArai 0:5b88d5760320 437 if ((data_byte ^ p_crc) & get_top_bit()) {
kenjiArai 0:5b88d5760320 438 p_crc ^= polynomial;
kenjiArai 0:5b88d5760320 439 }
kenjiArai 0:5b88d5760320 440 data_byte <<= 1;
kenjiArai 0:5b88d5760320 441 }
kenjiArai 0:5b88d5760320 442 }
kenjiArai 0:5b88d5760320 443 } else {
kenjiArai 0:5b88d5760320 444 for (crc_data_size_t byte = 0; byte < size; byte++) {
kenjiArai 0:5b88d5760320 445 p_crc ^= (reflect_bytes(data[byte]) << (width - 8));
kenjiArai 0:5b88d5760320 446
kenjiArai 0:5b88d5760320 447 // Perform modulo-2 division, a bit at a time
kenjiArai 0:5b88d5760320 448 for (uint8_t bit = 8; bit > 0; --bit) {
kenjiArai 0:5b88d5760320 449 if (p_crc & get_top_bit()) {
kenjiArai 0:5b88d5760320 450 p_crc = (p_crc << 1) ^ polynomial;
kenjiArai 0:5b88d5760320 451 } else {
kenjiArai 0:5b88d5760320 452 p_crc = (p_crc << 1);
kenjiArai 0:5b88d5760320 453 }
kenjiArai 0:5b88d5760320 454 }
kenjiArai 0:5b88d5760320 455 }
kenjiArai 0:5b88d5760320 456 }
kenjiArai 0:5b88d5760320 457 *crc = p_crc & get_crc_mask();
kenjiArai 0:5b88d5760320 458 return 0;
kenjiArai 0:5b88d5760320 459 }
kenjiArai 0:5b88d5760320 460
kenjiArai 0:5b88d5760320 461 /** CRC computation using ROM tables.
kenjiArai 0:5b88d5760320 462 *
kenjiArai 0:5b88d5760320 463 * @param buffer data buffer
kenjiArai 0:5b88d5760320 464 * @param size size of the data
kenjiArai 0:5b88d5760320 465 * @param crc CRC value is filled in, but the value is not the final
kenjiArai 0:5b88d5760320 466 * @return 0 on success or a negative error code on failure
kenjiArai 0:5b88d5760320 467 */
kenjiArai 0:5b88d5760320 468 int32_t table_compute_partial(const void *buffer, crc_data_size_t size, uint32_t *crc) const
kenjiArai 0:5b88d5760320 469 {
kenjiArai 0:5b88d5760320 470 MBED_ASSERT(crc != NULL);
kenjiArai 0:5b88d5760320 471
kenjiArai 0:5b88d5760320 472 const uint8_t *data = static_cast<const uint8_t *>(buffer);
kenjiArai 0:5b88d5760320 473 uint32_t p_crc = *crc;
kenjiArai 0:5b88d5760320 474 uint8_t data_byte = 0;
kenjiArai 0:5b88d5760320 475
kenjiArai 0:5b88d5760320 476 if (width <= 8) {
kenjiArai 0:5b88d5760320 477 uint8_t *crc_table = (uint8_t *)_crc_table;
kenjiArai 0:5b88d5760320 478 for (crc_data_size_t byte = 0; byte < size; byte++) {
kenjiArai 0:5b88d5760320 479 data_byte = reflect_bytes(data[byte]) ^ p_crc;
kenjiArai 0:5b88d5760320 480 p_crc = crc_table[data_byte];
kenjiArai 0:5b88d5760320 481 }
kenjiArai 0:5b88d5760320 482 } else if (width <= 16) {
kenjiArai 0:5b88d5760320 483 uint16_t *crc_table = (uint16_t *)_crc_table;
kenjiArai 0:5b88d5760320 484 for (crc_data_size_t byte = 0; byte < size; byte++) {
kenjiArai 0:5b88d5760320 485 data_byte = reflect_bytes(data[byte]) ^ (p_crc >> (width - 8));
kenjiArai 0:5b88d5760320 486 p_crc = crc_table[data_byte] ^ (p_crc << 8);
kenjiArai 0:5b88d5760320 487 }
kenjiArai 0:5b88d5760320 488 } else {
kenjiArai 0:5b88d5760320 489 uint32_t *crc_table = (uint32_t *)_crc_table;
kenjiArai 0:5b88d5760320 490 if (POLY_32BIT_REV_ANSI == polynomial) {
kenjiArai 0:5b88d5760320 491 for (crc_data_size_t i = 0; i < size; i++) {
kenjiArai 0:5b88d5760320 492 p_crc = (p_crc >> 4) ^ crc_table[(p_crc ^ (data[i] >> 0)) & 0xf];
kenjiArai 0:5b88d5760320 493 p_crc = (p_crc >> 4) ^ crc_table[(p_crc ^ (data[i] >> 4)) & 0xf];
kenjiArai 0:5b88d5760320 494 }
kenjiArai 0:5b88d5760320 495 } else {
kenjiArai 0:5b88d5760320 496 for (crc_data_size_t byte = 0; byte < size; byte++) {
kenjiArai 0:5b88d5760320 497 data_byte = reflect_bytes(data[byte]) ^ (p_crc >> (width - 8));
kenjiArai 0:5b88d5760320 498 p_crc = crc_table[data_byte] ^ (p_crc << 8);
kenjiArai 0:5b88d5760320 499 }
kenjiArai 0:5b88d5760320 500 }
kenjiArai 0:5b88d5760320 501 }
kenjiArai 0:5b88d5760320 502 *crc = p_crc & get_crc_mask();
kenjiArai 0:5b88d5760320 503 return 0;
kenjiArai 0:5b88d5760320 504 }
kenjiArai 0:5b88d5760320 505
kenjiArai 0:5b88d5760320 506 /** Constructor init called from all specialized cases of constructor.
kenjiArai 0:5b88d5760320 507 * Note: All constructor common code should be in this function.
kenjiArai 0:5b88d5760320 508 */
kenjiArai 0:5b88d5760320 509 void mbed_crc_ctor(void)
kenjiArai 0:5b88d5760320 510 {
kenjiArai 0:5b88d5760320 511 MBED_STATIC_ASSERT(width <= 32, "Max 32-bit CRC supported");
kenjiArai 0:5b88d5760320 512
kenjiArai 0:5b88d5760320 513 #if DEVICE_CRC
kenjiArai 0:5b88d5760320 514 if (POLY_32BIT_REV_ANSI == polynomial) {
kenjiArai 0:5b88d5760320 515 _crc_table = (uint32_t *)Table_CRC_32bit_Rev_ANSI;
kenjiArai 0:5b88d5760320 516 _mode = TABLE;
kenjiArai 0:5b88d5760320 517 return;
kenjiArai 0:5b88d5760320 518 }
kenjiArai 0:5b88d5760320 519 crc_mbed_config_t config;
kenjiArai 0:5b88d5760320 520 config.polynomial = polynomial;
kenjiArai 0:5b88d5760320 521 config.width = width;
kenjiArai 0:5b88d5760320 522 config.initial_xor = _initial_value;
kenjiArai 0:5b88d5760320 523 config.final_xor = _final_xor;
kenjiArai 0:5b88d5760320 524 config.reflect_in = _reflect_data;
kenjiArai 0:5b88d5760320 525 config.reflect_out = _reflect_remainder;
kenjiArai 0:5b88d5760320 526
kenjiArai 0:5b88d5760320 527 if (hal_crc_is_supported(&config)) {
kenjiArai 0:5b88d5760320 528 _mode = HARDWARE;
kenjiArai 0:5b88d5760320 529 return;
kenjiArai 0:5b88d5760320 530 }
kenjiArai 0:5b88d5760320 531 #endif
kenjiArai 0:5b88d5760320 532
kenjiArai 0:5b88d5760320 533 switch (polynomial) {
kenjiArai 0:5b88d5760320 534 case POLY_32BIT_ANSI:
kenjiArai 0:5b88d5760320 535 _crc_table = (uint32_t *)Table_CRC_32bit_ANSI;
kenjiArai 0:5b88d5760320 536 break;
kenjiArai 0:5b88d5760320 537 case POLY_32BIT_REV_ANSI:
kenjiArai 0:5b88d5760320 538 _crc_table = (uint32_t *)Table_CRC_32bit_Rev_ANSI;
kenjiArai 0:5b88d5760320 539 break;
kenjiArai 0:5b88d5760320 540 case POLY_8BIT_CCITT:
kenjiArai 0:5b88d5760320 541 _crc_table = (uint32_t *)Table_CRC_8bit_CCITT;
kenjiArai 0:5b88d5760320 542 break;
kenjiArai 0:5b88d5760320 543 case POLY_7BIT_SD:
kenjiArai 0:5b88d5760320 544 _crc_table = (uint32_t *)Table_CRC_7Bit_SD;
kenjiArai 0:5b88d5760320 545 break;
kenjiArai 0:5b88d5760320 546 case POLY_16BIT_CCITT:
kenjiArai 0:5b88d5760320 547 _crc_table = (uint32_t *)Table_CRC_16bit_CCITT;
kenjiArai 0:5b88d5760320 548 break;
kenjiArai 0:5b88d5760320 549 case POLY_16BIT_IBM:
kenjiArai 0:5b88d5760320 550 _crc_table = (uint32_t *)Table_CRC_16bit_IBM;
kenjiArai 0:5b88d5760320 551 break;
kenjiArai 0:5b88d5760320 552 default:
kenjiArai 0:5b88d5760320 553 _crc_table = NULL;
kenjiArai 0:5b88d5760320 554 break;
kenjiArai 0:5b88d5760320 555 }
kenjiArai 0:5b88d5760320 556 _mode = (_crc_table != NULL) ? TABLE : BITWISE;
kenjiArai 0:5b88d5760320 557 }
kenjiArai 0:5b88d5760320 558 #endif
kenjiArai 0:5b88d5760320 559 };
kenjiArai 0:5b88d5760320 560
kenjiArai 0:5b88d5760320 561 #if defined ( __CC_ARM )
kenjiArai 0:5b88d5760320 562 #elif defined ( __GNUC__ )
kenjiArai 0:5b88d5760320 563 #pragma GCC diagnostic pop
kenjiArai 0:5b88d5760320 564 #elif defined (__ICCARM__)
kenjiArai 0:5b88d5760320 565 #endif
kenjiArai 0:5b88d5760320 566
kenjiArai 0:5b88d5760320 567 /** @}*/
kenjiArai 0:5b88d5760320 568 } // namespace mbed
kenjiArai 0:5b88d5760320 569
kenjiArai 0:5b88d5760320 570 #endif