RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

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