Backup 1

Committer:
borlanic
Date:
Tue Apr 24 11:45:18 2018 +0000
Revision:
0:02dd72d1d465
BaBoRo_test2 - backup 1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
borlanic 0:02dd72d1d465 1 /* mbed Microcontroller Library
borlanic 0:02dd72d1d465 2 * Copyright (c) 2018 ARM Limited
borlanic 0:02dd72d1d465 3 *
borlanic 0:02dd72d1d465 4 * Licensed under the Apache License, Version 2.0 (the "License");
borlanic 0:02dd72d1d465 5 * you may not use this file except in compliance with the License.
borlanic 0:02dd72d1d465 6 * You may obtain a copy of the License at
borlanic 0:02dd72d1d465 7 *
borlanic 0:02dd72d1d465 8 * http://www.apache.org/licenses/LICENSE-2.0
borlanic 0:02dd72d1d465 9 *
borlanic 0:02dd72d1d465 10 * Unless required by applicable law or agreed to in writing, software
borlanic 0:02dd72d1d465 11 * distributed under the License is distributed on an "AS IS" BASIS,
borlanic 0:02dd72d1d465 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
borlanic 0:02dd72d1d465 13 * See the License for the specific language governing permissions and
borlanic 0:02dd72d1d465 14 * limitations under the License.
borlanic 0:02dd72d1d465 15 */
borlanic 0:02dd72d1d465 16 #ifndef MBED_CRC_API_H
borlanic 0:02dd72d1d465 17 #define MBED_CRC_API_H
borlanic 0:02dd72d1d465 18
borlanic 0:02dd72d1d465 19 #include <stdint.h>
borlanic 0:02dd72d1d465 20 #include "drivers/TableCRC.h"
borlanic 0:02dd72d1d465 21 #include "platform/mbed_assert.h"
borlanic 0:02dd72d1d465 22
borlanic 0:02dd72d1d465 23 /* This is invalid warning from the compiler for below section of code
borlanic 0:02dd72d1d465 24 if ((width < 8) && (NULL == _crc_table)) {
borlanic 0:02dd72d1d465 25 p_crc = (uint32_t)(p_crc << (8 - width));
borlanic 0:02dd72d1d465 26 }
borlanic 0:02dd72d1d465 27 Compiler warns of the shift operation with width as it is width=(std::uint8_t),
borlanic 0:02dd72d1d465 28 but we check for ( width < 8) before performing shift, so it should not be an issue.
borlanic 0:02dd72d1d465 29 */
borlanic 0:02dd72d1d465 30 #if defined ( __CC_ARM )
borlanic 0:02dd72d1d465 31 #pragma diag_suppress 62 // Shift count is negative
borlanic 0:02dd72d1d465 32 #elif defined ( __GNUC__ )
borlanic 0:02dd72d1d465 33 #pragma GCC diagnostic push
borlanic 0:02dd72d1d465 34 #pragma GCC diagnostic ignored "-Wshift-count-negative"
borlanic 0:02dd72d1d465 35 #endif
borlanic 0:02dd72d1d465 36
borlanic 0:02dd72d1d465 37 namespace mbed {
borlanic 0:02dd72d1d465 38 /** \addtogroup drivers */
borlanic 0:02dd72d1d465 39 /** @{*/
borlanic 0:02dd72d1d465 40
borlanic 0:02dd72d1d465 41 /** CRC Polynomial value
borlanic 0:02dd72d1d465 42 *
borlanic 0:02dd72d1d465 43 * Different polynomial values supported
borlanic 0:02dd72d1d465 44 */
borlanic 0:02dd72d1d465 45 typedef enum crc_polynomial {
borlanic 0:02dd72d1d465 46 POLY_OTHER = 0,
borlanic 0:02dd72d1d465 47 POLY_8BIT_CCITT = 0x07, // x8+x2+x+1
borlanic 0:02dd72d1d465 48 POLY_7BIT_SD = 0x9, // x7+x3+1;
borlanic 0:02dd72d1d465 49 POLY_16BIT_CCITT = 0x1021, // x16+x12+x5+1
borlanic 0:02dd72d1d465 50 POLY_16BIT_IBM = 0x8005, // x16+x15+x2+1
borlanic 0:02dd72d1d465 51 POLY_32BIT_ANSI = 0x04C11DB7, // x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
borlanic 0:02dd72d1d465 52 } crc_polynomial_t;
borlanic 0:02dd72d1d465 53
borlanic 0:02dd72d1d465 54 /** CRC object provides CRC generation through hardware/software
borlanic 0:02dd72d1d465 55 *
borlanic 0:02dd72d1d465 56 * ROM polynomial tables for supported polynomials (:: crc_polynomial_t) will be used for
borlanic 0:02dd72d1d465 57 * software CRC computation, if ROM tables are not available then CRC is computed runtime
borlanic 0:02dd72d1d465 58 * bit by bit for all data input.
borlanic 0:02dd72d1d465 59 *
borlanic 0:02dd72d1d465 60 * @tparam polynomial CRC polynomial value in hex
borlanic 0:02dd72d1d465 61 * @tparam width CRC polynomial width
borlanic 0:02dd72d1d465 62 *
borlanic 0:02dd72d1d465 63 * Example: Compute CRC data
borlanic 0:02dd72d1d465 64 * @code
borlanic 0:02dd72d1d465 65 *
borlanic 0:02dd72d1d465 66 * #include "mbed.h"
borlanic 0:02dd72d1d465 67 *
borlanic 0:02dd72d1d465 68 * int main() {
borlanic 0:02dd72d1d465 69 * MbedCRC<POLY_32BIT_ANSI, 32> ct;
borlanic 0:02dd72d1d465 70 *
borlanic 0:02dd72d1d465 71 * char test[] = "123456789";
borlanic 0:02dd72d1d465 72 * uint32_t crc = 0;
borlanic 0:02dd72d1d465 73 *
borlanic 0:02dd72d1d465 74 * printf("\nPolynomial = 0x%lx Width = %d \n", ct.get_polynomial(), ct.get_width());
borlanic 0:02dd72d1d465 75 *
borlanic 0:02dd72d1d465 76 * ct.compute((void *)test, strlen((const char*)test), &crc);
borlanic 0:02dd72d1d465 77 *
borlanic 0:02dd72d1d465 78 * printf("The CRC of data \"123456789\" is : 0x%lx\n", crc);
borlanic 0:02dd72d1d465 79 * return 0;
borlanic 0:02dd72d1d465 80 * }
borlanic 0:02dd72d1d465 81 * @endcode
borlanic 0:02dd72d1d465 82 * Example: Compute CRC with data available in parts
borlanic 0:02dd72d1d465 83 * @code
borlanic 0:02dd72d1d465 84 *
borlanic 0:02dd72d1d465 85 * #include "mbed.h"
borlanic 0:02dd72d1d465 86 * int main() {
borlanic 0:02dd72d1d465 87 * MbedCRC<POLY_32BIT_ANSI, 32> ct;
borlanic 0:02dd72d1d465 88 *
borlanic 0:02dd72d1d465 89 * char test[] = "123456789";
borlanic 0:02dd72d1d465 90 * uint32_t crc = 0;
borlanic 0:02dd72d1d465 91 *
borlanic 0:02dd72d1d465 92 * printf("\nPolynomial = 0x%lx Width = %d \n", ct.get_polynomial(), ct.get_width());
borlanic 0:02dd72d1d465 93 *
borlanic 0:02dd72d1d465 94 * ct.compute_partial_start(&crc);
borlanic 0:02dd72d1d465 95 * ct.compute_partial((void *)&test, 4, &crc);
borlanic 0:02dd72d1d465 96 * ct.compute_partial((void *)&test[4], 5, &crc);
borlanic 0:02dd72d1d465 97 * ct.compute_partial_stop(&crc);
borlanic 0:02dd72d1d465 98 *
borlanic 0:02dd72d1d465 99 * printf("The CRC of data \"123456789\" is : 0x%lx\n", crc);
borlanic 0:02dd72d1d465 100 * return 0;
borlanic 0:02dd72d1d465 101 * }
borlanic 0:02dd72d1d465 102 * @endcode
borlanic 0:02dd72d1d465 103 * @ingroup drivers
borlanic 0:02dd72d1d465 104 */
borlanic 0:02dd72d1d465 105
borlanic 0:02dd72d1d465 106 template <uint32_t polynomial=POLY_32BIT_ANSI, uint8_t width=32>
borlanic 0:02dd72d1d465 107 class MbedCRC
borlanic 0:02dd72d1d465 108 {
borlanic 0:02dd72d1d465 109 public:
borlanic 0:02dd72d1d465 110 typedef uint64_t crc_data_size_t;
borlanic 0:02dd72d1d465 111
borlanic 0:02dd72d1d465 112 /** Lifetime of CRC object
borlanic 0:02dd72d1d465 113 *
borlanic 0:02dd72d1d465 114 * @param initial_xor Inital value/seed to Xor
borlanic 0:02dd72d1d465 115 * @param final_xor Final Xor value
borlanic 0:02dd72d1d465 116 * @param reflect_data
borlanic 0:02dd72d1d465 117 * @param reflect_remainder
borlanic 0:02dd72d1d465 118 * @note Default constructor without any arguments is valid only for supported CRC polynomials. :: crc_polynomial_t
borlanic 0:02dd72d1d465 119 * MbedCRC <POLY_7BIT_SD, 7> ct; --- Valid POLY_7BIT_SD
borlanic 0:02dd72d1d465 120 * MbedCRC <0x1021, 16> ct; --- Valid POLY_16BIT_CCITT
borlanic 0:02dd72d1d465 121 * MbedCRC <POLY_16BIT_CCITT, 32> ct; --- Invalid, compilation error
borlanic 0:02dd72d1d465 122 * MbedCRC <POLY_16BIT_CCITT, 32> ct (i,f,rd,rr) Consturctor can be used for not supported polynomials
borlanic 0:02dd72d1d465 123 * MbedCRC<POLY_16BIT_CCITT, 16> sd(0, 0, false, false); Constructor can also be used for supported
borlanic 0:02dd72d1d465 124 * polynomials with different intial/final/reflect values
borlanic 0:02dd72d1d465 125 *
borlanic 0:02dd72d1d465 126 */
borlanic 0:02dd72d1d465 127 MbedCRC(uint32_t initial_xor, uint32_t final_xor, bool reflect_data, bool reflect_remainder) :
borlanic 0:02dd72d1d465 128 _initial_value(initial_xor), _final_xor(final_xor), _reflect_data(reflect_data),
borlanic 0:02dd72d1d465 129 _reflect_remainder(reflect_remainder), _crc_table(NULL)
borlanic 0:02dd72d1d465 130 {
borlanic 0:02dd72d1d465 131 mbed_crc_ctor();
borlanic 0:02dd72d1d465 132 }
borlanic 0:02dd72d1d465 133 MbedCRC();
borlanic 0:02dd72d1d465 134 virtual ~MbedCRC()
borlanic 0:02dd72d1d465 135 {
borlanic 0:02dd72d1d465 136 // Do nothing
borlanic 0:02dd72d1d465 137 }
borlanic 0:02dd72d1d465 138
borlanic 0:02dd72d1d465 139 /** Compute CRC for the data input
borlanic 0:02dd72d1d465 140 *
borlanic 0:02dd72d1d465 141 * @param buffer Data bytes
borlanic 0:02dd72d1d465 142 * @param size Size of data
borlanic 0:02dd72d1d465 143 * @param crc CRC is the output value
borlanic 0:02dd72d1d465 144 * @return 0 on success, negative error code on failure
borlanic 0:02dd72d1d465 145 */
borlanic 0:02dd72d1d465 146 int32_t compute(void *buffer, crc_data_size_t size, uint32_t *crc)
borlanic 0:02dd72d1d465 147 {
borlanic 0:02dd72d1d465 148 MBED_ASSERT(crc != NULL);
borlanic 0:02dd72d1d465 149 int32_t status;
borlanic 0:02dd72d1d465 150 if (0 != (status = compute_partial_start(crc))) {
borlanic 0:02dd72d1d465 151 *crc = 0;
borlanic 0:02dd72d1d465 152 return status;
borlanic 0:02dd72d1d465 153 }
borlanic 0:02dd72d1d465 154 if (0 != (status = compute_partial(buffer, size, crc))) {
borlanic 0:02dd72d1d465 155 *crc = 0;
borlanic 0:02dd72d1d465 156 return status;
borlanic 0:02dd72d1d465 157 }
borlanic 0:02dd72d1d465 158 if (0 != (status = compute_partial_stop(crc))) {
borlanic 0:02dd72d1d465 159 *crc = 0;
borlanic 0:02dd72d1d465 160 return status;
borlanic 0:02dd72d1d465 161 }
borlanic 0:02dd72d1d465 162 return 0;
borlanic 0:02dd72d1d465 163 }
borlanic 0:02dd72d1d465 164
borlanic 0:02dd72d1d465 165 /** Compute partial CRC for the data input.
borlanic 0:02dd72d1d465 166 *
borlanic 0:02dd72d1d465 167 * CRC data if not available fully, CRC can be computed in parts with available data.
borlanic 0:02dd72d1d465 168 * Previous CRC output should be passed as argument to the current compute_partial call.
borlanic 0:02dd72d1d465 169 * @pre: Call \ref compute_partial_start to start the partial CRC calculation.
borlanic 0:02dd72d1d465 170 * @post: Call \ref compute_partial_stop to get the final CRC value.
borlanic 0:02dd72d1d465 171 *
borlanic 0:02dd72d1d465 172 * @param buffer Data bytes
borlanic 0:02dd72d1d465 173 * @param size Size of data
borlanic 0:02dd72d1d465 174 * @param crc CRC value is intermediate CRC value filled by API.
borlanic 0:02dd72d1d465 175 * @return 0 on success or a negative error code on failure
borlanic 0:02dd72d1d465 176 * @note: CRC as output in compute_partial is not final CRC value, call @ref compute_partial_stop
borlanic 0:02dd72d1d465 177 * to get final correct CRC value.
borlanic 0:02dd72d1d465 178 */
borlanic 0:02dd72d1d465 179 int32_t compute_partial(void *buffer, crc_data_size_t size, uint32_t *crc)
borlanic 0:02dd72d1d465 180 {
borlanic 0:02dd72d1d465 181 if (NULL == _crc_table) {
borlanic 0:02dd72d1d465 182 // Compute bitwise CRC
borlanic 0:02dd72d1d465 183 return bitwise_compute_partial(buffer, size, crc);
borlanic 0:02dd72d1d465 184 } else {
borlanic 0:02dd72d1d465 185 // Table CRC
borlanic 0:02dd72d1d465 186 return table_compute_partial(buffer, size, crc);
borlanic 0:02dd72d1d465 187 }
borlanic 0:02dd72d1d465 188 }
borlanic 0:02dd72d1d465 189
borlanic 0:02dd72d1d465 190 /** Compute partial start, indicate start of partial computation
borlanic 0:02dd72d1d465 191 *
borlanic 0:02dd72d1d465 192 * This API should be called before performing any partial computation
borlanic 0:02dd72d1d465 193 * with compute_partial API.
borlanic 0:02dd72d1d465 194 *
borlanic 0:02dd72d1d465 195 * @param crc Initial CRC value set by the API
borlanic 0:02dd72d1d465 196 * @return 0 on success or a negative in case of failure
borlanic 0:02dd72d1d465 197 * @note: CRC is an out parameter and must be reused with compute_partial
borlanic 0:02dd72d1d465 198 * and compute_partial_stop without any modifications in application.
borlanic 0:02dd72d1d465 199 */
borlanic 0:02dd72d1d465 200 int32_t compute_partial_start(uint32_t *crc)
borlanic 0:02dd72d1d465 201 {
borlanic 0:02dd72d1d465 202 MBED_ASSERT(crc != NULL);
borlanic 0:02dd72d1d465 203 *crc = _initial_value;
borlanic 0:02dd72d1d465 204 return 0;
borlanic 0:02dd72d1d465 205 }
borlanic 0:02dd72d1d465 206
borlanic 0:02dd72d1d465 207 /** Get the final CRC value of partial computation.
borlanic 0:02dd72d1d465 208 *
borlanic 0:02dd72d1d465 209 * CRC value available in partial computation is not correct CRC, as some
borlanic 0:02dd72d1d465 210 * algorithms require remainder to be reflected and final value to be XORed
borlanic 0:02dd72d1d465 211 * This API is used to perform final computation to get correct CRC value.
borlanic 0:02dd72d1d465 212 *
borlanic 0:02dd72d1d465 213 * @param crc CRC result
borlanic 0:02dd72d1d465 214 */
borlanic 0:02dd72d1d465 215 int32_t compute_partial_stop(uint32_t *crc)
borlanic 0:02dd72d1d465 216 {
borlanic 0:02dd72d1d465 217 MBED_ASSERT(crc != NULL);
borlanic 0:02dd72d1d465 218 uint32_t p_crc = *crc;
borlanic 0:02dd72d1d465 219 if ((width < 8) && (NULL == _crc_table)) {
borlanic 0:02dd72d1d465 220 p_crc = (uint32_t)(p_crc << (8 - width));
borlanic 0:02dd72d1d465 221 }
borlanic 0:02dd72d1d465 222 *crc = (reflect_remainder(p_crc) ^ _final_xor) & get_crc_mask();
borlanic 0:02dd72d1d465 223 return 0;
borlanic 0:02dd72d1d465 224 }
borlanic 0:02dd72d1d465 225
borlanic 0:02dd72d1d465 226 /** Get the current CRC polynomial
borlanic 0:02dd72d1d465 227 *
borlanic 0:02dd72d1d465 228 * @return Polynomial value
borlanic 0:02dd72d1d465 229 */
borlanic 0:02dd72d1d465 230 uint32_t get_polynomial(void) const
borlanic 0:02dd72d1d465 231 {
borlanic 0:02dd72d1d465 232 return polynomial;
borlanic 0:02dd72d1d465 233 }
borlanic 0:02dd72d1d465 234
borlanic 0:02dd72d1d465 235 /** Get the current CRC width
borlanic 0:02dd72d1d465 236 *
borlanic 0:02dd72d1d465 237 * @return CRC width
borlanic 0:02dd72d1d465 238 */
borlanic 0:02dd72d1d465 239 uint8_t get_width(void) const
borlanic 0:02dd72d1d465 240 {
borlanic 0:02dd72d1d465 241 return width;
borlanic 0:02dd72d1d465 242 }
borlanic 0:02dd72d1d465 243
borlanic 0:02dd72d1d465 244 private:
borlanic 0:02dd72d1d465 245 uint32_t _initial_value;
borlanic 0:02dd72d1d465 246 uint32_t _final_xor;
borlanic 0:02dd72d1d465 247 bool _reflect_data;
borlanic 0:02dd72d1d465 248 bool _reflect_remainder;
borlanic 0:02dd72d1d465 249 uint32_t *_crc_table;
borlanic 0:02dd72d1d465 250
borlanic 0:02dd72d1d465 251 /** Get the current CRC data size
borlanic 0:02dd72d1d465 252 *
borlanic 0:02dd72d1d465 253 * @return CRC data size in bytes
borlanic 0:02dd72d1d465 254 */
borlanic 0:02dd72d1d465 255 uint8_t get_data_size(void) const
borlanic 0:02dd72d1d465 256 {
borlanic 0:02dd72d1d465 257 return (width <= 8 ? 1 : (width <= 16 ? 2 : 4));
borlanic 0:02dd72d1d465 258 }
borlanic 0:02dd72d1d465 259
borlanic 0:02dd72d1d465 260 /** Get the top bit of current CRC
borlanic 0:02dd72d1d465 261 *
borlanic 0:02dd72d1d465 262 * @return Top bit is set high for respective data width of current CRC
borlanic 0:02dd72d1d465 263 * Top bit for CRC width less then 8 bits will be set as 8th bit.
borlanic 0:02dd72d1d465 264 */
borlanic 0:02dd72d1d465 265 uint32_t get_top_bit(void) const
borlanic 0:02dd72d1d465 266 {
borlanic 0:02dd72d1d465 267 return (width < 8 ? (1u << 7) : (uint32_t)(1ul << (width - 1)));
borlanic 0:02dd72d1d465 268 }
borlanic 0:02dd72d1d465 269
borlanic 0:02dd72d1d465 270 /** Get the CRC data mask
borlanic 0:02dd72d1d465 271 *
borlanic 0:02dd72d1d465 272 * @return CRC data mask is generated based on current CRC width
borlanic 0:02dd72d1d465 273 */
borlanic 0:02dd72d1d465 274 uint32_t get_crc_mask(void) const
borlanic 0:02dd72d1d465 275 {
borlanic 0:02dd72d1d465 276 return (width < 8 ? ((1u << 8) - 1) : (uint32_t)((uint64_t)(1ull << width) - 1));
borlanic 0:02dd72d1d465 277 }
borlanic 0:02dd72d1d465 278
borlanic 0:02dd72d1d465 279 /** Final value of CRC is reflected
borlanic 0:02dd72d1d465 280 *
borlanic 0:02dd72d1d465 281 * @param data final crc value, which should be reflected
borlanic 0:02dd72d1d465 282 * @return Reflected CRC value
borlanic 0:02dd72d1d465 283 */
borlanic 0:02dd72d1d465 284 uint32_t reflect_remainder(uint32_t data) const
borlanic 0:02dd72d1d465 285 {
borlanic 0:02dd72d1d465 286 if (_reflect_remainder) {
borlanic 0:02dd72d1d465 287 uint32_t reflection = 0x0;
borlanic 0:02dd72d1d465 288 uint8_t const nBits = (width < 8 ? 8 : width);
borlanic 0:02dd72d1d465 289
borlanic 0:02dd72d1d465 290 for (uint8_t bit = 0; bit < nBits; ++bit) {
borlanic 0:02dd72d1d465 291 if (data & 0x01) {
borlanic 0:02dd72d1d465 292 reflection |= (1 << ((nBits - 1) - bit));
borlanic 0:02dd72d1d465 293 }
borlanic 0:02dd72d1d465 294 data = (data >> 1);
borlanic 0:02dd72d1d465 295 }
borlanic 0:02dd72d1d465 296 return (reflection);
borlanic 0:02dd72d1d465 297 } else {
borlanic 0:02dd72d1d465 298 return data;
borlanic 0:02dd72d1d465 299 }
borlanic 0:02dd72d1d465 300 }
borlanic 0:02dd72d1d465 301
borlanic 0:02dd72d1d465 302 /** Data bytes are reflected
borlanic 0:02dd72d1d465 303 *
borlanic 0:02dd72d1d465 304 * @param data value to be reflected
borlanic 0:02dd72d1d465 305 * @return Reflected data value
borlanic 0:02dd72d1d465 306 */
borlanic 0:02dd72d1d465 307 uint32_t reflect_bytes(uint32_t data) const
borlanic 0:02dd72d1d465 308 {
borlanic 0:02dd72d1d465 309 if(_reflect_data) {
borlanic 0:02dd72d1d465 310 uint32_t reflection = 0x0;
borlanic 0:02dd72d1d465 311
borlanic 0:02dd72d1d465 312 for (uint8_t bit = 0; bit < 8; ++bit) {
borlanic 0:02dd72d1d465 313 if (data & 0x01) {
borlanic 0:02dd72d1d465 314 reflection |= (1 << (7 - bit));
borlanic 0:02dd72d1d465 315 }
borlanic 0:02dd72d1d465 316 data = (data >> 1);
borlanic 0:02dd72d1d465 317 }
borlanic 0:02dd72d1d465 318 return (reflection);
borlanic 0:02dd72d1d465 319 } else {
borlanic 0:02dd72d1d465 320 return data;
borlanic 0:02dd72d1d465 321 }
borlanic 0:02dd72d1d465 322 }
borlanic 0:02dd72d1d465 323
borlanic 0:02dd72d1d465 324 /** Bitwise CRC computation
borlanic 0:02dd72d1d465 325 *
borlanic 0:02dd72d1d465 326 * @param buffer data buffer
borlanic 0:02dd72d1d465 327 * @param size size of the data
borlanic 0:02dd72d1d465 328 * @param crc CRC value is filled in, but the value is not the final
borlanic 0:02dd72d1d465 329 * @return 0 on success or a negative error code on failure
borlanic 0:02dd72d1d465 330 */
borlanic 0:02dd72d1d465 331 int32_t bitwise_compute_partial(const void *buffer, crc_data_size_t size, uint32_t *crc) const
borlanic 0:02dd72d1d465 332 {
borlanic 0:02dd72d1d465 333 MBED_ASSERT(crc != NULL);
borlanic 0:02dd72d1d465 334 MBED_ASSERT(buffer != NULL);
borlanic 0:02dd72d1d465 335
borlanic 0:02dd72d1d465 336 const uint8_t *data = static_cast<const uint8_t *>(buffer);
borlanic 0:02dd72d1d465 337 uint32_t p_crc = *crc;
borlanic 0:02dd72d1d465 338
borlanic 0:02dd72d1d465 339 if (width < 8) {
borlanic 0:02dd72d1d465 340 uint8_t data_byte;
borlanic 0:02dd72d1d465 341 for (crc_data_size_t byte = 0; byte < size; byte++) {
borlanic 0:02dd72d1d465 342 data_byte = reflect_bytes(data[byte]);
borlanic 0:02dd72d1d465 343 for (uint8_t bit = 8; bit > 0; --bit) {
borlanic 0:02dd72d1d465 344 p_crc <<= 1;
borlanic 0:02dd72d1d465 345 if (( data_byte ^ p_crc) & get_top_bit()) {
borlanic 0:02dd72d1d465 346 p_crc ^= polynomial;
borlanic 0:02dd72d1d465 347 }
borlanic 0:02dd72d1d465 348 data_byte <<= 1;
borlanic 0:02dd72d1d465 349 }
borlanic 0:02dd72d1d465 350 }
borlanic 0:02dd72d1d465 351 } else {
borlanic 0:02dd72d1d465 352 for (crc_data_size_t byte = 0; byte < size; byte++) {
borlanic 0:02dd72d1d465 353 p_crc ^= (reflect_bytes(data[byte]) << (width - 8));
borlanic 0:02dd72d1d465 354
borlanic 0:02dd72d1d465 355 // Perform modulo-2 division, a bit at a time
borlanic 0:02dd72d1d465 356 for (uint8_t bit = 8; bit > 0; --bit) {
borlanic 0:02dd72d1d465 357 if (p_crc & get_top_bit()) {
borlanic 0:02dd72d1d465 358 p_crc = (p_crc << 1) ^ polynomial;
borlanic 0:02dd72d1d465 359 } else {
borlanic 0:02dd72d1d465 360 p_crc = (p_crc << 1);
borlanic 0:02dd72d1d465 361 }
borlanic 0:02dd72d1d465 362 }
borlanic 0:02dd72d1d465 363 }
borlanic 0:02dd72d1d465 364 }
borlanic 0:02dd72d1d465 365 *crc = p_crc & get_crc_mask();
borlanic 0:02dd72d1d465 366 return 0;
borlanic 0:02dd72d1d465 367 }
borlanic 0:02dd72d1d465 368
borlanic 0:02dd72d1d465 369 /** CRC computation using ROM tables
borlanic 0:02dd72d1d465 370 *
borlanic 0:02dd72d1d465 371 * @param buffer data buffer
borlanic 0:02dd72d1d465 372 * @param size size of the data
borlanic 0:02dd72d1d465 373 * @param crc CRC value is filled in, but the value is not the final
borlanic 0:02dd72d1d465 374 * @return 0 on success or a negative error code on failure
borlanic 0:02dd72d1d465 375 */
borlanic 0:02dd72d1d465 376 int32_t table_compute_partial(const void *buffer, crc_data_size_t size, uint32_t *crc) const
borlanic 0:02dd72d1d465 377 {
borlanic 0:02dd72d1d465 378 MBED_ASSERT(crc != NULL);
borlanic 0:02dd72d1d465 379 MBED_ASSERT(buffer != NULL);
borlanic 0:02dd72d1d465 380
borlanic 0:02dd72d1d465 381 const uint8_t *data = static_cast<const uint8_t *>(buffer);
borlanic 0:02dd72d1d465 382 uint32_t p_crc = *crc;
borlanic 0:02dd72d1d465 383 uint8_t data_byte = 0;
borlanic 0:02dd72d1d465 384
borlanic 0:02dd72d1d465 385 if (width <= 8) {
borlanic 0:02dd72d1d465 386 uint8_t *crc_table = (uint8_t *)_crc_table;
borlanic 0:02dd72d1d465 387 for (crc_data_size_t byte = 0; byte < size; byte++) {
borlanic 0:02dd72d1d465 388 data_byte = reflect_bytes(data[byte]) ^ p_crc;
borlanic 0:02dd72d1d465 389 p_crc = crc_table[data_byte];
borlanic 0:02dd72d1d465 390 }
borlanic 0:02dd72d1d465 391 } else if (width <= 16) {
borlanic 0:02dd72d1d465 392 uint16_t *crc_table = (uint16_t *)_crc_table;
borlanic 0:02dd72d1d465 393 for (crc_data_size_t byte = 0; byte < size; byte++) {
borlanic 0:02dd72d1d465 394 data_byte = reflect_bytes(data[byte]) ^ (p_crc >> (width - 8));
borlanic 0:02dd72d1d465 395 p_crc = crc_table[data_byte] ^ (p_crc << 8);
borlanic 0:02dd72d1d465 396 }
borlanic 0:02dd72d1d465 397 } else {
borlanic 0:02dd72d1d465 398 uint32_t *crc_table = (uint32_t *)_crc_table;
borlanic 0:02dd72d1d465 399 for (crc_data_size_t byte = 0; byte < size; byte++) {
borlanic 0:02dd72d1d465 400 data_byte = reflect_bytes(data[byte]) ^ (p_crc >> (width - 8));
borlanic 0:02dd72d1d465 401 p_crc = crc_table[data_byte] ^ (p_crc << 8);
borlanic 0:02dd72d1d465 402 }
borlanic 0:02dd72d1d465 403 }
borlanic 0:02dd72d1d465 404 *crc = p_crc & get_crc_mask();
borlanic 0:02dd72d1d465 405 return 0;
borlanic 0:02dd72d1d465 406 }
borlanic 0:02dd72d1d465 407
borlanic 0:02dd72d1d465 408 /** Constructor init called from all specialized cases of constructor
borlanic 0:02dd72d1d465 409 * Note: All construtor common code should be in this function.
borlanic 0:02dd72d1d465 410 */
borlanic 0:02dd72d1d465 411 void mbed_crc_ctor(void) const
borlanic 0:02dd72d1d465 412 {
borlanic 0:02dd72d1d465 413 MBED_STATIC_ASSERT(width <= 32, "Max 32-bit CRC supported");
borlanic 0:02dd72d1d465 414 }
borlanic 0:02dd72d1d465 415 };
borlanic 0:02dd72d1d465 416
borlanic 0:02dd72d1d465 417 #if defined ( __CC_ARM )
borlanic 0:02dd72d1d465 418 #elif defined ( __GNUC__ )
borlanic 0:02dd72d1d465 419 #pragma GCC diagnostic pop
borlanic 0:02dd72d1d465 420 #endif
borlanic 0:02dd72d1d465 421
borlanic 0:02dd72d1d465 422 /** @}*/
borlanic 0:02dd72d1d465 423 } // namespace mbed
borlanic 0:02dd72d1d465 424
borlanic 0:02dd72d1d465 425 #endif