PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

566 lines
17KB

  1. /* FastCRC library code is placed under the MIT license
  2. * Copyright (c) 2014-2019 Frank Bösing
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. */
  24. //
  25. // HW-calculations are 32BIT
  26. //
  27. // Thanks to:
  28. // - Catalogue of parametrised CRC algorithms, CRC RevEng
  29. // http://reveng.sourceforge.net/crc-catalogue/
  30. //
  31. // - Danjel McGougan (CRC-Table-Generator)
  32. //
  33. #include "Arduino.h"
  34. #if defined(KINETISK)
  35. #include "mk20dx128.h"
  36. #include "FastCRC.h"
  37. // ===============================================
  38. typedef struct {
  39. union {
  40. uint32_t CRC; //CRC Data register
  41. struct {
  42. uint16_t CRC16;
  43. uint16_t CRC16_1;
  44. };
  45. struct {
  46. uint8_t CRC8;
  47. uint8_t CRC8_1;
  48. uint8_t CRC8_2;
  49. uint8_t CRC8_3;
  50. };
  51. };
  52. uint32_t GPOLY; //CRC Polynomial register
  53. uint32_t CTRL; //CRC Control register
  54. } CRC_T;
  55. static volatile CRC_T * const rCRC = (CRC_T *)0x40032000;
  56. #define CRC_CTRL_WAS 25 // Write CRC Data Register As Seed(1) / Data(0)
  57. #define CRC_CTRL_TCRC 24 // Width of CRC protocol (0=16 BIT, 1=32 BIT)
  58. #define CRC_CTRL_TOTR1 29 // TOTR[1]
  59. // ================= 7-BIT CRC ===================
  60. /** Constructor
  61. * Enables CRC-clock
  62. */
  63. FastCRC7::FastCRC7(){
  64. SIM_SCGC6 |= SIM_SCGC6_CRC;
  65. }
  66. /** CRC 7
  67. * MultiMediaCard interface
  68. * @param data Pointer to Data
  69. * @param datalen Length of Data
  70. * @return CRC value
  71. */
  72. uint8_t FastCRC7::crc7(const uint8_t *data, const uint16_t datalen)
  73. {
  74. // poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75
  75. return (generic(0x09, 0, CRC_FLAG_NOREFLECT, data, datalen));
  76. }
  77. /** Update
  78. * Call for subsequent calculations with previous seed
  79. * @param data Pointer to Data
  80. * @param datalen Length of Data
  81. * @return CRC value
  82. */
  83. uint8_t FastCRC7::update(const uint8_t *data, const uint16_t datalen)
  84. {
  85. const uint8_t *src = data;
  86. const uint8_t *target = src + datalen;
  87. while (((uintptr_t)src & 0x03) != 0 && (src < target)) {
  88. rCRC->CRC8_3 = *src++; //Write 8 BIT
  89. }
  90. while (src <= target-4) {
  91. rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
  92. src += 4;
  93. }
  94. while (src < target) {
  95. rCRC->CRC8_3 = *src++; //Write 8 Bit
  96. }
  97. //TODO: Check handling of CRC_CTRL_TOTR1 for other CRC7s
  98. /*
  99. if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
  100. return rCRC->CRC8 >> 1;
  101. else
  102. */
  103. return rCRC->CRC8_3 >> 1;
  104. }
  105. /** generic function for all 7-Bit CRCs
  106. * @param polynom Polynom
  107. * @param seed Seed
  108. * @param flags Flags
  109. * @param data Pointer to Data
  110. * @param datalen Length of Data
  111. * @return CRC value
  112. */
  113. uint8_t FastCRC7::generic(const uint8_t polynom, const uint8_t seed, const uint32_t flags, const uint8_t *data,const uint16_t datalen)
  114. {
  115. rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, Prepare to write seed(25)
  116. rCRC->GPOLY = ((uint32_t)polynom)<<(24 + 1); // Set polynom
  117. rCRC->CRC = ((uint32_t)seed<<(24 + 1)); // Write seed
  118. rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
  119. return update(data, datalen);
  120. }
  121. uint8_t FastCRC7::crc7_upd(const uint8_t *data, uint16_t datalen){return update(data, datalen);}
  122. // ================= 8-BIT CRC ===================
  123. /** Constructor
  124. * Enables CRC-clock
  125. */
  126. FastCRC8::FastCRC8(){
  127. SIM_SCGC6 |= SIM_SCGC6_CRC;
  128. }
  129. /** SMBUS CRC
  130. * aka CRC-8
  131. * @param data Pointer to Data
  132. * @param datalen Length of Data
  133. * @return CRC value
  134. */
  135. uint8_t FastCRC8::smbus(const uint8_t *data, const uint16_t datalen)
  136. {
  137. // poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4
  138. return generic(0x07, 0, CRC_FLAG_NOREFLECT, data, datalen);
  139. }
  140. /** MAXIM 8-Bit CRC
  141. * equivalent to _crc_ibutton_update() in crc16.h from avr_libc
  142. * @param data Pointer to Data
  143. * @param datalen Length of Data
  144. * @return CRC value
  145. */
  146. uint8_t FastCRC8::maxim(const uint8_t *data, const uint16_t datalen)
  147. {
  148. // poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1
  149. return generic(0x31, 0, CRC_FLAG_REFLECT, data, datalen);
  150. }
  151. /** Update
  152. * Call for subsequent calculations with previous seed
  153. * @param data Pointer to Data
  154. * @param datalen Length of Data
  155. * @return CRC value
  156. */
  157. uint8_t FastCRC8::update(const uint8_t *data, const uint16_t datalen)
  158. {
  159. const uint8_t *src = data;
  160. const uint8_t *target = src + datalen;
  161. while (((uintptr_t)src & 0x03) != 0 && (src < target)) {
  162. rCRC->CRC8_3 = *src++; //Write 8 BIT
  163. }
  164. while (src <= target-4) {
  165. rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
  166. src += 4;
  167. }
  168. while (src < target) {
  169. rCRC->CRC8_3 = *src++; //Write 8 Bit
  170. }
  171. if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
  172. return rCRC->CRC8;
  173. else
  174. return rCRC->CRC8_3;
  175. }
  176. /** generic function for all 8-Bit CRCs
  177. * @param polynom Polynom
  178. * @param seed Seed
  179. * @param flags Flags
  180. * @param data Pointer to Data
  181. * @param datalen Length of Data
  182. * @return CRC value
  183. */
  184. uint8_t FastCRC8::generic(const uint8_t polynom, const uint8_t seed, const uint32_t flags, const uint8_t *data,const uint16_t datalen)
  185. {
  186. rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, Prepare to write seed(25)
  187. rCRC->GPOLY = ((uint32_t)polynom)<<24; // Set polynom
  188. rCRC->CRC = ((uint32_t)seed<<24); // Write seed
  189. rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
  190. return update(data, datalen);
  191. }
  192. uint8_t FastCRC8::smbus_upd(const uint8_t *data, uint16_t datalen){return update(data, datalen);}
  193. uint8_t FastCRC8::maxim_upd(const uint8_t *data, uint16_t datalen){return update(data, datalen);}
  194. // ================= 14-BIT CRC ===================
  195. /** Constructor
  196. * Enables CRC-clock
  197. */
  198. FastCRC14::FastCRC14(){
  199. SIM_SCGC6 |= SIM_SCGC6_CRC;
  200. }
  201. /** CRC-14/DARC
  202. * @param data Pointer to Data
  203. * @param datalen Length of Data
  204. * @return CRC value
  205. */
  206. uint16_t FastCRC14::darc(const uint8_t *data,const uint16_t datalen)
  207. {
  208. // poly=0x0805 init=0x0000 refin=true refout=true xorout=0x0000 check=0x082d residue=0x0000
  209. return generic(0x0805, 0x0000, CRC_FLAG_REFLECT, data, datalen);
  210. }
  211. /** CRC-14/GSM
  212. * @param data Pointer to Data
  213. * @param datalen Length of Data
  214. * @return CRC value
  215. */
  216. uint16_t FastCRC14::gsm(const uint8_t *data,const uint16_t datalen)
  217. {
  218. // poly=0x202d init=0x0000 refin=false refout=false xorout=0x3fff check=0x30ae residue=0x031e
  219. return generic(0x202d, 0x0000, CRC_FLAG_NOREFLECT | CRC_FLAG_XOR, data, datalen);
  220. }
  221. /** CRC-14/ELORAN
  222. * @param data Pointer to Data
  223. * @param datalen Length of Data
  224. * @return CRC value
  225. */
  226. uint16_t FastCRC14::eloran(const uint8_t *data,const uint16_t datalen)
  227. {
  228. // poly=0x60b1 init=0x0000 refin=false refout=false xorout=0x0000 check=0x38d1
  229. return generic(0x60b1, 0x0, CRC_FLAG_NOREFLECT , data, datalen);
  230. }
  231. /** CRC-14/ft4 : TODO
  232. * @param data Pointer to Data
  233. * @param datalen Length of Data
  234. * @return CRC value
  235. */
  236. /*
  237. uint16_t FastCRC14::ft4(const uint8_t *data,const uint16_t datalen)
  238. {
  239. return generic(, , , data, datalen);
  240. }
  241. */
  242. /** Update
  243. * Call for subsequent calculations with previous seed
  244. * @param data Pointer to Data
  245. * @param datalen Length of Data
  246. * @return CRC value
  247. */
  248. uint16_t FastCRC14::update(const uint8_t *data, const uint16_t datalen)
  249. {
  250. const uint8_t *src = data;
  251. const uint8_t *target = src + datalen;
  252. while (((uintptr_t)src & 0x03) !=0 && (src < target)) {
  253. rCRC->CRC8_3 = *src++; //Write 8 BIT
  254. }
  255. while (src <= target-4) {
  256. rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
  257. src += 4;
  258. }
  259. while (src < target) {
  260. rCRC->CRC8_3 = *src++; //Write 8 Bit
  261. }
  262. if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
  263. return rCRC->CRC16;
  264. else
  265. return rCRC->CRC >> (32 - 14);
  266. }
  267. /** generic function for all 14-Bit CRCs
  268. * @param polynom Polynom
  269. * @param seed Seed
  270. * @param flags Flags
  271. * @param data Pointer to Data
  272. * @param datalen Length of Data
  273. * @return CRC value
  274. */
  275. uint16_t FastCRC14::generic(const uint16_t polynom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen)
  276. {
  277. rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS);// 32-Bit Mode, prepare to write seed(25)
  278. rCRC->GPOLY = ((uint32_t)polynom) << (32 - 14); // set polynom
  279. rCRC->CRC = ((uint32_t)seed << (32 - 14) ); // this is the seed
  280. rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
  281. return update(data, datalen);
  282. }
  283. uint16_t FastCRC14::darc_upd(const uint8_t *data, uint16_t len) {return update(data, len);}
  284. uint16_t FastCRC14::gsm_upd(const uint8_t *data, uint16_t len) {return update(data, len);}
  285. uint16_t FastCRC14::eloran_upd(const uint8_t *data, uint16_t len) {return update(data, len);}
  286. //uint16_t FastCRC14::ft4(const uint8_t *data, uint16_t len) {return update(data, len);}
  287. // ================= 16-BIT CRC ===================
  288. /** Constructor
  289. * Enables CRC-clock
  290. */
  291. FastCRC16::FastCRC16(){
  292. SIM_SCGC6 |= SIM_SCGC6_CRC;
  293. }
  294. /** CCITT
  295. * Alias "false CCITT"
  296. * @param data Pointer to Data
  297. * @param datalen Length of Data
  298. * @return CRC value
  299. */
  300. uint16_t FastCRC16::ccitt(const uint8_t *data,const uint16_t datalen)
  301. {
  302. // poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1
  303. return generic(0x1021, 0XFFFF, CRC_FLAG_NOREFLECT, data, datalen);
  304. }
  305. /** MCRF4XX
  306. * equivalent to _crc_ccitt_update() in crc16.h from avr_libc
  307. * @param data Pointer to Data
  308. * @param datalen Length of Data
  309. * @return CRC value
  310. */
  311. uint16_t FastCRC16::mcrf4xx(const uint8_t *data,const uint16_t datalen)
  312. {
  313. // poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91
  314. return generic(0x1021, 0XFFFF, CRC_FLAG_REFLECT , data, datalen);
  315. }
  316. /** MODBUS
  317. * equivalent to _crc_16_update() in crc16.h from avr_libc
  318. * @param data Pointer to Data
  319. * @param datalen Length of Data
  320. * @return CRC value
  321. */
  322. uint16_t FastCRC16::modbus(const uint8_t *data, const uint16_t datalen)
  323. {
  324. // poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37
  325. return generic(0x8005, 0XFFFF, CRC_FLAG_REFLECT, data, datalen);
  326. }
  327. /** KERMIT
  328. * Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
  329. * @param data Pointer to Data
  330. * @param datalen Length of Data
  331. * @return CRC value
  332. */
  333. uint16_t FastCRC16::kermit(const uint8_t *data, const uint16_t datalen)
  334. {
  335. // poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
  336. // sometimes byteswapped presentation of result
  337. return generic(0x1021, 0x00, CRC_FLAG_REFLECT, data, datalen);
  338. }
  339. /** XMODEM
  340. * Alias ZMODEM, CRC-16/ACORN
  341. * @param data Pointer to Data
  342. * @param datalen Length of Data
  343. * @return CRC value
  344. */
  345. uint16_t FastCRC16::xmodem(const uint8_t *data, const uint16_t datalen)
  346. {
  347. //width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3
  348. return generic(0x1021, 0, CRC_FLAG_NOREFLECT, data, datalen);
  349. }
  350. /** X25
  351. * Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
  352. * @param data Pointer to Data
  353. * @param datalen Length of Data
  354. * @return CRC value
  355. */
  356. uint16_t FastCRC16::x25(const uint8_t *data, const uint16_t datalen)
  357. {
  358. // poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e
  359. return generic(0x1021, 0XFFFF, CRC_FLAG_REFLECT | CRC_FLAG_XOR, data, datalen);
  360. }
  361. /** Update
  362. * Call for subsequent calculations with previous seed
  363. * @param data Pointer to Data
  364. * @param datalen Length of Data
  365. * @return CRC value
  366. */
  367. uint16_t FastCRC16::update(const uint8_t *data, const uint16_t datalen)
  368. {
  369. const uint8_t *src = data;
  370. const uint8_t *target = src + datalen;
  371. while (((uintptr_t)src & 0x03) !=0 && (src < target)) {
  372. rCRC->CRC8_3 = *src++; //Write 8 BIT
  373. }
  374. while (src <= target-4) {
  375. rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
  376. src += 4;
  377. }
  378. while (src < target) {
  379. rCRC->CRC8_3 = *src++; //Write 8 Bit
  380. }
  381. if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
  382. return rCRC->CRC16;
  383. else
  384. return rCRC->CRC16_1;
  385. }
  386. /** generic function for all 16-Bit CRCs
  387. * @param polynom Polynom
  388. * @param seed Seed
  389. * @param flags Flags
  390. * @param data Pointer to Data
  391. * @param datalen Length of Data
  392. * @return CRC value
  393. */
  394. uint16_t FastCRC16::generic(const uint16_t polynom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen)
  395. {
  396. rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS);// 32-Bit Mode, prepare to write seed(25)
  397. rCRC->GPOLY = ((uint32_t)polynom)<<16; // set polynom
  398. rCRC->CRC = ((uint32_t)seed<<16); // this is the seed
  399. rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
  400. return update(data, datalen);
  401. }
  402. uint16_t FastCRC16::ccitt_upd(const uint8_t *data, uint16_t len) {return update(data, len);}
  403. uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, uint16_t len){return update(data, len);}
  404. uint16_t FastCRC16::kermit_upd(const uint8_t *data, uint16_t len) {return update(data, len);}
  405. uint16_t FastCRC16::modbus_upd(const uint8_t *data, uint16_t len) {return update(data, len);}
  406. uint16_t FastCRC16::xmodem_upd(const uint8_t *data, uint16_t len) {return update(data, len);}
  407. uint16_t FastCRC16::x25_upd(const uint8_t *data, uint16_t len) {return update(data, len);}
  408. // ================= 32-BIT CRC ===================
  409. /** Constructor
  410. * Enables CRC-clock
  411. */
  412. FastCRC32::FastCRC32(){
  413. SIM_SCGC6 |= SIM_SCGC6_CRC;
  414. }
  415. /** CRC32
  416. * Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
  417. * @param data Pointer to Data
  418. * @param datalen Length of Data
  419. * @return CRC value
  420. */
  421. uint32_t FastCRC32::crc32(const uint8_t *data, const uint16_t datalen)
  422. {
  423. // poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926
  424. return generic(0x04C11DB7L, 0XFFFFFFFFL, CRC_FLAG_REFLECT | CRC_FLAG_XOR, data, datalen);
  425. }
  426. /** CKSUM
  427. * Alias CRC-32/POSIX
  428. * @param data Pointer to Data
  429. * @param datalen Length of Data
  430. * @return CRC value
  431. */
  432. uint32_t FastCRC32::cksum(const uint8_t *data, const uint16_t datalen)
  433. {
  434. // width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680
  435. return generic(0x04C11DB7L, 0, CRC_FLAG_NOREFLECT | CRC_FLAG_XOR, data, datalen);
  436. }
  437. /** Update
  438. * Call for subsequent calculations with previous seed
  439. * @param data Pointer to Data
  440. * @param datalen Length of Data
  441. * @return CRC value
  442. */
  443. //#pragma GCC diagnostic ignored "-Wpointer-arith"
  444. uint32_t FastCRC32::update(const uint8_t *data, const uint16_t datalen)
  445. {
  446. const uint8_t *src = data;
  447. const uint8_t *target = src + datalen;
  448. while (((uintptr_t)src & 0x03) != 0 && (src < target)) {
  449. rCRC->CRC8_3 = *src++; //Write 8 BIT
  450. }
  451. while (src <= target-4) {
  452. rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
  453. src += 4;
  454. }
  455. while (src < target) {
  456. rCRC->CRC8_3 = *src++; //Write 8 Bit
  457. }
  458. return rCRC->CRC;
  459. }
  460. /** generic function for all 32-Bit CRCs
  461. * @param polynom Polynom
  462. * @param seed Seed
  463. * @param flags Flags
  464. * @param data Pointer to Data
  465. * @param datalen Length of Data
  466. * @return CRC value
  467. */
  468. uint32_t FastCRC32::generic(const uint32_t polynom, const uint32_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen)
  469. {
  470. rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, prepare to write seed(25)
  471. rCRC->GPOLY = polynom; // Set polynom
  472. rCRC->CRC = seed; // This is the seed
  473. rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
  474. return update(data, datalen);
  475. }
  476. uint32_t FastCRC32::crc32_upd(const uint8_t *data, uint16_t len){return update(data, len);}
  477. uint32_t FastCRC32::cksum_upd(const uint8_t *data, uint16_t len){return update(data, len);}
  478. #endif // #if defined(KINETISK)