1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
/**************************************************************************//**
*
* @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-3-4 CHChen First version
*
******************************************************************************/
#include <rtconfig.h>
#if (defined(BSP_USING_CRC) && defined(RT_HWCRYPTO_USING_CRC))
#include <string.h>
#include <rtdevice.h>
#include <rtdbg.h>
#include "NuMicro.h"
#include "drv_pdma.h"
/* Private define ---------------------------------------------------------------*/
#define NU_CRYPTO_CRC_NAME "nu_CRC"
#define CRC_32_POLY 0x04C11DB7
#define CRC_CCITT_POLY 0x00001021
#define CRC_16_POLY 0x00008005
#define CRC_8_POLY 0x00000007
/* Private variables ------------------------------------------------------------*/
static struct rt_mutex s_CRC_mutex;
static rt_uint32_t nu_crc_run(
uint32_t u32OpMode,
uint32_t u32Seed,
uint32_t u32Attr,
uint8_t *pu8InData,
uint32_t u32DataLen
)
{
uint32_t u32CalChecksum = 0;
uint32_t i = 0;
rt_err_t result;
result = rt_mutex_take(&s_CRC_mutex, RT_WAITING_FOREVER);
RT_ASSERT(result == RT_EOK);
/* Configure CRC controller */
CRC_Open(u32OpMode, u32Attr, u32Seed, CRC_CPU_WDATA_8);
uint8_t *pu8InTempData = pu8InData;
while (i < u32DataLen)
{
if (((((uint32_t)pu8InTempData) % 4) != 0) || (u32DataLen - i < 4))
{
CRC->CTL &= ~CRC_CTL_DATLEN_Msk;
CRC_WRITE_DATA((*pu8InTempData) & 0xFF);
pu8InTempData ++;
i++;
}
else
{
CRC->CTL &= ~CRC_CTL_DATLEN_Msk;
CRC->CTL |= CRC_CPU_WDATA_32;
#if defined (NU_CRC_USE_PDMA)
int32_t i32PDMATransCnt = (u32DataLen - i) / 4 ;
i32PDMATransCnt = nu_pdma_mempush((void *)&CRC->DAT, pu8InTempData, 32, i32PDMATransCnt);
if (i32PDMATransCnt > 0)
{
pu8InTempData += (i32PDMATransCnt * 4);
i += (i32PDMATransCnt * 4);
}
#else
CRC_WRITE_DATA(*(uint32_t *)pu8InTempData);
pu8InTempData += 4;
i += 4;
#endif
}
}
/* Get checksum value */
u32CalChecksum = CRC_GetChecksum();
result = rt_mutex_release(&s_CRC_mutex);
RT_ASSERT(result == RT_EOK);
return u32CalChecksum;
}
rt_err_t nu_crc_init(void)
{
SYS_ResetModule(CRC_RST);
return rt_mutex_init(&s_CRC_mutex, NU_CRYPTO_CRC_NAME, RT_IPC_FLAG_PRIO);
}
rt_uint32_t nu_crc_update(struct hwcrypto_crc *ctx, const rt_uint8_t *in, rt_size_t length)
{
uint32_t u32OpMode;
uint32_t u32CRCAttr = 0;
rt_uint32_t crc_result = 0;
//select CRC operation mode
switch (ctx->crc_cfg.poly)
{
case CRC_32_POLY:
u32OpMode = CRC_32;
break;
case CRC_CCITT_POLY:
u32OpMode = CRC_CCITT;
break;
case CRC_16_POLY:
u32OpMode = CRC_16;
break;
case CRC_8_POLY:
u32OpMode = CRC_8;
break;
default:
return 0;
}
u32CRCAttr |= (ctx->crc_cfg.flags & CRC_FLAG_REFOUT) ? CRC_CHECKSUM_RVS : 0; //CRC Checksum Reverse
u32CRCAttr |= (ctx->crc_cfg.flags & CRC_FLAG_REFIN) ? CRC_WDATA_RVS : 0; //CRC Write Data Reverse
//Calculate CRC checksum, using config's last value as CRC seed
crc_result = nu_crc_run(u32OpMode, ctx->crc_cfg.last_val, u32CRCAttr, (uint8_t *)in, length);
//update CRC result to config's last value
ctx->crc_cfg.last_val = crc_result;
return crc_result ^ 0x00 ^ ctx->crc_cfg.xorout;
}
#endif //#if (defined(BSP_USING_CRC) && defined(RT_HWCRYPTO_USING_CRC))
|