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