Skip to content

Commit 7d24e1e

Browse files
committed
Update CRC code to match PR NETMF#526
1 parent f329bc8 commit 7d24e1e

File tree

1 file changed

+89
-27
lines changed

1 file changed

+89
-27
lines changed

DeviceCode/Targets/Native/STM32F4xx/CRC/CRC_functions.cpp

+89-27
Original file line numberDiff line numberDiff line change
@@ -13,72 +13,134 @@
1313

1414
#include <tinyhal.h>
1515

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+
1625
/*
1726
Interface to Cortex-M CRC calculation unit that implements the equivalent to the software implementation at Support\CRC project.
1827
CRC-32 (Ethernet) polynomial: 0x4C11DB7.
1928
buffer: pointer to the region block to be CRCed
2029
size: lenght of buffer to compute CRC
2130
crc: previous CRC value to start CRC computing
2231
*/
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+
2368
UINT32 SUPPORT_ComputeCRC(const void* buffer, int size, UINT32 initCrc)
2469
{
2570
CRC_HandleTypeDef hcrc;
26-
71+
2772
uint32_t index = 0U;
2873
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+
3179
// anything to do here?
3280
if(size == 0)
3381
{
3482
return initCrc;
3583
}
36-
37-
// init CRC unit
84+
85+
// init CRC unit
3886
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-
// }
5087

88+
// get pointer to buffer
5189
uint8_t* ptr = (uint8_t*)buffer;
5290

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))
5795
{
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;
60116

61117
// we'll be reading the buffer in steps of 4 bytes, so the size must be recalculated accordingly
62118
size = size >> 2;
63119

64-
// Enter Data to the CRC calculator
120+
// feed data into the CRC calculator
65121
for(index = 0U; index < size; index++)
66122
{
67123
// 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
69125
arg1 = __REV(*(uint32_t*)(ptr));
70126

71-
// feed the bytes to the CRC
127+
// feed the bytes to the CRC
72128
hcrc.Instance->DR = arg1;
73129

74130
// copy to return value
75131
crc = (uint32_t)hcrc.Instance->DR;
76132

77133
// 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!!
79135
ptr +=4;
80136
}
81137

138+
// compute CRC for remaining bytes, if any
139+
while(size_remainder--)
140+
{
141+
crc = FastCRC32(crc, *(uint8_t*)(ptr++));
142+
}
143+
82144
// Return the CRC computed value
83-
return crc;
145+
return crc;
84146
}

0 commit comments

Comments
 (0)