1 /**
2 ******************************************************************************
3 * @file stm32f0xx_hal_crc.c
4 * @author MCD Application Team
5 * @brief CRC HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the Cyclic Redundancy Check (CRC) peripheral:
8 * + Initialization and de-initialization functions
9 * + Peripheral Control functions
10 * + Peripheral State functions
11 *
12 ******************************************************************************
13 * @attention
14 *
15 * Copyright (c) 2016 STMicroelectronics.
16 * All rights reserved.
17 *
18 * This software is licensed under terms that can be found in the LICENSE file
19 * in the root directory of this software component.
20 * If no LICENSE file comes with this software, it is provided AS-IS.
21 *
22 ******************************************************************************
23 @verbatim
24 ===============================================================================
25 ##### How to use this driver #####
26 ===============================================================================
27 [..]
28 (+) Enable CRC AHB clock using __HAL_RCC_CRC_CLK_ENABLE();
29 (+) Initialize CRC calculator
30 (++) specify generating polynomial (peripheral default or non-default one)
31 (++) specify initialization value (peripheral default or non-default one)
32 (++) specify input data format
33 (++) specify input or output data inversion mode if any
34 (+) Use HAL_CRC_Accumulate() function to compute the CRC value of the
35 input data buffer starting with the previously computed CRC as
36 initialization value
37 (+) Use HAL_CRC_Calculate() function to compute the CRC value of the
38 input data buffer starting with the defined initialization value
39 (default or non-default) to initiate CRC calculation
40
41 @endverbatim
42 ******************************************************************************
43 */
44
45 /* Includes ------------------------------------------------------------------*/
46 #include "stm32f0xx_hal.h"
47
48 /** @addtogroup STM32F0xx_HAL_Driver
49 * @{
50 */
51
52 /** @defgroup CRC CRC
53 * @brief CRC HAL module driver.
54 * @{
55 */
56
57 #ifdef HAL_CRC_MODULE_ENABLED
58
59 /* Private typedef -----------------------------------------------------------*/
60 /* Private define ------------------------------------------------------------*/
61 /* Private macro -------------------------------------------------------------*/
62 /* Private variables ---------------------------------------------------------*/
63 /* Private function prototypes -----------------------------------------------*/
64 /** @defgroup CRC_Private_Functions CRC Private Functions
65 * @{
66 */
67 static uint32_t CRC_Handle_8(CRC_HandleTypeDef *hcrc, uint8_t pBuffer[], uint32_t BufferLength);
68 static uint32_t CRC_Handle_16(CRC_HandleTypeDef *hcrc, uint16_t pBuffer[], uint32_t BufferLength);
69 /**
70 * @}
71 */
72
73 /* Exported functions --------------------------------------------------------*/
74
75 /** @defgroup CRC_Exported_Functions CRC Exported Functions
76 * @{
77 */
78
79 /** @defgroup CRC_Exported_Functions_Group1 Initialization and de-initialization functions
80 * @brief Initialization and Configuration functions.
81 *
82 @verbatim
83 ===============================================================================
84 ##### Initialization and de-initialization functions #####
85 ===============================================================================
86 [..] This section provides functions allowing to:
87 (+) Initialize the CRC according to the specified parameters
88 in the CRC_InitTypeDef and create the associated handle
89 (+) DeInitialize the CRC peripheral
90 (+) Initialize the CRC MSP (MCU Specific Package)
91 (+) DeInitialize the CRC MSP
92
93 @endverbatim
94 * @{
95 */
96
97 /**
98 * @brief Initialize the CRC according to the specified
99 * parameters in the CRC_InitTypeDef and create the associated handle.
100 * @param hcrc CRC handle
101 * @retval HAL status
102 */
HAL_CRC_Init(CRC_HandleTypeDef * hcrc)103 HAL_StatusTypeDef HAL_CRC_Init(CRC_HandleTypeDef *hcrc)
104 {
105 /* Check the CRC handle allocation */
106 if (hcrc == NULL)
107 {
108 return HAL_ERROR;
109 }
110
111 /* Check the parameters */
112 assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
113
114 if (hcrc->State == HAL_CRC_STATE_RESET)
115 {
116 /* Allocate lock resource and initialize it */
117 hcrc->Lock = HAL_UNLOCKED;
118 /* Init the low level hardware */
119 HAL_CRC_MspInit(hcrc);
120 }
121
122 hcrc->State = HAL_CRC_STATE_BUSY;
123
124 #if defined(CRC_POL_POL)
125 /* check whether or not non-default generating polynomial has been
126 * picked up by user */
127 assert_param(IS_DEFAULT_POLYNOMIAL(hcrc->Init.DefaultPolynomialUse));
128 if (hcrc->Init.DefaultPolynomialUse == DEFAULT_POLYNOMIAL_ENABLE)
129 {
130 /* initialize peripheral with default generating polynomial */
131 WRITE_REG(hcrc->Instance->POL, DEFAULT_CRC32_POLY);
132 MODIFY_REG(hcrc->Instance->CR, CRC_CR_POLYSIZE, CRC_POLYLENGTH_32B);
133 }
134 else
135 {
136 /* initialize CRC peripheral with generating polynomial defined by user */
137 if (HAL_CRCEx_Polynomial_Set(hcrc, hcrc->Init.GeneratingPolynomial, hcrc->Init.CRCLength) != HAL_OK)
138 {
139 return HAL_ERROR;
140 }
141 }
142 #endif /* CRC_POL_POL */
143
144 /* check whether or not non-default CRC initial value has been
145 * picked up by user */
146 assert_param(IS_DEFAULT_INIT_VALUE(hcrc->Init.DefaultInitValueUse));
147 if (hcrc->Init.DefaultInitValueUse == DEFAULT_INIT_VALUE_ENABLE)
148 {
149 WRITE_REG(hcrc->Instance->INIT, DEFAULT_CRC_INITVALUE);
150 }
151 else
152 {
153 WRITE_REG(hcrc->Instance->INIT, hcrc->Init.InitValue);
154 }
155
156
157 /* set input data inversion mode */
158 assert_param(IS_CRC_INPUTDATA_INVERSION_MODE(hcrc->Init.InputDataInversionMode));
159 MODIFY_REG(hcrc->Instance->CR, CRC_CR_REV_IN, hcrc->Init.InputDataInversionMode);
160
161 /* set output data inversion mode */
162 assert_param(IS_CRC_OUTPUTDATA_INVERSION_MODE(hcrc->Init.OutputDataInversionMode));
163 MODIFY_REG(hcrc->Instance->CR, CRC_CR_REV_OUT, hcrc->Init.OutputDataInversionMode);
164
165 /* makes sure the input data format (bytes, halfwords or words stream)
166 * is properly specified by user */
167 assert_param(IS_CRC_INPUTDATA_FORMAT(hcrc->InputDataFormat));
168
169 /* Change CRC peripheral state */
170 hcrc->State = HAL_CRC_STATE_READY;
171
172 /* Return function status */
173 return HAL_OK;
174 }
175
176 /**
177 * @brief DeInitialize the CRC peripheral.
178 * @param hcrc CRC handle
179 * @retval HAL status
180 */
HAL_CRC_DeInit(CRC_HandleTypeDef * hcrc)181 HAL_StatusTypeDef HAL_CRC_DeInit(CRC_HandleTypeDef *hcrc)
182 {
183 /* Check the CRC handle allocation */
184 if (hcrc == NULL)
185 {
186 return HAL_ERROR;
187 }
188
189 /* Check the parameters */
190 assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
191
192 /* Check the CRC peripheral state */
193 if (hcrc->State == HAL_CRC_STATE_BUSY)
194 {
195 return HAL_BUSY;
196 }
197
198 /* Change CRC peripheral state */
199 hcrc->State = HAL_CRC_STATE_BUSY;
200
201 /* Reset CRC calculation unit */
202 __HAL_CRC_DR_RESET(hcrc);
203
204 /* Reset IDR register content */
205 __HAL_CRC_SET_IDR(hcrc, 0);
206
207 /* DeInit the low level hardware */
208 HAL_CRC_MspDeInit(hcrc);
209
210 /* Change CRC peripheral state */
211 hcrc->State = HAL_CRC_STATE_RESET;
212
213 /* Process unlocked */
214 __HAL_UNLOCK(hcrc);
215
216 /* Return function status */
217 return HAL_OK;
218 }
219
220 /**
221 * @brief Initializes the CRC MSP.
222 * @param hcrc CRC handle
223 * @retval None
224 */
HAL_CRC_MspInit(CRC_HandleTypeDef * hcrc)225 __weak void HAL_CRC_MspInit(CRC_HandleTypeDef *hcrc)
226 {
227 /* Prevent unused argument(s) compilation warning */
228 UNUSED(hcrc);
229
230 /* NOTE : This function should not be modified, when the callback is needed,
231 the HAL_CRC_MspInit can be implemented in the user file
232 */
233 }
234
235 /**
236 * @brief DeInitialize the CRC MSP.
237 * @param hcrc CRC handle
238 * @retval None
239 */
HAL_CRC_MspDeInit(CRC_HandleTypeDef * hcrc)240 __weak void HAL_CRC_MspDeInit(CRC_HandleTypeDef *hcrc)
241 {
242 /* Prevent unused argument(s) compilation warning */
243 UNUSED(hcrc);
244
245 /* NOTE : This function should not be modified, when the callback is needed,
246 the HAL_CRC_MspDeInit can be implemented in the user file
247 */
248 }
249
250 /**
251 * @}
252 */
253
254 /** @defgroup CRC_Exported_Functions_Group2 Peripheral Control functions
255 * @brief management functions.
256 *
257 @verbatim
258 ===============================================================================
259 ##### Peripheral Control functions #####
260 ===============================================================================
261 [..] This section provides functions allowing to:
262 (+) compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
263 using combination of the previous CRC value and the new one.
264
265 [..] or
266
267 (+) compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
268 independently of the previous CRC value.
269
270 @endverbatim
271 * @{
272 */
273
274 /**
275 * @brief Compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
276 * starting with the previously computed CRC as initialization value.
277 * @param hcrc CRC handle
278 * @param pBuffer pointer to the input data buffer, exact input data format is
279 * provided by hcrc->InputDataFormat.
280 * @param BufferLength input data buffer length (number of bytes if pBuffer
281 * type is * uint8_t, number of half-words if pBuffer type is * uint16_t,
282 * number of words if pBuffer type is * uint32_t).
283 * @note By default, the API expects a uint32_t pointer as input buffer parameter.
284 * Input buffer pointers with other types simply need to be cast in uint32_t
285 * and the API will internally adjust its input data processing based on the
286 * handle field hcrc->InputDataFormat.
287 * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
288 */
HAL_CRC_Accumulate(CRC_HandleTypeDef * hcrc,uint32_t pBuffer[],uint32_t BufferLength)289 uint32_t HAL_CRC_Accumulate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
290 {
291 uint32_t index; /* CRC input data buffer index */
292 uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
293
294 /* Change CRC peripheral state */
295 hcrc->State = HAL_CRC_STATE_BUSY;
296
297 switch (hcrc->InputDataFormat)
298 {
299 case CRC_INPUTDATA_FORMAT_WORDS:
300 /* Enter Data to the CRC calculator */
301 for (index = 0U; index < BufferLength; index++)
302 {
303 hcrc->Instance->DR = pBuffer[index];
304 }
305 temp = hcrc->Instance->DR;
306 break;
307
308 case CRC_INPUTDATA_FORMAT_BYTES:
309 temp = CRC_Handle_8(hcrc, (uint8_t *)pBuffer, BufferLength);
310 break;
311
312 case CRC_INPUTDATA_FORMAT_HALFWORDS:
313 temp = CRC_Handle_16(hcrc, (uint16_t *)(void *)pBuffer, BufferLength); /* Derogation MisraC2012 R.11.5 */
314 break;
315 default:
316 break;
317 }
318
319 /* Change CRC peripheral state */
320 hcrc->State = HAL_CRC_STATE_READY;
321
322 /* Return the CRC computed value */
323 return temp;
324 }
325
326 /**
327 * @brief Compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
328 * starting with hcrc->Instance->INIT as initialization value.
329 * @param hcrc CRC handle
330 * @param pBuffer pointer to the input data buffer, exact input data format is
331 * provided by hcrc->InputDataFormat.
332 * @param BufferLength input data buffer length (number of bytes if pBuffer
333 * type is * uint8_t, number of half-words if pBuffer type is * uint16_t,
334 * number of words if pBuffer type is * uint32_t).
335 * @note By default, the API expects a uint32_t pointer as input buffer parameter.
336 * Input buffer pointers with other types simply need to be cast in uint32_t
337 * and the API will internally adjust its input data processing based on the
338 * handle field hcrc->InputDataFormat.
339 * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
340 */
HAL_CRC_Calculate(CRC_HandleTypeDef * hcrc,uint32_t pBuffer[],uint32_t BufferLength)341 uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
342 {
343 uint32_t index; /* CRC input data buffer index */
344 uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
345
346 /* Change CRC peripheral state */
347 hcrc->State = HAL_CRC_STATE_BUSY;
348
349 /* Reset CRC Calculation Unit (hcrc->Instance->INIT is
350 * written in hcrc->Instance->DR) */
351 __HAL_CRC_DR_RESET(hcrc);
352
353 switch (hcrc->InputDataFormat)
354 {
355 case CRC_INPUTDATA_FORMAT_WORDS:
356 /* Enter 32-bit input data to the CRC calculator */
357 for (index = 0U; index < BufferLength; index++)
358 {
359 hcrc->Instance->DR = pBuffer[index];
360 }
361 temp = hcrc->Instance->DR;
362 break;
363
364 case CRC_INPUTDATA_FORMAT_BYTES:
365 /* Specific 8-bit input data handling */
366 temp = CRC_Handle_8(hcrc, (uint8_t *)pBuffer, BufferLength);
367 break;
368
369 case CRC_INPUTDATA_FORMAT_HALFWORDS:
370 /* Specific 16-bit input data handling */
371 temp = CRC_Handle_16(hcrc, (uint16_t *)(void *)pBuffer, BufferLength); /* Derogation MisraC2012 R.11.5 */
372 break;
373
374 default:
375 break;
376 }
377
378 /* Change CRC peripheral state */
379 hcrc->State = HAL_CRC_STATE_READY;
380
381 /* Return the CRC computed value */
382 return temp;
383 }
384
385 /**
386 * @}
387 */
388
389 /** @defgroup CRC_Exported_Functions_Group3 Peripheral State functions
390 * @brief Peripheral State functions.
391 *
392 @verbatim
393 ===============================================================================
394 ##### Peripheral State functions #####
395 ===============================================================================
396 [..]
397 This subsection permits to get in run-time the status of the peripheral.
398
399 @endverbatim
400 * @{
401 */
402
403 /**
404 * @brief Return the CRC handle state.
405 * @param hcrc CRC handle
406 * @retval HAL state
407 */
HAL_CRC_GetState(CRC_HandleTypeDef * hcrc)408 HAL_CRC_StateTypeDef HAL_CRC_GetState(CRC_HandleTypeDef *hcrc)
409 {
410 /* Return CRC handle state */
411 return hcrc->State;
412 }
413
414 /**
415 * @}
416 */
417
418 /**
419 * @}
420 */
421
422 /** @addtogroup CRC_Private_Functions
423 * @{
424 */
425
426 /**
427 * @brief Enter 8-bit input data to the CRC calculator.
428 * Specific data handling to optimize processing time.
429 * @param hcrc CRC handle
430 * @param pBuffer pointer to the input data buffer
431 * @param BufferLength input data buffer length
432 * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
433 */
CRC_Handle_8(CRC_HandleTypeDef * hcrc,uint8_t pBuffer[],uint32_t BufferLength)434 static uint32_t CRC_Handle_8(CRC_HandleTypeDef *hcrc, uint8_t pBuffer[], uint32_t BufferLength)
435 {
436 uint32_t i; /* input data buffer index */
437 uint16_t data;
438 __IO uint16_t *pReg;
439
440 /* Processing time optimization: 4 bytes are entered in a row with a single word write,
441 * last bytes must be carefully fed to the CRC calculator to ensure a correct type
442 * handling by the peripheral */
443 for (i = 0U; i < (BufferLength / 4U); i++)
444 {
445 hcrc->Instance->DR = ((uint32_t)pBuffer[4U * i] << 24U) | \
446 ((uint32_t)pBuffer[(4U * i) + 1U] << 16U) | \
447 ((uint32_t)pBuffer[(4U * i) + 2U] << 8U) | \
448 (uint32_t)pBuffer[(4U * i) + 3U];
449 }
450 /* last bytes specific handling */
451 if ((BufferLength % 4U) != 0U)
452 {
453 if ((BufferLength % 4U) == 1U)
454 {
455 *(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[4U * i]; /* Derogation MisraC2012 R.11.5 */
456 }
457 if ((BufferLength % 4U) == 2U)
458 {
459 data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) + 1U];
460 pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
461 *pReg = data;
462 }
463 if ((BufferLength % 4U) == 3U)
464 {
465 data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) + 1U];
466 pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
467 *pReg = data;
468
469 *(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[(4U * i) + 2U]; /* Derogation MisraC2012 R.11.5 */
470 }
471 }
472
473 /* Return the CRC computed value */
474 return hcrc->Instance->DR;
475 }
476
477 /**
478 * @brief Enter 16-bit input data to the CRC calculator.
479 * Specific data handling to optimize processing time.
480 * @param hcrc CRC handle
481 * @param pBuffer pointer to the input data buffer
482 * @param BufferLength input data buffer length
483 * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
484 */
CRC_Handle_16(CRC_HandleTypeDef * hcrc,uint16_t pBuffer[],uint32_t BufferLength)485 static uint32_t CRC_Handle_16(CRC_HandleTypeDef *hcrc, uint16_t pBuffer[], uint32_t BufferLength)
486 {
487 uint32_t i; /* input data buffer index */
488 __IO uint16_t *pReg;
489
490 /* Processing time optimization: 2 HalfWords are entered in a row with a single word write,
491 * in case of odd length, last HalfWord must be carefully fed to the CRC calculator to ensure
492 * a correct type handling by the peripheral */
493 for (i = 0U; i < (BufferLength / 2U); i++)
494 {
495 hcrc->Instance->DR = ((uint32_t)pBuffer[2U * i] << 16U) | (uint32_t)pBuffer[(2U * i) + 1U];
496 }
497 if ((BufferLength % 2U) != 0U)
498 {
499 pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
500 *pReg = pBuffer[2U * i];
501 }
502
503 /* Return the CRC computed value */
504 return hcrc->Instance->DR;
505 }
506
507 /**
508 * @}
509 */
510
511 #endif /* HAL_CRC_MODULE_ENABLED */
512 /**
513 * @}
514 */
515
516 /**
517 * @}
518 */
519