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