1 /***************************************************************************//**
2 * @file
3 * @brief General Purpose Cyclic Redundancy Check (GPCRC) API.
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 #ifndef EM_GPCRC_H
32 #define EM_GPCRC_H
33
34 #include "em_bus.h"
35 #include "em_device.h"
36 #if defined(GPCRC_PRESENT) && (GPCRC_COUNT > 0)
37
38 #include <stdint.h>
39 #include <stdbool.h>
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 /***************************************************************************//**
46 * @addtogroup gpcrc GPCRC - General Purpose CRC
47 * @brief General Purpose Cyclic Redundancy Check (GPCRC) API
48 *
49 * @details
50 * The GPCRC API functions provide full support for the GPCRC peripheral.
51 *
52 * The GPCRC module is a peripheral that implements a Cyclic Redundancy Check
53 * (CRC) function. It supports a fixed 32-bit polynomial and a user
54 * configurable 16-bit polynomial. The fixed 32-bit polynomial is the commonly
55 * used IEEE 802.3 polynomial 0x04C11DB7.
56 *
57 * When using a 16-bit polynomial it is up to the user to choose a polynomial
58 * that fits the application. Commonly used 16-bit polynomials are 0x1021
59 * (CCITT-16), 0x3D65 (IEC16-MBus), and 0x8005 (ZigBee, 802.15.4, and USB).
60 * See this link for other polynomials:
61 * https://en.wikipedia.org/wiki/Cyclic_redundancy_check
62 *
63 * Before a CRC calculation can begin, call the
64 * @ref GPCRC_Start function. This function will reset CRC calculation
65 * by copying the configured initialization value over to the CRC data register.
66 *
67 * There are two ways of sending input data to the GPCRC. Either write
68 * the input data into the input data register using input functions
69 * @ref GPCRC_InputU32, @ref GPCRC_InputU16 and @ref GPCRC_InputU8, or the
70 * user can configure @ref ldma to transfer data directly to one of the GPCRC
71 * input data registers.
72 *
73 * <b> Examples of GPCRC usage: </b>
74 *
75 * A CRC-32 Calculation:
76 *
77 * @include em_gpcrc_crc32.c
78 *
79 * A CRC-16 Calculation:
80 *
81 * @include em_gpcrc_crc16.c
82 *
83 * A CRC-CCITT calculation:
84 *
85 * @include em_gpcrc_ccit.c
86 *
87 * @{
88 ******************************************************************************/
89
90 /*******************************************************************************
91 ******************************* STRUCTS ***********************************
92 ******************************************************************************/
93
94 /** CRC initialization structure. */
95 typedef struct {
96 /**
97 * CRC polynomial value. GPCRC supports either a fixed 32-bit polynomial
98 * or a user-configurable 16 bit polynomial. The fixed 32-bit polynomial
99 * is the one used in IEEE 802.3, which has the value 0x04C11DB7. To use the
100 * 32-bit fixed polynomial, assign 0x04C11DB7 to the crcPoly field.
101 * To use a 16-bit polynomial, assign a value to crcPoly where the upper 16
102 * bits are zero.
103 *
104 * The polynomial should be written in normal bit order. For instance,
105 * to use the CRC-16 polynomial X^16 + X^15 + X^2 + 1, first convert
106 * it to hex representation and remove the highest order term
107 * of the polynomial. This will give 0x8005 as the value to write into
108 * crcPoly.
109 */
110 uint32_t crcPoly;
111
112 /**
113 * CRC initialization value. This value is assigned to the GPCRC_INIT register.
114 * The initValue is loaded into the data register when calling the
115 * @ref GPCRC_Start function or when one of the data registers are read
116 * while @ref autoInit is enabled.
117 */
118 uint32_t initValue;
119
120 /**
121 * Reverse byte order. This has an effect when sending a 32-bit word or
122 * 16-bit half word input to the CRC calculation. When set to true, the input
123 * bytes are reversed before entering the CRC calculation. When set to
124 * false, the input bytes stay in the same order.
125 */
126 bool reverseByteOrder;
127
128 /**
129 * Reverse bits within each input byte. This setting enables or disables byte
130 * level bit reversal. When byte-level bit reversal is enabled, then each byte
131 * of input data will be reversed before entering CRC calculation.
132 */
133 bool reverseBits;
134
135 /**
136 * Enable/disable byte mode. When byte mode is enabled, then all input
137 * is treated as single byte input even though the input is a 32-bit word
138 * or a 16-bit half word. Only the least significant byte of the data-word
139 * will be used for CRC calculation for all writes.
140 */
141 bool enableByteMode;
142
143 /**
144 * Enable automatic initialization by re-seeding the CRC result based on
145 * the init value after reading one of the CRC data registers.
146 */
147 bool autoInit;
148
149 /** Enable/disable GPCRC when initialization is completed. */
150 bool enable;
151 } GPCRC_Init_TypeDef;
152
153 /** Default configuration for GPCRC_Init_TypeDef structure. */
154 #define GPCRC_INIT_DEFAULT \
155 { \
156 0x04C11DB7UL, /* CRC32 Polynomial value. */ \
157 0x00000000UL, /* Initialization value. */ \
158 false, /* Byte order is normal. */ \
159 false, /* Bit order is not reversed on output. */ \
160 false, /* Disable byte mode. */ \
161 false, /* Disable automatic initialization on data read. */ \
162 true, /* Enable GPCRC. */ \
163 }
164
165 /*******************************************************************************
166 ****************************** PROTOTYPES *********************************
167 ******************************************************************************/
168
169 void GPCRC_Init(GPCRC_TypeDef * gpcrc, const GPCRC_Init_TypeDef * init);
170 void GPCRC_Reset(GPCRC_TypeDef * gpcrc);
171
172 /***************************************************************************//**
173 * @brief
174 * Enable/disable GPCRC.
175 *
176 * @param[in] gpcrc
177 * Pointer to GPCRC peripheral register block.
178 *
179 * @param[in] enable
180 * True to enable GPCRC, false to disable.
181 ******************************************************************************/
GPCRC_Enable(GPCRC_TypeDef * gpcrc,bool enable)182 __STATIC_INLINE void GPCRC_Enable(GPCRC_TypeDef * gpcrc, bool enable)
183 {
184 #if defined(GPCRC_EN_EN)
185 BUS_RegBitWrite(&gpcrc->EN, _GPCRC_EN_EN_SHIFT, enable);
186 #else
187 BUS_RegBitWrite(&gpcrc->CTRL, _GPCRC_CTRL_EN_SHIFT, enable);
188 #endif
189 }
190
191 /***************************************************************************//**
192 * @brief
193 * Issue a command to initialize the CRC calculation.
194 *
195 * @details
196 * Issues the command INIT in GPCRC_CMD that initializes the
197 * CRC calculation by writing the initial values to the DATA register.
198 *
199 * @param[in] gpcrc
200 * Pointer to GPCRC peripheral register block.
201 ******************************************************************************/
GPCRC_Start(GPCRC_TypeDef * gpcrc)202 __STATIC_INLINE void GPCRC_Start(GPCRC_TypeDef * gpcrc)
203 {
204 gpcrc->CMD = GPCRC_CMD_INIT;
205 }
206
207 /***************************************************************************//**
208 * @brief
209 * Set the initialization value of the CRC.
210 *
211 * @param [in] initValue
212 * Value to use to initialize a CRC calculation. This value is moved into
213 * the data register when calling @ref GPCRC_Start
214 *
215 * @param[in] gpcrc
216 * Pointer to GPCRC peripheral register block.
217 ******************************************************************************/
GPCRC_InitValueSet(GPCRC_TypeDef * gpcrc,uint32_t initValue)218 __STATIC_INLINE void GPCRC_InitValueSet(GPCRC_TypeDef * gpcrc, uint32_t initValue)
219 {
220 gpcrc->INIT = initValue;
221 }
222
223 /***************************************************************************//**
224 * @brief
225 * Write a 32-bit value to the input data register of the CRC.
226 *
227 * @details
228 * Use this function to write a 32-bit input data to the CRC. CRC
229 * calculation is based on the provided input data using the configured
230 * CRC polynomial.
231 *
232 * @param[in] gpcrc
233 * Pointer to GPCRC peripheral register block.
234 *
235 * @param[in] data
236 * Data to be written to the input data register.
237 ******************************************************************************/
GPCRC_InputU32(GPCRC_TypeDef * gpcrc,uint32_t data)238 __STATIC_INLINE void GPCRC_InputU32(GPCRC_TypeDef * gpcrc, uint32_t data)
239 {
240 gpcrc->INPUTDATA = data;
241 }
242
243 /***************************************************************************//**
244 * @brief
245 * Write a 16-bit value to the input data register of the CRC.
246 *
247 * @details
248 * Use this function to write a 16 bit input data to the CRC. CRC
249 * calculation is based on the provided input data using the configured
250 * CRC polynomial.
251 *
252 * @param[in] gpcrc
253 * Pointer to GPCRC peripheral register block.
254 *
255 * @param[in] data
256 * Data to be written to the input data register.
257 ******************************************************************************/
GPCRC_InputU16(GPCRC_TypeDef * gpcrc,uint16_t data)258 __STATIC_INLINE void GPCRC_InputU16(GPCRC_TypeDef * gpcrc, uint16_t data)
259 {
260 gpcrc->INPUTDATAHWORD = data;
261 }
262
263 /***************************************************************************//**
264 * @brief
265 * Write an 8-bit value to the CRC input data register.
266 *
267 * @details
268 * Use this function to write an 8-bit input data to the CRC. CRC
269 * calculation is based on the provided input data using the configured
270 * CRC polynomial.
271 *
272 * @param[in] gpcrc
273 * Pointer to GPCRC peripheral register block.
274 *
275 * @param[in] data
276 * Data to be written to the input data register.
277 ******************************************************************************/
GPCRC_InputU8(GPCRC_TypeDef * gpcrc,uint8_t data)278 __STATIC_INLINE void GPCRC_InputU8(GPCRC_TypeDef * gpcrc, uint8_t data)
279 {
280 gpcrc->INPUTDATABYTE = data;
281 }
282
283 /***************************************************************************//**
284 * @brief
285 * Read the CRC data register.
286 *
287 * @details
288 * Use this function to read the calculated CRC value.
289 *
290 * @param[in] gpcrc
291 * Pointer to GPCRC peripheral register block.
292 *
293 * @return
294 * Content of the CRC data register.
295 ******************************************************************************/
GPCRC_DataRead(GPCRC_TypeDef * gpcrc)296 __STATIC_INLINE uint32_t GPCRC_DataRead(GPCRC_TypeDef * gpcrc)
297 {
298 return gpcrc->DATA;
299 }
300
301 /***************************************************************************//**
302 * @brief
303 * Read the data register of the CRC bit reversed.
304 *
305 * @details
306 * Use this function to read the calculated CRC value bit reversed. When
307 * using a 32-bit polynomial, bits [31:0] are reversed, when using a
308 * 16-bit polynomial, bits [15:0] are reversed.
309 *
310 * @param[in] gpcrc
311 * Pointer to GPCRC peripheral register block.
312 *
313 * @return
314 * Content of the CRC data register bit reversed.
315 ******************************************************************************/
GPCRC_DataReadBitReversed(GPCRC_TypeDef * gpcrc)316 __STATIC_INLINE uint32_t GPCRC_DataReadBitReversed(GPCRC_TypeDef * gpcrc)
317 {
318 return gpcrc->DATAREV;
319 }
320
321 /***************************************************************************//**
322 * @brief
323 * Read the data register of the CRC byte reversed.
324 *
325 * @details
326 * Use this function to read the calculated CRC value byte reversed.
327 *
328 * @param[in] gpcrc
329 * Pointer to GPCRC peripheral register block.
330 *
331 * @return
332 * Content of the CRC data register byte reversed.
333 ******************************************************************************/
GPCRC_DataReadByteReversed(GPCRC_TypeDef * gpcrc)334 __STATIC_INLINE uint32_t GPCRC_DataReadByteReversed(GPCRC_TypeDef * gpcrc)
335 {
336 return gpcrc->DATABYTEREV;
337 }
338
339 /** @} (end addtogroup gpcrc) */
340
341 #ifdef __cplusplus
342 }
343 #endif
344
345 #endif /* defined(GPCRC_COUNT) && (GPCRC_COUNT > 0) */
346 #endif /* EM_GPCRC_H */
347