1 /**
2 * @file xmc_fce.c
3 * @date 2019-03-30
4 *
5 * @cond
6 *********************************************************************************************************************
7 * XMClib v2.1.24 - XMC Peripheral Driver Library
8 *
9 * Copyright (c) 2015-2019, Infineon Technologies AG
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
13 * following conditions are met:
14 *
15 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided with the distribution.
20 *
21 * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
22 * products derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
33 * Infineon Technologies AG dave@infineon.com).
34 *********************************************************************************************************************
35 *
36 * Change History
37 * --------------
38 *
39 * 2015-02-20:
40 * - Initial <br>
41 *
42 * 2015-06-20:
43 * - Removed GetDriverVersion API
44 *
45 * 2017-12-14:
46 * - XMC_FCE_CalculateCRC8()
47 * Ensure 32bit access to IR register
48 * - XMC_FCE_CalculateCRC16()
49 * Ensure 32bit access to IR register
50 * Remove restriction on data source allignment
51 * - XMC_FCE_CalculateCRC32()
52 * Ensure 32bit access to IR register
53 * Remove restriction on data source allignment
54 *
55 * 2019-03-30:
56 * - Added XMC_FCE_CalculateCRC16Ex() and XMC_FCE_CalculateCRC32Ex()
57 *
58 * @endcond
59 *
60 */
61
62 /**********************************************************************************************************************
63 * HEADER FILES
64 *********************************************************************************************************************/
65 #include <xmc_fce.h>
66
67 #if defined (FCE)
68 #include <xmc_scu.h>
69
70 /*******************************************************************************
71 * API IMPLEMENTATION
72 *********************************************************************************************************************/
73
74 /*
75 * Initialize the FCE peripheral:
76 * Update FCE configuration and initialize seed value
77 */
XMC_FCE_Init(const XMC_FCE_t * const engine)78 XMC_FCE_STATUS_t XMC_FCE_Init(const XMC_FCE_t *const engine)
79 {
80 engine->kernel_ptr->CFG = engine->fce_cfg_update.regval;
81 engine->kernel_ptr->CRC = engine->seedvalue;
82
83 return XMC_FCE_STATUS_OK;
84 }
85
86 /* Disable FCE */
XMC_FCE_Disable(void)87 void XMC_FCE_Disable(void)
88 {
89 FCE->CLC |= (uint32_t)FCE_CLC_DISR_Msk;
90
91 XMC_SCU_RESET_AssertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_FCE);
92
93 #if defined(CLOCK_GATING_SUPPORTED)
94 XMC_SCU_CLOCK_GatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_FCE);
95 #endif
96
97 }
98
99 /* Enable FCE */
XMC_FCE_Enable(void)100 void XMC_FCE_Enable(void)
101 {
102 #if defined(CLOCK_GATING_SUPPORTED)
103 XMC_SCU_CLOCK_UngatePeripheralClock(XMC_SCU_PERIPHERAL_CLOCK_FCE);
104 #endif
105
106 XMC_SCU_RESET_DeassertPeripheralReset(XMC_SCU_PERIPHERAL_RESET_FCE);
107
108 FCE->CLC &= (uint32_t)~FCE_CLC_DISR_Msk;
109 }
110
111 /* Calculate and return the SAE J1850 CRC8 checksum */
XMC_FCE_CalculateCRC8(const XMC_FCE_t * const engine,const uint8_t * data,uint32_t length,uint8_t * result)112 XMC_FCE_STATUS_t XMC_FCE_CalculateCRC8(const XMC_FCE_t *const engine,
113 const uint8_t *data,
114 uint32_t length,
115 uint8_t *result)
116 {
117 XMC_FCE_STATUS_t status = XMC_FCE_STATUS_OK;
118
119 XMC_ASSERT("XMC_FCE_CalculateCRC8: Wrong FCE kernel used", (engine -> kernel_ptr == XMC_FCE_CRC8));
120
121 if (length == 0UL)
122 {
123 status = XMC_FCE_STATUS_ERROR;
124 }
125 else
126 {
127 while (0UL != length)
128 {
129 engine->kernel_ptr->IR = (uint32_t)*data;
130 data++;
131 length -= 1U;
132 }
133
134 *result = (uint8_t)engine->kernel_ptr->CRC;
135 }
136
137 return status;
138 }
139
140 /* Calculate and return calculated CCITT CRC16 checksum */
XMC_FCE_CalculateCRC16(const XMC_FCE_t * const engine,const uint16_t * data,uint32_t length,uint16_t * result)141 XMC_FCE_STATUS_t XMC_FCE_CalculateCRC16(const XMC_FCE_t *const engine,
142 const uint16_t *data,
143 uint32_t length,
144 uint16_t *result)
145 {
146 XMC_FCE_STATUS_t status = XMC_FCE_STATUS_OK;
147
148 XMC_ASSERT("XMC_FCE_CalculateCRC16: Wrong FCE kernel used", (engine -> kernel_ptr == XMC_FCE_CRC16));
149 XMC_ASSERT("XMC_FCE_CalculateCRC16: Length field is empty", (length != 0));
150 XMC_ASSERT("XMC_FCE_CalculateCRC16: Length is not aligned", ((length & 0x1U) == 0));
151
152 /* Check length is a multiple of 2 */
153 if ((length == 0) || ((length & 0x1U) != 0U))
154 {
155 status = XMC_FCE_STATUS_ERROR;
156 }
157 else
158 {
159 while (0UL != length)
160 {
161 engine->kernel_ptr->IR = (uint32_t)*data;
162 data++;
163 length -= 2U;
164 }
165
166 *result = (uint16_t)engine->kernel_ptr->CRC;
167 }
168
169 return status;
170 }
171
XMC_FCE_CalculateCRC16Ex(const XMC_FCE_t * const engine,const uint8_t * data,uint32_t length,uint16_t * const result)172 XMC_FCE_STATUS_t XMC_FCE_CalculateCRC16Ex(const XMC_FCE_t *const engine,
173 const uint8_t *data,
174 uint32_t length,
175 uint16_t *const result)
176 {
177 XMC_FCE_STATUS_t status = XMC_FCE_STATUS_OK;
178
179 XMC_ASSERT("XMC_FCE_CalculateCRC16: Wrong FCE kernel used", (engine -> kernel_ptr == XMC_FCE_CRC16));
180 XMC_ASSERT("XMC_FCE_CalculateCRC16: Length field is empty", (length != 0));
181 XMC_ASSERT("XMC_FCE_CalculateCRC16: Length is not aligned", ((length & 0x1U) == 0));
182
183 /* Check length is a multiple of 2 */
184 if ((length == 0) || ((length & 0x1U) != 0U))
185 {
186 status = XMC_FCE_STATUS_ERROR;
187 }
188 else
189 {
190 const uint16_t *p = (const uint16_t *)data;
191 while (0UL != length)
192 {
193 engine->kernel_ptr->IR = __REV16(*p);
194 ++p;
195 length -= 2U;
196 }
197
198 *result = (uint16_t)engine->kernel_ptr->CRC;
199 }
200
201 return status;
202 }
203
204 /* Calculate and return the IEEE 802.3 Ethernet CRC32 checksum */
XMC_FCE_CalculateCRC32(const XMC_FCE_t * const engine,const uint32_t * data,uint32_t length,uint32_t * result)205 XMC_FCE_STATUS_t XMC_FCE_CalculateCRC32(const XMC_FCE_t *const engine,
206 const uint32_t *data,
207 uint32_t length,
208 uint32_t *result)
209 {
210 XMC_FCE_STATUS_t status = XMC_FCE_STATUS_OK;
211
212 XMC_ASSERT("XMC_FCE_CalculateCRC32: Wrong FCE kernel used", ((engine->kernel_ptr == XMC_FCE_CRC32_0) ||
213 (engine->kernel_ptr == XMC_FCE_CRC32_1)));
214 XMC_ASSERT("XMC_FCE_CalculateCRC32: Length field is empty", (length != 0));
215 XMC_ASSERT("XMC_FCE_CalculateCRC32: Length is not aligned", ((length & 0x3U) == 0));
216
217 /* Check length is a multiple of 4 */
218 if ((length == 0) || ((length & 0x3U) != 0U))
219 {
220 status = XMC_FCE_STATUS_ERROR;
221 }
222 else
223 {
224 while (0UL != length)
225 {
226 engine->kernel_ptr->IR = *data;
227 data++;
228 length -= 4U;
229 }
230
231 *result = engine->kernel_ptr->CRC;
232 }
233
234 return status;
235 }
236
237 /* Calculate and return the IEEE 802.3 Ethernet CRC32 checksum */
XMC_FCE_CalculateCRC32Ex(const XMC_FCE_t * const engine,const uint8_t * data,uint32_t length,uint32_t * const result)238 XMC_FCE_STATUS_t XMC_FCE_CalculateCRC32Ex(const XMC_FCE_t *const engine,
239 const uint8_t *data,
240 uint32_t length,
241 uint32_t *const result)
242 {
243 XMC_FCE_STATUS_t status = XMC_FCE_STATUS_OK;
244
245 XMC_ASSERT("XMC_FCE_CalculateCRC32: Wrong FCE kernel used", ((engine->kernel_ptr == XMC_FCE_CRC32_0) ||
246 (engine->kernel_ptr == XMC_FCE_CRC32_1)));
247 XMC_ASSERT("XMC_FCE_CalculateCRC32: Length field is empty", (length != 0));
248 XMC_ASSERT("XMC_FCE_CalculateCRC32: Length is not aligned", ((length & 0x3U) == 0));
249
250 /* Check length is a multiple of 4 */
251 if ((length == 0) || ((length & 0x3U) != 0U))
252 {
253 status = XMC_FCE_STATUS_ERROR;
254 }
255 else
256 {
257 const uint32_t *p = (const uint32_t *)data;
258 while (0UL != length)
259 {
260 engine->kernel_ptr->IR = __REV(*p);
261 ++p;
262 length -= 4U;
263 }
264
265 *result = engine->kernel_ptr->CRC;
266 }
267
268 return status;
269 }
270
271 /* Trigger mismatch in the CRC registers */
XMC_FCE_TriggerMismatch(const XMC_FCE_t * const engine,XMC_FCE_CTR_TEST_t test)272 void XMC_FCE_TriggerMismatch(const XMC_FCE_t *const engine, XMC_FCE_CTR_TEST_t test)
273 {
274 /* Create a 0 to 1 transition and clear to 0 once it is done */
275 engine->kernel_ptr->CTR &= ~((uint32_t)test);
276 engine->kernel_ptr->CTR |= (uint32_t)test;
277 engine->kernel_ptr->CTR &= ~((uint32_t)test);
278 }
279
280 /* Change endianness of 16-bit input buffer */
XMC_FCE_LittleEndian16bit(uint8_t * inbuffer,uint16_t * outbuffer,uint16_t length)281 void XMC_FCE_LittleEndian16bit(uint8_t* inbuffer, uint16_t* outbuffer, uint16_t length)
282 {
283 uint16_t counter = 0U;
284 uint16_t bytecounter = 0U;
285
286 if ((length & 0x01U) == 0)
287 {
288 for (counter = 0U; counter < (length >> 1); counter++)
289 {
290 outbuffer[counter] = 0U;
291 }
292
293 outbuffer[counter] = 0U;
294 counter = 0U;
295
296 while (length)
297 {
298 outbuffer[counter] = ((uint16_t)((uint16_t)inbuffer[bytecounter] << 8U) |
299 (inbuffer[bytecounter + 1U]));
300 counter += 1U;
301 bytecounter += 2U;
302 length -= 2U;
303 }
304 }
305 }
306
307 /* Change endianness of 32-bit input buffer */
XMC_FCE_LittleEndian32bit(uint8_t * inbuffer,uint32_t * outbuffer,uint16_t length)308 void XMC_FCE_LittleEndian32bit(uint8_t* inbuffer, uint32_t* outbuffer, uint16_t length)
309 {
310 uint16_t counter = 0U;
311 uint16_t bytecounter = 0U;
312
313 if ((length & 0x03U) == 0)
314 {
315 for (counter = 0U; counter < (length >> 2U); counter++)
316 {
317 outbuffer[counter] = 0U;
318 }
319
320 outbuffer[counter] = 0U;
321 counter = 0U;
322
323 while (length)
324 {
325 outbuffer[counter] = ((uint32_t)inbuffer[bytecounter] << 24U) |
326 ((uint32_t)inbuffer[bytecounter + 1U] << 16U) |
327 ((uint32_t)inbuffer[bytecounter + 2U] << 8U) |
328 (inbuffer[bytecounter + 3U]);
329 counter += 1U;
330 bytecounter += 4U;
331 length -= 4U;
332 }
333 }
334 }
335
336 #endif
337