aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios-contrib/os/various/crcsw.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios-contrib/os/various/crcsw.c')
-rw-r--r--lib/chibios-contrib/os/various/crcsw.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/lib/chibios-contrib/os/various/crcsw.c b/lib/chibios-contrib/os/various/crcsw.c
new file mode 100644
index 000000000..02a64f3ef
--- /dev/null
+++ b/lib/chibios-contrib/os/various/crcsw.c
@@ -0,0 +1,338 @@
1/*
2 ChibiOS - Copyright (C) 2015 Michael D. Spradling
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/**
18 * @file crcsw.c
19 * @brief CRC software driver.
20 @note SW implementation was based from:
21 * @note http://www.barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code
22 *
23 * @addtogroup CRC
24 * @{
25 */
26
27#include "hal.h"
28
29#if HAL_USE_CRC || defined(__DOXYGEN__)
30
31#if CRCSW_USE_CRC1 || defined(__DOXYGEN__)
32
33/*===========================================================================*/
34/* Driver local definitions. */
35/*===========================================================================*/
36
37/**
38 * @brief CRC default configuration.
39 */
40
41#if CRCSW_CRC32_TABLE == TRUE || defined(__DOXYGEN__)
42static const uint32_t crc32_table[256] = {
43 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
44 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
45 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
46 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
47 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
48 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
49 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
50 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
51 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
52 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
53 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
54 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
55 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
56 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
57 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
58 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
59 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
60 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
61 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
62 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
63 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
64 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
65 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
66 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
67 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
68 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
69 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
70 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
71 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
72 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
73 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
74 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
75 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
76 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
77 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
78 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
79 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
80 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
81 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
82 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
83 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
84 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
85 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
86 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
87 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
88 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
89 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
90 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
91 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
92 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
93 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
94 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
95 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
96 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
97 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
98 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
99 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
100 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
101 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
102 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
103 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
104 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
105 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
106 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
107};
108#endif
109
110#if CRCSW_CRC16_TABLE || defined(__DOXYGEN__)
111static const uint32_t crc16_table[256] = {
112 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
113 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
114 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
115 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
116 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
117 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
118 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
119 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
120 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
121 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
122 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
123 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
124 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
125 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
126 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
127 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
128 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
129 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
130 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
131 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
132 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
133 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
134 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
135 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
136 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
137 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
138 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
139 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
140 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
141 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
142 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
143 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
144};
145#endif
146
147/*===========================================================================*/
148/* Driver exported variables. */
149/*===========================================================================*/
150
151/** @brief CRC1 driver identifier.*/
152#if CRCSW_USE_CRC1 || defined(__DOXYGEN__)
153CRCDriver CRCD1;
154#endif
155
156#if CRCSW_CRC32_TABLE || defined(__DOXYGEN__)
157const CRCConfig crcsw_crc32_config = {
158 .poly_size = 32,
159 .poly = 0x04C11DB7,
160 .initial_val = 0xFFFFFFFF,
161 .final_val = 0xFFFFFFFF,
162 .reflect_data = 1,
163 .reflect_remainder = 1,
164 .table = crc32_table
165};
166#endif
167
168#if CRCSW_CRC16_TABLE || defined(__DOXYGEN__)
169const CRCConfig crcsw_crc16_config = {
170 .poly_size = 16,
171 .poly = 0x8005,
172 .initial_val = 0x0,
173 .final_val = 0x0,
174 .reflect_data = 1,
175 .reflect_remainder = 1,
176 .table = crc16_table
177};
178#endif
179
180/*===========================================================================*/
181/* Driver local variables and types. */
182/*===========================================================================*/
183
184/*===========================================================================*/
185/* Driver local functions. */
186/*===========================================================================*/
187
188#if (CRCSW_PROGRAMMABLE == TRUE)
189static uint32_t reflect(uint32_t data, uint8_t nBits) {
190 uint32_t reflection = 0x00000000;
191 uint8_t bit;
192
193 /* Reflect the data about the center bit. */
194 for (bit = 0; bit < nBits; ++bit) {
195 /* If the LSB bit is set, set the reflection of it. */
196 if (data & 0x01) {
197 reflection |= (1 << ((nBits - 1) - bit));
198 }
199
200 data = (data >> 1);
201 }
202
203 return reflection;
204}
205#endif
206
207/*===========================================================================*/
208/* Driver interrupt handlers. */
209/*===========================================================================*/
210
211/*===========================================================================*/
212/* Driver exported functions. */
213/*===========================================================================*/
214
215/**
216 * @brief Low level CRC software initialization.
217 *
218 * @notapi
219 */
220void crc_lld_init(void) {
221 crcObjectInit(&CRCD1);
222 CRCD1.crc = CRCD1.config->initial_val;
223}
224
225/**
226 * @brief Configures and activates the CRC peripheral.
227 *
228 * @param[in] crcp pointer to the @p CRCDriver object
229 *
230 * @notapi
231 */
232void crc_lld_start(CRCDriver *crcp) {
233 osalDbgAssert(crcp->config != NULL, "config must not be NULL");
234
235#if CRCSW_PROGRAMMABLE == FALSE
236#if CRCSW_CRC32_TABLE == TRUE && CRCSW_CRC16_TABLE == TRUE
237 osalDbgAssert((crcp->config == CRCSW_CRC32_TABLE_CONFIG) ||
238 (crcp->config == CRCSW_CRC16_TABLE_CONFIG), "config must be CRCSW_CRC32_TABLE_CONFIG or CRCSW_CRC16_TABLE_CONFIG");
239#elif CRCSW_CRC32_TABLE == TRUE && CRCSW_CRC16_TABLE == FALSE
240 osalDbgAssert(crcp->config == CRCSW_CRC32_TABLE_CONFIG,
241 "config must be CRCSW_CRC32_TABLE_CONFIG");
242#else
243 osalDbgAssert(crcp->config == CRCSW_CRC16_TABLE_CONFIG,
244 "config must be CRCSW_CRC16_TABLE_CONFIG");
245#endif
246#endif
247 crc_lld_reset(crcp);
248}
249
250
251/**
252 * @brief Deactivates the CRC peripheral.
253 *
254 * @param[in] crcp pointer to the @p CRCDriver object
255 *
256 * @notapi
257 */
258void crc_lld_stop(CRCDriver *crcp) {
259 (void)crcp;
260}
261
262/**
263 * @brief Resets current CRC calculation.
264 *
265 * @param[in] crcp pointer to the @p CRCDriver object
266 *
267 * @notapi
268 */
269void crc_lld_reset(CRCDriver *crcp) {
270 crcp->crc = crcp->config->initial_val;
271}
272
273/**
274 * @brief Returns calculated CRC from last reset
275 *
276 * @param[in] crcp pointer to the @p CRCDriver object
277 * @param[in] n size of buf in bytes
278 * @param[in] buf @p buffer location
279 *
280 * @notapi
281 */
282uint32_t crc_lld_calc(CRCDriver *crcp, size_t n, const void *buf) {
283 uint32_t i;
284 uint32_t crc;
285#if (CRCSW_CRC32_TABLE == TRUE) || (CRCSW_CRC16_TABLE == TRUE)
286 if (crcp->config->table != NULL) {
287 for (i = 0; i < n; i++) {
288 uint8_t data = *((uint8_t*)buf + i);
289 uint8_t idx = (crcp->crc ^ data);
290 crcp->crc = (crcp->config->table[idx] ^ (crcp->crc >> 8));
291 }
292 crc = crcp->crc;
293 }
294#endif
295
296#if (CRCSW_PROGRAMMABLE == TRUE)
297 // Mask off bits to poly size
298 uint32_t mask = 1 << (crcp->config->poly_size - 1);
299 mask |= (mask - 1);
300
301 crc = crcp->crc;
302 if (crcp->config->table == NULL) {
303 for (i = 0; i < n; i++) {
304 uint8_t data = *((uint8_t*)buf + i);
305 uint8_t bit;
306
307 if (crcp->config->reflect_data) {
308 data = reflect(data, 8);
309 }
310
311 /* Bring the next byte into the remainder. */
312 crc ^= (data << (crcp->config->poly_size - 8));
313
314 /* Perform modulo-2 division, a bit at a time. */
315 for (bit = 8; bit > 0; --bit) {
316 /* Try to divide the current data bit. */
317 if (crc & (1 << (crcp->config->poly_size - 1))) {
318 crc = (crc << 1) ^ crcp->config->poly;
319 } else {
320 crc <<= 1;
321 }
322 }
323 }
324
325 crcp->crc = crc;
326
327 if (crcp->config->reflect_remainder) {
328 crc = reflect(crc, crcp->config->poly_size);
329 }
330 }
331#endif
332
333 return (crc ^ crcp->config->final_val) & mask;
334}
335
336#endif /* CRCSW_USE_CRC1 */
337
338#endif /* HAL_USE_CRC */