STM32L443xx HAL User Manual
stm32l4xx_hal_crc.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_hal_crc.c
00004   * @author  MCD Application Team
00005   * @brief   CRC HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the Cyclic Redundancy Check (CRC) peripheral:
00008   *           + Initialization and de-initialization functions
00009   *           + Peripheral Control functions
00010   *           + Peripheral State functions
00011   *
00012   ******************************************************************************
00013   * @attention
00014   *
00015   * Copyright (c) 2017 STMicroelectronics.
00016   * All rights reserved.
00017   *
00018   * This software is licensed under terms that can be found in the LICENSE file
00019   * in the root directory of this software component.
00020   * If no LICENSE file comes with this software, it is provided AS-IS.
00021   *
00022   ******************************************************************************
00023   @verbatim
00024  ===============================================================================
00025                      ##### How to use this driver #####
00026  ===============================================================================
00027     [..]
00028          (+) Enable CRC AHB clock using __HAL_RCC_CRC_CLK_ENABLE();
00029          (+) Initialize CRC calculator
00030              (++) specify generating polynomial (peripheral default or non-default one)
00031              (++) specify initialization value (peripheral default or non-default one)
00032              (++) specify input data format
00033              (++) specify input or output data inversion mode if any
00034          (+) Use HAL_CRC_Accumulate() function to compute the CRC value of the
00035              input data buffer starting with the previously computed CRC as
00036              initialization value
00037          (+) Use HAL_CRC_Calculate() function to compute the CRC value of the
00038              input data buffer starting with the defined initialization value
00039              (default or non-default) to initiate CRC calculation
00040 
00041   @endverbatim
00042   ******************************************************************************
00043   */
00044 
00045 /* Includes ------------------------------------------------------------------*/
00046 #include "stm32l4xx_hal.h"
00047 
00048 /** @addtogroup STM32L4xx_HAL_Driver
00049   * @{
00050   */
00051 
00052 /** @defgroup CRC CRC
00053   * @brief CRC HAL module driver.
00054   * @{
00055   */
00056 
00057 #ifdef HAL_CRC_MODULE_ENABLED
00058 
00059 /* Private typedef -----------------------------------------------------------*/
00060 /* Private define ------------------------------------------------------------*/
00061 /* Private macro -------------------------------------------------------------*/
00062 /* Private variables ---------------------------------------------------------*/
00063 /* Private function prototypes -----------------------------------------------*/
00064 /** @defgroup CRC_Private_Functions CRC Private Functions
00065   * @{
00066   */
00067 static uint32_t CRC_Handle_8(CRC_HandleTypeDef *hcrc, uint8_t pBuffer[], uint32_t BufferLength);
00068 static uint32_t CRC_Handle_16(CRC_HandleTypeDef *hcrc, uint16_t pBuffer[], uint32_t BufferLength);
00069 /**
00070   * @}
00071   */
00072 
00073 /* Exported functions --------------------------------------------------------*/
00074 
00075 /** @defgroup CRC_Exported_Functions CRC Exported Functions
00076   * @{
00077   */
00078 
00079 /** @defgroup CRC_Exported_Functions_Group1 Initialization and de-initialization functions
00080   *  @brief    Initialization and Configuration functions.
00081   *
00082 @verbatim
00083  ===============================================================================
00084             ##### Initialization and de-initialization functions #####
00085  ===============================================================================
00086     [..]  This section provides functions allowing to:
00087       (+) Initialize the CRC according to the specified parameters
00088           in the CRC_InitTypeDef and create the associated handle
00089       (+) DeInitialize the CRC peripheral
00090       (+) Initialize the CRC MSP (MCU Specific Package)
00091       (+) DeInitialize the CRC MSP
00092 
00093 @endverbatim
00094   * @{
00095   */
00096 
00097 /**
00098   * @brief  Initialize the CRC according to the specified
00099   *         parameters in the CRC_InitTypeDef and create the associated handle.
00100   * @param  hcrc CRC handle
00101   * @retval HAL status
00102   */
00103 HAL_StatusTypeDef HAL_CRC_Init(CRC_HandleTypeDef *hcrc)
00104 {
00105   /* Check the CRC handle allocation */
00106   if (hcrc == NULL)
00107   {
00108     return HAL_ERROR;
00109   }
00110 
00111   /* Check the parameters */
00112   assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
00113 
00114   if (hcrc->State == HAL_CRC_STATE_RESET)
00115   {
00116     /* Allocate lock resource and initialize it */
00117     hcrc->Lock = HAL_UNLOCKED;
00118     /* Init the low level hardware */
00119     HAL_CRC_MspInit(hcrc);
00120   }
00121 
00122   hcrc->State = HAL_CRC_STATE_BUSY;
00123 
00124   /* check whether or not non-default generating polynomial has been
00125    * picked up by user */
00126   assert_param(IS_DEFAULT_POLYNOMIAL(hcrc->Init.DefaultPolynomialUse));
00127   if (hcrc->Init.DefaultPolynomialUse == DEFAULT_POLYNOMIAL_ENABLE)
00128   {
00129     /* initialize peripheral with default generating polynomial */
00130     WRITE_REG(hcrc->Instance->POL, DEFAULT_CRC32_POLY);
00131     MODIFY_REG(hcrc->Instance->CR, CRC_CR_POLYSIZE, CRC_POLYLENGTH_32B);
00132   }
00133   else
00134   {
00135     /* initialize CRC peripheral with generating polynomial defined by user */
00136     if (HAL_CRCEx_Polynomial_Set(hcrc, hcrc->Init.GeneratingPolynomial, hcrc->Init.CRCLength) != HAL_OK)
00137     {
00138       return HAL_ERROR;
00139     }
00140   }
00141 
00142   /* check whether or not non-default CRC initial value has been
00143    * picked up by user */
00144   assert_param(IS_DEFAULT_INIT_VALUE(hcrc->Init.DefaultInitValueUse));
00145   if (hcrc->Init.DefaultInitValueUse == DEFAULT_INIT_VALUE_ENABLE)
00146   {
00147     WRITE_REG(hcrc->Instance->INIT, DEFAULT_CRC_INITVALUE);
00148   }
00149   else
00150   {
00151     WRITE_REG(hcrc->Instance->INIT, hcrc->Init.InitValue);
00152   }
00153 
00154 
00155   /* set input data inversion mode */
00156   assert_param(IS_CRC_INPUTDATA_INVERSION_MODE(hcrc->Init.InputDataInversionMode));
00157   MODIFY_REG(hcrc->Instance->CR, CRC_CR_REV_IN, hcrc->Init.InputDataInversionMode);
00158 
00159   /* set output data inversion mode */
00160   assert_param(IS_CRC_OUTPUTDATA_INVERSION_MODE(hcrc->Init.OutputDataInversionMode));
00161   MODIFY_REG(hcrc->Instance->CR, CRC_CR_REV_OUT, hcrc->Init.OutputDataInversionMode);
00162 
00163   /* makes sure the input data format (bytes, halfwords or words stream)
00164    * is properly specified by user */
00165   assert_param(IS_CRC_INPUTDATA_FORMAT(hcrc->InputDataFormat));
00166 
00167   /* Change CRC peripheral state */
00168   hcrc->State = HAL_CRC_STATE_READY;
00169 
00170   /* Return function status */
00171   return HAL_OK;
00172 }
00173 
00174 /**
00175   * @brief  DeInitialize the CRC peripheral.
00176   * @param  hcrc CRC handle
00177   * @retval HAL status
00178   */
00179 HAL_StatusTypeDef HAL_CRC_DeInit(CRC_HandleTypeDef *hcrc)
00180 {
00181   /* Check the CRC handle allocation */
00182   if (hcrc == NULL)
00183   {
00184     return HAL_ERROR;
00185   }
00186 
00187   /* Check the parameters */
00188   assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
00189 
00190   /* Check the CRC peripheral state */
00191   if (hcrc->State == HAL_CRC_STATE_BUSY)
00192   {
00193     return HAL_BUSY;
00194   }
00195 
00196   /* Change CRC peripheral state */
00197   hcrc->State = HAL_CRC_STATE_BUSY;
00198 
00199   /* Reset CRC calculation unit */
00200   __HAL_CRC_DR_RESET(hcrc);
00201 
00202   /* Reset IDR register content */
00203   CLEAR_BIT(hcrc->Instance->IDR, CRC_IDR_IDR);
00204 
00205   /* DeInit the low level hardware */
00206   HAL_CRC_MspDeInit(hcrc);
00207 
00208   /* Change CRC peripheral state */
00209   hcrc->State = HAL_CRC_STATE_RESET;
00210 
00211   /* Process unlocked */
00212   __HAL_UNLOCK(hcrc);
00213 
00214   /* Return function status */
00215   return HAL_OK;
00216 }
00217 
00218 /**
00219   * @brief  Initializes the CRC MSP.
00220   * @param  hcrc CRC handle
00221   * @retval None
00222   */
00223 __weak void HAL_CRC_MspInit(CRC_HandleTypeDef *hcrc)
00224 {
00225   /* Prevent unused argument(s) compilation warning */
00226   UNUSED(hcrc);
00227 
00228   /* NOTE : This function should not be modified, when the callback is needed,
00229             the HAL_CRC_MspInit can be implemented in the user file
00230    */
00231 }
00232 
00233 /**
00234   * @brief  DeInitialize the CRC MSP.
00235   * @param  hcrc CRC handle
00236   * @retval None
00237   */
00238 __weak void HAL_CRC_MspDeInit(CRC_HandleTypeDef *hcrc)
00239 {
00240   /* Prevent unused argument(s) compilation warning */
00241   UNUSED(hcrc);
00242 
00243   /* NOTE : This function should not be modified, when the callback is needed,
00244             the HAL_CRC_MspDeInit can be implemented in the user file
00245    */
00246 }
00247 
00248 /**
00249   * @}
00250   */
00251 
00252 /** @defgroup CRC_Exported_Functions_Group2 Peripheral Control functions
00253   *  @brief    management functions.
00254   *
00255 @verbatim
00256  ===============================================================================
00257                       ##### Peripheral Control functions #####
00258  ===============================================================================
00259     [..]  This section provides functions allowing to:
00260       (+) compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
00261           using combination of the previous CRC value and the new one.
00262 
00263        [..]  or
00264 
00265       (+) compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
00266           independently of the previous CRC value.
00267 
00268 @endverbatim
00269   * @{
00270   */
00271 
00272 /**
00273   * @brief  Compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
00274   *         starting with the previously computed CRC as initialization value.
00275   * @param  hcrc CRC handle
00276   * @param  pBuffer pointer to the input data buffer, exact input data format is
00277   *         provided by hcrc->InputDataFormat.
00278   * @param  BufferLength input data buffer length (number of bytes if pBuffer
00279   *         type is * uint8_t, number of half-words if pBuffer type is * uint16_t,
00280   *         number of words if pBuffer type is * uint32_t).
00281   * @note  By default, the API expects a uint32_t pointer as input buffer parameter.
00282   *        Input buffer pointers with other types simply need to be cast in uint32_t
00283   *        and the API will internally adjust its input data processing based on the
00284   *        handle field hcrc->InputDataFormat.
00285   * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
00286   */
00287 uint32_t HAL_CRC_Accumulate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
00288 {
00289   uint32_t index;      /* CRC input data buffer index */
00290   uint32_t temp = 0U;  /* CRC output (read from hcrc->Instance->DR register) */
00291 
00292   /* Change CRC peripheral state */
00293   hcrc->State = HAL_CRC_STATE_BUSY;
00294 
00295   switch (hcrc->InputDataFormat)
00296   {
00297     case CRC_INPUTDATA_FORMAT_WORDS:
00298       /* Enter Data to the CRC calculator */
00299       for (index = 0U; index < BufferLength; index++)
00300       {
00301         hcrc->Instance->DR = pBuffer[index];
00302       }
00303       temp = hcrc->Instance->DR;
00304       break;
00305 
00306     case CRC_INPUTDATA_FORMAT_BYTES:
00307       temp = CRC_Handle_8(hcrc, (uint8_t *)pBuffer, BufferLength);
00308       break;
00309 
00310     case CRC_INPUTDATA_FORMAT_HALFWORDS:
00311       temp = CRC_Handle_16(hcrc, (uint16_t *)(void *)pBuffer, BufferLength);    /* Derogation MisraC2012 R.11.5 */
00312       break;
00313     default:
00314       break;
00315   }
00316 
00317   /* Change CRC peripheral state */
00318   hcrc->State = HAL_CRC_STATE_READY;
00319 
00320   /* Return the CRC computed value */
00321   return temp;
00322 }
00323 
00324 /**
00325   * @brief  Compute the 7, 8, 16 or 32-bit CRC value of an 8, 16 or 32-bit data buffer
00326   *         starting with hcrc->Instance->INIT as initialization value.
00327   * @param  hcrc CRC handle
00328   * @param  pBuffer pointer to the input data buffer, exact input data format is
00329   *         provided by hcrc->InputDataFormat.
00330   * @param  BufferLength input data buffer length (number of bytes if pBuffer
00331   *         type is * uint8_t, number of half-words if pBuffer type is * uint16_t,
00332   *         number of words if pBuffer type is * uint32_t).
00333   * @note  By default, the API expects a uint32_t pointer as input buffer parameter.
00334   *        Input buffer pointers with other types simply need to be cast in uint32_t
00335   *        and the API will internally adjust its input data processing based on the
00336   *        handle field hcrc->InputDataFormat.
00337   * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
00338   */
00339 uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
00340 {
00341   uint32_t index;      /* CRC input data buffer index */
00342   uint32_t temp = 0U;  /* CRC output (read from hcrc->Instance->DR register) */
00343 
00344   /* Change CRC peripheral state */
00345   hcrc->State = HAL_CRC_STATE_BUSY;
00346 
00347   /* Reset CRC Calculation Unit (hcrc->Instance->INIT is
00348   *  written in hcrc->Instance->DR) */
00349   __HAL_CRC_DR_RESET(hcrc);
00350 
00351   switch (hcrc->InputDataFormat)
00352   {
00353     case CRC_INPUTDATA_FORMAT_WORDS:
00354       /* Enter 32-bit input data to the CRC calculator */
00355       for (index = 0U; index < BufferLength; index++)
00356       {
00357         hcrc->Instance->DR = pBuffer[index];
00358       }
00359       temp = hcrc->Instance->DR;
00360       break;
00361 
00362     case CRC_INPUTDATA_FORMAT_BYTES:
00363       /* Specific 8-bit input data handling  */
00364       temp = CRC_Handle_8(hcrc, (uint8_t *)pBuffer, BufferLength);
00365       break;
00366 
00367     case CRC_INPUTDATA_FORMAT_HALFWORDS:
00368       /* Specific 16-bit input data handling  */
00369       temp = CRC_Handle_16(hcrc, (uint16_t *)(void *)pBuffer, BufferLength);    /* Derogation MisraC2012 R.11.5 */
00370       break;
00371 
00372     default:
00373       break;
00374   }
00375 
00376   /* Change CRC peripheral state */
00377   hcrc->State = HAL_CRC_STATE_READY;
00378 
00379   /* Return the CRC computed value */
00380   return temp;
00381 }
00382 
00383 /**
00384   * @}
00385   */
00386 
00387 /** @defgroup CRC_Exported_Functions_Group3 Peripheral State functions
00388   *  @brief    Peripheral State functions.
00389   *
00390 @verbatim
00391  ===============================================================================
00392                       ##### Peripheral State functions #####
00393  ===============================================================================
00394     [..]
00395     This subsection permits to get in run-time the status of the peripheral.
00396 
00397 @endverbatim
00398   * @{
00399   */
00400 
00401 /**
00402   * @brief  Return the CRC handle state.
00403   * @param  hcrc CRC handle
00404   * @retval HAL state
00405   */
00406 HAL_CRC_StateTypeDef HAL_CRC_GetState(CRC_HandleTypeDef *hcrc)
00407 {
00408   /* Return CRC handle state */
00409   return hcrc->State;
00410 }
00411 
00412 /**
00413   * @}
00414   */
00415 
00416 /**
00417   * @}
00418   */
00419 
00420 /** @addtogroup CRC_Private_Functions
00421   * @{
00422   */
00423 
00424 /**
00425   * @brief  Enter 8-bit input data to the CRC calculator.
00426   *         Specific data handling to optimize processing time.
00427   * @param  hcrc CRC handle
00428   * @param  pBuffer pointer to the input data buffer
00429   * @param  BufferLength input data buffer length
00430   * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
00431   */
00432 static uint32_t CRC_Handle_8(CRC_HandleTypeDef *hcrc, uint8_t pBuffer[], uint32_t BufferLength)
00433 {
00434   uint32_t i; /* input data buffer index */
00435   uint16_t data;
00436   __IO uint16_t *pReg;
00437 
00438   /* Processing time optimization: 4 bytes are entered in a row with a single word write,
00439    * last bytes must be carefully fed to the CRC calculator to ensure a correct type
00440    * handling by the peripheral */
00441   for (i = 0U; i < (BufferLength / 4U); i++)
00442   {
00443     hcrc->Instance->DR = ((uint32_t)pBuffer[4U * i] << 24U) | \
00444                          ((uint32_t)pBuffer[(4U * i) + 1U] << 16U) | \
00445                          ((uint32_t)pBuffer[(4U * i) + 2U] << 8U)  | \
00446                          (uint32_t)pBuffer[(4U * i) + 3U];
00447   }
00448   /* last bytes specific handling */
00449   if ((BufferLength % 4U) != 0U)
00450   {
00451     if ((BufferLength % 4U) == 1U)
00452     {
00453       *(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[4U * i];         /* Derogation MisraC2012 R.11.5 */
00454     }
00455     if ((BufferLength % 4U) == 2U)
00456     {
00457       data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) + 1U];
00458       pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR);                    /* Derogation MisraC2012 R.11.5 */
00459       *pReg = data;
00460     }
00461     if ((BufferLength % 4U) == 3U)
00462     {
00463       data = ((uint16_t)(pBuffer[4U * i]) << 8U) | (uint16_t)pBuffer[(4U * i) + 1U];
00464       pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR);                    /* Derogation MisraC2012 R.11.5 */
00465       *pReg = data;
00466 
00467       *(__IO uint8_t *)(__IO void *)(&hcrc->Instance->DR) = pBuffer[(4U * i) + 2U];  /* Derogation MisraC2012 R.11.5 */
00468     }
00469   }
00470 
00471   /* Return the CRC computed value */
00472   return hcrc->Instance->DR;
00473 }
00474 
00475 /**
00476   * @brief  Enter 16-bit input data to the CRC calculator.
00477   *         Specific data handling to optimize processing time.
00478   * @param  hcrc CRC handle
00479   * @param  pBuffer pointer to the input data buffer
00480   * @param  BufferLength input data buffer length
00481   * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
00482   */
00483 static uint32_t CRC_Handle_16(CRC_HandleTypeDef *hcrc, uint16_t pBuffer[], uint32_t BufferLength)
00484 {
00485   uint32_t i;  /* input data buffer index */
00486   __IO uint16_t *pReg;
00487 
00488   /* Processing time optimization: 2 HalfWords are entered in a row with a single word write,
00489    * in case of odd length, last HalfWord must be carefully fed to the CRC calculator to ensure
00490    * a correct type handling by the peripheral */
00491   for (i = 0U; i < (BufferLength / 2U); i++)
00492   {
00493     hcrc->Instance->DR = ((uint32_t)pBuffer[2U * i] << 16U) | (uint32_t)pBuffer[(2U * i) + 1U];
00494   }
00495   if ((BufferLength % 2U) != 0U)
00496   {
00497     pReg = (__IO uint16_t *)(__IO void *)(&hcrc->Instance->DR);                 /* Derogation MisraC2012 R.11.5 */
00498     *pReg = pBuffer[2U * i];
00499   }
00500 
00501   /* Return the CRC computed value */
00502   return hcrc->Instance->DR;
00503 }
00504 
00505 /**
00506   * @}
00507   */
00508 
00509 #endif /* HAL_CRC_MODULE_ENABLED */
00510 /**
00511   * @}
00512   */
00513 
00514 /**
00515   * @}
00516   */