1 /**
2 ******************************************************************************
3 * @file stm32l4xx_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) 2017 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 "stm32l4xx_hal.h"
47
48 /** @addtogroup STM32L4xx_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 /* check whether or not non-default generating polynomial has been
125 * picked up by user */
126 assert_param(IS_DEFAULT_POLYNOMIAL(hcrc->Init.DefaultPolynomialUse));
127 if (hcrc->Init.DefaultPolynomialUse == DEFAULT_POLYNOMIAL_ENABLE)
128 {
129 /* initialize peripheral with default generating polynomial */
130 WRITE_REG(hcrc->Instance->POL, DEFAULT_CRC32_POLY);
131 MODIFY_REG(hcrc->Instance->CR, CRC_CR_POLYSIZE, CRC_POLYLENGTH_32B);
132 }
133 else
134 {
135 /* initialize CRC peripheral with generating polynomial defined by user */
136 if (HAL_CRCEx_Polynomial_Set(hcrc, hcrc->Init.GeneratingPolynomial, hcrc->Init.CRCLength) != HAL_OK)
137 {
138 return HAL_ERROR;
139 }
140 }
141
142 /* check whether or not non-default CRC initial value has been
143 * picked up by user */
144 assert_param(IS_DEFAULT_INIT_VALUE(hcrc->Init.DefaultInitValueUse));
145 if (hcrc->Init.DefaultInitValueUse == DEFAULT_INIT_VALUE_ENABLE)
146 {
147 WRITE_REG(hcrc->Instance->INIT, DEFAULT_CRC_INITVALUE);
148 }
149 else
150 {
151 WRITE_REG(hcrc->Instance->INIT, hcrc->Init.InitValue);
152 }
153
154
155 /* set input data inversion mode */
156 assert_param(IS_CRC_INPUTDATA_INVERSION_MODE(hcrc->Init.InputDataInversionMode));
157 MODIFY_REG(hcrc->Instance->CR, CRC_CR_REV_IN, hcrc->Init.InputDataInversionMode);
158
159 /* set output data inversion mode */
160 assert_param(IS_CRC_OUTPUTDATA_INVERSION_MODE(hcrc->Init.OutputDataInversionMode));
161 MODIFY_REG(hcrc->Instance->CR, CRC_CR_REV_OUT, hcrc->Init.OutputDataInversionMode);
162
163 /* makes sure the input data format (bytes, halfwords or words stream)
164 * is properly specified by user */
165 assert_param(IS_CRC_INPUTDATA_FORMAT(hcrc->InputDataFormat));
166
167 /* Change CRC peripheral state */
168 hcrc->State = HAL_CRC_STATE_READY;
169
170 /* Return function status */
171 return HAL_OK;
172 }
173
174 /**
175 * @brief DeInitialize the CRC peripheral.
176 * @param hcrc CRC handle
177 * @retval HAL status
178 */
HAL_CRC_DeInit(CRC_HandleTypeDef * hcrc)179 HAL_StatusTypeDef HAL_CRC_DeInit(CRC_HandleTypeDef *hcrc)
180 {
181 /* Check the CRC handle allocation */
182 if (hcrc == NULL)
183 {
184 return HAL_ERROR;
185 }
186
187 /* Check the parameters */
188 assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
189
190 /* Check the CRC peripheral state */
191 if (hcrc->State == HAL_CRC_STATE_BUSY)
192 {
193 return HAL_BUSY;
194 }
195
196 /* Change CRC peripheral state */
197 hcrc->State = HAL_CRC_STATE_BUSY;
198
199 /* Reset CRC calculation unit */
200 __HAL_CRC_DR_RESET(hcrc);
201
202 #if defined(CRC_IDR32BITSLENGTH_SUPPORT)
203 /* Reset IDR register content */
204 __HAL_CRC_SET_IDR(hcrc, 0);
205
206 #else
207 /* Reset IDR register content */
208 CLEAR_BIT(hcrc->Instance->IDR, CRC_IDR_IDR);
209
210 #endif /* CRC_IDR32BITSLENGTH_SUPPORT */
211 /* DeInit the low level hardware */
212 HAL_CRC_MspDeInit(hcrc);
213
214 /* Change CRC peripheral state */
215 hcrc->State = HAL_CRC_STATE_RESET;
216
217 /* Process unlocked */
218 __HAL_UNLOCK(hcrc);
219
220 /* Return function status */
221 return HAL_OK;
222 }
223
224 /**
225 * @brief Initializes the CRC MSP.
226 * @param hcrc CRC handle
227 * @retval None
228 */
HAL_CRC_MspInit(CRC_HandleTypeDef * hcrc)229 __weak void HAL_CRC_MspInit(CRC_HandleTypeDef *hcrc)
230 {
231 /* Prevent unused argument(s) compilation warning */
232 UNUSED(hcrc);
233
234 /* NOTE : This function should not be modified, when the callback is needed,
235 the HAL_CRC_MspInit can be implemented in the user file
236 */
237 }
238
239 /**
240 * @brief DeInitialize the CRC MSP.
241 * @param hcrc CRC handle
242 * @retval None
243 */
HAL_CRC_MspDeInit(CRC_HandleTypeDef * hcrc)244 __weak void HAL_CRC_MspDeInit(CRC_HandleTypeDef *hcrc)
245 {
246 /* Prevent unused argument(s) compilation warning */
247 UNUSED(hcrc);
248
249 /* NOTE : This function should not be modified, when the callback is needed,
250 the HAL_CRC_MspDeInit can be implemented in the user file
251 */
252 }
253
254 /**
255 * @}
256 */
257
258 /** @defgroup CRC_Exported_Functions_Group2 Peripheral Control functions
259 * @brief management functions.
260 *
261 @verbatim
262 ===============================================================================
263 ##### Peripheral Control functions #####
264 ===============================================================================
265 [..] This section provides functions allowing to:
266 (+) compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
267 using combination of the previous CRC value and the new one.
268
269 [..] or
270
271 (+) compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
272 independently of the previous CRC value.
273
274 @endverbatim
275 * @{
276 */
277
278 /**
279 * @brief Compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
280 * starting with the previously computed CRC as initialization value.
281 * @param hcrc CRC handle
282 * @param pBuffer pointer to the input data buffer, exact input data format is
283 * provided by hcrc->InputDataFormat.
284 * @param BufferLength input data buffer length (number of bytes if pBuffer
285 * type is * uint8_t, number of half-words if pBuffer type is * uint16_t,
286 * number of words if pBuffer type is * uint32_t).
287 * @note By default, the API expects a uint32_t pointer as input buffer parameter.
288 * Input buffer pointers with other types simply need to be cast in uint32_t
289 * and the API will internally adjust its input data processing based on the
290 * handle field hcrc->InputDataFormat.
291 * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
292 */
HAL_CRC_Accumulate(CRC_HandleTypeDef * hcrc,uint32_t pBuffer[],uint32_t BufferLength)293 uint32_t HAL_CRC_Accumulate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
294 {
295 uint32_t index; /* CRC input data buffer index */
296 uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
297
298 /* Change CRC peripheral state */
299 hcrc->State = HAL_CRC_STATE_BUSY;
300
301 switch (hcrc->InputDataFormat)
302 {
303 case CRC_INPUTDATA_FORMAT_WORDS:
304 /* Enter Data to the CRC calculator */
305 for (index = 0U; index < BufferLength; index++)
306 {
307 hcrc->Instance->DR = pBuffer[index];
308 }
309 temp = hcrc->Instance->DR;
310 break;
311
312 case CRC_INPUTDATA_FORMAT_BYTES:
313 temp = CRC_Handle_8(hcrc, (uint8_t *)pBuffer, BufferLength);
314 break;
315
316 case CRC_INPUTDATA_FORMAT_HALFWORDS:
317 temp = CRC_Handle_16(hcrc, (uint16_t *)(void *)pBuffer, BufferLength); /* Derogation MisraC2012 R.11.5 */
318 break;
319 default:
320 break;
321 }
322
323 /* Change CRC peripheral state */
324 hcrc->State = HAL_CRC_STATE_READY;
325
326 /* Return the CRC computed value */
327 return temp;
328 }
329
330 /**
331 * @brief Compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
332 * starting with hcrc->Instance->INIT as initialization value.
333 * @param hcrc CRC handle
334 * @param pBuffer pointer to the input data buffer, exact input data format is
335 * provided by hcrc->InputDataFormat.
336 * @param BufferLength input data buffer length (number of bytes if pBuffer
337 * type is * uint8_t, number of half-words if pBuffer type is * uint16_t,
338 * number of words if pBuffer type is * uint32_t).
339 * @note By default, the API expects a uint32_t pointer as input buffer parameter.
340 * Input buffer pointers with other types simply need to be cast in uint32_t
341 * and the API will internally adjust its input data processing based on the
342 * handle field hcrc->InputDataFormat.
343 * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
344 */
HAL_CRC_Calculate(CRC_HandleTypeDef * hcrc,uint32_t pBuffer[],uint32_t BufferLength)345 uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
346 {
347 uint32_t index; /* CRC input data buffer index */
348 uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
349
350 /* Change CRC peripheral state */
351 hcrc->State = HAL_CRC_STATE_BUSY;
352
353 /* Reset CRC Calculation Unit (hcrc->Instance->INIT is
354 * written in hcrc->Instance->DR) */
355 __HAL_CRC_DR_RESET(hcrc);
356
357 switch (hcrc->InputDataFormat)
358 {
359 case CRC_INPUTDATA_FORMAT_WORDS:
360 /* Enter 32-bit input data to the CRC calculator */
361 for (index = 0U; index < BufferLength; index++)
362 {
363 hcrc->Instance->DR = pBuffer[index];
364 }
365 temp = hcrc->Instance->DR;
366 break;
367
368 case CRC_INPUTDATA_FORMAT_BYTES:
369 /* Specific 8-bit input data handling */
370 temp = CRC_Handle_8(hcrc, (uint8_t *)pBuffer, BufferLength);
371 break;
372
373 case CRC_INPUTDATA_FORMAT_HALFWORDS:
374 /* Specific 16-bit input data handling */
375 temp = CRC_Handle_16(hcrc, (uint16_t *)(void *)pBuffer, BufferLength); /* Derogation MisraC2012 R.11.5 */
376 break;
377
378 default:
379 break;
380 }
381
382 /* Change CRC peripheral state */
383 hcrc->State = HAL_CRC_STATE_READY;
384
385 /* Return the CRC computed value */
386 return temp;
387 }
388
389 /**
390 * @}
391 */
392
393 /** @defgroup CRC_Exported_Functions_Group3 Peripheral State functions
394 * @brief Peripheral State functions.
395 *
396 @verbatim
397 ===============================================================================
398 ##### Peripheral State functions #####
399 ===============================================================================
400 [..]
401 This subsection permits to get in run-time the status of the peripheral.
402
403 @endverbatim
404 * @{
405 */
406
407 /**
408 * @brief Return the CRC handle state.
409 * @param hcrc CRC handle
410 * @retval HAL state
411 */
HAL_CRC_GetState(const CRC_HandleTypeDef * hcrc)412 HAL_CRC_StateTypeDef HAL_CRC_GetState(const CRC_HandleTypeDef *hcrc)
413 {
414 /* Return CRC handle state */
415 return hcrc->State;
416 }
417
418 /**
419 * @}
420 */
421
422 /**
423 * @}
424 */
425
426 /** @addtogroup CRC_Private_Functions
427 * @{
428 */
429
430 /**
431 * @brief Enter 8-bit input data to the CRC calculator.
432 * Specific data handling to optimize processing time.
433 * @param hcrc CRC handle
434 * @param pBuffer pointer to the input data buffer
435 * @param BufferLength input data buffer length
436 * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
437 */
CRC_Handle_8(CRC_HandleTypeDef * hcrc,uint8_t pBuffer[],uint32_t BufferLength)438 static uint32_t CRC_Handle_8(CRC_HandleTypeDef *hcrc, uint8_t pBuffer[], uint32_t BufferLength)
439 {
440 uint32_t i; /* input data buffer index */
441 uint16_t data;
442 __IO uint16_t *pReg;
443
444 /* Processing time optimization: 4 bytes are entered in a row with a single word write,
445 * last bytes must be carefully fed to the CRC calculator to ensure a correct type
446 * handling by the peripheral */
447 for (i = 0U; i < (BufferLength / 4U); i++)
448 {
449 hcrc->Instance->DR = ((uint32_t)pBuffer[4U * i] << 24U) | \
450 ((uint32_t)pBuffer[(4U * i) + 1U] << 16U) | \
451 ((uint32_t)pBuffer[(4U * i) + 2U] << 8U) | \
452 (uint32_t)pBuffer[(4U * i) + 3U];
453 }
454 /* last bytes specific handling */
455 if ((BufferLength % 4U) != 0U)
456 {
457 if ((BufferLength % 4U) == 1U)
458 {
459 *(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[4U * i]; /* Derogation MisraC2012 R.11.5 */
460 }
461 if ((BufferLength % 4U) == 2U)
462 {
463 data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) + 1U];
464 pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
465 *pReg = data;
466 }
467 if ((BufferLength % 4U) == 3U)
468 {
469 data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) + 1U];
470 pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
471 *pReg = data;
472
473 *(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[(4U * i) + 2U]; /* Derogation MisraC2012 R.11.5 */
474 }
475 }
476
477 /* Return the CRC computed value */
478 return hcrc->Instance->DR;
479 }
480
481 /**
482 * @brief Enter 16-bit input data to the CRC calculator.
483 * Specific data handling to optimize processing time.
484 * @param hcrc CRC handle
485 * @param pBuffer pointer to the input data buffer
486 * @param BufferLength input data buffer length
487 * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
488 */
CRC_Handle_16(CRC_HandleTypeDef * hcrc,uint16_t pBuffer[],uint32_t BufferLength)489 static uint32_t CRC_Handle_16(CRC_HandleTypeDef *hcrc, uint16_t pBuffer[], uint32_t BufferLength)
490 {
491 uint32_t i; /* input data buffer index */
492 __IO uint16_t *pReg;
493
494 /* Processing time optimization: 2 HalfWords are entered in a row with a single word write,
495 * in case of odd length, last HalfWord must be carefully fed to the CRC calculator to ensure
496 * a correct type handling by the peripheral */
497 for (i = 0U; i < (BufferLength / 2U); i++)
498 {
499 hcrc->Instance->DR = ((uint32_t)pBuffer[2U * i] << 16U) | (uint32_t)pBuffer[(2U * i) + 1U];
500 }
501 if ((BufferLength % 2U) != 0U)
502 {
503 pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR); /* Derogation MisraC2012 R.11.5 */
504 *pReg = pBuffer[2U * i];
505 }
506
507 /* Return the CRC computed value */
508 return hcrc->Instance->DR;
509 }
510
511 /**
512 * @}
513 */
514
515 #endif /* HAL_CRC_MODULE_ENABLED */
516 /**
517 * @}
518 */
519
520 /**
521 * @}
522 */
523