Skip to content

Commit 3d0f168

Browse files
authored
Merge pull request #9347 from kevinong0108/improve_crc
stm32: Improve the CRC function to support fully accumulate
2 parents 31579fe + 5ccdd67 commit 3d0f168

File tree

1 file changed

+93
-17
lines changed

1 file changed

+93
-17
lines changed

targets/TARGET_STM/mbed_crc_api.c

Lines changed: 93 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,57 @@
77

88
static CRC_HandleTypeDef current_state;
99
static uint32_t final_xor;
10-
10+
static uint32_t crc_mask;
11+
12+
/* STM32 CRC preipheral features
13+
+-------------------------+-----------------------+---------------+---------------+
14+
| Feature | F1/L1/F2/F4 series | F0 series (#1)| L0/F3/L4/F7 |
15+
+-========================+=======================+===============+===============+
16+
| Reversibility option | NO | YES |
17+
| on I/O data | | |
18+
+-------------------------+-----------------------+---------------+---------------+
19+
| CRC initial Value | Fixed to 0xFFFFFFFF | Programmable | Programmable |
20+
| | | on 32 bits | on 8,16,32 |
21+
+-------------------------+-----------------------+---------------+---------------+
22+
| Handled data size in bit| 32 | 8,16,32 |
23+
+-------------------------+---------------------------------------+---------------+
24+
| Polynomial size in bit | 32 | 7,8,16,32 |
25+
+-------------------------+---------------------------------------+---------------+
26+
| Polynomial coefficients | Fixed to 0x4C11DB7 | Programmable |
27+
+-------------------------+---------------------------------------+---------------+
28+
29+
#1 The STM32F0 series which supported polynomial in 7, 8, 16, 32 bits as below list:
30+
STM32F071xB
31+
STM32F072xB
32+
STM32F078xx
33+
STM32F091xC
34+
STM32F098xx
35+
*/
1136
bool hal_crc_is_supported(const crc_mbed_config_t *config)
1237
{
1338
if (config == NULL) {
1439
return false;
1540
}
1641

17-
if (config->polynomial != POLY_32BIT_ANSI) {
18-
return false;
19-
}
20-
21-
if (config->width != 32) {
22-
return false;
23-
}
24-
25-
if ((config->final_xor != 0xFFFFFFFFU) && (config->final_xor != 0)) {
42+
#if defined(TARGET_STM32F1) || defined(TARGET_STM32F2) || defined(TARGET_STM32F4) || defined(TARGET_STM32L1)
43+
/* Currently, mbed supported input data format fix on bytes,
44+
so those devices are not supported at default. */
45+
return false;
46+
#elif !defined(CRC_POLYLENGTH_7B)
47+
/* Some targets are not support polynomial in 7, 8, 16 bits, ex. STM32F070RB,
48+
so those devices are not supported at default. */
49+
return false;
50+
#else
51+
if (config->width != 32 && config->width != 16 && config->width != 8 && config->width != 7) {
2652
return false;
2753
}
28-
2954
return true;
55+
#endif
56+
}
57+
58+
static uint32_t get_crc_mask(int width)
59+
{
60+
return (width < 8 ? ((1u << 8) - 1) : (uint32_t)((uint64_t)(1ull << width) - 1));
3061
}
3162

3263
void hal_crc_compute_partial_start(const crc_mbed_config_t *config)
@@ -36,21 +67,46 @@ void hal_crc_compute_partial_start(const crc_mbed_config_t *config)
3667
__HAL_RCC_CRC_CLK_ENABLE();
3768

3869
final_xor = config->final_xor;
70+
crc_mask = get_crc_mask(config->width);
3971

4072
current_state.Instance = CRC;
73+
#if !defined(TARGET_STM32F1) && !defined(TARGET_STM32F2) && !defined(TARGET_STM32F4) && !defined(TARGET_STM32L1) && defined(CRC_POLYLENGTH_7B)
4174
current_state.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
42-
current_state.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
4375
current_state.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
76+
current_state.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
4477
current_state.Init.InitValue = config->initial_xor;
45-
current_state.Init.CRCLength = CRC_POLYLENGTH_32B;
78+
current_state.Init.GeneratingPolynomial = config->polynomial;
79+
80+
switch (config->width)
81+
{
82+
case HAL_CRC_LENGTH_32B:
83+
current_state.Init.CRCLength = CRC_POLYLENGTH_32B;
84+
break;
85+
case HAL_CRC_LENGTH_16B:
86+
current_state.Init.CRCLength = CRC_POLYLENGTH_16B;
87+
break;
88+
case HAL_CRC_LENGTH_8B:
89+
current_state.Init.CRCLength = CRC_POLYLENGTH_8B;
90+
break;
91+
case HAL_CRC_LENGTH_7B:
92+
current_state.Init.CRCLength = CRC_POLYLENGTH_7B;
93+
break;
94+
default:
95+
MBED_ASSERT(false);
96+
break;
97+
}
98+
4699
current_state.Init.InputDataInversionMode =
47100
config->reflect_in ? CRC_INPUTDATA_INVERSION_BYTE
48101
: CRC_INPUTDATA_INVERSION_NONE;
49102
current_state.Init.OutputDataInversionMode =
50103
config->reflect_out ? CRC_OUTPUTDATA_INVERSION_ENABLE
51104
: CRC_OUTPUTDATA_INVERSION_DISABLE;
105+
#endif
52106

53-
HAL_CRC_Init(&current_state);
107+
if (HAL_CRC_Init(&current_state) != HAL_OK) {
108+
MBED_ASSERT(false);
109+
}
54110
}
55111

56112
void hal_crc_compute_partial(const uint8_t *data, const size_t size)
@@ -62,9 +118,29 @@ void hal_crc_compute_partial(const uint8_t *data, const size_t size)
62118

63119
uint32_t hal_crc_get_result(void)
64120
{
65-
const uint32_t result = current_state.Instance->DR;
66-
67-
return (final_xor == 0xFFFFFFFFU) ? ~result : result;
121+
uint32_t result = current_state.Instance->DR;
122+
123+
#if !defined(TARGET_STM32F1) && !defined(TARGET_STM32F2) && !defined(TARGET_STM32F4) && !defined(TARGET_STM32L1) && defined(CRC_POLYLENGTH_7B)
124+
/* The CRC-7 SD needs to shift left by 1 bit after obtaining the result, but the output
125+
* inversion of CRC peripheral will convert the result before shift left by 1 bit, so
126+
* the result seems to have shifted after the conversion.
127+
*
128+
* Example:
129+
* [Gerenal setps]
130+
* 1. Before output inversion: 0x75 (0111 0101)
131+
* 2. Left shift by 1 bit: 0xEA (1110 1010)
132+
* 3. After output inversion: 0x57 (0101 0111)
133+
*
134+
* [STM32 CRC peripheral steps]
135+
* 1. Before output inversion: 0x75 (0111 0101)
136+
* 2. After output inversion: 0x57 (0101 0111) <= no needs shift again
137+
*/
138+
if (current_state.Init.CRCLength == CRC_POLYLENGTH_7B &&
139+
current_state.Init.GeneratingPolynomial == POLY_7BIT_SD &&
140+
current_state.Init.OutputDataInversionMode == CRC_OUTPUTDATA_INVERSION_DISABLE)
141+
result = result << 1;
142+
#endif
143+
return (result ^ final_xor) & crc_mask;
68144
}
69145

70146
#endif // DEVICE_CRC

0 commit comments

Comments
 (0)