283 lines
11 KiB
C
283 lines
11 KiB
C
|
/*
|
||
|
* 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;
|
||
|
}
|