1 /**
2 *********************************************************************************
3 *
4 * @file ald_crc.c
5 * @brief CRC module driver.
6 *
7 * @version V1.0
8 * @date 06 Mar. 2023
9 * @author AE Team
10 * @note
11 * Change Logs:
12 * Date Author Notes
13 * 06 Mar. 2023 Lisq The first version
14 *
15 * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 *
19 * Licensed under the Apache License, Version 2.0 (the License); you may
20 * not use this file except in compliance with the License.
21 * You may obtain a copy of the License at
22 *
23 * www.apache.org/licenses/LICENSE-2.0
24 *
25 * Unless required by applicable law or agreed to in writing, software
26 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
27 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28 * See the License for the specific language governing permissions and
29 * limitations under the License.
30 **********************************************************************************
31 */
32
33 #include "ald_crc.h"
34
35 /** @addtogroup ES32VF2264_ALD
36 * @{
37 */
38
39 /** @defgroup CRC CRC
40 * @brief CRC module driver
41 * @{
42 */
43 /** @addtogroup CRC_Private_Functions CRC Private Functions
44 * @{
45 */
46 void ald_crc_reset(ald_crc_handle_t *hperh);
47 static void crc_dma_calculate_cplt(void *arg);
48 /**
49 * @}
50 */
51
52
53 /** @defgroup CRC_Public_Functions CRC Public Functions
54 * @{
55 */
56
57 /** @defgroup CRC_Public_Functions_Group1 Initialization functions
58 * @brief Initialization and Configuration functions
59 * @{
60 */
61
62 /**
63 * @brief Initializes the CRC mode according to the specified parameters in
64 * the crc_handle_t and create the associated handle.
65 * @param hperh: Pointer to a crc_handle_t structure that contains
66 * the configuration information for the specified CRC module.
67 * @retval Status, see @ref ald_status_t.
68 */
ald_crc_init(ald_crc_handle_t * hperh)69 ald_status_t ald_crc_init(ald_crc_handle_t *hperh)
70 {
71 uint32_t tmp = 0;
72
73 if (hperh == NULL)
74 return ALD_ERROR;
75
76 assert_param(IS_CRC(hperh->perh));
77 assert_param(IS_CRC_MODE(hperh->init.mode));
78 assert_param(IS_FUNC_STATE(hperh->init.chs_rev));
79 assert_param(IS_FUNC_STATE(hperh->init.data_inv));
80 assert_param(IS_FUNC_STATE(hperh->init.data_rev));
81 assert_param(IS_FUNC_STATE(hperh->init.chs_inv));
82
83 ald_crc_reset(hperh);
84 __LOCK(hperh);
85
86 ALD_CRC_ENABLE(hperh);
87
88 tmp = hperh->perh->CR;
89
90 tmp |= ((hperh->init.chs_rev << CRC_CR_CHSREV_POS) | (hperh->init.data_inv << CRC_CR_DATINV_POS) |
91 (hperh->init.chs_inv << CRC_CR_CHSINV_POS) | (hperh->init.mode << CRC_CR_MODE_POSS) |
92 (ALD_CRC_DATASIZE_8 << CRC_CR_DATLEN_POSS) | (hperh->init.data_rev << CRC_CR_DATREV_POS) |
93 (0 << CRC_CR_BYTORD_POS));
94
95 hperh->perh->CR = tmp;
96 hperh->perh->SEED = hperh->init.seed;
97 ALD_CRC_RESET(hperh);
98
99 hperh->state = ALD_CRC_STATE_READY;
100
101 __UNLOCK(hperh);
102 return ALD_OK;
103 }
104
105 /**
106 * @}
107 */
108
109 /** @defgroup CRC_Public_Functions_Group2 Calculate functions
110 * @brief Calculate functions
111 * @{
112 */
113
114 /**
115 * @brief Calculate the crc value of data by byte.
116 * @param hperh: Pointer to a crc_handle_t structure that contains
117 * the configuration information for the specified CRC module.
118 * @param buf: Pointer to data buffer
119 * @param size: The size of data to be calculate
120 * @retval result, the result of a amount data
121 */
ald_crc_calculate(ald_crc_handle_t * hperh,uint8_t * buf,uint32_t size)122 uint32_t ald_crc_calculate(ald_crc_handle_t *hperh, uint8_t *buf, uint32_t size)
123 {
124 uint32_t i;
125 uint32_t ret;
126
127 assert_param(IS_CRC(hperh->perh));
128
129 if (buf == NULL || size == 0)
130 return 0;
131
132 __LOCK(hperh);
133 MODIFY_REG(hperh->perh->CR, CRC_CR_DATLEN_MSK, ALD_CRC_DATASIZE_8 << CRC_CR_DATLEN_POSS);
134 hperh->state = ALD_CRC_STATE_BUSY;
135
136 for (i = 0; i < size; i++)
137 *((volatile uint8_t *)&(hperh->perh->DATA)) = buf[i];
138
139 ret = CRC->CHECKSUM;
140 hperh->state = ALD_CRC_STATE_READY;
141 __UNLOCK(hperh);
142
143 return ret;
144 }
145
146 /**
147 * @brief Calculate the crc value of data by halfword.
148 * @param hperh: Pointer to a crc_handle_t structure that contains
149 * the configuration information for the specified CRC module.
150 * @param buf: Pointer to data buffer
151 * @param size: The size of data to be calculate,width is 2 bytes.
152 * @retval result, the result of a amount data
153 */
ald_crc_calculate_halfword(ald_crc_handle_t * hperh,uint16_t * buf,uint32_t size)154 uint32_t ald_crc_calculate_halfword(ald_crc_handle_t *hperh, uint16_t *buf, uint32_t size)
155 {
156 uint32_t i;
157 uint32_t ret;
158
159 assert_param(IS_CRC(hperh->perh));
160
161 if (buf == NULL || size == 0)
162 return 0;
163
164 __LOCK(hperh);
165 MODIFY_REG(hperh->perh->CR, CRC_CR_DATLEN_MSK, ALD_CRC_DATASIZE_16 << CRC_CR_DATLEN_POSS);
166 hperh->state = ALD_CRC_STATE_BUSY;
167
168 for (i = 0; i < size; i++)
169 *((volatile uint16_t *)&(hperh->perh->DATA)) = buf[i];
170
171 ret = CRC->CHECKSUM;
172 hperh->state = ALD_CRC_STATE_READY;
173 __UNLOCK(hperh);
174
175 return ret;
176 }
177
178 /**
179 * @brief Calculate the crc value of data by word.
180 * @param hperh: Pointer to a crc_handle_t structure that contains
181 * the configuration information for the specified CRC module.
182 * @param buf: Pointer to data buffer
183 * @param size: The size of data to be calculate,width is 4 bytes
184 * @retval result, the result of a amount data
185 */
ald_crc_calculate_word(ald_crc_handle_t * hperh,uint32_t * buf,uint32_t size)186 uint32_t ald_crc_calculate_word(ald_crc_handle_t *hperh, uint32_t *buf, uint32_t size)
187 {
188 uint32_t i;
189 uint32_t ret;
190
191 assert_param(IS_CRC(hperh->perh));
192
193 if (buf == NULL || size == 0)
194 return 0;
195
196 __LOCK(hperh);
197 MODIFY_REG(hperh->perh->CR, CRC_CR_DATLEN_MSK, ALD_CRC_DATASIZE_32 << CRC_CR_DATLEN_POSS);
198 hperh->state = ALD_CRC_STATE_BUSY;
199
200 for (i = 0; i < size; i++)
201 CRC->DATA = buf[i];
202
203 for (i = 0; i < 3; i++);
204
205 ret = CRC->CHECKSUM;
206 hperh->state = ALD_CRC_STATE_READY;
207 __UNLOCK(hperh);
208
209 return ret;
210 }
211
212 /**
213 * @}
214 */
215
216 /** @defgroup CRC_Public_Functions_Group3 DMA operation functions
217 * @brief DMA operation functions
218 * @{
219 */
220
221 /**
222 * @brief Calculate an amount of data used dma channel
223 * @param hperh: Pointer to a crc_handle_t structure that contains
224 * the configuration information for the specified CRC module.
225 * @param buf: Pointer to data buffer
226 * @param res: Pointer to result
227 * @param size: Amount of data to be Calculate
228 * @param channel: DMA channel as CRC transmit
229 * @retval Status, see @ref ald_status_t.
230 */
ald_crc_calculate_by_dma(ald_crc_handle_t * hperh,uint8_t * buf,uint32_t * res,uint16_t size,uint8_t channel)231 ald_status_t ald_crc_calculate_by_dma(ald_crc_handle_t *hperh, uint8_t *buf, uint32_t *res, uint16_t size, uint8_t channel)
232 {
233 if (hperh->state != ALD_CRC_STATE_READY)
234 return ALD_BUSY;
235
236 if (buf == NULL || size == 0)
237 return ALD_ERROR;
238
239 __LOCK(hperh);
240 MODIFY_REG(hperh->perh->CR, CRC_CR_DATLEN_MSK, ALD_CRC_DATASIZE_8 << CRC_CR_DATLEN_POSS);
241
242 hperh->state = ALD_CRC_STATE_BUSY;
243
244 hperh->cal_buf = buf;
245 hperh->cal_res = res;
246
247 if (hperh->hdma.perh == NULL)
248 hperh->hdma.perh = DMA;
249
250 hperh->hdma.cplt_tc_arg = (void *)hperh;
251 hperh->hdma.cplt_tc_cbk = &crc_dma_calculate_cplt;
252
253 ald_dma_config_struct(&(hperh->hdma.config));
254 hperh->hdma.config.src_data_width = ALD_DMA_DATA_SIZE_BYTE;
255 hperh->hdma.config.dst_data_width = ALD_DMA_DATA_SIZE_BYTE;
256 hperh->hdma.config.src = (void *)buf;
257 hperh->hdma.config.dst = (void *)&hperh->perh->DATA;
258 hperh->hdma.config.size = size;
259 hperh->hdma.config.src_inc = ALD_DMA_DATA_INC_ENABLE;
260 hperh->hdma.config.dst_inc = ALD_DMA_DATA_INC_DISABLE;
261 hperh->hdma.config.msel = ALD_DMA_MSEL_CRC;
262 hperh->hdma.config.msigsel = ALD_DMA_MSIGSEL_NONE;
263 hperh->hdma.config.channel = channel;
264 ald_dma_config_basic(&(hperh->hdma));
265 ald_dma_interrupt_config(channel, ALD_DMA_IT_FLAG_TC, ENABLE);
266
267 __UNLOCK(hperh);
268 ALD_CRC_DMA_ENABLE(hperh);
269
270 return ALD_OK;
271 }
272
273 /**
274 * @brief Calculate an amount of data used dma channel,data width is half-word.
275 * @param hperh: Pointer to a crc_handle_t structure that contains
276 * the configuration information for the specified CRC module.
277 * @param buf: Pointer to half_word data buffer
278 * @param res: Pointer to result
279 * @param size: Amount of half_word data to be Calculate
280 * @param channel: DMA channel as CRC transmit
281 * @retval Status, see @ref ald_status_t.
282 */
ald_crc_calculate_halfword_by_dma(ald_crc_handle_t * hperh,uint16_t * buf,uint32_t * res,uint16_t size,uint8_t channel)283 ald_status_t ald_crc_calculate_halfword_by_dma(ald_crc_handle_t *hperh, uint16_t *buf, uint32_t *res, uint16_t size, uint8_t channel)
284 {
285 if (hperh->state != ALD_CRC_STATE_READY)
286 return ALD_BUSY;
287
288 if (buf == NULL || size == 0)
289 return ALD_ERROR;
290
291 __LOCK(hperh);
292 MODIFY_REG(hperh->perh->CR, CRC_CR_DATLEN_MSK, ALD_CRC_DATASIZE_16 << CRC_CR_DATLEN_POSS);
293
294 hperh->state = ALD_CRC_STATE_BUSY;
295
296 hperh->cal_buf = (uint8_t *)buf;
297 hperh->cal_res = res;
298
299 if (hperh->hdma.perh == NULL)
300 hperh->hdma.perh = DMA;
301
302 hperh->hdma.cplt_tc_arg = (void *)hperh;
303 hperh->hdma.cplt_tc_cbk = &crc_dma_calculate_cplt;
304
305 ald_dma_config_struct(&(hperh->hdma.config));
306 hperh->hdma.config.src_data_width = ALD_DMA_DATA_SIZE_HALFWORD;
307 hperh->hdma.config.dst_data_width = ALD_DMA_DATA_SIZE_HALFWORD;
308 hperh->hdma.config.src = (void *)buf;
309 hperh->hdma.config.dst = (void *)&hperh->perh->DATA;
310 hperh->hdma.config.size = size;
311 hperh->hdma.config.src_inc = ALD_DMA_DATA_INC_ENABLE;
312 hperh->hdma.config.dst_inc = ALD_DMA_DATA_INC_DISABLE;
313 hperh->hdma.config.msel = ALD_DMA_MSEL_CRC;
314 hperh->hdma.config.msigsel = ALD_DMA_MSIGSEL_NONE;
315 hperh->hdma.config.channel = channel;
316 ald_dma_config_basic(&(hperh->hdma));
317 ald_dma_interrupt_config(channel, ALD_DMA_IT_FLAG_TC, ENABLE);
318
319 __UNLOCK(hperh);
320 ALD_CRC_DMA_ENABLE(hperh);
321
322 return ALD_OK;
323 }
324
325 /**
326 * @brief Calculate an amount of data used dma channel,data width is word.
327 * @param hperh: Pointer to a crc_handle_t structure that contains
328 * the configuration information for the specified CRC module.
329 * @param buf: Pointer to word data buffer
330 * @param res: Pointer to result
331 * @param size: Amount of word data to be Calculate
332 * @param channel: DMA channel as CRC transmit
333 * @retval Status, see @ref ald_status_t.
334 */
ald_crc_calculate_word_by_dma(ald_crc_handle_t * hperh,uint32_t * buf,uint32_t * res,uint16_t size,uint8_t channel)335 ald_status_t ald_crc_calculate_word_by_dma(ald_crc_handle_t *hperh, uint32_t *buf, uint32_t *res, uint16_t size, uint8_t channel)
336 {
337 if (hperh->state != ALD_CRC_STATE_READY)
338 return ALD_BUSY;
339
340 if (buf == NULL || size == 0)
341 return ALD_ERROR;
342
343 __LOCK(hperh);
344 MODIFY_REG(hperh->perh->CR, CRC_CR_DATLEN_MSK, ALD_CRC_DATASIZE_32 << CRC_CR_DATLEN_POSS);
345
346 hperh->state = ALD_CRC_STATE_BUSY;
347
348 hperh->cal_buf = (uint8_t *)buf;
349 hperh->cal_res = res;
350
351 if (hperh->hdma.perh == NULL)
352 hperh->hdma.perh = DMA;
353
354 hperh->hdma.cplt_tc_arg = (void *)hperh;
355 hperh->hdma.cplt_tc_cbk = &crc_dma_calculate_cplt;
356
357 ald_dma_config_struct(&(hperh->hdma.config));
358 hperh->hdma.config.src_data_width = ALD_DMA_DATA_SIZE_WORD;
359 hperh->hdma.config.dst_data_width = ALD_DMA_DATA_SIZE_WORD;
360 hperh->hdma.config.src = (void *)buf;
361 hperh->hdma.config.dst = (void *)&hperh->perh->DATA;
362 hperh->hdma.config.size = size;
363 hperh->hdma.config.src_inc = ALD_DMA_DATA_INC_ENABLE;
364 hperh->hdma.config.dst_inc = ALD_DMA_DATA_INC_DISABLE;
365 hperh->hdma.config.msel = ALD_DMA_MSEL_CRC;
366 hperh->hdma.config.msigsel = ALD_DMA_MSIGSEL_NONE;
367 hperh->hdma.config.channel = channel;
368 ald_dma_config_basic(&(hperh->hdma));
369 ald_dma_interrupt_config(channel, ALD_DMA_IT_FLAG_TC, ENABLE);
370
371 __UNLOCK(hperh);
372 ALD_CRC_DMA_ENABLE(hperh);
373
374 return ALD_OK;
375 }
376
377
378 /**
379 * @brief Pauses the DMA Transfer.
380 * @param hperh: Pointer to a crc_handle_t structure that contains
381 * the configuration information for the specified CRC module.
382 * @retval Status, see @ref ald_status_t.
383 */
ald_crc_dma_pause(ald_crc_handle_t * hperh)384 ald_status_t ald_crc_dma_pause(ald_crc_handle_t *hperh)
385 {
386 __LOCK(hperh);
387 ALD_CRC_DMA_DISABLE(hperh);
388 __UNLOCK(hperh);
389
390 return ALD_OK;
391 }
392
393 /**
394 * @brief Resumes the DMA Transfer.
395 * @param hperh: Pointer to a crc_handle_t structure that contains
396 * the configuration information for the specified CRC module.
397 * @retval Status, see @ref ald_status_t.
398 */
ald_crc_dma_resume(ald_crc_handle_t * hperh)399 ald_status_t ald_crc_dma_resume(ald_crc_handle_t *hperh)
400 {
401 __LOCK(hperh);
402 ALD_CRC_DMA_ENABLE(hperh);
403 __UNLOCK(hperh);
404
405 return ALD_OK;
406 }
407
408 /**
409 * @brief Stops the DMA Transfer.
410 * @param hperh: Pointer to a crc_handle_t structure that contains
411 * the configuration information for the specified CRC module.
412 * @retval Status, see @ref ald_status_t.
413 */
ald_crc_dma_stop(ald_crc_handle_t * hperh)414 ald_status_t ald_crc_dma_stop(ald_crc_handle_t *hperh)
415 {
416 __LOCK(hperh);
417 ALD_CRC_DMA_DISABLE(hperh);
418 __UNLOCK(hperh);
419
420 hperh->state = ALD_CRC_STATE_READY;
421 return ALD_OK;
422 }
423
424 /**
425 * @}
426 */
427
428 /** @defgroup CRC_Public_Functions_Group4 Peripheral State and Errors functions
429 * @brief CRC State and Errors functions
430 * @{
431 */
432
433 /**
434 * @brief Returns the CRC state.
435 * @param hperh: Pointer to a crc_handle_t structure that contains
436 * the configuration information for the specified CRC module.
437 * @retval CRC state
438 */
ald_crc_get_state(ald_crc_handle_t * hperh)439 ald_crc_state_t ald_crc_get_state(ald_crc_handle_t *hperh)
440 {
441 assert_param(IS_CRC(hperh->perh));
442
443 return hperh->state;
444 }
445 /**
446 * @}
447 */
448
449 /**
450 * @}
451 */
452
453 /** @defgroup CRC_Private_Functions CRC Private Functions
454 * @brief CRC Private functions
455 * @{
456 */
457
458 /**
459 * @brief Reset the CRC peripheral.
460 * @param hperh: Pointer to a crc_handle_t structure that contains
461 * the configuration information for the specified CRC module.
462 * @retval None
463 */
ald_crc_reset(ald_crc_handle_t * hperh)464 void ald_crc_reset(ald_crc_handle_t *hperh)
465 {
466 hperh->perh->DATA = 0x0;
467 hperh->perh->CR = 0x2;
468 hperh->perh->SEED = 0xFFFFFFFF;
469
470 hperh->state = ALD_CRC_STATE_READY;
471 __UNLOCK(hperh);
472 return;
473 }
474
475 /**
476 * @brief DMA CRC calculate process complete callback.
477 * @param arg: Pointer to a crc_handle_t structure that contains
478 * the configuration information for the specified CRC module.
479 * @retval None
480 */
crc_dma_calculate_cplt(void * arg)481 static void crc_dma_calculate_cplt(void *arg)
482 {
483 ald_crc_handle_t *hperh = (ald_crc_handle_t *)arg;
484
485 *(hperh->cal_res) = CRC->CHECKSUM;
486 ALD_CRC_DMA_DISABLE(hperh);
487
488 hperh->state = ALD_CRC_STATE_READY;
489
490 if (hperh->cal_cplt_cbk)
491 hperh->cal_cplt_cbk(hperh);
492 }
493 /**
494 * @}
495 */
496
497 /**
498 * @}
499 */
500
501 /**
502 * @}
503 */
504