1 /*!
2     \file    gd32e50x_can.c
3     \brief   CAN driver
4 
5     \version 2020-03-10, V1.0.0, firmware for GD32E50x
6     \version 2021-03-23, V1.2.0, firmware for GD32E50x
7 */
8 
9 /*
10     Copyright (c) 2021, GigaDevice Semiconductor Inc.
11 
12     Redistribution and use in source and binary forms, with or without modification,
13 are permitted provided that the following conditions are met:
14 
15     1. Redistributions of source code must retain the above copyright notice, this
16        list of conditions and the following disclaimer.
17     2. Redistributions in binary form must reproduce the above copyright notice,
18        this list of conditions and the following disclaimer in the documentation
19        and/or other materials provided with the distribution.
20     3. Neither the name of the copyright holder nor the names of its contributors
21        may be used to endorse or promote products derived from this software without
22        specific prior written permission.
23 
24     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGE.
34 */
35 
36 #include "gd32e50x_can.h"
37 #include <stdlib.h>
38 
39 #define CAN_ERROR_HANDLE(s)     do{}while(1)
40 
41 #ifdef GD32E508
42 /* BS1[6:0] + BS2[4:0] */
43 #define DEV_CAN_BT_SEG_MAX            158U
44 #define DEV_CAN_BT_SEG_MIN             3U
45 
46 /* BS1[3:0] + BS2[2:0] */
47 #define DEV_CAN_FD_BT_SEG_MAX          22U
48 #define DEV_CAN_FD_BT_SEG_MIN          3U
49 
50 /* CAN related register mask */
51 #define DEV_CAN_BS1_MASK            0x000F0000U
52 #define DEV_CAN_BS2_MASK            0x00700000U
53 #define DEV_CAN_FD_SJW_MASK         0x07000000U
54 #else
55 /* BS1[3:0] + BS2[2:0] */
56 #define DEV_CAN_BT_SEG_MAX             22U
57 #define DEV_CAN_BT_SEG_MIN             3U
58 #endif /* GD32E508 */
59 
60 /* CAN related register mask */
61 #define DEV_CAN_BAUDPSC_MASK        0x000003FFU
62 #define DEV_CAN_SJW_MASK            0x1F000000U
63 
64 
65 /* This table can be used to calculate data length in FD mode */
66 const uint8_t g_can_fdlength_table[] = {12, 16, 20, 24, 32, 48, 64};
67 
68 #ifdef GD32E508
69 /* This table can be used to calculate bit time: timing_pts{BS1[3:0], BS2[2:0]} */
70 static const uint32_t timing_pts[23][2] = {
71     {0x0, 0x0},      /* 2, 50% */
72     {0x1, 0x0},      /* 3, 67% */
73     {0x2, 0x0},      /* 4, 75% */
74     {0x3, 0x0},      /* 5, 80% */
75     {0x3, 0x1},      /* 6, 67% */
76     {0x4, 0x1},      /* 7, 71% */
77     {0x5, 0x1},      /* 8, 75% */
78     {0x6, 0x1},      /* 9, 78% */
79     {0x6, 0x2},      /* 10, 70% */
80     {0x7, 0x2},      /* 11, 73% */
81     {0x8, 0x2},      /* 12, 75% */
82     {0x9, 0x2},      /* 13, 77% */
83     {0x9, 0x3},      /* 14, 71% */
84     {0xA, 0x3},      /* 15, 73% */
85     {0xB, 0x3},      /* 16, 75% */
86     {0xC, 0x3},      /* 17, 76% */
87     {0xD, 0x3},      /* 18, 78% */
88     {0xD, 0x4},      /* 19, 74% */
89     {0xE, 0x4},      /* 20, 75% */
90     {0xF, 0x4},      /* 21, 76% */
91     {0xF, 0x5},      /* 22, 73% */
92     {0xF, 0x6},      /* 23, 70% */
93     {0xF, 0x7},      /* 24, 67% */
94 };
95 #endif /* GD32E508 */
96 
97 static unsigned int dev_can_baudrate_set(uint32_t freq);
98 #ifdef GD32E508
99 static unsigned int dev_can_fd_baudrate_set(uint32_t freq);
100 #endif /* GD32E508 */
101 /*!
102     \brief      deinitialize CAN
103     \param[in]  can_periph
104     \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
105     \param[out] none
106     \retval     none
107 */
can_deinit(uint32_t can_periph)108 void can_deinit(uint32_t can_periph)
109 {
110 #if defined(GD32E50X_CL) || defined(GD32E508)
111     switch(can_periph){
112     case CAN0:
113          rcu_periph_reset_enable(RCU_CAN0RST);
114          rcu_periph_reset_disable(RCU_CAN0RST);
115          break;
116     case CAN1:
117          rcu_periph_reset_enable(RCU_CAN1RST);
118          rcu_periph_reset_disable(RCU_CAN1RST);
119          break;
120     case CAN2:
121          rcu_periph_reset_enable(RCU_CAN2RST);
122          rcu_periph_reset_disable(RCU_CAN2RST);
123          break;
124     default:
125          break;
126     }
127 #else
128     switch(can_periph){
129     case CAN0:
130          rcu_periph_reset_enable(RCU_CAN0RST);
131          rcu_periph_reset_disable(RCU_CAN0RST);
132          break;
133     case CAN1:
134          rcu_periph_reset_enable(RCU_CAN1RST);
135          rcu_periph_reset_disable(RCU_CAN1RST);
136          break;
137     default:
138          break;
139     }
140 #endif
141 }
142 
143 /*!
144     \brief      initialize CAN parameter struct
145     \param[in]  type: the type of CAN parameter struct
146                 only one parameter can be selected which is shown as below:
147       \arg        CAN_INIT_STRUCT: the CAN initial struct
148       \arg        CAN_FILTER_STRUCT: the CAN filter struct
149       \arg        CAN_FD_FRAME_STRUCT: the CAN FD initial struct
150       \arg        CAN_TX_MESSAGE_STRUCT: the CAN TX message struct
151       \arg        CAN_RX_MESSAGE_STRUCT: the CAN RX message struct
152     \param[in]  p_struct: the pointer of the specific struct
153     \param[out] none
154     \retval     none
155 */
can_struct_para_init(can_struct_type_enum type,void * p_struct)156 void can_struct_para_init(can_struct_type_enum type, void* p_struct)
157 {
158     uint8_t i;
159 
160     if(NULL == p_struct){
161         CAN_ERROR_HANDLE("struct parameter can not be NULL \r\n");
162     }
163     /* get type of the struct */
164     switch(type){
165         /* used for can_init() */
166         case CAN_INIT_STRUCT:
167             ((can_parameter_struct*)p_struct)->auto_bus_off_recovery = DISABLE;
168             ((can_parameter_struct*)p_struct)->auto_retrans = DISABLE;
169             ((can_parameter_struct*)p_struct)->auto_wake_up = DISABLE;
170             ((can_parameter_struct*)p_struct)->prescaler = 0x0400U;
171             ((can_parameter_struct*)p_struct)->rec_fifo_overwrite = DISABLE;
172             ((can_parameter_struct*)p_struct)->resync_jump_width = CAN_BT_SJW_1TQ;
173             ((can_parameter_struct*)p_struct)->time_segment_1 = CAN_BT_BS1_3TQ;
174             ((can_parameter_struct*)p_struct)->time_segment_2 = CAN_BT_BS2_1TQ;
175             ((can_parameter_struct*)p_struct)->time_triggered = DISABLE;
176             ((can_parameter_struct*)p_struct)->trans_fifo_order = DISABLE;
177             ((can_parameter_struct*)p_struct)->working_mode = CAN_NORMAL_MODE;
178 
179             break;
180         /* used for can_filter_init() */
181         case CAN_FILTER_STRUCT:
182             ((can_filter_parameter_struct*)p_struct)->filter_bits = CAN_FILTERBITS_32BIT;
183             ((can_filter_parameter_struct*)p_struct)->filter_enable = DISABLE;
184             ((can_filter_parameter_struct*)p_struct)->filter_fifo_number = CAN_FIFO0;
185             ((can_filter_parameter_struct*)p_struct)->filter_list_high = 0x0000U;
186             ((can_filter_parameter_struct*)p_struct)->filter_list_low = 0x0000U;
187             ((can_filter_parameter_struct*)p_struct)->filter_mask_high = 0x0000U;
188             ((can_filter_parameter_struct*)p_struct)->filter_mask_low = 0x0000U;
189             ((can_filter_parameter_struct*)p_struct)->filter_mode = CAN_FILTERMODE_MASK;
190             ((can_filter_parameter_struct*)p_struct)->filter_number = 0U;
191 
192             break;
193 #ifdef GD32E508
194         /* used for can_fd_init() */
195         case CAN_FD_FRAME_STRUCT:
196             ((can_fdframe_struct*)p_struct)->data_prescaler = 0x0400U;
197             ((can_fdframe_struct*)p_struct)->data_resync_jump_width = 1U - 1U;
198             ((can_fdframe_struct*)p_struct)->data_time_segment_1 = 3U - 1U;
199             ((can_fdframe_struct*)p_struct)->data_time_segment_2 = 2U - 1U;
200             ((can_fdframe_struct*)p_struct)->delay_compensation = DISABLE;
201             ((can_fdframe_struct*)p_struct)->esi_mode = CAN_ESIMOD_HARDWARE;
202             ((can_fdframe_struct*)p_struct)->excp_event_detect = ENABLE;
203             ((can_fdframe_struct*)p_struct)->fd_frame = DISABLE;
204             ((can_fdframe_struct*)p_struct)->iso_bosch = CAN_FDMOD_ISO;
205             ((can_fdframe_struct*)p_struct)->p_delay_compensation = 0U;
206 
207             break;
208         /* used for can_message_transmit() */
209         case CAN_TX_MESSAGE_STRUCT:
210             ((can_trasnmit_message_struct*)p_struct)->fd_brs = CAN_BRS_DISABLE;
211             ((can_trasnmit_message_struct*)p_struct)->fd_esi = CAN_ESI_DOMINANT;
212             ((can_trasnmit_message_struct*)p_struct)->fd_flag = CAN_FDF_CLASSIC;
213 
214             for(i = 0U; i < 64U; i++){
215                 ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U;
216             }
217 
218             ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u;
219             ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U;
220             ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD;
221             ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA;
222             ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U;
223 
224             break;
225         /* used for can_message_receive() */
226         case CAN_RX_MESSAGE_STRUCT:
227             ((can_receive_message_struct*)p_struct)->fd_brs = CAN_BRS_DISABLE;
228             ((can_receive_message_struct*)p_struct)->fd_esi = CAN_ESI_DOMINANT;
229             ((can_receive_message_struct*)p_struct)->fd_flag = CAN_FDF_CLASSIC;
230 
231             for(i = 0U; i < 64U; i++){
232                 ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U;
233             }
234 
235             ((can_receive_message_struct*)p_struct)->rx_dlen = 0U;
236             ((can_receive_message_struct*)p_struct)->rx_efid = 0U;
237             ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD;
238             ((can_receive_message_struct*)p_struct)->rx_fi = 0U;
239             ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA;
240             ((can_receive_message_struct*)p_struct)->rx_sfid = 0U;
241 
242             break;
243 #else
244         /* used for can_message_transmit() */
245         case CAN_TX_MESSAGE_STRUCT:
246             for(i = 0U; i < 8U; i++){
247                 ((can_trasnmit_message_struct*)p_struct)->tx_data[i] = 0U;
248             }
249 
250             ((can_trasnmit_message_struct*)p_struct)->tx_dlen = 0u;
251             ((can_trasnmit_message_struct*)p_struct)->tx_efid = 0U;
252             ((can_trasnmit_message_struct*)p_struct)->tx_ff = (uint8_t)CAN_FF_STANDARD;
253             ((can_trasnmit_message_struct*)p_struct)->tx_ft = (uint8_t)CAN_FT_DATA;
254             ((can_trasnmit_message_struct*)p_struct)->tx_sfid = 0U;
255 
256             break;
257         /* used for can_message_receive() */
258         case CAN_RX_MESSAGE_STRUCT:
259             for(i = 0U; i < 8U; i++){
260                 ((can_receive_message_struct*)p_struct)->rx_data[i] = 0U;
261             }
262 
263             ((can_receive_message_struct*)p_struct)->rx_dlen = 0U;
264             ((can_receive_message_struct*)p_struct)->rx_efid = 0U;
265             ((can_receive_message_struct*)p_struct)->rx_ff = (uint8_t)CAN_FF_STANDARD;
266             ((can_receive_message_struct*)p_struct)->rx_fi = 0U;
267             ((can_receive_message_struct*)p_struct)->rx_ft = (uint8_t)CAN_FT_DATA;
268             ((can_receive_message_struct*)p_struct)->rx_sfid = 0U;
269 
270             break;
271 
272 #endif /* GD32E508 */
273         default:
274             CAN_ERROR_HANDLE("parameter is invalid \r\n");
275     }
276 }
277 
278 /*!
279     \brief      initialize CAN
280     \param[in]  can_periph
281       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
282     \param[in]  can_parameter_init: parameters for CAN initializtion
283       \arg        working_mode: CAN_NORMAL_MODE, CAN_LOOPBACK_MODE, CAN_SILENT_MODE, CAN_SILENT_LOOPBACK_MODE
284       \arg        resync_jump_width: 0x00 - 0x07
285       \arg        time_segment_1: 0x00 - 0x7F
286       \arg        time_segment_2: 0x00 - 0x1F
287       \arg        time_triggered: ENABLE or DISABLE
288       \arg        auto_bus_off_recovery: ENABLE or DISABLE
289       \arg        auto_wake_up: ENABLE or DISABLE
290       \arg        auto_retrans: ENABLE or DISABLE
291       \arg        rec_fifo_overwrite: ENABLE or DISABLE
292       \arg        trans_fifo_order: ENABLE or DISABLE
293       \arg        prescaler: 0x0001 - 0x0400
294     \param[out] none
295     \retval     ErrStatus: SUCCESS or ERROR
296 */
can_init(uint32_t can_periph,can_parameter_struct * can_parameter_init)297 ErrStatus can_init(uint32_t can_periph, can_parameter_struct* can_parameter_init)
298 {
299     uint32_t timeout = CAN_TIMEOUT;
300     ErrStatus flag = ERROR;
301 #ifdef GD32E508
302     uint32_t fdctl_status;
303 #endif /* GD32E508 */
304 
305     /* disable sleep mode */
306     CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD;
307     /* enable initialize mode */
308     CAN_CTL(can_periph) |= CAN_CTL_IWMOD;
309     /* wait ACK */
310     while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
311         timeout--;
312     }
313     /* check initialize working success */
314     if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){
315         flag = ERROR;
316     }else{
317 #ifdef GD32E508
318         /* set the bit timing register */
319         fdctl_status = CAN_FDCTL(can_periph);
320         if(CAN_FDCTL_FDEN != (fdctl_status&CAN_FDCTL_FDEN)){
321             /* CAN FD disable, should frist enable, then write */
322             fdctl_status = fdctl_status | CAN_FDCTL_FDEN;
323             CAN_FDCTL(can_periph) = fdctl_status;
324             CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \
325                                   BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \
326                                   BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \
327                                   BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \
328                                   BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U)));
329             fdctl_status = fdctl_status & (~CAN_FDCTL_FDEN);
330             CAN_FDCTL(can_periph) = fdctl_status;
331         }else{
332            /* CAN FD enable */
333            CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \
334                                  BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \
335                                  BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \
336                                  BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \
337                                  BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U)));
338         }
339 #else
340         /* set the bit timing register */
341         CAN_BT(can_periph) = (BT_MODE((uint32_t)can_parameter_init->working_mode) | \
342                               BT_SJW((uint32_t)can_parameter_init->resync_jump_width) | \
343                               BT_BS1((uint32_t)can_parameter_init->time_segment_1) | \
344                               BT_BS2((uint32_t)can_parameter_init->time_segment_2) | \
345                               BT_BAUDPSC(((uint32_t)(can_parameter_init->prescaler) - 1U)));
346 
347 #endif /* GD32E508 */
348         /* time trigger communication mode */
349         if(ENABLE == can_parameter_init->time_triggered){
350             CAN_CTL(can_periph) |= CAN_CTL_TTC;
351         }else{
352             CAN_CTL(can_periph) &= ~CAN_CTL_TTC;
353         }
354         /* automatic bus-off managment */
355         if(ENABLE == can_parameter_init->auto_bus_off_recovery){
356             CAN_CTL(can_periph) |= CAN_CTL_ABOR;
357         }else{
358             CAN_CTL(can_periph) &= ~CAN_CTL_ABOR;
359         }
360         /* automatic wakeup mode */
361         if(ENABLE == can_parameter_init->auto_wake_up){
362             CAN_CTL(can_periph) |= CAN_CTL_AWU;
363         }else{
364             CAN_CTL(can_periph) &= ~CAN_CTL_AWU;
365         }
366         /* automatic retransmission mode */
367         if(ENABLE == can_parameter_init->auto_retrans){
368             CAN_CTL(can_periph) &= ~CAN_CTL_ARD;
369         }else{
370             CAN_CTL(can_periph) |= CAN_CTL_ARD;
371         }
372         /* receive fifo overwrite mode */
373         if(ENABLE == can_parameter_init->rec_fifo_overwrite){
374             CAN_CTL(can_periph) |= CAN_CTL_RFOD;
375         }else{
376             CAN_CTL(can_periph) &= ~CAN_CTL_RFOD;
377         }
378         /* transmit fifo order */
379         if(ENABLE == can_parameter_init->trans_fifo_order){
380             CAN_CTL(can_periph) |= CAN_CTL_TFO;
381         }else{
382             CAN_CTL(can_periph) &= ~CAN_CTL_TFO;
383         }
384         /* disable initialize mode */
385         CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD;
386         timeout = CAN_TIMEOUT;
387         /* wait the ACK */
388         while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
389             timeout--;
390         }
391         /* check exit initialize mode */
392         if(0U != timeout){
393             flag = SUCCESS;
394         }
395     }
396     return flag;
397 }
398 
399 /*!
400     \brief      initialize CAN filter
401     \param[in]  can_periph
402       \arg        CANx(x=0,2),the CAN2 only for GD32E50X_CL and GD32E508
403     \param[in]  can_filter_parameter_init: struct for CAN filter initialization
404       \arg        filter_list_high: 0x0000 - 0xFFFF
405       \arg        filter_list_low: 0x0000 - 0xFFFF
406       \arg        filter_mask_high: 0x0000 - 0xFFFF
407       \arg        filter_mask_low: 0x0000 - 0xFFFF
408       \arg        filter_fifo_number: CAN_FIFO0, CAN_FIFO1
409       \arg        filter_number: In CAN0(0 - 27), In CAN2(0 - 14)
410       \arg        filter_mode: CAN_FILTERMODE_MASK, CAN_FILTERMODE_LIST
411       \arg        filter_bits: CAN_FILTERBITS_32BIT, CAN_FILTERBITS_16BIT
412       \arg        filter_enable: ENABLE or DISABLE
413     \param[out] none
414     \retval     none
415 */
can_filter_init(uint32_t can_periph,can_filter_parameter_struct * can_filter_parameter_init)416 void can_filter_init(uint32_t can_periph, can_filter_parameter_struct* can_filter_parameter_init)
417 {
418     uint32_t val = 0U;
419 
420     val = ((uint32_t)1) << (can_filter_parameter_init->filter_number);
421     /* filter lock disable */
422     CAN_FCTL(can_periph) |= CAN_FCTL_FLD;
423     /* disable filter */
424     CAN_FW(can_periph) &= ~(uint32_t)val;
425 
426     /* filter 16 bits */
427     if(CAN_FILTERBITS_16BIT == can_filter_parameter_init->filter_bits){
428         /* set filter 16 bits */
429         CAN_FSCFG(can_periph) &= ~(uint32_t)val;
430         /* first 16 bits list and first 16 bits mask or first 16 bits list and second 16 bits list */
431         CAN_FDATA0(can_periph, can_filter_parameter_init->filter_number) = \
432                                 FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS) | \
433                                 FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS);
434         /* second 16 bits list and second 16 bits mask or third 16 bits list and fourth 16 bits list */
435         CAN_FDATA1(can_periph, can_filter_parameter_init->filter_number) = \
436                                 FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) | \
437                                 FDATA_MASK_LOW((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS);
438     }
439     /* filter 32 bits */
440     if(CAN_FILTERBITS_32BIT == can_filter_parameter_init->filter_bits){
441         /* set filter 32 bits */
442         CAN_FSCFG(can_periph) |= (uint32_t)val;
443         /* 32 bits list or first 32 bits list */
444         CAN_FDATA0(can_periph, can_filter_parameter_init->filter_number) = \
445                                 FDATA_MASK_HIGH((can_filter_parameter_init->filter_list_high) & CAN_FILTER_MASK_16BITS) |
446                                 FDATA_MASK_LOW((can_filter_parameter_init->filter_list_low) & CAN_FILTER_MASK_16BITS);
447         /* 32 bits mask or second 32 bits list */
448         CAN_FDATA1(can_periph, can_filter_parameter_init->filter_number) = \
449                                 FDATA_MASK_HIGH((can_filter_parameter_init->filter_mask_high) & CAN_FILTER_MASK_16BITS) |
450                                 FDATA_MASK_LOW((can_filter_parameter_init->filter_mask_low) & CAN_FILTER_MASK_16BITS);
451     }
452 
453     /* filter mode */
454     if(CAN_FILTERMODE_MASK == can_filter_parameter_init->filter_mode){
455         /* mask mode */
456         CAN_FMCFG(can_periph) &= ~(uint32_t)val;
457     }else{
458         /* list mode */
459         CAN_FMCFG(can_periph) |= (uint32_t)val;
460     }
461 
462     /* filter FIFO */
463     if(CAN_FIFO0 == (can_filter_parameter_init->filter_fifo_number)){
464         /* FIFO0 */
465         CAN_FAFIFO(can_periph) &= ~(uint32_t)val;
466     }else{
467         /* FIFO1 */
468         CAN_FAFIFO(can_periph) |= (uint32_t)val;
469     }
470 
471     /* filter working */
472     if(ENABLE == can_filter_parameter_init->filter_enable){
473 
474         CAN_FW(can_periph) |= (uint32_t)val;
475     }
476 
477     /* filter lock enable */
478     CAN_FCTL(can_periph) &= ~CAN_FCTL_FLD;
479 }
480 
481 /*!
482     \brief      CAN filter mask mode initialization
483     \param[in]  can_periph
484       \arg        CANx(x=0,2),the CAN2 only for GD32E50X_CL and GD32E508
485     \param[in]  id: extended(11-bits) or standard(29-bits) identifier
486       \arg        0x00000000 - 0x1FFFFFFF
487     \param[in]  mask: extended(11-bits) or standard(29-bits) identifier mask
488       \arg        0x00000000 - 0x1FFFFFFF
489     \param[in]  format_fifo: format and fifo states
490                 only one parameter can be selected which is shown as below:
491       \arg        CAN_STANDARD_FIFO0
492       \arg        CAN_STANDARD_FIFO1
493       \arg        CAN_EXTENDED_FIFO0
494       \arg        CAN_EXTENDED_FIFO1
495     \param[in]  filter_number: filter sequence number
496       \arg        In CAN0:0 - 27 ,In CAN2:0 - 14
497     \param[out] none
498     \retval     none
499 */
can_filter_mask_mode_init(uint32_t can_periph,uint32_t id,uint32_t mask,can_format_fifo_enum format_fifo,uint16_t filter_number)500 void can_filter_mask_mode_init(uint32_t can_periph, uint32_t id, uint32_t mask, can_format_fifo_enum format_fifo, uint16_t filter_number)
501 {
502     can_filter_parameter_struct can_filter;
503 
504     /* Initialize the filter structure */
505     can_struct_para_init(CAN_FILTER_STRUCT, &can_filter);
506 
507     /* filter config */
508     can_filter.filter_number = filter_number;
509     can_filter.filter_mode = CAN_FILTERMODE_MASK;
510     can_filter.filter_bits = CAN_FILTERBITS_32BIT;
511     can_filter.filter_enable = ENABLE;
512 
513     switch(format_fifo){
514         /* standard FIFO 0 */
515         case CAN_STANDARD_FIFO0:
516             can_filter.filter_fifo_number = CAN_FIFO0;
517             /* configure SFID[10:0] */
518             can_filter.filter_list_high = (uint16_t)id << 5;
519             can_filter.filter_list_low = 0x0000U;
520             /* configure SFID[10:0] mask */
521             can_filter.filter_mask_high = (uint16_t)mask << 5;
522             /* both data and remote frames can be received */
523             can_filter.filter_mask_low = 0x0000U;
524 
525             break;
526         /* standard FIFO 1 */
527         case CAN_STANDARD_FIFO1:
528             can_filter.filter_fifo_number = CAN_FIFO1;
529             /* configure SFID[10:0] */
530             can_filter.filter_list_high = (uint16_t)id << 5;
531             can_filter.filter_list_low =  0x0000U;
532             /* configure SFID[10:0] mask */
533             can_filter.filter_mask_high = (uint16_t)mask << 5;
534             /* both data and remote frames can be received */
535             can_filter.filter_mask_low = 0x0000U;
536 
537             break;
538         /* extended FIFO 0 */
539         case CAN_EXTENDED_FIFO0:
540             can_filter.filter_fifo_number = CAN_FIFO0;
541             /* configure EFID[28:13] */
542             can_filter.filter_list_high = (uint16_t)(id >> 13);
543             /* configure EFID[12:0] and frame format bit set */
544             can_filter.filter_list_low = ((uint16_t)(id << 3)) | (1U << 2);
545             /* configure EFID[28:13] mask */
546             can_filter.filter_mask_high = (uint16_t)(mask >> 13);
547             /* configure EFID[12:0] and frame format bit mask */
548             /* both data and remote frames can be received */
549             can_filter.filter_mask_low = ((uint16_t)(mask << 3)) | (1U << 2);
550 
551             break;
552         /* extended FIFO 1 */
553         case CAN_EXTENDED_FIFO1:
554             can_filter.filter_fifo_number = CAN_FIFO1;
555             /* configure EFID[28:13] */
556             can_filter.filter_list_high = (uint16_t)(id >> 13);
557             /* configure EFID[12:0] and frame format bit set */
558             can_filter.filter_list_low = ((uint16_t)(id << 3)) | (1U << 2);
559             /* configure EFID[28:13] mask */
560             can_filter.filter_mask_high = (uint16_t)(mask >> 13);
561             /* configure EFID[12:0] and frame format bit mask */
562             /* both data and remote frames can be received */
563             can_filter.filter_mask_low = ((uint16_t)(mask << 3)) | (1U << 2);
564 
565             break;
566         default:
567             CAN_ERROR_HANDLE("parameter is invalid \r\n");
568     }
569 
570     can_filter_init(can_periph, &can_filter);
571 }
572 
573 /*!
574     \brief      CAN communication mode configure
575     \param[in]  can_periph
576       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
577     \param[in]  mode: communication mode
578                 only one parameter can be selected which is shown as below:
579       \arg        CAN_NORMAL_MODE
580       \arg        CAN_LOOPBACK_MODE
581       \arg        CAN_SILENT_MODE
582       \arg        CAN_SILENT_LOOPBACK_MODE
583     \param[out] none
584     \retval     ErrStatus: SUCCESS or ERROR
585 */
can_monitor_mode_set(uint32_t can_periph,uint8_t mode)586 ErrStatus can_monitor_mode_set(uint32_t can_periph, uint8_t mode)
587 {
588     ErrStatus reval = SUCCESS;
589     uint32_t timeout = CAN_TIMEOUT;
590 
591     if(mode == (mode & CAN_SILENT_LOOPBACK_MODE)){
592         /* disable sleep mode */
593         CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD);
594         /* set initialize mode */
595         CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD;
596         /* wait the acknowledge */
597         timeout = CAN_TIMEOUT;
598         while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
599             timeout--;
600         }
601 
602         if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){
603             reval = ERROR;
604         }else{
605             CAN_BT(can_periph) &= ~BT_MODE(3);
606             CAN_BT(can_periph) |= BT_MODE(mode);
607 
608             timeout = CAN_TIMEOUT;
609             /* enter normal mode */
610             CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD);
611             /* wait the acknowledge */
612             while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){
613                 timeout--;
614             }
615             if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){
616                 reval = ERROR;
617             }
618         }
619     }else{
620         reval = ERROR;
621     }
622 
623     return reval;
624 }
625 
626 #ifdef GD32E508
627 /*!
628     \brief      initialize CAN FD function
629     \param[in]  can_periph
630       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
631     \param[in]  can_fdframe_init: parameters for CAN FD initializtion
632       \arg        fd_frame: ENABLE or DISABLE
633       \arg        excp_event_detect: ENABLE or DISABLE
634       \arg        delay_compensation: ENABLE or DISABLE
635       \arg        p_delay_compensation: the pointer of tdc struct
636                   can_fd_tdc_struct:
637                     tdc_mode: CAN_TDCMOD_CALC_AND_OFFSET or CAN_TDCMOD_OFFSET
638                     tdc_filter: 0x00 - 0x07
639                     tdc_offset: 0x00 - 0x07
640       \arg        iso_bosch: CAN_FDMOD_ISO or CAN_FDMOD_BOSCH
641       \arg        esi_mode: CAN_ESIMOD_HARDWARE or CAN_ESIMOD_SOFTWARE
642       \arg        data_resync_jump_width: 0x00 - 0x07
643       \arg        data_time_segment_1: 0x00 - 0x0F
644       \arg        data_time_segment_2: 0x00 - 0x07
645       \arg        data_prescaler: 0x0001 - 0x0400
646     \param[out] none
647     \retval     ErrStatus: SUCCESS or ERROR
648 */
can_fd_init(uint32_t can_periph,can_fdframe_struct * can_fdframe_init)649 ErrStatus can_fd_init(uint32_t can_periph, can_fdframe_struct* can_fdframe_init)
650 {
651     uint32_t timeout = CAN_TIMEOUT;
652     uint32_t tempreg = 0U;
653 
654     /* check null pointer */
655     if(0 == can_fdframe_init){
656         return ERROR;
657     }
658     /* disable sleep mode */
659     CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD;
660     /* enable initialize mode */
661     CAN_CTL(can_periph) |= CAN_CTL_IWMOD;
662     /* wait ACK */
663     while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
664         timeout--;
665     }
666     /* check initialize working success */
667     if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){
668         return ERROR;
669     }else{
670         /* set the data bit timing register */
671         CAN_DBT(can_periph) = (BT_DSJW((uint32_t)can_fdframe_init->data_resync_jump_width) | \
672                                BT_DBS1((uint32_t)can_fdframe_init->data_time_segment_1) | \
673                                BT_DBS2((uint32_t)can_fdframe_init->data_time_segment_2) | \
674                                BT_BAUDPSC(((uint32_t)can_fdframe_init->data_prescaler) - 1U));
675 
676         tempreg = can_fdframe_init->esi_mode | can_fdframe_init->iso_bosch;
677 
678         /* Protocol exception event detection */
679         if(ENABLE == can_fdframe_init->excp_event_detect){
680             tempreg &= ~CAN_FDCTL_PRED;
681         }else{
682             tempreg |= CAN_FDCTL_PRED;
683         }
684 
685         /* Transmitter delay compensation mode */
686         if(ENABLE == can_fdframe_init->delay_compensation){
687             tempreg |= CAN_FDCTL_TDCEN;
688             /* p_delay_compensation pointer should be config when TDC mode is enabled */
689             if(0 != can_fdframe_init->p_delay_compensation){
690                 tempreg |= (can_fdframe_init->p_delay_compensation->tdc_mode & CAN_FDCTL_TDCMOD);
691                 CAN_FDTDC(can_periph) = (FDTDC_TDCF(can_fdframe_init->p_delay_compensation->tdc_filter) | FDTDC_TDCO(can_fdframe_init->p_delay_compensation->tdc_offset));
692             }else{
693                 return ERROR;
694             }
695         }else{
696             /* Transmitter delay compensation mode is disabled */
697             tempreg &= ~CAN_FDCTL_TDCEN;
698         }
699 
700         /* FD operation mode */
701         if(ENABLE == can_fdframe_init->fd_frame){
702             tempreg |= CAN_FDCTL_FDEN;
703         }else{
704             tempreg &= ~CAN_FDCTL_FDEN;
705         }
706         CAN_FDCTL(can_periph) = tempreg;
707 
708         /* disable initialize mode */
709         CAN_CTL(can_periph) &= ~CAN_CTL_IWMOD;
710         timeout = CAN_TIMEOUT;
711         /* wait the ACK */
712         while((CAN_STAT_IWS == (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
713             timeout--;
714         }
715         /* check exit initialize mode */
716         if(0U == timeout){
717             return ERROR;
718         }
719     }
720 
721     return SUCCESS;
722 }
723 
724 /*!
725     \brief      CAN baud rate configure in classic mode
726     \param[in]  can_periph
727       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
728     \param[in]  hz: frequency, range from 1 to 1000000 Hz
729     \param[out] none
730     \retval     ErrStatus: SUCCESS or ERROR
731 */
can_frequency_set(uint32_t can_periph,uint32_t hz)732 ErrStatus can_frequency_set(uint32_t can_periph, uint32_t hz)
733 {
734     ErrStatus reval = SUCCESS;
735     uint32_t reg_temp;
736     uint32_t fdctl_status;
737     /* The maximum baud rate support to 1M  */
738     if(hz <= 1000000U) {
739         if(SUCCESS == can_working_mode_set(can_periph, GD32_CAN_MODE_INITIALIZE)){
740             reg_temp = CAN_BT(can_periph);
741             reg_temp &= (CAN_BT_LCMOD | CAN_BT_SCMOD);
742             fdctl_status = CAN_FDCTL(can_periph);
743             if(CAN_FDCTL_FDEN != (fdctl_status&CAN_FDCTL_FDEN)){
744                 /* CAN FD disable, should frist enable, then write */
745                 fdctl_status = fdctl_status | CAN_FDCTL_FDEN;
746                 CAN_FDCTL(can_periph) = fdctl_status;
747                 CAN_BT(can_periph) = reg_temp | dev_can_baudrate_set(hz);
748                 fdctl_status = fdctl_status & (~CAN_FDCTL_FDEN);
749                 CAN_FDCTL(can_periph) = fdctl_status;
750             }else{
751                 /* CAN FD enable */
752                 CAN_BT(can_periph) = reg_temp | dev_can_baudrate_set(hz);
753             }
754         }else {
755             reval = ERROR;
756         }
757 
758         if(SUCCESS != can_working_mode_set(can_periph, GD32_CAN_MODE_NORMAL)){
759             reval = ERROR;
760         }
761     }else{
762         reval = ERROR;
763     }
764 
765     return reval;
766 }
767 
768 /*!
769     \brief      CAN baud rate configure in FD mode
770     \param[in]  can_periph
771       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
772     \param[in]  hz: frequency
773     \param[out] none
774     \retval     ErrStatus: SUCCESS or ERROR
775 */
can_fd_frequency_set(uint32_t can_periph,uint32_t hz)776 ErrStatus can_fd_frequency_set(uint32_t can_periph, uint32_t hz)
777 {
778     ErrStatus reval = SUCCESS;
779 
780     if(SUCCESS == can_working_mode_set(can_periph, GD32_CAN_MODE_INITIALIZE)){
781         CAN_DBT(can_periph) = dev_can_fd_baudrate_set(hz);
782     }else {
783         reval = ERROR;
784     }
785 
786     if(SUCCESS != can_working_mode_set(can_periph, GD32_CAN_MODE_NORMAL)){
787         reval = ERROR;
788     }
789 
790     return reval;
791 }
792 
793 /*!
794     \brief      CAN FD frame function enable
795     \param[in]  can_periph
796     \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
797     \param[out] none
798     \retval     none
799 */
can_fd_function_enable(uint32_t can_periph)800 void can_fd_function_enable(uint32_t can_periph)
801 {
802     CAN_FDCTL(can_periph) |= CAN_FDCTL_FDEN;
803 }
804 
805 /*!
806     \brief      CAN FD frame function disable
807     \param[in]  can_periph
808     \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL
809     \param[out] none
810     \retval     none
811 */
can_fd_function_disable(uint32_t can_periph)812 void can_fd_function_disable(uint32_t can_periph)
813 {
814     CAN_FDCTL(can_periph) &= ~CAN_FDCTL_FDEN;
815 }
816 #else
817 /*!
818     \brief      CAN baud rate configure in classic mode
819     \param[in]  can_periph
820       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
821     \param[in]  hz: frequency, range from 1 to 1000000 Hz
822     \param[out] none
823     \retval     ErrStatus: SUCCESS or ERROR
824 */
can_frequency_set(uint32_t can_periph,uint32_t hz)825 ErrStatus can_frequency_set(uint32_t can_periph, uint32_t hz)
826 {
827     ErrStatus reval = SUCCESS;
828     uint32_t reg_temp;
829 
830     /* The maximum baud rate support to 1M  */
831     if(hz <= 1000000U) {
832         if(SUCCESS == can_working_mode_set(can_periph, GD32_CAN_MODE_INITIALIZE)){
833             reg_temp = CAN_BT(can_periph);
834             reg_temp &= (CAN_BT_LCMOD | CAN_BT_SCMOD);
835 
836             CAN_BT(can_periph) = reg_temp | dev_can_baudrate_set(hz);
837         }else {
838             reval = ERROR;
839         }
840 
841         if(SUCCESS != can_working_mode_set(can_periph, GD32_CAN_MODE_NORMAL)){
842             reval = ERROR;
843         }
844     }else{
845         reval = ERROR;
846     }
847 
848     return reval;
849 }
850 #endif /* GD32E508 */
851 
852 /*!
853     \brief      set CAN1 fliter start bank number
854     \param[in]  start_bank: CAN1 start bank number
855                 only one parameter can be selected which is shown as below:
856       \arg        (1..27)
857     \param[out] none
858     \retval     none
859 */
can1_filter_start_bank(uint8_t start_bank)860 void can1_filter_start_bank(uint8_t start_bank)
861 {
862     /* filter lock disable */
863     CAN_FCTL(CAN0) |= CAN_FCTL_FLD;
864     /* set CAN1 filter start number */
865     CAN_FCTL(CAN0) &= ~(uint32_t)CAN_FCTL_HBC1F;
866     CAN_FCTL(CAN0) |= FCTL_HBC1F(start_bank);
867     /* filter lock enable */
868     CAN_FCTL(CAN0) &= ~CAN_FCTL_FLD;
869 }
870 
871 /*!
872     \brief      enable CAN debug freeze
873     \param[in]  can_periph
874       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
875     \param[out] none
876     \retval     none
877 */
can_debug_freeze_enable(uint32_t can_periph)878 void can_debug_freeze_enable(uint32_t can_periph)
879 {
880     /* set DFZ bit */
881     CAN_CTL(can_periph) |= CAN_CTL_DFZ;
882 #ifdef GD32E50X_CL
883     switch(can_periph){
884         case CAN0:
885              dbg_periph_enable(DBG_CAN0_HOLD);
886              break;
887         case CAN1:
888              dbg_periph_enable(DBG_CAN1_HOLD);
889              break;
890         case CAN2:
891              dbg_periph_enable(DBG_CAN2_HOLD);
892              break;
893         default:
894              break;
895     }
896 #else
897     switch(can_periph){
898         case CAN0:
899              dbg_periph_enable(DBG_CAN0_HOLD);
900              break;
901         case CAN1:
902              dbg_periph_enable(DBG_CAN1_HOLD);
903              break;
904         default:
905              break;
906     }
907 #endif
908 }
909 
910 /*!
911     \brief      disable CAN debug freeze
912     \param[in]  can_periph
913       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
914     \param[out] none
915     \retval     none
916 */
can_debug_freeze_disable(uint32_t can_periph)917 void can_debug_freeze_disable(uint32_t can_periph)
918 {
919     /* set DFZ bit */
920     CAN_CTL(can_periph) &= ~CAN_CTL_DFZ;
921 #ifdef GD32E50X_CL
922     switch(can_periph){
923         case CAN0:
924              dbg_periph_disable(DBG_CAN0_HOLD);
925              break;
926         case CAN1:
927              dbg_periph_disable(DBG_CAN1_HOLD);
928              break;
929         case CAN2:
930              dbg_periph_disable(DBG_CAN2_HOLD);
931              break;
932         default:
933              break;
934 #else
935     switch(can_periph){
936         case CAN0:
937              dbg_periph_disable(DBG_CAN0_HOLD);
938              break;
939         case CAN1:
940              dbg_periph_disable(DBG_CAN1_HOLD);
941              break;
942         default:
943              break;
944 #endif
945     }
946 }
947 
948 /*!
949     \brief      enable CAN time trigger mode
950     \param[in]  can_periph
951       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
952     \param[out] none
953     \retval     none
954 */
955 void can_time_trigger_mode_enable(uint32_t can_periph)
956 {
957     uint8_t mailbox_number;
958 
959     /* enable the tcc mode */
960     CAN_CTL(can_periph) |= CAN_CTL_TTC;
961     /* enable time stamp */
962     for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){
963         CAN_TMP(can_periph, mailbox_number) |= CAN_TMP_TSEN;
964     }
965 }
966 
967 /*!
968     \brief      disable CAN time trigger mode
969     \param[in]  can_periph
970       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
971     \param[out] none
972     \retval     none
973 */
974 void can_time_trigger_mode_disable(uint32_t can_periph)
975 {
976     uint8_t mailbox_number;
977 
978     /* disable the TCC mode */
979     CAN_CTL(can_periph) &= ~CAN_CTL_TTC;
980     /* reset TSEN bits */
981     for(mailbox_number = 0U; mailbox_number < 3U; mailbox_number++){
982         CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_TSEN;
983     }
984 }
985 
986 /*!
987     \brief       transmit CAN message
988     \param[in]  can_periph
989       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
990     \param[in]  transmit_message: struct for CAN transmit message
991       \arg        tx_sfid: 0x00000000 - 0x000007FF
992       \arg        tx_efid: 0x00000000 - 0x1FFFFFFF
993       \arg        tx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED
994       \arg        tx_ft: CAN_FT_DATA, CAN_FT_REMOTE
995       \arg        tx_dlen: 0 - 8 (FD mode: 0 - 8, or 12, 16, 20, 24, 32, 48, 64)
996       \arg        tx_data[]: 0x00 - 0xFF
997     \param[out] none
998     \retval     mailbox_number
999 */
1000 uint8_t can_message_transmit(uint32_t can_periph, can_trasnmit_message_struct* transmit_message)
1001 {
1002     uint8_t mailbox_number = CAN_MAILBOX0;
1003     volatile uint32_t p_temp;
1004 #ifdef GD32E508
1005     uint8_t i = 0U;
1006     uint8_t hit = 0U;
1007     uint32_t canfd_en = 0U;
1008     uint32_t reg_temp = 0U;
1009 #endif /* GD32E508 */
1010 
1011     /* select one empty mailbox */
1012     if(CAN_TSTAT_TME0 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME0)){
1013         mailbox_number = CAN_MAILBOX0;
1014     }else if(CAN_TSTAT_TME1 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME1)){
1015         mailbox_number = CAN_MAILBOX1;
1016     }else if(CAN_TSTAT_TME2 == (CAN_TSTAT(can_periph)&CAN_TSTAT_TME2)){
1017         mailbox_number = CAN_MAILBOX2;
1018     }else{
1019         mailbox_number = CAN_NOMAILBOX;
1020     }
1021     /* return no mailbox empty */
1022     if(CAN_NOMAILBOX == mailbox_number){
1023         return CAN_NOMAILBOX;
1024     }
1025 
1026     CAN_TMI(can_periph, mailbox_number) &= CAN_TMI_TEN;
1027     if(CAN_FF_STANDARD == transmit_message->tx_ff){
1028         /* set transmit mailbox standard identifier */
1029         CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_SFID(transmit_message->tx_sfid) | \
1030                                                 transmit_message->tx_ft);
1031     }else{
1032         /* set transmit mailbox extended identifier */
1033         CAN_TMI(can_periph, mailbox_number) |= (uint32_t)(TMI_EFID(transmit_message->tx_efid) | \
1034                                                 transmit_message->tx_ff | \
1035                                                 transmit_message->tx_ft);
1036     }
1037 
1038 #ifdef GD32E508
1039     if(CAN_FDF_CLASSIC == transmit_message->fd_flag){
1040         /* set the data length */
1041         CAN_TMP(can_periph, mailbox_number) &= ~(CAN_TMP_DLENC|CAN_TMP_ESI|CAN_TMP_BRS|CAN_TMP_FDF);
1042         CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen;
1043         /* set the data */
1044         CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \
1045                                                   TMDATA0_DB2(transmit_message->tx_data[2]) | \
1046                                                   TMDATA0_DB1(transmit_message->tx_data[1]) | \
1047                                                   TMDATA0_DB0(transmit_message->tx_data[0]);
1048         CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \
1049                                                   TMDATA1_DB6(transmit_message->tx_data[6]) | \
1050                                                   TMDATA1_DB5(transmit_message->tx_data[5]) | \
1051                                                   TMDATA1_DB4(transmit_message->tx_data[4]);
1052     }else{
1053         canfd_en = CAN_FDCTL(can_periph) & CAN_FDCTL_FDEN;
1054         /* check FD funciton has been enabled */
1055         if(canfd_en){
1056             if(transmit_message->tx_dlen <= 8U){
1057                 /* set the data length */
1058                 reg_temp |= transmit_message->tx_dlen;
1059             }else{
1060                 /* data length greater than 8 */
1061                 for(i = 0U; i < 7U; i++){
1062                     if(transmit_message->tx_dlen == g_can_fdlength_table[i]){
1063                         hit = 1U;
1064                         break;
1065                     }
1066                 }
1067                 /* data length is valid */
1068                 if(1U == hit){
1069                    reg_temp |= 9U + i;
1070                 }else{
1071                     CAN_ERROR_HANDLE("dlen is invalid \r\n");
1072                 }
1073             }
1074             reg_temp |= (((uint32_t)transmit_message->fd_brs << 5U) | ((uint32_t)transmit_message->fd_esi << 4U) | ((uint32_t)transmit_message->fd_flag << 7U));
1075             CAN_TMP(can_periph, mailbox_number) = reg_temp;
1076 
1077             /* set the data */
1078             i = transmit_message->tx_dlen / 4U;
1079 
1080             /* data length is 5-7 need send 2 word */
1081             if((1U==i) && (4U!=transmit_message->tx_dlen)){
1082                 i++;
1083             }
1084             p_temp = (uint32_t)transmit_message->tx_data;
1085             if((0U==i)){
1086                 CAN_TMDATA0(can_periph, mailbox_number) = *(uint32_t *)p_temp;
1087             }else{
1088                 for(; i>0U; i--){
1089                     CAN_TMDATA0(can_periph, mailbox_number) = *(uint32_t *)p_temp;
1090                     p_temp = ((uint32_t)((uint32_t)p_temp + 4U));
1091                 }
1092             }
1093 
1094         }else{
1095             CAN_ERROR_HANDLE("CAN FD function disabled \r\n");
1096         }
1097     }
1098 #else
1099     /* set the data length */
1100     CAN_TMP(can_periph, mailbox_number) &= ~CAN_TMP_DLENC;
1101     CAN_TMP(can_periph, mailbox_number) |= transmit_message->tx_dlen;
1102     /* set the data */
1103     CAN_TMDATA0(can_periph, mailbox_number) = TMDATA0_DB3(transmit_message->tx_data[3]) | \
1104                                               TMDATA0_DB2(transmit_message->tx_data[2]) | \
1105                                               TMDATA0_DB1(transmit_message->tx_data[1]) | \
1106                                               TMDATA0_DB0(transmit_message->tx_data[0]);
1107     CAN_TMDATA1(can_periph, mailbox_number) = TMDATA1_DB7(transmit_message->tx_data[7]) | \
1108                                               TMDATA1_DB6(transmit_message->tx_data[6]) | \
1109                                               TMDATA1_DB5(transmit_message->tx_data[5]) | \
1110                                               TMDATA1_DB4(transmit_message->tx_data[4]);
1111 #endif /* GD32E508 */
1112     /* enable transmission */
1113     CAN_TMI(can_periph, mailbox_number) |= CAN_TMI_TEN;
1114 
1115     return mailbox_number;
1116 }
1117 
1118 /*!
1119     \brief      get CAN transmit state
1120     \param[in]  can_periph
1121       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1122     \param[in]  mailbox_number
1123                 only one parameter can be selected which is shown as below:
1124       \arg        CAN_MAILBOX(x=0,1,2)
1125     \param[out] none
1126     \retval     can_transmit_state_enum
1127 */
1128 can_transmit_state_enum can_transmit_states(uint32_t can_periph, uint8_t mailbox_number)
1129 {
1130     can_transmit_state_enum state = CAN_TRANSMIT_FAILED;
1131     uint32_t val = 0U;
1132 
1133     /* check selected mailbox state */
1134     switch(mailbox_number){
1135     /* mailbox0 */
1136     case CAN_MAILBOX0:
1137         val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0);
1138         break;
1139     /* mailbox1 */
1140     case CAN_MAILBOX1:
1141         val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1);
1142         break;
1143     /* mailbox2 */
1144     case CAN_MAILBOX2:
1145         val = CAN_TSTAT(can_periph) & (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2);
1146         break;
1147     default:
1148         val = CAN_TRANSMIT_FAILED;
1149         break;
1150     }
1151 
1152     switch(val){
1153         /* transmit pending */
1154     case (CAN_STATE_PENDING):
1155         state = CAN_TRANSMIT_PENDING;
1156         break;
1157         /* mailbox0 transmit succeeded */
1158     case (CAN_TSTAT_MTF0 | CAN_TSTAT_MTFNERR0 | CAN_TSTAT_TME0):
1159         state = CAN_TRANSMIT_OK;
1160         break;
1161         /* mailbox1 transmit succeeded */
1162     case (CAN_TSTAT_MTF1 | CAN_TSTAT_MTFNERR1 | CAN_TSTAT_TME1):
1163         state = CAN_TRANSMIT_OK;
1164         break;
1165         /* mailbox2 transmit succeeded */
1166     case (CAN_TSTAT_MTF2 | CAN_TSTAT_MTFNERR2 | CAN_TSTAT_TME2):
1167         state = CAN_TRANSMIT_OK;
1168         break;
1169         /* transmit failed */
1170     default:
1171         state = CAN_TRANSMIT_FAILED;
1172         break;
1173     }
1174     return state;
1175 }
1176 
1177 /*!
1178     \brief      stop CAN transmission
1179     \param[in]  can_periph
1180       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1181     \param[in]  mailbox_number
1182                 only one parameter can be selected which is shown as below:
1183       \arg        CAN_MAILBOXx(x=0,1,2)
1184     \param[out] none
1185     \retval     none
1186 */
1187 void can_transmission_stop(uint32_t can_periph, uint8_t mailbox_number)
1188 {
1189     if(CAN_MAILBOX0 == mailbox_number){
1190         CAN_TSTAT(can_periph) |= CAN_TSTAT_MST0;
1191         while(CAN_TSTAT_MST0 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST0)){
1192         }
1193     }else if(CAN_MAILBOX1 == mailbox_number){
1194         CAN_TSTAT(can_periph) |= CAN_TSTAT_MST1;
1195         while(CAN_TSTAT_MST1 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST1)){
1196         }
1197     }else if(CAN_MAILBOX2 == mailbox_number){
1198         CAN_TSTAT(can_periph) |= CAN_TSTAT_MST2;
1199         while(CAN_TSTAT_MST2 == (CAN_TSTAT(can_periph) & CAN_TSTAT_MST2)){
1200         }
1201     }else{
1202         /* illegal parameters */
1203     }
1204 }
1205 
1206 /*!
1207     \brief      CAN receive message
1208     \param[in]  can_periph
1209       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1210     \param[in]  fifo_number
1211       \arg        CAN_FIFOx(x=0,1)
1212     \param[out] receive_message: struct for CAN receive message
1213       \arg        rx_sfid: 0x00000000 - 0x000007FF
1214       \arg        rx_efid: 0x00000000 - 0x1FFFFFFF
1215       \arg        rx_ff: CAN_FF_STANDARD, CAN_FF_EXTENDED
1216       \arg        rx_ft: CAN_FT_DATA, CAN_FT_REMOTE
1217       \arg        rx_dlen: 0 - 8 (FD mode: 0 - 8, or 12, 16, 20, 24, 32, 48, 64)
1218       \arg        rx_data[]: 0x00 - 0xFF
1219       \arg        rx_fi: 0 - 27
1220     \retval     none
1221 */
1222 void can_message_receive(uint32_t can_periph, uint8_t fifo_number, can_receive_message_struct* receive_message)
1223 {
1224     volatile uint32_t p_temp;
1225 #ifdef GD32E508
1226     uint32_t canfd_en = 0U;
1227     uint32_t data_temp;
1228     uint8_t canfd_recv_cnt = 0U;
1229     uint8_t i;
1230 #endif /* GD32E508 */
1231 
1232     /* get the frame format */
1233     receive_message->rx_ff = (uint8_t)(CAN_RFIFOMI_FF & CAN_RFIFOMI(can_periph, fifo_number));
1234     if(CAN_FF_STANDARD == receive_message->rx_ff){
1235         /* get standard identifier */
1236         receive_message->rx_sfid = (uint32_t)(GET_RFIFOMI_SFID(CAN_RFIFOMI(can_periph, fifo_number)));
1237     }else{
1238         /* get extended identifier */
1239         receive_message->rx_efid = (uint32_t)(GET_RFIFOMI_EFID(CAN_RFIFOMI(can_periph, fifo_number)));
1240     }
1241 
1242     /* get frame type */
1243     receive_message->rx_ft = (uint8_t)(CAN_RFIFOMI_FT & CAN_RFIFOMI(can_periph, fifo_number));
1244     /* filtering index */
1245     receive_message->rx_fi = (uint8_t)(GET_RFIFOMP_FI(CAN_RFIFOMP(can_periph, fifo_number)));
1246 
1247 #ifdef GD32E508
1248     receive_message->fd_flag = (uint8_t)((CAN_RFIFOMP_FDF & CAN_RFIFOMP(can_periph, fifo_number))>>7);
1249 
1250     canfd_en = CAN_FDCTL(can_periph) & CAN_FDCTL_FDEN;
1251     if(!canfd_en){
1252         if(CAN_FDF_CLASSIC == receive_message->fd_flag){
1253             /* get recevie data length */
1254             receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number)));
1255             /* receive data */
1256             receive_message->rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number)));
1257             receive_message->rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number)));
1258             receive_message->rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number)));
1259             receive_message->rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number)));
1260             receive_message->rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number)));
1261             receive_message->rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number)));
1262             receive_message->rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number)));
1263             receive_message->rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number)));
1264         }else{
1265             CAN_ERROR_HANDLE("CAN FD function disabled \r\n");
1266         }
1267     }else{
1268         /* check FD funciton has been enabled */
1269         /* get recevie data length */
1270         canfd_recv_cnt = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number)));
1271 
1272         if(canfd_recv_cnt <= 8U){
1273             /* set the data length */
1274             receive_message->rx_dlen = canfd_recv_cnt;
1275         }else{
1276             receive_message->rx_dlen = g_can_fdlength_table[canfd_recv_cnt - 9U];
1277         }
1278 
1279         receive_message->fd_brs = (uint8_t)((CAN_RFIFOMP(can_periph, fifo_number) & CAN_RFIFOMP_BRS) >> 5);
1280         receive_message->fd_esi = (uint8_t)((CAN_RFIFOMP(can_periph, fifo_number) & CAN_RFIFOMP_ESI) >> 4);
1281 
1282         /* get the data */
1283         i = receive_message->rx_dlen / 4U;
1284 
1285         /* data length is 5-7 need receive 2 word */
1286         if((1U==i) && (4U!=receive_message->rx_dlen)){
1287             i++;
1288         }
1289         p_temp = (uint32_t)(uint32_t)receive_message->rx_data;
1290         if(0U==i){
1291             data_temp = CAN_RFIFOMDATA0(can_periph, fifo_number);
1292             *(uint32_t *)p_temp = data_temp;
1293         }else{
1294             /* get the data by reading from CAN_RFIFOMDATA0 register*/
1295             for(; i>0U; i--){
1296                 data_temp = CAN_RFIFOMDATA0(can_periph, fifo_number);
1297                 *(uint32_t *)p_temp = data_temp;
1298                 p_temp = ((uint32_t)((uint32_t)p_temp + 4U));
1299             }
1300         }
1301     }
1302 #else
1303     /* get recevie data length */
1304     receive_message->rx_dlen = (uint8_t)(GET_RFIFOMP_DLENC(CAN_RFIFOMP(can_periph, fifo_number)));
1305 
1306     /* receive data */
1307     receive_message -> rx_data[0] = (uint8_t)(GET_RFIFOMDATA0_DB0(CAN_RFIFOMDATA0(can_periph, fifo_number)));
1308     receive_message -> rx_data[1] = (uint8_t)(GET_RFIFOMDATA0_DB1(CAN_RFIFOMDATA0(can_periph, fifo_number)));
1309     receive_message -> rx_data[2] = (uint8_t)(GET_RFIFOMDATA0_DB2(CAN_RFIFOMDATA0(can_periph, fifo_number)));
1310     receive_message -> rx_data[3] = (uint8_t)(GET_RFIFOMDATA0_DB3(CAN_RFIFOMDATA0(can_periph, fifo_number)));
1311     receive_message -> rx_data[4] = (uint8_t)(GET_RFIFOMDATA1_DB4(CAN_RFIFOMDATA1(can_periph, fifo_number)));
1312     receive_message -> rx_data[5] = (uint8_t)(GET_RFIFOMDATA1_DB5(CAN_RFIFOMDATA1(can_periph, fifo_number)));
1313     receive_message -> rx_data[6] = (uint8_t)(GET_RFIFOMDATA1_DB6(CAN_RFIFOMDATA1(can_periph, fifo_number)));
1314     receive_message -> rx_data[7] = (uint8_t)(GET_RFIFOMDATA1_DB7(CAN_RFIFOMDATA1(can_periph, fifo_number)));
1315 
1316 #endif /* GD32E508 */
1317     /* release FIFO */
1318     if(CAN_FIFO0 == fifo_number){
1319         CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0;
1320     }else{
1321         CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1;
1322     }
1323 }
1324 
1325 /*!
1326     \brief      release FIFO0
1327     \param[in]  can_periph
1328       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1329     \param[in]  fifo_number
1330                 only one parameter can be selected which is shown as below:
1331       \arg        CAN_FIFOx(x=0,1)
1332     \param[out] none
1333     \retval     none
1334 */
1335 void can_fifo_release(uint32_t can_periph, uint8_t fifo_number)
1336 {
1337     if(CAN_FIFO0 == fifo_number){
1338         CAN_RFIFO0(can_periph) |= CAN_RFIFO0_RFD0;
1339     }else if(CAN_FIFO1 == fifo_number){
1340         CAN_RFIFO1(can_periph) |= CAN_RFIFO1_RFD1;
1341     }else{
1342         /* illegal parameters */
1343         CAN_ERROR_HANDLE("CAN FIFO NUM is invalid \r\n");
1344     }
1345 }
1346 
1347 /*!
1348     \brief      CAN receive message length
1349     \param[in]  can_periph
1350       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1351     \param[in]  fifo_number
1352                 only one parameter can be selected which is shown as below:
1353       \arg        CAN_FIFOx(x=0,1)
1354     \param[out] none
1355     \retval     message length
1356 */
1357 uint8_t can_receive_message_length_get(uint32_t can_periph, uint8_t fifo_number)
1358 {
1359     uint8_t val = 0U;
1360 
1361     if(CAN_FIFO0 == fifo_number){
1362         /* FIFO0 */
1363         val = (uint8_t)(CAN_RFIFO0(can_periph) & CAN_RFIF_RFL_MASK);
1364     }else if(CAN_FIFO1 == fifo_number){
1365         /* FIFO1 */
1366         val = (uint8_t)(CAN_RFIFO1(can_periph) & CAN_RFIF_RFL_MASK);
1367     }else{
1368         /* illegal parameters */
1369     }
1370     return val;
1371 }
1372 
1373 /*!
1374     \brief      set CAN working mode
1375     \param[in]  can_periph
1376       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1377     \param[in]  can_working_mode
1378                 only one parameter can be selected which is shown as below:
1379       \arg        GD32_CAN_MODE_INITIALIZE
1380       \arg        GD32_CAN_MODE_NORMAL
1381       \arg        GD32_CAN_MODE_SLEEP
1382     \param[out] none
1383     \retval     ErrStatus: SUCCESS or ERROR
1384 */
1385 ErrStatus can_working_mode_set(uint32_t can_periph, uint8_t working_mode)
1386 {
1387     ErrStatus flag = ERROR;
1388     /* timeout for IWS or also for SLPWS bits */
1389     uint32_t timeout = CAN_TIMEOUT;
1390 
1391     if(GD32_CAN_MODE_INITIALIZE == working_mode){
1392         /* disable sleep mode */
1393         CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_SLPWMOD);
1394         /* set initialize mode */
1395         CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_IWMOD;
1396         /* wait the acknowledge */
1397         while((CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)) && (0U != timeout)){
1398             timeout--;
1399         }
1400         if(CAN_STAT_IWS != (CAN_STAT(can_periph) & CAN_STAT_IWS)){
1401             flag = ERROR;
1402         }else{
1403             flag = SUCCESS;
1404         }
1405     }else if(GD32_CAN_MODE_NORMAL == working_mode){
1406         /* enter normal mode */
1407         CAN_CTL(can_periph) &= ~(uint32_t)(CAN_CTL_SLPWMOD | CAN_CTL_IWMOD);
1408         /* wait the acknowledge */
1409         while((0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))) && (0U != timeout)){
1410             timeout--;
1411         }
1412         if(0U != (CAN_STAT(can_periph) & (CAN_STAT_IWS | CAN_STAT_SLPWS))){
1413             flag = ERROR;
1414         }else{
1415             flag = SUCCESS;
1416         }
1417     }else if(GD32_CAN_MODE_SLEEP == working_mode){
1418         /* disable initialize mode */
1419         CAN_CTL(can_periph) &= (~(uint32_t)CAN_CTL_IWMOD);
1420         /* set sleep mode */
1421         CAN_CTL(can_periph) |= (uint8_t)CAN_CTL_SLPWMOD;
1422         /* wait the acknowledge */
1423         while((CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0U != timeout)){
1424             timeout--;
1425         }
1426         if(CAN_STAT_SLPWS != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){
1427             flag = ERROR;
1428         }else{
1429             flag = SUCCESS;
1430         }
1431     }else{
1432         flag = ERROR;
1433     }
1434     return flag;
1435 }
1436 
1437 /*!
1438     \brief      wake up CAN
1439     \param[in]  can_periph
1440       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1441     \param[out] none
1442     \retval     ErrStatus: SUCCESS or ERROR
1443 */
1444 ErrStatus can_wakeup(uint32_t can_periph)
1445 {
1446     ErrStatus flag = ERROR;
1447     uint32_t timeout = CAN_TIMEOUT;
1448 
1449     /* wakeup */
1450     CAN_CTL(can_periph) &= ~CAN_CTL_SLPWMOD;
1451 
1452     while((0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)) && (0x00U != timeout)){
1453         timeout--;
1454     }
1455     /* check state */
1456     if(0U != (CAN_STAT(can_periph) & CAN_STAT_SLPWS)){
1457         flag = ERROR;
1458     }else{
1459         flag = SUCCESS;
1460     }
1461     return flag;
1462 }
1463 
1464 /*!
1465     \brief      get CAN error type
1466     \param[in]  can_periph
1467       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1468     \param[out] none
1469     \retval     can_error_enum
1470       \arg        CAN_ERROR_NONE: no error
1471       \arg        CAN_ERROR_FILL: fill error
1472       \arg        CAN_ERROR_FORMATE: format error
1473       \arg        CAN_ERROR_ACK: ACK error
1474       \arg        CAN_ERROR_BITRECESSIVE: bit recessive
1475       \arg        CAN_ERROR_BITDOMINANTER: bit dominant error
1476       \arg        CAN_ERROR_CRC: CRC error
1477       \arg        CAN_ERROR_SOFTWARECFG: software configure
1478 */
1479 can_error_enum can_error_get(uint32_t can_periph)
1480 {
1481     can_error_enum error;
1482     error = CAN_ERROR_NONE;
1483 
1484     /* get error type */
1485     error = (can_error_enum)(GET_ERR_ERRN(CAN_ERR(can_periph)));
1486     return error;
1487 }
1488 
1489 /*!
1490     \brief      get CAN receive error number
1491     \param[in]  can_periph
1492       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL
1493     \param[out] none
1494     \retval     error number
1495 */
1496 uint8_t can_receive_error_number_get(uint32_t can_periph)
1497 {
1498     uint8_t val;
1499 
1500     /* get error count */
1501     val = (uint8_t)(GET_ERR_RECNT(CAN_ERR(can_periph)));
1502     return val;
1503 }
1504 
1505 /*!
1506     \brief      get CAN transmit error number
1507     \param[in]  can_periph
1508       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1509     \param[out] none
1510     \retval     error number
1511 */
1512 uint8_t can_transmit_error_number_get(uint32_t can_periph)
1513 {
1514     uint8_t val;
1515 
1516     val = (uint8_t)(GET_ERR_TECNT(CAN_ERR(can_periph)));
1517     return val;
1518 }
1519 
1520 /*!
1521     \brief      enable CAN interrupt
1522     \param[in]  can_periph
1523       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1524     \param[in]  interrupt
1525                 one or more parameters can be selected which are shown as below:
1526       \arg        CAN_INT_TME: transmit mailbox empty interrupt enable
1527       \arg        CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable
1528       \arg        CAN_INT_RFF0: receive FIFO0 full interrupt enable
1529       \arg        CAN_INT_RFO0: receive FIFO0 overfull interrupt enable
1530       \arg        CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable
1531       \arg        CAN_INT_RFF1: receive FIFO1 full interrupt enable
1532       \arg        CAN_INT_RFO1: receive FIFO1 overfull interrupt enable
1533       \arg        CAN_INT_WERR: warning error interrupt enable
1534       \arg        CAN_INT_PERR: passive error interrupt enable
1535       \arg        CAN_INT_BO: bus-off interrupt enable
1536       \arg        CAN_INT_ERRN: error number interrupt enable
1537       \arg        CAN_INT_ERR: error interrupt enable
1538       \arg        CAN_INT_WU: wakeup interrupt enable
1539       \arg        CAN_INT_SLPW: sleep working interrupt enable
1540     \param[out] none
1541     \retval     none
1542 */
1543 void can_interrupt_enable(uint32_t can_periph, uint32_t interrupt)
1544 {
1545     CAN_INTEN(can_periph) |= interrupt;
1546 }
1547 
1548 /*!
1549     \brief      disable CAN interrupt
1550     \param[in]  can_periph
1551       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1552     \param[in]  interrupt
1553                 one or more parameters can be selected which are shown as below:
1554       \arg        CAN_INT_TME: transmit mailbox empty interrupt enable
1555       \arg        CAN_INT_RFNE0: receive FIFO0 not empty interrupt enable
1556       \arg        CAN_INT_RFF0: receive FIFO0 full interrupt enable
1557       \arg        CAN_INT_RFO0: receive FIFO0 overfull interrupt enable
1558       \arg        CAN_INT_RFNE1: receive FIFO1 not empty interrupt enable
1559       \arg        CAN_INT_RFF1: receive FIFO1 full interrupt enable
1560       \arg        CAN_INT_RFO1: receive FIFO1 overfull interrupt enable
1561       \arg        CAN_INT_WERR: warning error interrupt enable
1562       \arg        CAN_INT_PERR: passive error interrupt enable
1563       \arg        CAN_INT_BO: bus-off interrupt enable
1564       \arg        CAN_INT_ERRN: error number interrupt enable
1565       \arg        CAN_INT_ERR: error interrupt enable
1566       \arg        CAN_INT_WU: wakeup interrupt enable
1567       \arg        CAN_INT_SLPW: sleep working interrupt enable
1568     \param[out] none
1569     \retval     none
1570 */
1571 void can_interrupt_disable(uint32_t can_periph, uint32_t interrupt)
1572 {
1573     CAN_INTEN(can_periph) &= ~interrupt;
1574 }
1575 
1576 /*!
1577     \brief      get CAN flag state
1578     \param[in]  can_periph
1579       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1580     \param[in]  flag: CAN flags, refer to can_flag_enum
1581                 only one parameter can be selected which is shown as below:
1582       \arg        CAN_FLAG_RXL: RX level
1583       \arg        CAN_FLAG_LASTRX: last sample value of RX pin
1584       \arg        CAN_FLAG_RS: receiving state
1585       \arg        CAN_FLAG_TS: transmitting state
1586       \arg        CAN_FLAG_SLPIF: status change flag of entering sleep working mode
1587       \arg        CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode
1588       \arg        CAN_FLAG_ERRIF: error flag
1589       \arg        CAN_FLAG_SLPWS: sleep working state
1590       \arg        CAN_FLAG_IWS: initial working state
1591       \arg        CAN_FLAG_TMLS2: transmit mailbox 2 last sending in Tx FIFO
1592       \arg        CAN_FLAG_TMLS1: transmit mailbox 1 last sending in Tx FIFO
1593       \arg        CAN_FLAG_TMLS0: transmit mailbox 0 last sending in Tx FIFO
1594       \arg        CAN_FLAG_TME2: transmit mailbox 2 empty
1595       \arg        CAN_FLAG_TME1: transmit mailbox 1 empty
1596       \arg        CAN_FLAG_TME0: transmit mailbox 0 empty
1597       \arg        CAN_FLAG_MTE2: mailbox 2 transmit error
1598       \arg        CAN_FLAG_MTE1: mailbox 1 transmit error
1599       \arg        CAN_FLAG_MTE0: mailbox 0 transmit error
1600       \arg        CAN_FLAG_MAL2: mailbox 2 arbitration lost
1601       \arg        CAN_FLAG_MAL1: mailbox 1 arbitration lost
1602       \arg        CAN_FLAG_MAL0: mailbox 0 arbitration lost
1603       \arg        CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error
1604       \arg        CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error
1605       \arg        CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error
1606       \arg        CAN_FLAG_MTF2: mailbox 2 transmit finished
1607       \arg        CAN_FLAG_MTF1: mailbox 1 transmit finished
1608       \arg        CAN_FLAG_MTF0: mailbox 0 transmit finished
1609       \arg        CAN_FLAG_RFO0: receive FIFO0 overfull
1610       \arg        CAN_FLAG_RFF0: receive FIFO0 full
1611       \arg        CAN_FLAG_RFO1: receive FIFO1 overfull
1612       \arg        CAN_FLAG_RFF1: receive FIFO1 full
1613       \arg        CAN_FLAG_BOERR: bus-off error
1614       \arg        CAN_FLAG_PERR: passive error
1615       \arg        CAN_FLAG_WERR: warning error
1616     \param[out] none
1617     \retval     FlagStatus: SET or RESET
1618 */
1619 FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag)
1620 {
1621     /* get flag and interrupt enable state */
1622     if(RESET != (CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag)))){
1623         return SET;
1624     }else{
1625         return RESET;
1626     }
1627 }
1628 
1629 /*!
1630     \brief      clear CAN flag state
1631     \param[in]  can_periph
1632       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1633     \param[in]  flag: CAN flags, refer to can_flag_enum
1634                 only one parameter can be selected which is shown as below:
1635       \arg        CAN_FLAG_SLPIF: status change flag of entering sleep working mode
1636       \arg        CAN_FLAG_WUIF: status change flag of wakeup from sleep working mode
1637       \arg        CAN_FLAG_ERRIF: error flag
1638       \arg        CAN_FLAG_MTE2: mailbox 2 transmit error
1639       \arg        CAN_FLAG_MTE1: mailbox 1 transmit error
1640       \arg        CAN_FLAG_MTE0: mailbox 0 transmit error
1641       \arg        CAN_FLAG_MAL2: mailbox 2 arbitration lost
1642       \arg        CAN_FLAG_MAL1: mailbox 1 arbitration lost
1643       \arg        CAN_FLAG_MAL0: mailbox 0 arbitration lost
1644       \arg        CAN_FLAG_MTFNERR2: mailbox 2 transmit finished with no error
1645       \arg        CAN_FLAG_MTFNERR1: mailbox 1 transmit finished with no error
1646       \arg        CAN_FLAG_MTFNERR0: mailbox 0 transmit finished with no error
1647       \arg        CAN_FLAG_MTF2: mailbox 2 transmit finished
1648       \arg        CAN_FLAG_MTF1: mailbox 1 transmit finished
1649       \arg        CAN_FLAG_MTF0: mailbox 0 transmit finished
1650       \arg        CAN_FLAG_RFO0: receive FIFO0 overfull
1651       \arg        CAN_FLAG_RFF0: receive FIFO0 full
1652       \arg        CAN_FLAG_RFO1: receive FIFO1 overfull
1653       \arg        CAN_FLAG_RFF1: receive FIFO1 full
1654     \param[out] none
1655     \retval     none
1656 */
1657 void can_flag_clear(uint32_t can_periph, can_flag_enum flag)
1658 {
1659     CAN_REG_VAL(can_periph, flag) |= BIT(CAN_BIT_POS(flag));
1660 }
1661 
1662 /*!
1663     \brief      get CAN interrupt flag state
1664     \param[in]  can_periph
1665       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1666     \param[in]  int_flag: CAN interrupt flags, refer to can_interrupt_flag_enum
1667                 only one parameter can be selected which is shown as below:
1668       \arg        CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering
1669       \arg        CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode
1670       \arg        CAN_INT_FLAG_ERRIF: error interrupt flag
1671       \arg        CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag
1672       \arg        CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag
1673       \arg        CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag
1674       \arg        CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag
1675       \arg        CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag
1676       \arg        CAN_INT_FLAG_RFL0: receive FIFO0 not empty interrupt flag
1677       \arg        CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag
1678       \arg        CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag
1679       \arg        CAN_INT_FLAG_RFL1: receive FIFO1 not empty interrupt flag
1680       \arg        CAN_INT_FLAG_ERRN: error number interrupt flag
1681       \arg        CAN_INT_FLAG_BOERR: bus-off error interrupt flag
1682       \arg        CAN_INT_FLAG_PERR: passive error interrupt flag
1683       \arg        CAN_INT_FLAG_WERR: warning error interrupt flag
1684     \param[out] none
1685     \retval     FlagStatus: SET or RESET
1686 */
1687 FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum int_flag)
1688 {
1689     uint32_t ret1 = RESET;
1690     uint32_t ret2 = RESET;
1691 
1692     /* get the staus of interrupt flag */
1693     if (int_flag == CAN_INT_FLAG_RFL0) {
1694         ret1 = can_receive_message_length_get(can_periph, CAN_FIFO0);
1695     } else if (int_flag == CAN_INT_FLAG_RFL1) {
1696         ret1 = can_receive_message_length_get(can_periph, CAN_FIFO1);
1697     } else if (int_flag == CAN_INT_FLAG_ERRN) {
1698         ret1 = can_error_get(can_periph);
1699     } else {
1700         ret1 = CAN_REG_VALS(can_periph, int_flag) & BIT(CAN_BIT_POS0(int_flag));
1701     }
1702     /* get the staus of interrupt enale bit */
1703     ret2 = CAN_INTEN(can_periph) & BIT(CAN_BIT_POS1(int_flag));
1704     if(ret1 && ret2){
1705         return SET;
1706     }else{
1707         return RESET;
1708     }
1709 }
1710 
1711 /*!
1712     \brief      clear CAN interrupt flag state
1713     \param[in]  can_periph
1714       \arg        CANx(x=0,1,2),the CAN2 only for GD32E50X_CL and GD32E508
1715     \param[in]  int_flag: CAN interrupt flags, refer to can_interrupt_flag_enum
1716                 only one parameter can be selected which is shown as below:
1717       \arg        CAN_INT_FLAG_SLPIF: status change interrupt flag of sleep working mode entering
1718       \arg        CAN_INT_FLAG_WUIF: status change interrupt flag of wakeup from sleep working mode
1719       \arg        CAN_INT_FLAG_ERRIF: error interrupt flag
1720       \arg        CAN_INT_FLAG_MTF2: mailbox 2 transmit finished interrupt flag
1721       \arg        CAN_INT_FLAG_MTF1: mailbox 1 transmit finished interrupt flag
1722       \arg        CAN_INT_FLAG_MTF0: mailbox 0 transmit finished interrupt flag
1723       \arg        CAN_INT_FLAG_RFO0: receive FIFO0 overfull interrupt flag
1724       \arg        CAN_INT_FLAG_RFF0: receive FIFO0 full interrupt flag
1725       \arg        CAN_INT_FLAG_RFO1: receive FIFO1 overfull interrupt flag
1726       \arg        CAN_INT_FLAG_RFF1: receive FIFO1 full interrupt flag
1727     \param[out] none
1728     \retval     none
1729 */
1730 void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum int_flag)
1731 {
1732     CAN_REG_VALS(can_periph, int_flag) |= BIT(CAN_BIT_POS0(int_flag));
1733 }
1734 
1735 /*!
1736     \brief      auto config can baud rate by frequency
1737     \param[in]  freq: the frequency of the baud rate
1738     \param[out] none
1739     \retval     CAN_BT register set value
1740 */
1741 static unsigned int dev_can_baudrate_set(uint32_t freq)
1742 {
1743     uint32_t reval;
1744     uint32_t baud_psc_min;
1745     uint32_t baud_psc;
1746     uint32_t temp;
1747     uint32_t bt_reg_config;
1748     uint32_t bits = 0U;
1749     uint32_t bs_div_value = 0U;
1750 
1751     struct brate_data_str{
1752         uint32_t bits;
1753         uint32_t baud_psc;
1754         uint32_t min_num;
1755     };
1756 
1757     struct brate_data_str brate_data = {0U, 0U, 0xFFFFFFFFU};
1758 
1759     /* computes the value that the CAN_BT register needs to be configured */
1760     /* for CAN:(BAUDPSC[9:0] + 1) * ((BS1[3:0] + 1) + (BS2[2:0] + 1) + SJW(always 1)) */
1761     /* for CAN-FD:(BAUDPSC[9:0] + 1) * ((BS1[6:0] + 1) + (BS2[4:0] + 1) + SJW(always 1)) */
1762     bt_reg_config = (rcu_clock_freq_get(CK_APB1) / freq);
1763     /* BAUDPSC[9:0] minimum value */
1764     baud_psc_min = bt_reg_config / DEV_CAN_BT_SEG_MAX;
1765     /* BAUDPSC[9:0] maximum value */
1766     baud_psc = bt_reg_config / DEV_CAN_BT_SEG_MIN;
1767 
1768     /* preference for larger baud_psc */
1769     while((baud_psc >= baud_psc_min) && (baud_psc < 0xFFFFU)){
1770         for(bits=0u; bits<=DEV_CAN_BT_SEG_MAX; bits++){
1771             temp = (bits + 3U) * (baud_psc + 1U);
1772 
1773             /* get the combination of smallest difference */
1774             /* calculation the difference */
1775             if(temp>bt_reg_config){
1776                 temp = temp - bt_reg_config;
1777             }else{
1778                 temp = bt_reg_config - temp;
1779             }
1780             /* set the combination with small difference */
1781             if(temp<brate_data.min_num){
1782                     brate_data.baud_psc = baud_psc;
1783                     brate_data.bits = bits;
1784                     brate_data.min_num = temp;
1785                 }
1786         }
1787         baud_psc--;
1788     }
1789 
1790     /* BS1 is 5 times of BS2 */
1791     bs_div_value = brate_data.bits / 5U;
1792     reval = (BT_BS1(brate_data.bits-bs_div_value))
1793           | (BT_BS2(bs_div_value))
1794           | ((0U                  << 24) & DEV_CAN_SJW_MASK)
1795           | ((brate_data.baud_psc)       & DEV_CAN_BAUDPSC_MASK);
1796 
1797     return reval;
1798 }
1799 
1800 #ifdef GD32E508
1801 /*!
1802     \brief      auto config can fd baud rate by frequency
1803     \param[in]  freq: the frequency of the baud rate
1804     \param[out] none
1805     \retval     CAN_BT register set value
1806 */
1807 static unsigned int dev_can_fd_baudrate_set(uint32_t freq)
1808 {
1809     uint32_t reval;
1810     uint32_t baud_psc;
1811     uint32_t baud_psc_max;
1812     uint32_t temp;
1813     uint32_t bt_reg_config;
1814     uint8_t flag;
1815     uint32_t bits = 0U;
1816 
1817     struct brate_data_str{
1818         uint32_t bits;
1819         uint32_t baud_psc;
1820         uint32_t min_num;
1821     };
1822 
1823     struct brate_data_str brate_data = {0U, 0U, 0xFFFFFFFFU};
1824 
1825     flag = 0U;
1826     /* computes the value that the CAN_BT register needs to be configured */
1827     /* (BAUDPSC[9:0] + 1) * ((BS1[3:0] + 1) + (BS2[2:0] + 1) + SJW(always 1)) */
1828     bt_reg_config = (rcu_clock_freq_get(CK_APB1) / freq);
1829     /* BAUDPSC[9:0] minimum value */
1830     baud_psc = bt_reg_config / DEV_CAN_FD_BT_SEG_MAX;
1831     /* BAUDPSC[9:0] maximum value */
1832     baud_psc_max = bt_reg_config / DEV_CAN_FD_BT_SEG_MIN;
1833 
1834     while((!flag) && (baud_psc < baud_psc_max)){
1835         for(bits=0u; bits<=DEV_CAN_FD_BT_SEG_MAX; bits++){
1836             temp = (bits + 3U) * (baud_psc + 1U);
1837 
1838             /* get the combination of smallest difference */
1839             if(temp == bt_reg_config){
1840                 flag = 1U;
1841                 break;
1842             }else{
1843                 /* calculation the difference */
1844                 if(temp>bt_reg_config){
1845                     temp = temp - bt_reg_config;
1846                 }else{
1847                     temp = bt_reg_config - temp;
1848                 }
1849                 /* set the combination with small difference */
1850                 if(temp<brate_data.min_num){
1851                         brate_data.baud_psc = baud_psc;
1852                         brate_data.bits = bits;
1853                         brate_data.min_num = temp;
1854                     }
1855             }
1856         }
1857         if(flag){
1858             break;
1859         }
1860         baud_psc++;
1861     }
1862 
1863     /* set the combination value */
1864     if(flag){
1865         reval = ((timing_pts[bits][1] << 20) & DEV_CAN_BS2_MASK)
1866               | ((timing_pts[bits][0] << 16) & DEV_CAN_BS1_MASK)
1867               | ((0U                  << 24) & DEV_CAN_FD_SJW_MASK)
1868               | ((baud_psc)                  & DEV_CAN_BAUDPSC_MASK);
1869     }else{
1870         reval = ((timing_pts[brate_data.bits][1] << 20) & DEV_CAN_BS2_MASK)
1871               | ((timing_pts[brate_data.bits][0] << 16) & DEV_CAN_BS1_MASK)
1872               | ((0U                             << 24) & DEV_CAN_FD_SJW_MASK)
1873               | ((brate_data.baud_psc)                  & DEV_CAN_BAUDPSC_MASK);
1874     }
1875 
1876     return reval;
1877 }
1878 #endif /* GD32E508 */
1879