Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

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