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