1 /*
2  * Copyright (c) 2006-2025, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author            Notes
8  * 2021-10-29     mazhiyuan         first version
9  * 2025-02-11     kurisaW           support can and canfd drivers for RZ family
10  */
11 
12 #include "drv_can.h"
13 
14 static struct ra_can_config can_config[] =
15 {
16 #ifdef BSP_USING_CAN0
17     CAN0_CONFIG,
18 #endif
19 
20 #ifdef BSP_USING_CAN1
21     CAN1_CONFIG
22 #endif
23 };
24 
25 enum
26 {
27 #ifdef BSP_USING_CAN0
28     CAN0_INDEX,
29 #endif
30 
31 #ifdef BSP_USING_CAN1
32     CAN1_INDEX,
33 #endif
34 };
35 
36 static struct ra_can can_obj[sizeof(can_config) / sizeof(can_config[0])] = {0};
37 
38 static const struct ra_baud_rate_tab can_baud_rate_tab[] =
39 {
40     {CAN1MBaud, 3, 6, 3, 1 + 4},
41     {CAN800kBaud, 4, 15, 5, 1 + 2},
42     {CAN500kBaud, 4, 14, 5, 1 + 4},
43     {CAN250kBaud, 4, 14, 5, 1 + 9},
44     {CAN125kBaud, 4, 14, 5, 1 + 19},
45     {CAN100kBaud, 4, 14, 5, 1 + 24},
46     {CAN50kBaud, 4, 14, 5, 1 + 49},
47     {CAN20kBaud, 4, 14, 5, 1 + 124},
48     {CAN10kBaud, 4, 14, 5, 1 + 249}
49 };
50 
51 #if defined(BSP_USING_CANFD)
52 
53 #define can_instance_ctrl_t         canfd_instance_ctrl_t
54 
55 #define R_CAN_Open                  R_CANFD_Open
56 #define R_BSP_IrqStatusClear        R_BSP_IrqClearPending
57 #define R_CAN_ModeTransition        R_CANFD_ModeTransition
58 #define R_CAN_InfoGet               R_CANFD_InfoGet
59 #define R_CAN_Write                 R_CANFD_Write
60 
61 #endif
62 
get_can_baud_index(rt_uint32_t baud)63 static rt_uint32_t get_can_baud_index(rt_uint32_t baud)
64 {
65     rt_uint32_t len, index;
66 
67     len = sizeof(can_baud_rate_tab) / sizeof(can_baud_rate_tab[0]);
68     for (index = 0; index < len; index++)
69     {
70         if (can_baud_rate_tab[index].baud_rate == baud)
71             return index;
72     }
73 
74     return 0; /* default baud is CAN1MBaud */
75 }
76 
ra_can_get_config(void)77 static void ra_can_get_config(void)
78 {
79     struct can_configure config = CANDEFAULTCONFIG;
80 #ifdef BSP_USING_CAN0
81     can_obj[CAN0_INDEX].can_dev.config = config;
82     can_obj[CAN0_INDEX].can_dev.config.msgboxsz = 32;
83     can_obj[CAN0_INDEX].can_dev.config.sndboxnumber = 1;
84     can_obj[CAN0_INDEX].can_dev.config.ticks = 50;
85 #endif
86 #ifdef BSP_USING_CAN1
87     can_obj[CAN1_INDEX].can_dev.config = config;
88     can_obj[CAN1_INDEX].can_dev.config.msgboxsz = 32;
89     can_obj[CAN1_INDEX].can_dev.config.sndboxnumber = 1;
90     can_obj[CAN1_INDEX].can_dev.config.ticks = 50;
91 #endif
92 }
ra_can_configure(struct rt_can_device * can_dev,struct can_configure * cfg)93 rt_err_t ra_can_configure(struct rt_can_device *can_dev, struct can_configure *cfg)
94 {
95     struct ra_can *can;
96     RT_ASSERT(can_dev != RT_NULL);
97     RT_ASSERT(cfg != RT_NULL);
98 
99     fsp_err_t err = FSP_SUCCESS;
100 
101     can = rt_container_of(can_dev, struct ra_can, can_dev);
102     RT_ASSERT(can != RT_NULL);
103 
104     err = R_CAN_Open(can->config->p_api_ctrl, can->config->p_cfg);
105     if (FSP_SUCCESS != err)
106     {
107         return -RT_ERROR;
108     }
109     return RT_EOK;
110 }
ra_can_control(struct rt_can_device * can_dev,int cmd,void * arg)111 rt_err_t ra_can_control(struct rt_can_device *can_dev, int cmd, void *arg)
112 {
113     struct ra_can *can;
114     can_info_t can_info;
115     rt_uint32_t argval;
116     RT_ASSERT(can_dev != RT_NULL);
117     can = rt_container_of(can_dev, struct ra_can, can_dev);
118     switch (cmd)
119     {
120     case RT_DEVICE_CTRL_CLR_INT:
121         R_BSP_IrqStatusClear((IRQn_Type)arg);
122         break;
123     case RT_CAN_CMD_SET_BAUD:
124         argval = (rt_uint32_t) arg;
125         if (argval != CAN1MBaud &&
126                 argval != CAN800kBaud &&
127                 argval != CAN500kBaud &&
128                 argval != CAN250kBaud &&
129                 argval != CAN125kBaud &&
130                 argval != CAN100kBaud &&
131                 argval != CAN50kBaud  &&
132                 argval != CAN20kBaud  &&
133                 argval != CAN10kBaud)
134         {
135             return -RT_ERROR;
136         }
137         if (argval != can->can_dev.config.baud_rate)
138         {
139             can->can_dev.config.baud_rate = argval;
140             uint32_t index = get_can_baud_index(argval);
141             can->config->p_cfg->p_bit_timing->baud_rate_prescaler = can_baud_rate_tab[index].prescaler;
142             can->config->p_cfg->p_bit_timing->synchronization_jump_width = can_baud_rate_tab[index].sjw;
143             can->config->p_cfg->p_bit_timing->time_segment_1 = can_baud_rate_tab[index].ts1;
144             can->config->p_cfg->p_bit_timing->time_segment_2 = can_baud_rate_tab[index].ts2;
145             return ra_can_configure(&can->can_dev, &can->can_dev.config);
146         }
147         break;
148     case RT_CAN_CMD_SET_MODE:
149         argval = (rt_uint32_t) arg;
150         if (argval != RT_CAN_MODE_NORMAL &&
151                 argval != RT_CAN_MODE_LISTEN &&
152                 argval != RT_CAN_MODE_LOOPBACK)
153         {
154             return -RT_ERROR;
155         }
156         if (argval != can->can_dev.config.mode)
157         {
158             can_test_mode_t mode_to_set;
159             can->can_dev.config.mode = argval;
160             switch (argval)
161             {
162             case RT_CAN_MODE_NORMAL:
163                 mode_to_set = CAN_TEST_MODE_DISABLED;
164             case RT_CAN_MODE_LISTEN:
165                 mode_to_set = CAN_TEST_MODE_LISTEN;
166             case RT_CAN_MODE_LOOPBACK:
167                 mode_to_set = CAN_TEST_MODE_LOOPBACK_INTERNAL;
168             }
169             R_CAN_ModeTransition(can->config->p_api_ctrl, ((can_instance_ctrl_t *)(can->config->p_api_ctrl))->operation_mode, mode_to_set);
170         }
171         break;
172     case RT_CAN_CMD_GET_STATUS:
173         R_CAN_InfoGet(can->config->p_api_ctrl, &can_info);
174         can->can_dev.status.rcverrcnt = can_info.error_count_receive;
175         can->can_dev.status.snderrcnt = can_info.error_count_transmit;
176         can->can_dev.status.errcode = can_info.error_code;
177         rt_memcpy(arg, &can->can_dev.status, sizeof(can->can_dev.status));
178         break;
179     default:
180         return -RT_ERROR;
181     }
182     return RT_EOK;
183 }
ra_can_sendmsg(struct rt_can_device * can_dev,const void * buf,rt_uint32_t boxno)184 rt_ssize_t ra_can_sendmsg(struct rt_can_device *can_dev, const void *buf, rt_uint32_t boxno)
185 {
186     struct ra_can *can;
187     can_frame_t g_can_tx_frame;
188     struct rt_can_msg *msg_rt = (struct rt_can_msg *)buf;
189     RT_ASSERT(can_dev != RT_NULL);
190     RT_ASSERT(buf != RT_NULL);
191 
192     g_can_tx_frame.id = msg_rt->id;
193     g_can_tx_frame.id_mode = msg_rt->ide;
194     g_can_tx_frame.type = msg_rt->rtr;
195     g_can_tx_frame.data_length_code = msg_rt->len;
196 #if defined(BSP_USING_CANFD) && defined(BSP_USING_CAN_RZ)
197     g_can_tx_frame.options = 0;
198 #elif defined(BSP_USING_CANFD)
199     g_can_tx_frame.options = CANFD_FRAME_OPTION_FD | CANFD_FRAME_OPTION_BRS;
200 #else
201     g_can_tx_frame.options = 0;
202 #endif
203     memcpy(g_can_tx_frame.data, msg_rt->data, 8);
204     can = rt_container_of(can_dev, struct ra_can, can_dev);
205     RT_ASSERT(boxno < can->config->num_of_mailboxs);
206 
207     if (R_CAN_Write(can->config->p_api_ctrl, boxno, &g_can_tx_frame) != FSP_SUCCESS)
208     {
209         rt_exit_critical();
210         return -RT_ERROR;
211     }
212     return RT_EOK;
213 }
214 
ra_can_recvmsg(struct rt_can_device * can_dev,void * buf,rt_uint32_t boxno)215 rt_ssize_t ra_can_recvmsg(struct rt_can_device *can_dev, void *buf, rt_uint32_t boxno)
216 {
217     struct rt_can_msg *msg_rt = (struct rt_can_msg *)buf;
218     can_frame_t *msg_ra;
219     struct ra_can *can;
220 
221     RT_ASSERT(can_dev != RT_NULL);
222     RT_ASSERT(buf != RT_NULL);
223     can = rt_container_of(can_dev, struct ra_can, can_dev);
224     RT_ASSERT(boxno < can->config->num_of_mailboxs);
225     if (can->callback_args->mailbox != boxno)
226         return 0;
227 #if defined(BSP_USING_CANFD)
228     msg_ra = &can->callback_args->frame;
229 #else
230     msg_ra = can->callback_args->p_frame;
231 #endif
232 
233     msg_rt->id = msg_ra->id;
234     msg_rt->ide = msg_ra->id_mode;
235     msg_rt->rtr = msg_ra->type;
236     msg_rt->rsv = RT_NULL;
237     msg_rt->len = msg_ra->data_length_code;
238     msg_rt->priv = boxno;
239     msg_rt->hdr_index = RT_NULL;
240     memcpy(msg_rt->data, msg_ra->data, msg_ra->data_length_code);
241     return sizeof(struct rt_can_msg);
242 }
243 const struct rt_can_ops ra_can_ops =
244 {
245     .configure = ra_can_configure,
246     .control = ra_can_control,
247     .sendmsg = ra_can_sendmsg,
248     .recvmsg = ra_can_recvmsg
249 };
250 
251 #ifdef BSP_USING_CAN0
can0_callback(can_callback_args_t * p_args)252 void can0_callback(can_callback_args_t *p_args)
253 {
254     rt_interrupt_enter();
255     switch (p_args->event)
256     {
257     case CAN_EVENT_TX_COMPLETE:
258         rt_hw_can_isr(&can_obj[CAN0_INDEX].can_dev, RT_CAN_EVENT_TX_DONE | p_args->mailbox << 8);
259         break;
260     case CAN_EVENT_RX_COMPLETE:
261         can_obj[CAN0_INDEX].callback_args = p_args;
262         if (p_args->event == CAN_EVENT_RX_COMPLETE)
263             rt_hw_can_isr(&can_obj[CAN0_INDEX].can_dev, RT_CAN_EVENT_RX_IND | p_args->mailbox << 8);
264         break;
265     case CAN_EVENT_TX_ABORTED:
266         rt_hw_can_isr(&can_obj[CAN0_INDEX].can_dev, RT_CAN_EVENT_TX_FAIL | p_args->mailbox << 8);
267         break;
268     case CAN_EVENT_MAILBOX_MESSAGE_LOST:    //overwrite/overrun error event
269     case CAN_EVENT_BUS_RECOVERY:            //Bus recovery error event
270     case CAN_EVENT_ERR_BUS_OFF:             //error Bus Off event
271     case CAN_EVENT_ERR_PASSIVE:             //error passive event
272     case CAN_EVENT_ERR_WARNING:             //error warning event
273     case CAN_EVENT_ERR_BUS_LOCK:            //error bus lock
274     case CAN_EVENT_ERR_CHANNEL:             //error channel
275     case CAN_EVENT_ERR_GLOBAL:              //error global
276     case CAN_EVENT_TX_FIFO_EMPTY:           //error transmit FIFO is empty
277     {
278         break;
279     }
280     }
281     rt_interrupt_leave();
282 }
283 #endif
284 
285 #ifdef BSP_USING_CAN1
can1_callback(can_callback_args_t * p_args)286 void can1_callback(can_callback_args_t *p_args)
287 {
288     rt_interrupt_enter();
289     switch (p_args->event)
290     {
291     case CAN_EVENT_TX_COMPLETE:
292         rt_hw_can_isr(&can_obj[CAN1_INDEX].can_dev, RT_CAN_EVENT_TX_DONE | p_args->mailbox << 8);
293         break;
294     case CAN_EVENT_RX_COMPLETE:
295         can_obj[CAN1_INDEX].callback_args = p_args;
296         if (p_args->event == CAN_EVENT_RX_COMPLETE)
297             rt_hw_can_isr(&can_obj[CAN1_INDEX].can_dev, RT_CAN_EVENT_RX_IND | p_args->mailbox << 8);
298         break;
299     case CAN_EVENT_TX_ABORTED:
300         rt_hw_can_isr(&can_obj[CAN1_INDEX].can_dev, RT_CAN_EVENT_TX_FAIL | p_args->mailbox << 8);
301         break;
302     case CAN_EVENT_MAILBOX_MESSAGE_LOST:    //overwrite/overrun error event
303     case CAN_EVENT_BUS_RECOVERY:            //Bus recovery error event
304     case CAN_EVENT_ERR_BUS_OFF:             //error Bus Off event
305     case CAN_EVENT_ERR_PASSIVE:             //error passive event
306     case CAN_EVENT_ERR_WARNING:             //error warning event
307     case CAN_EVENT_ERR_BUS_LOCK:            //error bus lock
308     case CAN_EVENT_ERR_CHANNEL:             //error channel
309     case CAN_EVENT_ERR_GLOBAL:              //error global
310     {
311         break;
312     }
313     }
314     rt_interrupt_leave();
315 }
316 #endif
317 
rt_hw_can_init(void)318 int rt_hw_can_init(void)
319 {
320     rt_err_t result = 0;
321     rt_size_t obj_num = sizeof(can_obj) / sizeof(struct ra_can);
322     ra_can_get_config();
323     for (int i = 0; i < obj_num; i++)
324     {
325         /* init CAN object */
326         can_obj[i].config = &can_config[i];
327         can_obj[i].can_dev.ops = &ra_can_ops;
328         /* register CAN device */
329         result = rt_hw_can_register(&can_obj[i].can_dev, can_obj[i].config->name, can_obj[i].can_dev.ops, RT_NULL);
330         RT_ASSERT(result == RT_EOK);
331     }
332 
333     return result;
334 }
335 INIT_BOARD_EXPORT(rt_hw_can_init);
336