|
13 | 13 |
|
14 | 14 | #include <tinyhal.h>
|
15 | 15 |
|
| 16 | +#define CRC_BASE (AHB1PERIPH_BASE + 0x3000U) |
| 17 | +#define CRC ((CRC_TypeDef *) CRC_BASE) |
| 18 | + |
| 19 | +typedef struct |
| 20 | +{ |
| 21 | + CRC_TypeDef *Instance; /*!< Register base address */ |
| 22 | +}CRC_HandleTypeDef; |
| 23 | + |
| 24 | + |
16 | 25 | /*
|
17 | 26 | Interface to Cortex-M CRC calculation unit that implements the equivalent to the software implementation at Support\CRC project.
|
18 | 27 | CRC-32 (Ethernet) polynomial: 0x4C11DB7.
|
19 | 28 | buffer: pointer to the region block to be CRCed
|
20 | 29 | size: lenght of buffer to compute CRC
|
21 | 30 | crc: previous CRC value to start CRC computing
|
22 | 31 | */
|
| 32 | + |
| 33 | +/* NOTE: is good for F1, L1, F2 and F4 units series, other have diferent configurations and polynomial coefficients */ |
| 34 | + |
| 35 | +static UINT32 ReverseCRC32(UINT32 targetCRC) |
| 36 | +{ |
| 37 | + // nibble lookup table for _REVERSE_ CRC32 polynomial 0x4C11DB7 |
| 38 | + static const UINT32 crc32NibbleTable[16] = |
| 39 | + { |
| 40 | + 0x00000000, 0xB2B4BCB6, 0x61A864DB, 0xD31CD86D, 0xC350C9B6, 0x71E47500, 0xA2F8AD6D, 0x104C11DB, |
| 41 | + 0x82608EDB, 0x30D4326D, 0xE3C8EA00, 0x517C56B6, 0x4130476D, 0xF384FBDB, 0x209823B6, 0x922C9F00 |
| 42 | + }; |
| 43 | + UINT8 counter = 8; |
| 44 | + |
| 45 | + while(counter--) |
| 46 | + { |
| 47 | + targetCRC = (targetCRC >> 4) ^ crc32NibbleTable[targetCRC & 0x0F]; |
| 48 | + } |
| 49 | + |
| 50 | + return targetCRC; |
| 51 | +} |
| 52 | + |
| 53 | +UINT32 FastCRC32(UINT32 initial_crc, uint8_t data) |
| 54 | +{ |
| 55 | + // nibble lookup table for CRC32 polynomial 0x4C11DB7 |
| 56 | + static const UINT32 crc32NibbleTable[16] = |
| 57 | + { |
| 58 | + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, |
| 59 | + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD |
| 60 | + }; |
| 61 | + |
| 62 | + initial_crc = crc32NibbleTable[(initial_crc >> 28) ^ (data >> 4)] ^ (initial_crc << 4) ; |
| 63 | + initial_crc = crc32NibbleTable[(initial_crc >> 28) ^ (data & 0xF)] ^ (initial_crc << 4) ; |
| 64 | + |
| 65 | + return initial_crc; |
| 66 | +} |
| 67 | + |
23 | 68 | UINT32 SUPPORT_ComputeCRC(const void* buffer, int size, UINT32 initCrc)
|
24 | 69 | {
|
25 | 70 | CRC_HandleTypeDef hcrc;
|
26 |
| - |
| 71 | + |
27 | 72 | uint32_t index = 0U;
|
28 | 73 | uint32_t arg1;
|
29 |
| - UINT32 crc; |
30 |
| - |
| 74 | + uint32_t size_remainder = 0U; |
| 75 | + volatile UINT32 crc, crc_temp; |
| 76 | + volatile UINT32 targetCRC; |
| 77 | + volatile UINT32 currentCRC; |
| 78 | + |
31 | 79 | // anything to do here?
|
32 | 80 | if(size == 0)
|
33 | 81 | {
|
34 | 82 | return initCrc;
|
35 | 83 | }
|
36 |
| - |
37 |
| - // init CRC unit |
| 84 | + |
| 85 | + // init CRC unit |
38 | 86 | hcrc.Instance = CRC;
|
39 |
| - HAL_CRC_Init(&hcrc); |
40 |
| - |
41 |
| - // Reset CRC Calculation Unit |
42 |
| - __HAL_CRC_DR_RESET(&hcrc); |
43 |
| - |
44 |
| - // // if crc (argument for initial value) is not 0, init the CRC calculation unit with this value |
45 |
| - // if(crc != 0) |
46 |
| - // { |
47 |
| - // // init CRC value |
48 |
| - // hcrc.Instance->DR = __RBIT(crc); |
49 |
| - // } |
50 | 87 |
|
| 88 | + // get pointer to buffer |
51 | 89 | uint8_t* ptr = (uint8_t*)buffer;
|
52 | 90 |
|
53 |
| - // CRC calculation unit is initialed with 0xFFFFFFFF which is not good for our CRC calculations |
54 |
| - // feeding 0xFFFFFFFF to the calculation unit will set the register to 0x00000000 |
55 |
| - |
56 |
| - while(hcrc.Instance->DR != 0x0) |
| 91 | + // need to reset CRC peripheral if: |
| 92 | + // - CRC initial value is 0 |
| 93 | + // - the initial CRC is NOT already loaded in the calculation register |
| 94 | + if(initCrc == 0 || (hcrc.Instance->DR != initCrc)) |
57 | 95 | {
|
58 |
| - hcrc.Instance->DR = 0xFFFFFFFF; |
59 |
| - } |
| 96 | + // Reset CRC Calculation Unit |
| 97 | + (&hcrc)->Instance->CR |= CRC_CR_RESET; |
| 98 | + |
| 99 | + // CRC calculation unit is initiated with 0xFFFFFFFF which is not a initial value for our CRC calculation |
| 100 | + // feeding 0xFFFFFFFF to the calculation unit will set the register to 0x00000000 |
| 101 | + while(hcrc.Instance->DR != 0x0) |
| 102 | + { |
| 103 | + hcrc.Instance->DR = hcrc.Instance->DR; |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + if(initCrc != 0 && hcrc.Instance->DR != initCrc) |
| 108 | + { |
| 109 | + // we have an initial value for CRC calculation and that is not loaded in the CRC calculation register |
| 110 | + // load calculation register with REVERSE initial CRC32 value (because of STM32F4 shift order) |
| 111 | + hcrc.Instance->DR = ReverseCRC32(initCrc); |
| 112 | + } |
| 113 | + |
| 114 | + // set variable to hold how many bytes remain after processing the buffer in steps of 4 bytes |
| 115 | + size_remainder = size & 3; |
60 | 116 |
|
61 | 117 | // we'll be reading the buffer in steps of 4 bytes, so the size must be recalculated accordingly
|
62 | 118 | size = size >> 2;
|
63 | 119 |
|
64 |
| - // Enter Data to the CRC calculator |
| 120 | + // feed data into the CRC calculator |
65 | 121 | for(index = 0U; index < size; index++)
|
66 | 122 | {
|
67 | 123 | // take the next 4 bytes as if they were a UINT32
|
68 |
| - // because the CRC calculation unit expects the bytes in reverse order, reverse the byte order first |
| 124 | + // because the CRC calculation unit expects the bytes in reverse order, reverse the byte order first |
69 | 125 | arg1 = __REV(*(uint32_t*)(ptr));
|
70 | 126 |
|
71 |
| - // feed the bytes to the CRC |
| 127 | + // feed the bytes to the CRC |
72 | 128 | hcrc.Instance->DR = arg1;
|
73 | 129 |
|
74 | 130 | // copy to return value
|
75 | 131 | crc = (uint32_t)hcrc.Instance->DR;
|
76 | 132 |
|
77 | 133 | // increase pointer by 4 to the next position
|
78 |
| - // we are reading UINT32 from a UINT8 pointer |
| 134 | + // !! we are reading UINT32 from a UINT8 pointer!! |
79 | 135 | ptr +=4;
|
80 | 136 | }
|
81 | 137 |
|
| 138 | + // compute CRC for remaining bytes, if any |
| 139 | + while(size_remainder--) |
| 140 | + { |
| 141 | + crc = FastCRC32(crc, *(uint8_t*)(ptr++)); |
| 142 | + } |
| 143 | + |
82 | 144 | // Return the CRC computed value
|
83 |
| - return crc; |
| 145 | + return crc; |
84 | 146 | }
|
0 commit comments