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