1 /*
2 * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8 #include "fsl_crc.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13 /*! @internal @brief Has data register with name CRC. */
14 #if defined(FSL_FEATURE_CRC_HAS_CRC_REG) && FSL_FEATURE_CRC_HAS_CRC_REG
15 #define DATA CRC
16 #define DATALL CRCLL
17 #endif
18
19 #if defined(CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT) && CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT
20 /* @brief Default user configuration structure for CRC-16-CCITT */
21 #define CRC_DRIVER_DEFAULT_POLYNOMIAL 0x1021U
22 /*< CRC-16-CCIT polynomial x**16 + x**12 + x**5 + x**0 */
23 #define CRC_DRIVER_DEFAULT_SEED 0xFFFFU
24 /*< Default initial checksum */
25 #define CRC_DRIVER_DEFAULT_REFLECT_IN false
26 /*< Default is no transpose */
27 #define CRC_DRIVER_DEFAULT_REFLECT_OUT false
28 /*< Default is transpose bytes */
29 #define CRC_DRIVER_DEFAULT_COMPLEMENT_CHECKSUM false
30 /*< Default is without complement of CRC data register read data */
31 #define CRC_DRIVER_DEFAULT_CRC_BITS kCrcBits16
32 /*< Default is 16-bit CRC protocol */
33 #define CRC_DRIVER_DEFAULT_CRC_RESULT kCrcFinalChecksum
34 /*< Default is resutl type is final checksum */
35 #endif /* CRC_DRIVER_USE_CRC16_CCIT_FALSE_AS_DEFAULT */
36
37 /*! @brief CRC type of transpose of read write data */
38 typedef enum _crc_transpose_type
39 {
40 kCrcTransposeNone = 0U, /*! No transpose */
41 kCrcTransposeBits = 1U, /*! Tranpose bits in bytes */
42 kCrcTransposeBitsAndBytes = 2U, /*! Transpose bytes and bits in bytes */
43 kCrcTransposeBytes = 3U, /*! Transpose bytes */
44 } crc_transpose_type_t;
45
46 /*!
47 * @brief CRC module configuration.
48 *
49 * This structure holds the configuration for the CRC module.
50 */
51 typedef struct _crc_module_config
52 {
53 uint32_t polynomial; /*!< CRC Polynomial, MSBit first.@n
54 Example polynomial: 0x1021 = 1_0000_0010_0001 = x^12+x^5+1 */
55 uint32_t seed; /*!< Starting checksum value */
56 crc_transpose_type_t readTranspose; /*!< Type of transpose when reading CRC result. */
57 crc_transpose_type_t writeTranspose; /*!< Type of transpose when writing CRC input data. */
58 bool complementChecksum; /*!< True if the result shall be complement of the actual checksum. */
59 crc_bits_t crcBits; /*!< Selects 16- or 32- bit CRC protocol. */
60 } crc_module_config_t;
61
62 /*******************************************************************************
63 * Code
64 ******************************************************************************/
65
66 /*!
67 * @brief Returns transpose type for CRC protocol reflect in parameter.
68 *
69 * This functions helps to set writeTranspose member of crc_config_t structure. Reflect in is CRC protocol parameter.
70 *
71 * @param enable True or false for the selected CRC protocol Reflect In (refin) parameter.
72 */
CRC_GetTransposeTypeFromReflectIn(bool enable)73 static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectIn(bool enable)
74 {
75 return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeBytes);
76 }
77
78 /*!
79 * @brief Returns transpose type for CRC protocol reflect out parameter.
80 *
81 * This functions helps to set readTranspose member of crc_config_t structure. Reflect out is CRC protocol parameter.
82 *
83 * @param enable True or false for the selected CRC protocol Reflect Out (refout) parameter.
84 */
CRC_GetTransposeTypeFromReflectOut(bool enable)85 static inline crc_transpose_type_t CRC_GetTransposeTypeFromReflectOut(bool enable)
86 {
87 return ((enable) ? kCrcTransposeBitsAndBytes : kCrcTransposeNone);
88 }
89
90 /*!
91 * @brief Starts checksum computation.
92 *
93 * Configures the CRC module for the specified CRC protocol. @n
94 * Starts the checksum computation by writing the seed value
95 *
96 * @param base CRC peripheral address.
97 * @param config Pointer to protocol configuration structure.
98 */
CRC_ConfigureAndStart(CRC_Type * base,const crc_module_config_t * config)99 static void CRC_ConfigureAndStart(CRC_Type *base, const crc_module_config_t *config)
100 {
101 uint32_t crcControl;
102
103 /* pre-compute value for CRC control registger based on user configuraton without WAS field */
104 crcControl = 0 | CRC_CTRL_TOT(config->writeTranspose) | CRC_CTRL_TOTR(config->readTranspose) |
105 CRC_CTRL_FXOR(config->complementChecksum) | CRC_CTRL_TCRC(config->crcBits);
106
107 /* make sure the control register is clear - WAS is deasserted, and protocol is set */
108 base->CTRL = crcControl;
109
110 /* write polynomial register */
111 base->GPOLY = config->polynomial;
112
113 /* write pre-computed control register value along with WAS to start checksum computation */
114 base->CTRL = crcControl | CRC_CTRL_WAS(true);
115
116 /* write seed (initial checksum) */
117 base->DATA = config->seed;
118
119 /* deassert WAS by writing pre-computed CRC control register value */
120 base->CTRL = crcControl;
121 }
122
123 /*!
124 * @brief Starts final checksum computation.
125 *
126 * Configures the CRC module for the specified CRC protocol. @n
127 * Starts final checksum computation by writing the seed value.
128 * @note CRC_Get16bitResult() or CRC_Get32bitResult() return final checksum
129 * (output reflection and xor functions are applied).
130 *
131 * @param base CRC peripheral address.
132 * @param protocolConfig Pointer to protocol configuration structure.
133 */
CRC_SetProtocolConfig(CRC_Type * base,const crc_config_t * protocolConfig)134 static void CRC_SetProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig)
135 {
136 crc_module_config_t moduleConfig;
137 /* convert protocol to CRC peripheral module configuration, prepare for final checksum */
138 moduleConfig.polynomial = protocolConfig->polynomial;
139 moduleConfig.seed = protocolConfig->seed;
140 moduleConfig.readTranspose = CRC_GetTransposeTypeFromReflectOut(protocolConfig->reflectOut);
141 moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn);
142 moduleConfig.complementChecksum = protocolConfig->complementChecksum;
143 moduleConfig.crcBits = protocolConfig->crcBits;
144
145 CRC_ConfigureAndStart(base, &moduleConfig);
146 }
147
148 /*!
149 * @brief Starts intermediate checksum computation.
150 *
151 * Configures the CRC module for the specified CRC protocol. @n
152 * Starts intermediate checksum computation by writing the seed value.
153 * @note CRC_Get16bitResult() or CRC_Get32bitResult() return intermediate checksum (raw data register value).
154 *
155 * @param base CRC peripheral address.
156 * @param protocolConfig Pointer to protocol configuration structure.
157 */
CRC_SetRawProtocolConfig(CRC_Type * base,const crc_config_t * protocolConfig)158 static void CRC_SetRawProtocolConfig(CRC_Type *base, const crc_config_t *protocolConfig)
159 {
160 crc_module_config_t moduleConfig;
161 /* convert protocol to CRC peripheral module configuration, prepare for intermediate checksum */
162 moduleConfig.polynomial = protocolConfig->polynomial;
163 moduleConfig.seed = protocolConfig->seed;
164 moduleConfig.readTranspose =
165 kCrcTransposeNone; /* intermediate checksum does no transpose of data register read value */
166 moduleConfig.writeTranspose = CRC_GetTransposeTypeFromReflectIn(protocolConfig->reflectIn);
167 moduleConfig.complementChecksum = false; /* intermediate checksum does no xor of data register read value */
168 moduleConfig.crcBits = protocolConfig->crcBits;
169
170 CRC_ConfigureAndStart(base, &moduleConfig);
171 }
172
CRC_Init(CRC_Type * base,const crc_config_t * config)173 void CRC_Init(CRC_Type *base, const crc_config_t *config)
174 {
175 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
176 /* ungate clock */
177 CLOCK_EnableClock(kCLOCK_Crc0);
178 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
179 /* configure CRC module and write the seed */
180 if (config->crcResult == kCrcFinalChecksum)
181 {
182 CRC_SetProtocolConfig(base, config);
183 }
184 else
185 {
186 CRC_SetRawProtocolConfig(base, config);
187 }
188 }
189
CRC_GetDefaultConfig(crc_config_t * config)190 void CRC_GetDefaultConfig(crc_config_t *config)
191 {
192 static const crc_config_t crc16ccit = {
193 CRC_DRIVER_DEFAULT_POLYNOMIAL, CRC_DRIVER_DEFAULT_SEED,
194 CRC_DRIVER_DEFAULT_REFLECT_IN, CRC_DRIVER_DEFAULT_REFLECT_OUT,
195 CRC_DRIVER_DEFAULT_COMPLEMENT_CHECKSUM, CRC_DRIVER_DEFAULT_CRC_BITS,
196 CRC_DRIVER_DEFAULT_CRC_RESULT,
197 };
198
199 *config = crc16ccit;
200 }
201
CRC_WriteData(CRC_Type * base,const uint8_t * data,size_t dataSize)202 void CRC_WriteData(CRC_Type *base, const uint8_t *data, size_t dataSize)
203 {
204 const uint32_t *data32;
205
206 /* 8-bit reads and writes till source address is aligned 4 bytes */
207 while ((dataSize) && ((uint32_t)data & 3U))
208 {
209 base->ACCESS8BIT.DATALL = *data;
210 data++;
211 dataSize--;
212 }
213
214 /* use 32-bit reads and writes as long as possible */
215 data32 = (const uint32_t *)data;
216 while (dataSize >= sizeof(uint32_t))
217 {
218 base->DATA = *data32;
219 data32++;
220 dataSize -= sizeof(uint32_t);
221 }
222
223 data = (const uint8_t *)data32;
224
225 /* 8-bit reads and writes till end of data buffer */
226 while (dataSize)
227 {
228 base->ACCESS8BIT.DATALL = *data;
229 data++;
230 dataSize--;
231 }
232 }
233
CRC_Get32bitResult(CRC_Type * base)234 uint32_t CRC_Get32bitResult(CRC_Type *base)
235 {
236 return base->DATA;
237 }
238
CRC_Get16bitResult(CRC_Type * base)239 uint16_t CRC_Get16bitResult(CRC_Type *base)
240 {
241 uint32_t retval;
242 uint32_t totr; /* type of transpose read bitfield */
243
244 retval = base->DATA;
245 totr = (base->CTRL & CRC_CTRL_TOTR_MASK) >> CRC_CTRL_TOTR_SHIFT;
246
247 /* check transpose type to get 16-bit out of 32-bit register */
248 if (totr >= 2U)
249 {
250 /* transpose of bytes for read is set, the result CRC is in CRC_DATA[HU:HL] */
251 retval &= 0xFFFF0000U;
252 retval = retval >> 16U;
253 }
254 else
255 {
256 /* no transpose of bytes for read, the result CRC is in CRC_DATA[LU:LL] */
257 retval &= 0x0000FFFFU;
258 }
259 return (uint16_t)retval;
260 }
261