| /* |
| * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. |
| * Copyright 2016-2017 NXP |
| * |
| * Redistribution and use in source and binary forms, with or without modification, |
| * are permitted provided that the following conditions are met: |
| * |
| * o Redistributions of source code must retain the above copyright notice, this list |
| * of conditions and the following disclaimer. |
| * |
| * o Redistributions in binary form must reproduce the above copyright notice, this |
| * list of conditions and the following disclaimer in the documentation and/or |
| * other materials provided with the distribution. |
| * |
| * o Neither the name of the copyright holder nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
| * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| #include "fsl_crc.h" |
| |
| /******************************************************************************* |
| * Definitions |
| ******************************************************************************/ |
| /*! @internal @brief Has data register with name CRC. */ |
| #if defined(FSL_FEATURE_CRC_HAS_CRC_REG) && FSL_FEATURE_CRC_HAS_CRC_REG |
| #define DATA CRC |
| #define DATALL CRCLL |
| #endif |
| |
| #if defined(CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT) && CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT |
| /* @brief Default user configuration structure for CRC-16-CCITT */ |
| #define CRC_DRIVER_DEFAULT_POLYNOMIAL 0x1021U |
| /*< CRC-16-CCIT polynomial x**16 + x**12 + x**5 + x**0 */ |
| #define CRC_DRIVER_DEFAULT_SEED 0xFFFFU |
| /*< Default initial checksum */ |
| #define CRC_DRIVER_DEFAULT_REFLECT_IN false |
| /*< Default is no transpose */ |
| #define CRC_DRIVER_DEFAULT_REFLECT_OUT false |
| /*< Default is transpose bytes */ |
| #define CRC_DRIVER_DEFAULT_COMPLEMENT_CHECKSUM false |
| /*< Default is without complement of CRC data register read data */ |
| #define CRC_DRIVER_DEFAULT_CRC_BITS kCrcBits16 |
| /*< Default is 16-bit CRC protocol */ |
| #define CRC_DRIVER_DEFAULT_CRC_RESULT kCrcFinalChecksum |
| /*< Default is resutl type is final checksum */ |
| #endif /* CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT */ |
| |
| /*! @brief CRC type of transpose of read write data */ |
| typedef enum _crc_transpose_type |
| { |
| kCrcTransposeNone = 0U, /*! No transpose */ |
| kCrcTransposeBits = 1U, /*! Tranpose bits in bytes */ |
| kCrcTransposeBitsAndBytes = 2U, /*! Transpose bytes and bits in bytes */ |
| kCrcTransposeBytes = 3U, /*! Transpose bytes */ |
| } crc_transpose_type_t; |
| |
| /*! |
| * @brief CRC module configuration. |
| * |
| * This structure holds the configuration for the CRC module. |
| */ |
| typedef struct _crc_module_config |
| { |
| uint32_t polynomial; /*!< CRC Polynomial, MSBit first.@n |
| Example polynomial: 0x1021 = 1_0000_0010_0001 = x^12+x^5+1 */ |
| uint32_t seed; /*!< Starting checksum value */ |
| crc_transpose_type_t readTranspose; /*!< Type of transpose when reading CRC result. */ |
| crc_transpose_type_t writeTranspose; /*!< Type of transpose when writing CRC input data. */ |
| bool complementChecksum; /*!< True if the result shall be complement of the actual checksum. */ |
| crc_bits_t crcBits; /*!< Selects 16- or 32- bit CRC protocol. */ |
| } crc_module_config_t; |
| |
| /******************************************************************************* |
| * Code |
| ******************************************************************************/ |
| |
| /*! |
| * @brief Returns transpose type for CRC protocol reflect in parameter. |
| * |
| * This functions helps to set writeTranspose member of crc_config_t structure. Reflect in is CRC protocol parameter. |
| * |
| * @param enable True or false for the selected CRC protocol Reflect In (refin) parameter. |
| */ |
| static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectIn(bool enable) |
| { |
| return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeBytes); |
| } |
| |
| /*! |
| * @brief Returns transpose type for CRC protocol reflect out parameter. |
| * |
| * This functions helps to set readTranspose member of crc_config_t structure. Reflect out is CRC protocol parameter. |
| * |
| * @param enable True or false for the selected CRC protocol Reflect Out (refout) parameter. |
| */ |
| static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectOut(bool enable) |
| { |
| return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeNone); |
| } |
| |
| /*! |
| * @brief Starts checksum computation. |
| * |
| * Configures the CRC module for the specified CRC protocol. @n |
| * Starts the checksum computation by writing the seed value |
| * |
| * @param base CRC peripheral address. |
| * @param config Pointer to protocol configuration structure. |
| */ |
| static void CRC_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *config) |
| { |
| uint32_t crcControl; |
| |
| /* pre-compute value for CRC control registger based on user configuraton without WAS field */ |
| crcControl = 0 | CRC_CTRL_TOT(config->writeTranspose) | CRC_CTRL_TOTR(config->readTranspose) | |
| CRC_CTRL_FXOR(config->complementChecksum) | CRC_CTRL_TCRC(config->crcBits); |
| |
| /* make sure the control register is clear - WAS is deasserted, and protocol is set */ |
| base->CTRL = crcControl; |
| |
| /* write polynomial register */ |
| base->GPOLY = config->polynomial; |
| |
| /* write pre-computed control register value along with WAS to start checksum computation */ |
| base->CTRL = crcControl | CRC_CTRL_WAS(true); |
| |
| /* write seed (initial checksum) */ |
| base->DATA = config->seed; |
| |
| /* deassert WAS by writing pre-computed CRC control register value */ |
| base->CTRL = crcControl; |
| } |
| |
| /*! |
| * @brief Starts final checksum computation. |
| * |
| * Configures the CRC module for the specified CRC protocol. @n |
| * Starts final checksum computation by writing the seed value. |
| * @note CRC_Get16bitResult() or CRC_Get32bitResult() return final checksum |
| * (output reflection and xor functions are applied). |
| * |
| * @param base CRC peripheral address. |
| * @param protocolConfig Pointer to protocol configuration structure. |
| */ |
| static void CRC_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) |
| { |
| crc_module_config_t moduleConfig; |
| /* convert protocol to CRC peripheral module configuration, prepare for final checksum */ |
| moduleConfig.polynomial = protocolConfig->polynomial; |
| moduleConfig.seed = protocolConfig->seed; |
| moduleConfig.readTranspose = CRC_GetTransposeTypeFromReflectOut(protocolConfig->reflectOut); |
| moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); |
| moduleConfig.complementChecksum = protocolConfig->complementChecksum; |
| moduleConfig.crcBits = protocolConfig->crcBits; |
| |
| CRC_ConfigureAndStart(base, &moduleConfig); |
| } |
| |
| /*! |
| * @brief Starts intermediate checksum computation. |
| * |
| * Configures the CRC module for the specified CRC protocol. @n |
| * Starts intermediate checksum computation by writing the seed value. |
| * @note CRC_Get16bitResult() or CRC_Get32bitResult() return intermediate checksum (raw data register value). |
| * |
| * @param base CRC peripheral address. |
| * @param protocolConfig Pointer to protocol configuration structure. |
| */ |
| static void CRC_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig) |
| { |
| crc_module_config_t moduleConfig; |
| /* convert protocol to CRC peripheral module configuration, prepare for intermediate checksum */ |
| moduleConfig.polynomial = protocolConfig->polynomial; |
| moduleConfig.seed = protocolConfig->seed; |
| moduleConfig.readTranspose = |
| kCrcTransposeNone; /* intermediate checksum does no transpose of data register read value */ |
| moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn); |
| moduleConfig.complementChecksum = false; /* intermediate checksum does no xor of data register read value */ |
| moduleConfig.crcBits = protocolConfig->crcBits; |
| |
| CRC_ConfigureAndStart(base, &moduleConfig); |
| } |
| |
| void CRC_Init(CRC_Type *base, const crc_config_t *config) |
| { |
| #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
| /* ungate clock */ |
| CLOCK_EnableClock(kCLOCK_Crc0); |
| #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
| /* configure CRC module and write the seed */ |
| if (config->crcResult == kCrcFinalChecksum) |
| { |
| CRC_SetProtocolConfig(base, config); |
| } |
| else |
| { |
| CRC_SetRawProtocolConfig(base, config); |
| } |
| } |
| |
| void CRC_GetDefaultConfig(crc_config_t *config) |
| { |
| static const crc_config_t crc16ccit = { |
| CRC_DRIVER_DEFAULT_POLYNOMIAL, CRC_DRIVER_DEFAULT_SEED, |
| CRC_DRIVER_DEFAULT_REFLECT_IN, CRC_DRIVER_DEFAULT_REFLECT_OUT, |
| CRC_DRIVER_DEFAULT_COMPLEMENT_CHECKSUM, CRC_DRIVER_DEFAULT_CRC_BITS, |
| CRC_DRIVER_DEFAULT_CRC_RESULT, |
| }; |
| |
| *config = crc16ccit; |
| } |
| |
| void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize) |
| { |
| const uint32_t *data32; |
| |
| /* 8-bit reads and writes till source address is aligned 4 bytes */ |
| while ((dataSize) && ((uint32_t)data & 3U)) |
| { |
| base->ACCESS8BIT.DATALL = *data; |
| data++; |
| dataSize--; |
| } |
| |
| /* use 32-bit reads and writes as long as possible */ |
| data32 = (const uint32_t *)data; |
| while (dataSize >= sizeof(uint32_t)) |
| { |
| base->DATA = *data32; |
| data32++; |
| dataSize -= sizeof(uint32_t); |
| } |
| |
| data = (const uint8_t *)data32; |
| |
| /* 8-bit reads and writes till end of data buffer */ |
| while (dataSize) |
| { |
| base->ACCESS8BIT.DATALL = *data; |
| data++; |
| dataSize--; |
| } |
| } |
| |
| uint32_t CRC_Get32bitResult(CRC_Type *base) |
| { |
| return base->DATA; |
| } |
| |
| uint16_t CRC_Get16bitResult(CRC_Type *base) |
| { |
| uint32_t retval; |
| uint32_t totr; /* type of transpose read bitfield */ |
| |
| retval = base->DATA; |
| totr = (base->CTRL & CRC_CTRL_TOTR_MASK) >> CRC_CTRL_TOTR_SHIFT; |
| |
| /* check transpose type to get 16-bit out of 32-bit register */ |
| if (totr >= 2U) |
| { |
| /* transpose of bytes for read is set, the result CRC is in CRC_DATA[HU:HL] */ |
| retval &= 0xFFFF0000U; |
| retval = retval >> 16U; |
| } |
| else |
| { |
| /* no transpose of bytes for read, the result CRC is in CRC_DATA[LU:LL] */ |
| retval &= 0x0000FFFFU; |
| } |
| return (uint16_t)retval; |
| } |