1 /*
2 * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /******************************************************************************
18 * @file ck_crc.c
19 * @brief CSI Source File for CRC Driver
20 * @version V1.0
21 * @date 02. June 2017
22 ******************************************************************************/
23 #include <stdio.h>
24 #include "drv_crc.h"
25 #include "ck_crc.h"
26
27 #define ERR_CRC(errno) (CSI_DRV_ERRNO_CRC_BASE | errno)
28 #define CRC_NULL_PARAM_CHK(para) \
29 do { \
30 if (para == NULL) { \
31 return ERR_CRC(EDRV_PARAMETER); \
32 } \
33 } while (0)
34
35 typedef struct {
36 uint32_t base;
37 crc_event_cb_t cb;
38 crc_status_t status;
39 } ck_crc_priv_t;
40
41
42 static ck_crc_priv_t crc_handle[CONFIG_CRC_NUM];
43 /* Driver Capabilities */
44 static const crc_capabilities_t driver_capabilities = {
45 .ROHC = 1, /* ROHC mode */
46 .MAXIM = 1, /* MAXIM mode */
47 .X25 = 1, /* X25 mode */
48 .CCITT = 1, /* CCITT mode */
49 .USB = 1, /* USB mode */
50 .IBM = 1, /* IBM mode */
51 .MODBUS = 1 /* MODBUS mode */
52 };
53
54 //
55 // Functions
56 //
57
58 static ck_crc_reg_t *crc_reg = NULL;
59
crc_set_mode(crc_mode_e mode,crc_standard_crc_e standard)60 static int32_t crc_set_mode(crc_mode_e mode, crc_standard_crc_e standard)
61 {
62 if (mode == CRC_MODE_CRC16) {
63 switch (standard) {
64 case CRC_STANDARD_CRC_MODBUS:
65 crc_reg->CRC_SEL = 0x0;
66 crc_reg->CRC_INIT = 0xffff;
67 break;
68
69 case CRC_STANDARD_CRC_IBM:
70 crc_reg->CRC_SEL = 0x0;
71 crc_reg->CRC_INIT = 0x0;
72 break;
73
74 case CRC_STANDARD_CRC_MAXIM:
75 crc_reg->CRC_SEL = 0x4;
76 crc_reg->CRC_INIT = 0x0;
77 break;
78
79 case CRC_STANDARD_CRC_USB:
80 crc_reg->CRC_SEL = 0x4;
81 crc_reg->CRC_INIT = 0xffff;
82 break;
83
84 case CRC_STANDARD_CRC_CCITT:
85 crc_reg->CRC_SEL = 0x1;
86 crc_reg->CRC_INIT = 0x0;
87 break;
88
89 case CRC_STANDARD_CRC_X25:
90 crc_reg->CRC_SEL = 0x5;
91 crc_reg->CRC_INIT = 0xffff;
92 break;
93
94 default:
95 return ERR_CRC(EDRV_PARAMETER);
96 }
97 } else if (mode == CRC_MODE_CRC8) {
98 switch (standard) {
99 case CRC_STANDARD_CRC_MAXIM:
100 crc_reg->CRC_SEL = 0x2;
101 crc_reg->CRC_INIT = 0x0;
102 break;
103
104 case CRC_STANDARD_CRC_ROHC:
105 crc_reg->CRC_SEL = 0x3;
106 crc_reg->CRC_INIT = 0xff;
107 break;
108
109 default:
110 return ERR_CRC(EDRV_PARAMETER);
111 }
112 } else {
113 return ERR_CRC(EDRV_PARAMETER);
114 }
115
116 return 0;
117 }
118
crc_set_data(uint32_t data)119 static int32_t crc_set_data(uint32_t data)
120 {
121 crc_reg->CRC_DATA = data;
122 return 0;
123 }
124
crc_get_data(uint32_t * data)125 static int32_t crc_get_data(uint32_t *data)
126 {
127 *data = crc_reg->CRC_DATA;
128 return 0;
129 }
130
target_get_crc_count(void)131 int32_t __attribute__((weak)) target_get_crc_count(void)
132 {
133 return 0;
134 }
135
target_get_crc(int32_t idx,uint32_t * base)136 int32_t __attribute__((weak)) target_get_crc(int32_t idx, uint32_t *base)
137 {
138 return NULL;
139 }
140
141 /**
142 \brief get crc handle count.
143 \return crc handle count
144 */
csi_crc_get_instance_count(void)145 int32_t csi_crc_get_instance_count(void)
146 {
147 return target_get_crc_count();
148 }
149
150 /**
151 \brief Initialize CRC Interface. 1. Initializes the resources needed for the CRC interface 2.registers event callback function
152 \param[in] idx must not exceed return value of csi_crc_get_handle_count()
153 \param[in] cb_event Pointer to \ref crc_event_cb_t
154 \return return crc handle if success
155 */
csi_crc_initialize(int32_t idx,crc_event_cb_t cb_event)156 crc_handle_t csi_crc_initialize(int32_t idx, crc_event_cb_t cb_event)
157 {
158 if (idx < 0 || idx >= CONFIG_CRC_NUM) {
159 return NULL;
160 }
161
162 /* obtain the crc information */
163 uint32_t base = 0u;
164 int32_t real_idx = target_get_crc(idx, &base);
165
166 if (real_idx != idx) {
167 return NULL;
168 }
169
170 ck_crc_priv_t *crc_priv = &crc_handle[idx];
171 crc_reg = (ck_crc_reg_t *)(crc_priv->base);
172
173 crc_priv->base = base;
174 crc_priv->cb = cb_event;
175 crc_priv->status.busy = 0;
176
177 return (crc_handle_t)crc_priv;
178 }
179
180 /**
181 \brief De-initialize CRC Interface. stops operation and releases the software resources used by the interface
182 \param[in] handle crc handle to operate.
183 \return error code
184 */
csi_crc_uninitialize(crc_handle_t handle)185 int32_t csi_crc_uninitialize(crc_handle_t handle)
186 {
187 CRC_NULL_PARAM_CHK(handle);
188
189 ck_crc_priv_t *crc_priv = handle;
190 crc_priv->cb = NULL;
191
192 return 0;
193 }
194
195 /**
196 \brief Get driver capabilities.
197 \param[in] handle crc handle to operate.
198 \return \ref crc_capabilities_t
199 */
csi_crc_get_capabilities(crc_handle_t handle)200 crc_capabilities_t csi_crc_get_capabilities(crc_handle_t handle)
201 {
202 return driver_capabilities;
203 }
204
205 /**
206 \brief config crc mode.
207 \param[in] handle crc handle to operate.
208 \param[in] mode \ref crc_mode_e
209 \param[in] standard \ref crc_standard_crc_e
210 \return error code
211 */
csi_crc_config(crc_handle_t handle,crc_mode_e mode,crc_standard_crc_e standard)212 int32_t csi_crc_config(crc_handle_t handle, crc_mode_e mode, crc_standard_crc_e standard)
213 {
214 CRC_NULL_PARAM_CHK(handle);
215
216 /* set the crc mode */
217 uint32_t ret = crc_set_mode(mode, standard);
218
219 return ret;
220 }
221
222 /**
223 \brief calculate crc.
224 \param[in] handle crc handle to operate.
225 \param[in] in Pointer to the input data
226 \param[out] out Pointer to the result.
227 \param[in] len intpu data len.
228 \return error code
229 */
csi_crc_calculate(crc_handle_t handle,const void * in,void * out,uint32_t len)230 int32_t csi_crc_calculate(crc_handle_t handle, const void *in, void *out, uint32_t len)
231 {
232 CRC_NULL_PARAM_CHK(handle);
233 CRC_NULL_PARAM_CHK(in);
234 CRC_NULL_PARAM_CHK(out);
235 if (len <= 0) {
236 return ERR_CRC(EDRV_PARAMETER);
237 }
238
239 ck_crc_priv_t *crc_priv = handle;
240 crc_reg = (ck_crc_reg_t *)(crc_priv->base);
241
242 crc_priv->status.busy = 1;
243
244 /* put the data int the register */
245 uint8_t cur;
246 uint8_t *p = (uint8_t *)in;
247 for (cur=0; cur<len - 3; cur += 4, p+=4) {
248 crc_set_data(p[0]
249 | (p[1] << 8)
250 | (p[2] << 16)
251 | (p[3] << 24));
252 }
253 uint32_t data = 0;
254 uint8_t i;
255 if (cur < len) {
256 for (i=0; i<len-cur; i++) {
257 data |= (p[cur + i] << (i*8));
258 }
259 crc_set_data(data);
260 }
261
262 crc_get_data((uint32_t *)out);
263 crc_priv->status.busy = 0;
264
265 return 0;
266 }
267
268 /**
269 \brief Get CRC status.
270 \param[in] handle crc handle to operate.
271 \return CRC status \ref crc_status_t
272 */
csi_crc_get_status(crc_handle_t handle)273 crc_status_t csi_crc_get_status(crc_handle_t handle)
274 {
275 ck_crc_priv_t *crc_priv = handle;
276 return crc_priv->status;
277 }
278