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