1 /*
2 * Copyright (c) 2006-2022, Synwit Technology Co.,Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-02-16 lik first version
9 */
10
11 #include "drv_can.h"
12
13 #ifdef RT_USING_CAN
14 #ifdef BSP_USING_CAN
15
16 //#define DRV_DEBUG
17 #define LOG_TAG "drv.can"
18 #include <drv_log.h>
19
20 #if !defined(BSP_USING_CAN0) && !defined(BSP_USING_CAN1)
21 #error "Please define at least one BSP_USING_CANx"
22 /* this driver can be disabled at menuconfig ? RT-Thread Components ? Device Drivers */
23 #endif
24
25 #ifdef BSP_USING_CAN0
26 #ifndef CAN0_CFG
27 #define CAN0_CFG \
28 { \
29 .name = "can0", \
30 .CANx = CAN0, \
31 }
32 #endif /* CAN0_CFG */
33 #endif /* BSP_USING_CAN0 */
34
35 #ifdef BSP_USING_CAN1
36 #ifndef CAN1_CFG
37 #define CAN1_CFG \
38 { \
39 .name = "can1", \
40 .CANx = CAN1, \
41 }
42 #endif /* CAN1_CFG */
43 #endif /* BSP_USING_CAN1 */
44
45 #define PRESCL_Pos 0
46 #define BS1_Pos 16
47 #define BS2_Pos 20
48 #define SJW_Pos 24
49 #define PRESCL_Msk (0x3FF << PRESCL_Pos)
50 #define BS1_Msk ((0x0F) << BS1_Pos)
51 #define BS2_Msk ((0x07) << BS2_Pos)
52 #define SJW_Msk (0x3 << SJW_Pos)
53
54 struct swm_baud_rate_tab
55 {
56 rt_uint32_t baud_rate;
57 rt_uint32_t config_data;
58 };
59 #define BAUD_DATA(TYPE, NO) ((can_baud_rate_tab[NO].config_data & TYPE##_Msk) >> TYPE##_Pos)
60
61 struct swm_can_cfg
62 {
63 const char *name;
64 CAN_TypeDef *CANx;
65 CAN_InitStructure CAN_initstruct;
66 };
67
68 struct swm_can_device
69 {
70 struct swm_can_cfg *can_cfg;
71 struct rt_can_device can_device;
72 };
73 /* SystemCoreClock 152MHz(max) 150MHz不能生成CAN1MBaud */
74 static const struct swm_baud_rate_tab can_baud_rate_tab[] =
75 {
76 {CAN1MBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (1 << PRESCL_Pos))},
77 {CAN500kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (3 << PRESCL_Pos))},
78 {CAN250kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (7 << PRESCL_Pos))},
79 {CAN125kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (15 << PRESCL_Pos))},
80 {CAN100kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (19 << PRESCL_Pos))},
81 {CAN50kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (39 << PRESCL_Pos))},
82 {CAN20kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (99 << PRESCL_Pos))},
83 {CAN10kBaud, ((CAN_SJW_4tq << SJW_Pos) | (CAN_BS1_12tq << BS1_Pos) | (CAN_BS2_6tq << BS2_Pos) | (199 << PRESCL_Pos))}};
84
85 enum
86 {
87 #ifdef BSP_USING_CAN0
88 CAN0_INDEX,
89 #endif
90 #ifdef BSP_USING_CAN1
91 CAN1_INDEX,
92 #endif
93 };
94
95 static struct swm_can_cfg swm_can_cfg[] =
96 {
97 #ifdef BSP_USING_CAN0
98 CAN0_CFG,
99 #endif
100 #ifdef BSP_USING_CAN1
101 CAN1_CFG,
102 #endif
103 };
104
105 static struct swm_can_device can_obj[sizeof(swm_can_cfg) / sizeof(swm_can_cfg[0])];
106
get_can_baud_index(rt_uint32_t baud)107 static rt_uint32_t get_can_baud_index(rt_uint32_t baud)
108 {
109 rt_uint32_t len, index;
110
111 len = sizeof(can_baud_rate_tab) / sizeof(can_baud_rate_tab[0]);
112 for (index = 0; index < len; index++)
113 {
114 if (can_baud_rate_tab[index].baud_rate == baud)
115 return index;
116 }
117
118 return 0; /* default baud is CAN1MBaud */
119 }
120
swm_can_config(struct rt_can_device * can_device,struct can_configure * cfg)121 static rt_err_t swm_can_config(struct rt_can_device *can_device, struct can_configure *cfg)
122 {
123 struct swm_can_device *can_dev;
124 rt_uint32_t baud_index;
125 rt_uint32_t can_mode;
126
127 RT_ASSERT(can_device);
128 RT_ASSERT(cfg);
129 can_dev = (struct swm_can_device *)can_device->parent.user_data;
130 RT_ASSERT(can_dev);
131
132 switch (cfg->mode)
133 {
134 case RT_CAN_MODE_NORMAL:
135 can_mode = CAN_MODE_NORMAL;
136 break;
137 case RT_CAN_MODE_LISTEN:
138 can_mode = CAN_MODE_LISTEN;
139 break;
140 case RT_CAN_MODE_LOOPBACK:
141 can_mode = CAN_MODE_SELFTEST;
142 break;
143 case RT_CAN_MODE_LOOPBACKANLISTEN:
144 can_mode = CAN_MODE_SELFTEST;
145 break;
146 }
147
148 baud_index = get_can_baud_index(cfg->baud_rate);
149
150 CAN_Close(can_dev->can_cfg->CANx); //一些关键寄存器只能在CAN关闭时设置
151
152 can_dev->can_cfg->CANx->CR &= ~(CAN_CR_LOM_Msk | CAN_CR_STM_Msk);
153 can_dev->can_cfg->CANx->CR |= (can_mode << CAN_CR_LOM_Pos);
154
155 can_dev->can_cfg->CANx->BT1 = (0 << CAN_BT1_SAM_Pos) |
156 (BAUD_DATA(BS1, baud_index) << CAN_BT1_TSEG1_Pos) |
157 (BAUD_DATA(BS2, baud_index) << CAN_BT1_TSEG2_Pos);
158
159 can_dev->can_cfg->CANx->BT0 = (BAUD_DATA(SJW, baud_index) << CAN_BT0_SJW_Pos) |
160 ((BAUD_DATA(PRESCL, baud_index) & 0x3F) << CAN_BT0_BRP_Pos);
161
162 can_dev->can_cfg->CANx->BT2 = ((BAUD_DATA(PRESCL, baud_index) >> 6) << CAN_BT2_BRP_Pos);
163
164 can_dev->can_cfg->CANx->RXERR = 0; //只能在复位模式下清除
165 can_dev->can_cfg->CANx->TXERR = 0;
166
167 /* can start */
168 CAN_Open(can_dev->can_cfg->CANx);
169
170 return RT_EOK;
171 }
172
swm_can_control(struct rt_can_device * can_device,int cmd,void * arg)173 static rt_err_t swm_can_control(struct rt_can_device *can_device, int cmd, void *arg)
174 {
175 rt_uint32_t argval;
176 struct swm_can_device *can_dev;
177 struct rt_can_filter_config *filter_cfg;
178
179 RT_ASSERT(can_device != RT_NULL);
180 can_dev = (struct swm_can_device *)can_device->parent.user_data;
181 RT_ASSERT(can_dev != RT_NULL);
182
183 switch (cmd)
184 {
185 case RT_DEVICE_CTRL_CLR_INT:
186 argval = (rt_uint32_t)arg;
187 if (argval == RT_DEVICE_FLAG_INT_RX)
188 {
189 can_dev->can_cfg->CANx->IE &= ~(CAN_IE_RXDA_Msk | CAN_IE_RXOV_Msk);
190 }
191 else if (argval == RT_DEVICE_FLAG_INT_TX)
192 {
193 can_dev->can_cfg->CANx->IE &= ~CAN_IE_TXBR_Msk;
194 }
195 else if (argval == RT_DEVICE_CAN_INT_ERR)
196 {
197 can_dev->can_cfg->CANx->IE &= ~(CAN_IE_ARBLOST_Msk | CAN_IE_BUSERR_Msk | CAN_IE_ERRWARN_Msk | CAN_IE_ERRPASS_Msk);
198 }
199 break;
200 case RT_DEVICE_CTRL_SET_INT:
201 argval = (rt_uint32_t)arg;
202 if (argval == RT_DEVICE_FLAG_INT_RX)
203 {
204 can_dev->can_cfg->CANx->IE |= (CAN_IE_RXDA_Msk | CAN_IE_RXOV_Msk);
205 }
206 else if (argval == RT_DEVICE_FLAG_INT_TX)
207 {
208 can_dev->can_cfg->CANx->IE |= CAN_IE_TXBR_Msk;
209 }
210 else if (argval == RT_DEVICE_CAN_INT_ERR)
211 {
212 can_dev->can_cfg->CANx->IE |= (CAN_IE_ARBLOST_Msk | CAN_IE_BUSERR_Msk | CAN_IE_ERRWARN_Msk | CAN_IE_ERRPASS_Msk);
213 }
214 break;
215 case RT_CAN_CMD_SET_FILTER:
216 {
217 rt_uint32_t filter_idx = 0;
218
219 if (RT_NULL == arg)
220 {
221 /* default filter config */
222 }
223 else
224 {
225 filter_cfg = (struct rt_can_filter_config *)arg;
226 /* get default filter */
227 for (int i = 0; i < filter_cfg->count; i++)
228 {
229 if (filter_cfg->items[i].hdr_bank == -1)
230 {
231 filter_idx = i;
232 }
233 else
234 {
235 filter_idx = filter_cfg->items[i].hdr_bank;
236 }
237
238 if (filter_cfg->items[i].ide == RT_CAN_STDID)
239 {
240 can_dev->can_cfg->CANx->AFM &= ~(1 << filter_idx);
241
242 can_dev->can_cfg->CANx->ACR[filter_idx] = __REV(filter_cfg->items[i].id << 5);
243 can_dev->can_cfg->CANx->AMR[filter_idx] = __REV(~(filter_cfg->items[i].mask << 5));
244
245 can_dev->can_cfg->CANx->AFE |= (1 << filter_idx);
246 }
247 else if (filter_cfg->items[i].ide == RT_CAN_EXTID)
248 {
249 can_dev->can_cfg->CANx->AFM |= (1 << filter_idx);
250
251 can_dev->can_cfg->CANx->ACR[filter_idx] = __REV(filter_cfg->items[i].id << 3);
252 can_dev->can_cfg->CANx->AMR[filter_idx] = __REV(~(filter_cfg->items[i].mask << 3));
253
254 can_dev->can_cfg->CANx->AFE |= (1 << filter_idx);
255 }
256 }
257 }
258 break;
259 }
260 case RT_CAN_CMD_SET_MODE:
261 argval = (rt_uint32_t)arg;
262 if (argval != RT_CAN_MODE_NORMAL &&
263 argval != RT_CAN_MODE_LISTEN &&
264 argval != RT_CAN_MODE_LOOPBACK &&
265 argval != RT_CAN_MODE_LOOPBACKANLISTEN)
266 {
267 return -RT_ERROR;
268 }
269 if (argval != can_dev->can_device.config.mode)
270 {
271 can_dev->can_device.config.mode = argval;
272 return swm_can_config(&can_dev->can_device, &can_dev->can_device.config);
273 }
274 break;
275 case RT_CAN_CMD_SET_BAUD:
276 argval = (rt_uint32_t)arg;
277 if (argval != CAN1MBaud &&
278 argval != CAN800kBaud &&
279 argval != CAN500kBaud &&
280 argval != CAN250kBaud &&
281 argval != CAN125kBaud &&
282 argval != CAN100kBaud &&
283 argval != CAN50kBaud &&
284 argval != CAN20kBaud &&
285 argval != CAN10kBaud)
286 {
287 return -RT_ERROR;
288 }
289 if (argval != can_dev->can_device.config.baud_rate)
290 {
291 can_dev->can_device.config.baud_rate = argval;
292 return swm_can_config(&can_dev->can_device, &can_dev->can_device.config);
293 }
294 break;
295 case RT_CAN_CMD_SET_PRIV:
296 argval = (rt_uint32_t)arg;
297 if (argval != RT_CAN_MODE_PRIV &&
298 argval != RT_CAN_MODE_NOPRIV)
299 {
300 return -RT_ERROR;
301 }
302 if (argval != can_dev->can_device.config.privmode)
303 {
304 can_dev->can_device.config.privmode = argval;
305 return swm_can_config(&can_dev->can_device, &can_dev->can_device.config);
306 }
307 break;
308 case RT_CAN_CMD_GET_STATUS:
309 {
310 can_dev->can_device.status.rcverrcnt = can_dev->can_cfg->CANx->RXERR;
311 can_dev->can_device.status.snderrcnt = can_dev->can_cfg->CANx->TXERR;
312 can_dev->can_device.status.lasterrtype = (can_dev->can_cfg->CANx->ECC >> 6) & 0x03;
313 can_dev->can_device.status.errcode = can_dev->can_cfg->CANx->ECC & 0x1F;
314 rt_memcpy(arg, &can_dev->can_device.status, sizeof(can_dev->can_device.status));
315 }
316 break;
317 }
318
319 return RT_EOK;
320 }
321
swm_can_sendmsg(struct rt_can_device * can_device,const void * buf,rt_uint32_t box_num)322 static int swm_can_sendmsg(struct rt_can_device *can_device, const void *buf, rt_uint32_t box_num)
323 {
324 uint32_t i;
325 struct swm_can_device *can_dev;
326
327 RT_ASSERT(can_device != RT_NULL);
328 can_dev = (struct swm_can_device *)can_device->parent.user_data;
329 struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
330
331 if (RT_CAN_STDID == pmsg->ide)
332 {
333 can_dev->can_cfg->CANx->FRAME.DATA[0] = pmsg->id >> 3;
334 can_dev->can_cfg->CANx->FRAME.DATA[1] = pmsg->id << 5;
335
336 if (RT_CAN_DTR == pmsg->rtr)
337 {
338 can_dev->can_cfg->CANx->FRAME.INFO = (0 << CAN_INFO_FF_Pos) |
339 (0 << CAN_INFO_RTR_Pos) |
340 (pmsg->len << CAN_INFO_DLC_Pos);
341
342 for(i = 0; i < pmsg->len; i++)
343 {
344 can_dev->can_cfg->CANx->FRAME.DATA[i+2] = pmsg->data[i];
345 }
346
347 if(can_dev->can_cfg->CANx->CR & CAN_CR_STM_Msk)
348 {
349 can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_SRR_Pos);
350 }
351 else
352 {
353 can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_TXREQ_Pos);
354 }
355 }
356 else
357 {
358 can_dev->can_cfg->CANx->FRAME.INFO = (0 << CAN_INFO_FF_Pos) |
359 (1 << CAN_INFO_RTR_Pos) |
360 (0 << CAN_INFO_DLC_Pos);
361
362 can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_TXREQ_Pos);
363 }
364 }
365 else
366 {
367 can_dev->can_cfg->CANx->FRAME.DATA[0] = pmsg->id >> 21;
368 can_dev->can_cfg->CANx->FRAME.DATA[1] = pmsg->id >> 13;
369 can_dev->can_cfg->CANx->FRAME.DATA[2] = pmsg->id >> 5;
370 can_dev->can_cfg->CANx->FRAME.DATA[3] = pmsg->id << 3;
371
372 if (RT_CAN_DTR == pmsg->rtr)
373 {
374 can_dev->can_cfg->CANx->FRAME.INFO = (1 << CAN_INFO_FF_Pos) |
375 (0 << CAN_INFO_RTR_Pos) |
376 (pmsg->len << CAN_INFO_DLC_Pos);
377
378 for(i = 0; i < pmsg->len; i++)
379 {
380 can_dev->can_cfg->CANx->FRAME.DATA[i+4] = pmsg->data[i];
381 }
382
383 if(can_dev->can_cfg->CANx->CR & CAN_CR_STM_Msk)
384 {
385 can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_SRR_Pos);
386 }
387 else
388 {
389 can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_TXREQ_Pos);
390 }
391 }
392 else
393 {
394 can_dev->can_cfg->CANx->FRAME.INFO = (1 << CAN_INFO_FF_Pos) |
395 (1 << CAN_INFO_RTR_Pos) |
396 (0 << CAN_INFO_DLC_Pos);
397
398 can_dev->can_cfg->CANx->CMD = (1 << CAN_CMD_TXREQ_Pos);
399 }
400 }
401 return RT_EOK;
402 }
403
swm_can_recvmsg(struct rt_can_device * can_device,void * buf,rt_uint32_t fifo)404 static int swm_can_recvmsg(struct rt_can_device *can_device, void *buf, rt_uint32_t fifo)
405 {
406 uint32_t i;
407 struct swm_can_device *can_dev;
408 RT_ASSERT(can_device != RT_NULL);
409 can_dev = (struct swm_can_device *)can_device->parent.user_data;
410
411 struct rt_can_msg *pmsg = (struct rt_can_msg *) buf;
412
413 CAN_RXMessage CAN_RXMsg;
414
415 /* get data */
416 CAN_Receive(can_dev->can_cfg->CANx, &CAN_RXMsg);
417 /* get id */
418 if (CAN_RXMsg.format == CAN_FRAME_STD)
419 {
420 pmsg->ide = RT_CAN_STDID;
421 }
422 else
423 {
424 pmsg->ide = RT_CAN_EXTID;
425 }
426 pmsg->id = CAN_RXMsg.id;
427
428 /* get type */
429 if (CAN_RXMsg.remote == 0)
430 {
431 pmsg->rtr = RT_CAN_DTR;
432 }
433 else
434 {
435 pmsg->rtr = RT_CAN_RTR;
436 }
437 /* get len */
438 pmsg->len = CAN_RXMsg.size;
439
440 for(i = 0; i < pmsg->len; i++)
441 {
442 pmsg->data[i] = CAN_RXMsg.data[i];
443 }
444
445 return RT_EOK;
446 }
447
448 static const struct rt_can_ops swm_can_ops =
449 {
450 .configure = swm_can_config,
451 .control = swm_can_control,
452 .sendmsg = swm_can_sendmsg,
453 .recvmsg = swm_can_recvmsg,
454 };
455
swm_can_isr(struct rt_can_device * can_device)456 static void swm_can_isr(struct rt_can_device *can_device)
457 {
458 struct swm_can_device *can_dev;
459 RT_ASSERT(can_device != RT_NULL);
460 can_dev = (struct swm_can_device *)can_device->parent.user_data;
461
462 uint32_t int_sr = CAN_INTStat(can_dev->can_cfg->CANx);
463
464 if(int_sr & CAN_IF_RXDA_Msk)
465 {
466 rt_hw_can_isr(can_device, RT_CAN_EVENT_RX_IND);
467 }
468 else if (int_sr & CAN_IF_RXOV_Msk)
469 {
470 rt_hw_can_isr(can_device, RT_CAN_EVENT_RXOF_IND);
471 }
472 else if (int_sr & CAN_IF_TXBR_Msk)
473 {
474 rt_hw_can_isr(can_device, RT_CAN_EVENT_TX_DONE);
475 }
476 else if (int_sr & CAN_IE_ERRWARN_Msk)
477 {
478 }
479 else if (int_sr & CAN_IE_ERRPASS_Msk)
480 {
481 }
482 else if (int_sr & CAN_IE_ARBLOST_Msk)
483 {
484 }
485 else if (int_sr & CAN_IE_BUSERR_Msk)
486 {
487 }
488 }
489
490 #ifdef BSP_USING_CAN0
491 /**
492 * @brief This function handles CAN0 interrupts.
493 */
CAN0_Handler(void)494 void CAN0_Handler(void)
495 {
496 rt_interrupt_enter();
497 swm_can_isr(&(can_obj[CAN0_INDEX].can_device));
498 rt_interrupt_leave();
499 }
500 #endif /* BSP_USING_CAN0 */
501
502 #ifdef BSP_USING_CAN1
503 /**
504 * @brief This function handles CAN1 interrupts.
505 */
CAN1_Handler(void)506 void CAN1_Handler(void)
507 {
508 rt_interrupt_enter();
509 swm_can_isr(&(can_obj[CAN0_INDEX].can_device));
510 rt_interrupt_leave();
511 }
512 #endif /* BSP_USING_CAN1 */
513
swm_can_init(void)514 int swm_can_init(void)
515 {
516 int i = 0;
517 int result = RT_EOK;
518
519 struct can_configure config = CANDEFAULTCONFIG;
520 config.privmode = RT_CAN_MODE_NOPRIV;
521 config.ticks = 50;
522 #ifdef RT_CAN_USING_HDR
523 config.maxhdr = 16;
524 #endif
525
526 #ifdef BSP_USING_CAN0
527 PORT_Init(PORTB, PIN5, PORTB_PIN5_CAN0_RX, 1);
528 PORT_Init(PORTB, PIN4, PORTB_PIN4_CAN0_TX, 0);
529 SYS->CLKEN0 |= (0x01 << SYS_CLKEN0_CAN0_Pos);
530 NVIC_EnableIRQ(CAN0_IRQn);
531 #endif
532
533 #ifdef BSP_USING_CAN1
534 PORT_Init(PORTB, PIN3, PORTB_PIN3_CAN1_RX, 1);
535 PORT_Init(PORTB, PIN2, PORTB_PIN2_CAN1_TX, 0);
536 SYS->CLKEN1 |= (0x01 << SYS_CLKEN1_CAN1_Pos);
537 NVIC_EnableIRQ(CAN1_IRQn);
538 #endif
539
540 for (i = 0; i < sizeof(swm_can_cfg) / sizeof(swm_can_cfg[0]); i++)
541 {
542 can_obj[i].can_device.config = config;
543 can_obj[i].can_cfg = &swm_can_cfg[i];
544 result = rt_hw_can_register(&can_obj[i].can_device,
545 can_obj[i].can_cfg->name,
546 &swm_can_ops,
547 &can_obj[i]);
548 if (result != RT_EOK)
549 {
550 LOG_E("%s register fail.", can_obj[i].can_cfg->name);
551 }
552 else
553 {
554 LOG_D("%s register success.", can_obj[i].can_cfg->name);
555 }
556 }
557
558 return result;
559 return 0;
560 }
561
562 INIT_BOARD_EXPORT(swm_can_init);
563
564 #endif /* BSP_USING_CAN */
565 #endif /* RT_USING_CAN */
566