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