1 /*!
2     \file    gd32a50x_can.c
3     \brief   CAN driver
4 
5     \version 2022-01-30, V1.0.0, firmware for GD32A50x
6 */
7 
8 /*
9     Copyright (c) 2022, GigaDevice Semiconductor Inc.
10 
11     Redistribution and use in source and binary forms, with or without modification,
12 are permitted provided that the following conditions are met:
13 
14     1. Redistributions of source code must retain the above copyright notice, this
15        list of conditions and the following disclaimer.
16     2. Redistributions in binary form must reproduce the above copyright notice,
17        this list of conditions and the following disclaimer in the documentation
18        and/or other materials provided with the distribution.
19     3. Neither the name of the copyright holder nor the names of its contributors
20        may be used to endorse or promote products derived from this software without
21        specific prior written permission.
22 
23     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 OF SUCH DAMAGE.
33 */
34 
35 #include "gd32a50x_can.h"
36 
37 /* DLC to data size in bytes definitions */
38 static const uint8_t dlc_to_databytes[16] = {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 12U, 16U, 20U, 24U, 32U, 48U, 64U};
39 
40 /* computes the maximum payload size (in bytes), given a dlc */
41 static uint32_t can_payload_size_compute(uint32_t dlc_value);
42 /* swap data to little endian */
43 static void can_data_to_little_endian_swap(uint32_t dest[], uint32_t src[], uint32_t len);
44 /* swap data to big endian */
45 static void can_data_to_big_endian_swap(uint32_t dest[], uint32_t src[], uint32_t len);
46 /* computes the dlc field value, given a payload size (in bytes) */
47 static uint32_t can_dlc_value_compute(uint32_t payload_size);
48 
49 /*!
50     \brief      deinitialize CAN
51     \param[in]  can_periph: CANx(x=0,1)
52     \param[out] none
53     \retval     none
54 */
can_deinit(uint32_t can_periph)55 void can_deinit(uint32_t can_periph)
56 {
57     if(CAN0 == can_periph) {
58         /* reset CAN0 */
59         rcu_periph_reset_enable(RCU_CAN0RST);
60         rcu_periph_reset_disable(RCU_CAN0RST);
61     }
62     if(CAN1 == can_periph) {
63         /* reset CAN1 */
64         rcu_periph_reset_enable(RCU_CAN1RST);
65         rcu_periph_reset_disable(RCU_CAN1RST);
66     }
67 }
68 
69 /*!
70     \brief      reset CAN internal state machines and CAN registers
71     \param[in]  can_periph: CANx(x=0,1)
72     \param[out] none
73     \retval     ERROR or SUCCESS
74 */
can_software_reset(uint32_t can_periph)75 ErrStatus can_software_reset(uint32_t can_periph)
76 {
77     uint32_t timeout = CAN_DELAY;
78 
79     /* reset internal state machines and CAN registers */
80     CAN_CTL0(can_periph) |= CAN_CTL0_SWRST;
81     /* wait reset complete */
82     while((CAN_CTL0(can_periph) & CAN_CTL0_SWRST) && (timeout)) {
83         timeout--;
84     }
85     if(CAN_CTL0(can_periph) & CAN_CTL0_SWRST) {
86         return ERROR;
87     }
88     return SUCCESS;
89 }
90 
91 /*!
92     \brief      CAN module initialization
93     \param[in]  can_periph: CANx(x=0,1)
94     \param[in]  can_parameter_init: can parameter struct
95                   internal_counter_source: CAN_TIMER_SOURCE_BIT_CLOCK, CAN_TIMER_SOURCE_EXTERNAL_TIME_TICK
96                   self_reception: ENABLE, DISABLE
97                   mb_tx_order: CAN_TX_HIGH_PRIORITY_MB_FIRST, CAN_TX_LOW_NUM_MB_FIRST
98                   mb_tx_abort_enable: ENABLE, DISABLE
99                   local_priority_enable: ENABLE, DISABLE
100                   mb_rx_ide_rtr_type: CAN_IDE_RTR_COMPARED, CAN_IDE_RTR_FILTERED
101                   mb_remote_frame: CAN_GEN_REMOTE_RESPONSE_FRAME, CAN_STORE_REMOTE_REQUEST_FRAME
102                   rx_private_filter_queue_enable: ENABLE, DISABLE
103                   edge_filter_enable: ENABLE, DISABLE
104                   protocol_exception_enable: ENABLE, DISABLE
105                   rx_filter_order: CAN_RX_FILTER_ORDER_FIFO_FIRST, CAN_RX_FILTER_ORDER_MAILBOX_FIRST
106                   memory_size: CAN_MEMSIZE_1_UNIT, CAN_MEMSIZE_2_UNIT, CAN_MEMSIZE_3_UNIT, CAN_MEMSIZE_4_UNIT,
107                                CAN_MEMSIZE_5_UNIT, CAN_MEMSIZE_6_UNIT, CAN_MEMSIZE_7_UNIT, CAN_MEMSIZE_8_UNIT,
108                                CAN_MEMSIZE_9_UNIT, CAN_MEMSIZE_10_UNIT, CAN_MEMSIZE_11_UNIT, CAN_MEMSIZE_12_UNIT,
109                                CAN_MEMSIZE_13_UNIT, CAN_MEMSIZE_14_UNIT, CAN_MEMSIZE_15_UNIT, CAN_MEMSIZE_16_UNIT,
110                                CAN_MEMSIZE_17_UNIT, CAN_MEMSIZE_18_UNIT, CAN_MEMSIZE_19_UNIT, CAN_MEMSIZE_20_UNIT,
111                                CAN_MEMSIZE_21_UNIT, CAN_MEMSIZE_22_UNIT, CAN_MEMSIZE_23_UNIT, CAN_MEMSIZE_24_UNIT,
112                                CAN_MEMSIZE_25_UNIT, CAN_MEMSIZE_26_UNIT, CAN_MEMSIZE_27_UNIT, CAN_MEMSIZE_28_UNIT,
113                                CAN_MEMSIZE_29_UNIT, CAN_MEMSIZE_30_UNIT, CAN_MEMSIZE_31_UNIT, CAN_MEMSIZE_32_UNIT
114                   mb_public_filter: 0x00000000 ~ 0xFFFFFFFF
115                   prescaler: 1~1024
116                   resync_jump_width: 1~32
117                   prop_time_segment: 1~64
118                   time_segment_1: 1~32
119                   time_segment_2: 1~32
120     \param[out] none
121     \retval     ERROR or SUCCESS
122 */
can_init(uint32_t can_periph,can_parameter_struct * can_parameter_init)123 ErrStatus can_init(uint32_t can_periph, can_parameter_struct *can_parameter_init)
124 {
125     uint32_t i;
126     uint32_t *canram = (uint32_t *)(CAN_RAM(can_periph));
127 
128     /* clear CAN RAM */
129     for(i = 0U; i < CAN_MAX_RAM_SIZE; i++) {
130         canram[i] = 0U;
131     }
132     /* reset CAN_RFIFOMPFx */
133     for(i = 0U; i < CAN_MAX_MAILBOX_NUM; i++) {
134         CAN_RFIFOMPF(can_periph, i) = 0x00000000U;
135     }
136 
137     /* reset internal state machines and CAN registers */
138     if(ERROR == can_software_reset(can_periph)) {
139         return ERROR;
140     }
141 
142     /* reset CAN_INTEN */
143     CAN_INTEN(can_periph) = 0U;
144     /* reset CAN_STAT */
145     CAN_STAT(can_periph) = (uint32_t)0xFFFFFFFFU;
146     CAN_TIMER(can_periph);
147     while(CAN_STAT(can_periph) & CAN_STAT_MS5_RFNE) {
148         CAN_STAT(can_periph) = CAN_STAT_MS5_RFNE;
149     }
150 
151     /* clear register bits */
152     CAN_CTL0(can_periph) &= ~(CAN_CTL0_RFEN | CAN_CTL0_FDEN | CAN_CTL0_SRDIS | CAN_CTL0_LAPRIOEN | CAN_CTL0_MST | CAN_CTL0_RPFQEN | CAN_CTL0_MSZ);
153     CAN_CTL2(can_periph) &= ~(CAN_CTL2_ITSRC | CAN_CTL2_IDERTR_RMF | CAN_CTL2_RRFRMS | CAN_CTL2_RFO | CAN_CTL2_EFDIS | CAN_CTL2_PREEN);
154     CAN_CTL1(can_periph) &= ~CAN_CTL1_MTO;
155     CAN_BT(can_periph) &= ~(CAN_BT_BAUDPSC | CAN_BT_SJW | CAN_BT_PTS | CAN_BT_PBS1 | CAN_BT_PBS2);
156 
157     /* set self reception */
158     if((uint8_t)DISABLE == can_parameter_init->self_reception) {
159         CAN_CTL0(can_periph) |= CAN_CTL0_SRDIS;
160     }
161     /* enable local arbitration priority */
162     if((uint8_t)ENABLE == can_parameter_init->local_priority_enable) {
163         CAN_CTL0(can_periph) |= CAN_CTL0_LAPRIOEN;
164     }
165     /* set rx private filters and mailbox queue */
166     if((uint8_t)ENABLE == can_parameter_init->rx_private_filter_queue_enable) {
167         CAN_CTL0(can_periph) |= CAN_CTL0_RPFQEN;
168     }
169     /* configure edge filtering */
170     if((uint32_t)DISABLE == can_parameter_init->edge_filter_enable) {
171         CAN_CTL2(can_periph) |= CAN_CTL2_EFDIS;
172     }
173     /* configure protocol exception */
174     if((uint32_t)ENABLE == can_parameter_init->protocol_exception_enable) {
175         CAN_CTL2(can_periph) |= CAN_CTL2_PREEN;
176     }
177     /* set mailbox stop transmission */
178     if((uint8_t)ENABLE == can_parameter_init->mb_tx_abort_enable) {
179         CAN_CTL0(can_periph) |= CAN_CTL0_MST;
180     }
181 
182     /* set internal counter source */
183     CAN_CTL2(can_periph) |= can_parameter_init->internal_counter_source;
184     /* set mailbox arbitration process order */
185     CAN_CTL1(can_periph) |= can_parameter_init->mb_tx_order;
186     /* set IDE and RTR field filter type */
187     CAN_CTL2(can_periph) |= can_parameter_init->mb_rx_ide_rtr_type;
188     /* configure remote request frame */
189     CAN_CTL2(can_periph) |= can_parameter_init->mb_remote_frame;
190     /* set mailbox public filter */
191     CAN_RMPUBF(can_periph) = can_parameter_init->mb_public_filter;
192     /* configure receive filter order */
193     CAN_CTL2(can_periph) |= can_parameter_init->rx_filter_order;
194     /* set memory size */
195     CAN_CTL0(can_periph) |= can_parameter_init->memory_size;
196     /* set time segment */
197     CAN_BT(can_periph) |= (uint32_t)(BT_BAUDPSC(can_parameter_init->prescaler - 1U) |
198                                      BT_SJW((uint32_t)can_parameter_init->resync_jump_width - 1U) |
199                                      BT_PTS((uint32_t)can_parameter_init->prop_time_segment - 1U) |
200                                      BT_PBS1((uint32_t)can_parameter_init->time_segment_1 - 1U) |
201                                      BT_PBS2((uint32_t)can_parameter_init->time_segment_2 - 1U));
202 
203     return SUCCESS;
204 }
205 
206 /*!
207     \brief      initialize CAN parameter structure with a default value
208     \param[in]  type: the type of CAN parameter struct
209                 only one parameter can be selected which is shown as below:
210       \arg        CAN_INIT_STRUCT: the CAN initial struct
211       \arg        CAN_FD_INIT_STRUCT: the CAN FD initial struct
212       \arg        CAN_FIFO_INIT_STRUCT: the CAN FIFO initial struct
213       \arg        CAN_PN_MODE_INIT_STRUCT: the CAN Pretended Networking mode initial struct
214       \arg        CAN_PN_MODE_FILTER_STRUCT: the CAN Pretended Networking mode filter struct
215       \arg        CAN_MDSC_STRUCT: mailbox descriptor strcut
216       \arg        CAN_FDES_STRUCT: Rx fifo descriptor strcut
217       \arg        CAN_FIFO_ID_FILTER_STRUCT: Rx fifo id filter strcut
218       \arg        CAN_CRC_STRUCT: CRC strcut
219       \arg        CAN_ERRCNT_STRUCT: error counter strcut
220     \param[in]  p_struct: the pointer of the specific struct
221     \param[out] none
222     \retval     none
223 */
can_struct_para_init(can_struct_type_enum type,void * p_struct)224 void can_struct_para_init(can_struct_type_enum type, void *p_struct)
225 {
226     /* get type of the struct */
227     switch(type) {
228     /* used for initialize can_parameter_struct */
229     case CAN_INIT_STRUCT:
230         ((can_parameter_struct *)p_struct)->self_reception = (uint8_t)DISABLE;
231         ((can_parameter_struct *)p_struct)->internal_counter_source = CAN_TIMER_SOURCE_BIT_CLOCK;
232         ((can_parameter_struct *)p_struct)->mb_tx_order = CAN_TX_HIGH_PRIORITY_MB_FIRST;
233         ((can_parameter_struct *)p_struct)->mb_tx_abort_enable = (uint8_t)ENABLE;
234         ((can_parameter_struct *)p_struct)->local_priority_enable = (uint8_t)DISABLE;
235         ((can_parameter_struct *)p_struct)->mb_rx_ide_rtr_type = CAN_IDE_RTR_COMPARED;
236         ((can_parameter_struct *)p_struct)->mb_remote_frame = CAN_STORE_REMOTE_REQUEST_FRAME;
237         ((can_parameter_struct *)p_struct)->rx_private_filter_queue_enable = (uint8_t)DISABLE;
238         ((can_parameter_struct *)p_struct)->edge_filter_enable = (uint32_t)DISABLE;
239         ((can_parameter_struct *)p_struct)->protocol_exception_enable = (uint32_t)DISABLE;
240         ((can_parameter_struct *)p_struct)->rx_filter_order = CAN_RX_FILTER_ORDER_FIFO_FIRST;
241         ((can_parameter_struct *)p_struct)->memory_size = CAN_MEMSIZE_32_UNIT;
242         ((can_parameter_struct *)p_struct)->mb_public_filter = 0xFFFFFFFFU;
243         ((can_parameter_struct *)p_struct)->prescaler = 0x00000001U;
244         ((can_parameter_struct *)p_struct)->resync_jump_width = 0x01U;
245         ((can_parameter_struct *)p_struct)->prop_time_segment = 0x01U;
246         ((can_parameter_struct *)p_struct)->time_segment_1 = 0x01U;
247         ((can_parameter_struct *)p_struct)->time_segment_2 = 0x01U;
248         break;
249     /* used for initialize can_fd_parameter_struct */
250     case CAN_FD_INIT_STRUCT:
251         ((can_fd_parameter_struct *)p_struct)->iso_can_fd_enable = (uint32_t)DISABLE;
252         ((can_fd_parameter_struct *)p_struct)->bitrate_switch_enable = (uint32_t)ENABLE;
253         ((can_fd_parameter_struct *)p_struct)->mailbox_data_size = CAN_MAILBOX_DATA_SIZE_8_BYTES;
254         ((can_fd_parameter_struct *)p_struct)->tdc_enable = (uint32_t)DISABLE;
255         ((can_fd_parameter_struct *)p_struct)->tdc_offset = 0x00U;
256         ((can_fd_parameter_struct *)p_struct)->prescaler = 0x00000001U;
257         ((can_fd_parameter_struct *)p_struct)->resync_jump_width = 0x01U;
258         ((can_fd_parameter_struct *)p_struct)->prop_time_segment = 0x00U;
259         ((can_fd_parameter_struct *)p_struct)->time_segment_1 = 0x01U;
260         ((can_fd_parameter_struct *)p_struct)->time_segment_2 = 0x01U;
261         break;
262     /* used for initialize can_fifo_parameter_struct */
263     case CAN_FIFO_INIT_STRUCT:
264         ((can_fifo_parameter_struct *)p_struct)->dma_enable = (uint8_t)DISABLE;
265         ((can_fifo_parameter_struct *)p_struct)->filter_format_and_number = CAN_RXFIFO_FILTER_A_NUM_8;
266         ((can_fifo_parameter_struct *)p_struct)->fifo_public_filter = 0xFFFFFFFFU;
267         break;
268     /* used for initialize can_pn_mode_config_struct */
269     case CAN_PN_MODE_INIT_STRUCT:
270         ((can_pn_mode_config_struct *)p_struct)->timeout_int = (uint32_t)DISABLE;
271         ((can_pn_mode_config_struct *)p_struct)->match_int = (uint32_t)DISABLE;
272         ((can_pn_mode_config_struct *)p_struct)->num_matches = 0x01U;
273         ((can_pn_mode_config_struct *)p_struct)->match_timeout = 0x0000U;
274         ((can_pn_mode_config_struct *)p_struct)->frame_filter = CAN_PN_FRAME_FILTERING_ID;
275         ((can_pn_mode_config_struct *)p_struct)->id_filter = CAN_PN_ID_FILTERING_EXACT;
276         ((can_pn_mode_config_struct *)p_struct)->data_filter = CAN_PN_DATA_FILTERING_EXACT;
277         break;
278     /* used for initialize can_pn_mode_filter_struct */
279     case CAN_PN_MODE_FILTER_STRUCT:
280         ((can_pn_mode_filter_struct *)p_struct)->remote_frame = (uint32_t)RESET;
281         ((can_pn_mode_filter_struct *)p_struct)->extended_frame = (uint32_t)RESET;
282         ((can_pn_mode_filter_struct *)p_struct)->id = 0x00000000U;
283         ((can_pn_mode_filter_struct *)p_struct)->dlc_high_threshold = 0x00000000U;
284         ((can_pn_mode_filter_struct *)p_struct)->dlc_low_threshold = 0x00000000U;
285         ((can_pn_mode_filter_struct *)p_struct)->payload[0] = 0x00000000U;
286         ((can_pn_mode_filter_struct *)p_struct)->payload[1] = 0x00000000U;
287         break;
288     /* used for initialize can_mailbox_descriptor_struct */
289     case CAN_MDSC_STRUCT:
290         ((can_mailbox_descriptor_struct *)p_struct)->timestamp = 0x00000000U;
291         ((can_mailbox_descriptor_struct *)p_struct)->dlc = 0x00000000U;
292         ((can_mailbox_descriptor_struct *)p_struct)->rtr = 0x00000000U;
293         ((can_mailbox_descriptor_struct *)p_struct)->ide = 0x00000000U;
294         ((can_mailbox_descriptor_struct *)p_struct)->srr = 0x00000000U;
295         ((can_mailbox_descriptor_struct *)p_struct)->reserve1 = 0x00000000U;
296         ((can_mailbox_descriptor_struct *)p_struct)->code = 0x00000000U;
297         ((can_mailbox_descriptor_struct *)p_struct)->reserve2 = 0x00000000U;
298         ((can_mailbox_descriptor_struct *)p_struct)->esi = 0x00000000U;
299         ((can_mailbox_descriptor_struct *)p_struct)->brs = 0x00000000U;
300         ((can_mailbox_descriptor_struct *)p_struct)->fdf = 0x00000000U;
301         ((can_mailbox_descriptor_struct *)p_struct)->id = 0x00000000U;
302         ((can_mailbox_descriptor_struct *)p_struct)->prio = 0x00000000U;
303         ((can_mailbox_descriptor_struct *)p_struct)->data = (void *)0x00000000U;
304         ((can_mailbox_descriptor_struct *)p_struct)->data_bytes = 0x00000000U;
305         ((can_mailbox_descriptor_struct *)p_struct)->padding = 0x0000U;
306         break;
307     /* used for initialize can_rx_fifo_struct */
308     case CAN_FDES_STRUCT:
309         ((can_rx_fifo_struct *)p_struct)->timestamp = 0x00000000U;
310         ((can_rx_fifo_struct *)p_struct)->dlc = 0x00000000U;
311         ((can_rx_fifo_struct *)p_struct)->rtr = 0x00000000U;
312         ((can_rx_fifo_struct *)p_struct)->ide = 0x00000000U;
313         ((can_rx_fifo_struct *)p_struct)->srr = 0x00000000U;
314         ((can_rx_fifo_struct *)p_struct)->idhit = 0x00000000U;
315         ((can_rx_fifo_struct *)p_struct)->id = 0x00000000U;
316         ((can_rx_fifo_struct *)p_struct)->data[0] = 0x00000000U;
317         ((can_rx_fifo_struct *)p_struct)->data[1] = 0x00000000U;
318         break;
319     /* used for initialize can_rx_fifo_id_filter_struct */
320     case CAN_FIFO_ID_FILTER_STRUCT:
321         ((can_rx_fifo_id_filter_struct *)p_struct)->remote_frame = 0x00000000U;
322         ((can_rx_fifo_id_filter_struct *)p_struct)->extended_frame = 0x00000000U;
323         ((can_rx_fifo_id_filter_struct *)p_struct)->id = 0x00000000U;
324         break;
325     /* used for initialize can_crc_struct */
326     case CAN_CRC_STRUCT:
327         ((can_crc_struct *)p_struct)->classical_frm_mb_number = 0x00000000U;
328         ((can_crc_struct *)p_struct)->classical_frm_transmitted_crc = 0x00000000U;
329         ((can_crc_struct *)p_struct)->classical_fd_frm_mb_number = 0x00000000U;
330         ((can_crc_struct *)p_struct)->classical_fd_frm_transmitted_crc = 0x00000000U;
331         break;
332     /* used for initialize can_crc_struct */
333     case CAN_ERRCNT_STRUCT:
334         ((can_error_counter_struct *)p_struct)->fd_data_phase_rx_errcnt = 0x00U;
335         ((can_error_counter_struct *)p_struct)->fd_data_phase_tx_errcnt = 0x00U;
336         ((can_error_counter_struct *)p_struct)->rx_errcnt = 0x00U;
337         ((can_error_counter_struct *)p_struct)->tx_errcnt = 0x00U;
338         break;
339     default:
340         break;
341     }
342 }
343 
344 /*!
345     \brief      configure receive fifo/mailbox private filter
346     \param[in]  can_periph: CANx(x=0,1)
347     \param[in]  index: mailbox index
348     \param[in]  filter_data: filter data to configure
349     \param[out] none
350     \retval     none
351 */
can_private_filter_config(uint32_t can_periph,uint32_t index,uint32_t filter_data)352 void can_private_filter_config(uint32_t can_periph, uint32_t index, uint32_t filter_data)
353 {
354     CAN_RFIFOMPF(can_periph, index) = filter_data;
355 }
356 
357 /*!
358     \brief      enter the corresponding mode
359     \param[in]  can_periph: CANx(x=0,1)
360     \param[in]  mode: the mode to enter
361                 only one parameter can be selected which is shown as below:
362       \arg        GD32_CAN_NORMAL_MODE: normal mode
363       \arg        GD32_CAN_MONITOR_MODE: monitor mode
364       \arg        GD32_CAN_LOOPBACK_SILENT_MODE: loopback mode
365       \arg        GD32_CAN_INACTIVE_MODE: inactive mode
366       \arg        GD32_CAN_DISABLE_MODE: disable mode
367       \arg        GD32_CAN_PN_MODE: Pretended Networking mode
368     \param[out] none
369     \retval     ERROR or SUCCESS
370 */
can_operation_mode_enter(uint32_t can_periph,can_operation_modes_enum mode)371 ErrStatus can_operation_mode_enter(uint32_t can_periph, can_operation_modes_enum mode)
372 {
373     uint32_t timeout;
374     ErrStatus ret = SUCCESS;
375 
376     /* enter INACTIVE mode */
377     /* exit can_disable mode */
378     CAN_CTL0(can_periph) &= ~CAN_CTL0_CANDIS;
379     /* enter inactive mode */
380     CAN_CTL0(can_periph) |= CAN_CTL0_HALT | CAN_CTL0_INAMOD;
381     /* exit Pretended Networking mode */
382     CAN_CTL0(can_periph) &= ~(CAN_CTL0_PNEN | CAN_CTL0_PNMOD);
383     timeout = CAN_DELAY;
384     /* wait for inactive mode state */
385     while(((CAN_CTL0_NRDY | CAN_CTL0_INAS) != (CAN_CTL0(can_periph) & (CAN_CTL0_NRDY | CAN_CTL0_INAS))) && (timeout)) {
386         timeout--;
387     }
388     if((CAN_CTL0_NRDY | CAN_CTL0_INAS) != (CAN_CTL0(can_periph) & (CAN_CTL0_NRDY | CAN_CTL0_INAS))) {
389         return ERROR;
390     }
391 
392     /* configure the modes */
393     switch(mode) {
394     case GD32_CAN_NORMAL_MODE:
395         CAN_CTL1(can_periph) &= ~(CAN_CTL1_LSCMOD | CAN_CTL1_MMOD);
396         break;
397     case GD32_CAN_MONITOR_MODE:
398         CAN_CTL1(can_periph) &= ~CAN_CTL1_LSCMOD;
399         CAN_CTL1(can_periph) |= CAN_CTL1_MMOD;
400         break;
401     case GD32_CAN_LOOPBACK_SILENT_MODE:
402         CAN_CTL1(can_periph) &= ~CAN_CTL1_MMOD;
403         CAN_CTL0(can_periph) &= ~CAN_CTL0_SRDIS;
404         CAN_FDCTL(can_periph) &= ~CAN_FDCTL_TDCEN;
405         CAN_CTL1(can_periph) |= CAN_CTL1_LSCMOD;
406         break;
407     case GD32_CAN_INACTIVE_MODE:
408         break;
409     case GD32_CAN_DISABLE_MODE:
410         CAN_CTL0(can_periph) |= CAN_CTL0_CANDIS;
411         break;
412     case GD32_CAN_PN_MODE:
413         CAN_CTL0(can_periph) |= (CAN_CTL0_PNEN | CAN_CTL0_PNMOD);
414         break;
415     default:
416         break;
417     }
418 
419     /* exit INACTIVE mode */
420     if(GD32_CAN_INACTIVE_MODE != mode) {
421         /* exit inactive mode */
422         CAN_CTL0(can_periph) &= ~(CAN_CTL0_HALT | CAN_CTL0_INAMOD);
423         timeout = CAN_DELAY;
424         while((CAN_CTL0(can_periph) & CAN_CTL0_INAS) && (timeout)) {
425             timeout--;
426         }
427         if(CAN_CTL0(can_periph) & CAN_CTL0_INAS) {
428             return ERROR;
429         }
430     }
431 
432     if(GD32_CAN_PN_MODE == mode) {
433         timeout = CAN_DELAY;
434         while((0U == (CAN_CTL0(can_periph) & CAN_CTL0_PNS)) && (timeout)) {
435             timeout--;
436         }
437         if(0U == (CAN_CTL0(can_periph) & CAN_CTL0_PNS)) {
438             return ERROR;
439         }
440     }
441     return ret;
442 }
443 
444 /*!
445     \brief      get operation mode
446     \param[in]  can_periph: CANx(x=0,1)
447     \param[out] none
448     \retval     can_operation_modes_enum
449 */
can_operation_mode_get(uint32_t can_periph)450 can_operation_modes_enum can_operation_mode_get(uint32_t can_periph)
451 {
452     uint32_t reg;
453     can_operation_modes_enum state = GD32_CAN_NORMAL_MODE;
454 
455     reg = CAN_CTL0(can_periph);
456     reg &= (CAN_CTL0_NRDY | CAN_CTL0_INAS | CAN_CTL0_PNS | CAN_CTL0_LPS);
457 
458     if((CAN_CTL0_NRDY | CAN_CTL0_LPS) == reg) {
459         state = GD32_CAN_DISABLE_MODE;
460     } else if((CAN_CTL0_NRDY | CAN_CTL0_INAS) == reg) {
461         state = GD32_CAN_INACTIVE_MODE;
462     } else if(0U == reg) {
463         if(CAN_CTL1(can_periph)&CAN_CTL1_MMOD) {
464             state = GD32_CAN_MONITOR_MODE;
465         } else if(CAN_CTL1(can_periph)&CAN_CTL1_LSCMOD) {
466             state = GD32_CAN_LOOPBACK_SILENT_MODE;
467         } else {
468             state = GD32_CAN_NORMAL_MODE;
469         }
470     } else if(CAN_CTL0_PNS == reg) {
471         state = GD32_CAN_PN_MODE;
472     } else {
473         /* should not get here */
474     }
475 
476     return state;
477 }
478 
479 /*!
480     \brief      exit inactive mode
481     \param[in]  can_periph: CANx(x=0,1)
482     \param[out] none
483     \retval     ERROR or SUCCESS
484 */
can_inactive_mode_exit(uint32_t can_periph)485 ErrStatus can_inactive_mode_exit(uint32_t can_periph)
486 {
487     uint32_t timeout;
488 
489     /* exit inactive mode */
490     CAN_CTL0(can_periph) &= ~CAN_CTL0_HALT;
491     timeout = CAN_DELAY;
492     while((CAN_CTL0(can_periph) & CAN_CTL0_INAS) && (timeout)) {
493         timeout--;
494     }
495     if(CAN_CTL0(can_periph) & CAN_CTL0_INAS) {
496         return ERROR;
497     } else {
498         return SUCCESS;
499     }
500 }
501 
502 /*!
503     \brief      exit Pretended Networking mode
504     \param[in]  can_periph: CANx(x=0,1)
505     \param[in]  none
506     \param[out] none
507     \retval     ERROR or SUCCESS
508 */
can_pn_mode_exit(uint32_t can_periph)509 ErrStatus can_pn_mode_exit(uint32_t can_periph)
510 {
511     uint32_t timeout;
512 
513     CAN_CTL0(can_periph) &= ~(CAN_CTL0_PNEN | CAN_CTL0_PNMOD);
514     timeout = CAN_DELAY;
515     while((CAN_CTL0(can_periph) & CAN_CTL0_PNS) && (timeout)) {
516         timeout--;
517     }
518     if(CAN_CTL0(can_periph) & CAN_CTL0_PNS) {
519         return ERROR;
520     } else {
521         return SUCCESS;
522     }
523 }
524 
525 /*!
526     \brief      can FD initialize
527     \param[in]  can_periph: CANx(x=0,1)
528     \param[in]  can_fd_para_init: can fd parameter struct
529                   iso_can_fd_enable: ENABLE, DISABLE
530                   bitrate_switch_enable: ENABLE, DISABLE
531                   mailbox_data_size: CAN_MAILBOX_DATA_SIZE_8_BYTES, CAN_MAILBOX_DATA_SIZE_16_BYTES,
532                                      CAN_MAILBOX_DATA_SIZE_32_BYTES, CAN_MAILBOX_DATA_SIZE_64_BYTES
533                   tdc_enable: ENABLE, DISABLE
534                   tdc_offset: 0 ~ 31
535                   prescaler: 1~1024
536                   resync_jump_width: 1~8
537                   prop_time_segment: 0~31
538                   time_segment_1: 1~8
539                   time_segment_2: 2~8
540     \param[out] none
541     \retval     none
542 */
can_fd_config(uint32_t can_periph,can_fd_parameter_struct * can_fd_para_init)543 void can_fd_config(uint32_t can_periph, can_fd_parameter_struct *can_fd_para_init)
544 {
545     /* clear register bits, then enable FD mode */
546     CAN_CTL0(can_periph) &= ~CAN_CTL0_RFEN;
547     CAN_CTL1(can_periph) &= ~CAN_CTL1_BSPMOD;
548     CAN_CTL2(can_periph) &= ~CAN_CTL2_ISO;
549     CAN_FDCTL(can_periph) &= ~(CAN_FDCTL_BRSEN | CAN_FDCTL_MDSZ | CAN_FDCTL_TDCEN | CAN_FDCTL_TDCO);
550     CAN_FDBT(can_periph) &= ~(CAN_FDBT_DBAUDPSC | CAN_FDBT_DSJW | CAN_FDBT_DPTS | CAN_FDBT_DPBS1 | CAN_FDBT_DPBS2);
551     CAN_CTL0(can_periph) |= CAN_CTL0_FDEN;
552 
553     /* support ISO or non-ISO mode */
554     if((uint32_t)ENABLE == can_fd_para_init->iso_can_fd_enable) {
555         CAN_CTL2(can_periph) |= CAN_CTL2_ISO;
556     }
557     /* set TDC parameter */
558     if((uint32_t)ENABLE == can_fd_para_init->tdc_enable) {
559         CAN_FDCTL(can_periph) |= CAN_FDCTL_TDCEN;
560     }
561     /* set data bit rate */
562     if((uint32_t)ENABLE == can_fd_para_init->bitrate_switch_enable) {
563         CAN_FDCTL(can_periph) |= CAN_FDCTL_BRSEN;
564     }
565 
566     /* set mailbox data size */
567     CAN_FDCTL(can_periph) |= can_fd_para_init->mailbox_data_size;
568     /* configure FD bit timing */
569     CAN_FDBT(can_periph) |= (uint32_t)(FDBT_DBAUDPSC(can_fd_para_init->prescaler - 1U) |
570                                        FDBT_DSJW((uint32_t)can_fd_para_init->resync_jump_width - 1U) |
571                                        FDBT_DPTS(can_fd_para_init->prop_time_segment) |
572                                        FDBT_DPBS1((uint32_t)can_fd_para_init->time_segment_1 - 1U) |
573                                        FDBT_DPBS2((uint32_t)can_fd_para_init->time_segment_2 - 1U));
574     /* configure transmitter delay compensation offset */
575     CAN_FDCTL(can_periph) |= FDCTL_TDCO(can_fd_para_init->tdc_offset);
576 }
577 
578 /*!
579     \brief      enable bit rate switching
580     \param[in]  can_periph: CANx(x=0,1)
581     \param[out] none
582     \retval     none
583 */
can_bitrate_switch_enable(uint32_t can_periph)584 void can_bitrate_switch_enable(uint32_t can_periph)
585 {
586     CAN_FDCTL(can_periph) |= CAN_FDCTL_BRSEN;
587 }
588 
589 /*!
590     \brief      disable bit rate switching
591     \param[in]  can_periph: CANx(x=0,1)
592     \param[out] none
593     \retval     none
594 */
can_bitrate_switch_disable(uint32_t can_periph)595 void can_bitrate_switch_disable(uint32_t can_periph)
596 {
597     CAN_FDCTL(can_periph) &= ~CAN_FDCTL_BRSEN;
598 }
599 
600 /*!
601     \brief      get transmitter delay compensation value
602     \param[in]  can_periph: CANx(x=0,1)
603     \param[out] none
604     \retval     0 - 0x3F
605 */
can_tdc_get(uint32_t can_periph)606 uint32_t can_tdc_get(uint32_t can_periph)
607 {
608     uint32_t reg = 0U;
609 
610     reg = CAN_FDCTL(can_periph);
611 
612     return GET_FDCTL_TDCV(reg);
613 }
614 
615 /*!
616     \brief      enable transmitter delay compensation
617     \param[in]  can_periph: CANx(x=0,1)
618     \param[out] none
619     \retval     none
620 */
can_tdc_enable(uint32_t can_periph)621 void can_tdc_enable(uint32_t can_periph)
622 {
623     CAN_FDCTL(can_periph) |= CAN_FDCTL_TDCEN;
624 }
625 
626 /*!
627     \brief      disable transmitter delay compensation
628     \param[in]  can_periph: CANx(x=0,1)
629     \param[out] none
630     \retval     none
631 */
can_tdc_disable(uint32_t can_periph)632 void can_tdc_disable(uint32_t can_periph)
633 {
634     CAN_FDCTL(can_periph) &= ~CAN_FDCTL_TDCEN;
635 }
636 
637 /*!
638     \brief      configure rx FIFO
639     \param[in]  can_periph: CANx(x=0,1)
640     \param[in]  can_fifo_para_init: fifo parameter struct
641                   dma_enable: ENABLE, DISABLE
642                   filter_format_and_number: CAN_RXFIFO_FILTER_A_NUM_8, CAN_RXFIFO_FILTER_A_NUM_16, CAN_RXFIFO_FILTER_A_NUM_24, CAN_RXFIFO_FILTER_A_NUM_32,
643                                             CAN_RXFIFO_FILTER_A_NUM_40, CAN_RXFIFO_FILTER_A_NUM_48, CAN_RXFIFO_FILTER_A_NUM_56, CAN_RXFIFO_FILTER_A_NUM_64,
644                                             CAN_RXFIFO_FILTER_A_NUM_72, CAN_RXFIFO_FILTER_A_NUM_80, CAN_RXFIFO_FILTER_A_NUM_88, CAN_RXFIFO_FILTER_A_NUM_96, CAN_RXFIFO_FILTER_A_NUM_104,
645                                             CAN_RXFIFO_FILTER_B_NUM_16, CAN_RXFIFO_FILTER_B_NUM_32, CAN_RXFIFO_FILTER_B_NUM_48, CAN_RXFIFO_FILTER_B_NUM_64,
646                                             CAN_RXFIFO_FILTER_B_NUM_80, CAN_RXFIFO_FILTER_B_NUM_96, CAN_RXFIFO_FILTER_B_NUM_112, CAN_RXFIFO_FILTER_B_NUM_128,
647                                             CAN_RXFIFO_FILTER_B_NUM_144, CAN_RXFIFO_FILTER_B_NUM_160, CAN_RXFIFO_FILTER_B_NUM_176, CAN_RXFIFO_FILTER_B_NUM_192, CAN_RXFIFO_FILTER_B_NUM_208,
648                                             CAN_RXFIFO_FILTER_C_NUM_32, CAN_RXFIFO_FILTER_C_NUM_64, CAN_RXFIFO_FILTER_C_NUM_96, CAN_RXFIFO_FILTER_C_NUM_128,
649                                             CAN_RXFIFO_FILTER_C_NUM_160, CAN_RXFIFO_FILTER_C_NUM_192, CAN_RXFIFO_FILTER_C_NUM_224, CAN_RXFIFO_FILTER_C_NUM_256,
650                                             CAN_RXFIFO_FILTER_C_NUM_288, CAN_RXFIFO_FILTER_C_NUM_320, CAN_RXFIFO_FILTER_C_NUM_352, CAN_RXFIFO_FILTER_C_NUM_384, CAN_RXFIFO_FILTER_C_NUM_416,
651                                             CAN_RXFIFO_FILTER_D
652                   fifo_public_filter: 0x00000000 ~ 0xFFFFFFFF
653     \param[out] none
654     \retval     none
655 */
can_rx_fifo_config(uint32_t can_periph,can_fifo_parameter_struct * can_fifo_para_init)656 void can_rx_fifo_config(uint32_t can_periph, can_fifo_parameter_struct *can_fifo_para_init)
657 {
658     uint32_t num;
659 
660     /* clear register bits, disable FD mode, then enable rx FIFO mode */
661     CAN_CTL0(can_periph) &= ~(CAN_CTL0_FDEN | CAN_CTL0_DMAEN | CAN_CTL0_FS);
662     CAN_CTL2(can_periph) &= ~CAN_CTL2_RFFN;
663     CAN_CTL0(can_periph) |= CAN_CTL0_RFEN;
664 
665     /* clear FIFO status */
666     CAN_STAT(can_periph) = (uint32_t)0xFFFFFFFFU;
667     while(CAN_STAT(can_periph) & CAN_STAT_MS5_RFNE) {
668         CAN_STAT(can_periph) = CAN_STAT_MS5_RFNE;
669     }
670 
671     /* set DMA mode */
672     if((uint8_t)ENABLE == can_fifo_para_init->dma_enable) {
673         CAN_CTL0(can_periph) |= CAN_CTL0_DMAEN;
674     }
675 
676     /* configure filter format */
677     CAN_CTL0(can_periph) |= (can_fifo_para_init->filter_format_and_number & CAN_CTL0_FS);
678     /* configure filter number */
679     CAN_CTL2(can_periph) |= (can_fifo_para_init->filter_format_and_number & CAN_CTL2_RFFN);
680     /* configure fifo public fiter */
681     CAN_RFIFOPUBF(can_periph) = can_fifo_para_init->fifo_public_filter;
682     /* configure fifo private fiter */
683     if(!(CAN_CTL0(can_periph) & CAN_CTL0_RPFQEN)) {
684         for(num = 0U; num < CAN_MAX_MAILBOX_NUM; num++) {
685             CAN_RFIFOMPF(can_periph, num) = can_fifo_para_init->fifo_public_filter;
686         }
687     }
688 }
689 
690 /*!
691     \brief      configure rx FIFO filter table
692     \param[in]  can_periph: CANx(x=0,1)
693     \param[in]  id_filter_table: id filter table struct
694                   remote_frame: CAN_DATA_FRAME_ACCEPTED, CAN_REMOTE_FRAME_ACCEPTED
695                   extended_frame: CAN_STANDARD_FRAME_ACCEPTED, CAN_EXTENDED_FRAME_ACCEPTED
696                   id: 11 bits for standard frame, 29 bits for extended frame
697     \param[out] none
698     \retval     none
699 */
can_rx_fifo_filter_table_config(uint32_t can_periph,can_rx_fifo_id_filter_struct id_filter_table[])700 void can_rx_fifo_filter_table_config(uint32_t can_periph, can_rx_fifo_id_filter_struct id_filter_table[])
701 {
702     /* set rx FIFO ID filter table elements */
703     uint32_t i = 0U, j = 0U, num_of_filters = 0U;
704     uint32_t val = 0U;
705     uint32_t id_format = 0U;
706     uint32_t *filter_table = (uint32_t *)(uint32_t)(CAN_RAM(can_periph) + 0x00000060U);
707 
708     num_of_filters = (GET_CTL2_RFFN(CAN_CTL2(can_periph)) + 1U) * 8U;
709     id_format = CAN_CTL0(can_periph) & CAN_CTL0_FS;
710 
711     switch(id_format) {
712     case(CAN_FIFO_FILTER_FORMAT_A):
713         /* one full id (standard and extended) per id filter table element */
714         for(i = 0U; i < num_of_filters; i++) {
715             val = 0U;
716 
717             if(CAN_REMOTE_FRAME_ACCEPTED == id_filter_table[i].remote_frame) {
718                 val |= CAN_FDESX_RTR_A;
719             }
720             if(CAN_EXTENDED_FRAME_ACCEPTED == id_filter_table[i].extended_frame) {
721                 val |= CAN_FDESX_IDE_A;
722                 val |= (uint32_t)FIFO_FILTER_ID_EXD_A(id_filter_table[i].id);
723             } else {
724                 val |= (uint32_t)FIFO_FILTER_ID_STD_A(id_filter_table[i].id);
725             }
726             filter_table[i] = val;
727         }
728         break;
729     case(CAN_FIFO_FILTER_FORMAT_B):
730         /* two full standard id or two partial 14-bit (standard and extended) id */
731         j = 0U;
732         for(i = 0U; i < num_of_filters; i++) {
733             val = 0U;
734 
735             if(CAN_REMOTE_FRAME_ACCEPTED == id_filter_table[j].remote_frame) {
736                 val |= CAN_FDESX_RTR_B0;
737             }
738             if(CAN_EXTENDED_FRAME_ACCEPTED == id_filter_table[j].extended_frame) {
739                 val |= CAN_FDESX_IDE_B0;
740                 val |= (uint32_t)FIFO_FILTER_ID_EXD_B0(id_filter_table[j].id);
741             } else {
742                 val |= (uint32_t)FIFO_FILTER_ID_STD_B0(id_filter_table[j].id);
743             }
744             j++;
745 
746             if(CAN_REMOTE_FRAME_ACCEPTED == id_filter_table[j].remote_frame) {
747                 val |= CAN_FDESX_RTR_B1;
748             }
749             if(CAN_EXTENDED_FRAME_ACCEPTED == id_filter_table[j].extended_frame) {
750                 val |= CAN_FDESX_IDE_B1;
751                 val |= (uint32_t)FIFO_FILTER_ID_EXD_B1(id_filter_table[j].id);
752             } else {
753                 val |= (uint32_t)FIFO_FILTER_ID_STD_B1(id_filter_table[j].id);
754             }
755             j++;
756 
757             filter_table[i] = val;
758         }
759         break;
760     case(CAN_FIFO_FILTER_FORMAT_C):
761         /* four partial 8-bit standard id per id filter table element */
762         j = 0U;
763         for(i = 0U; i < num_of_filters; i++) {
764             val = 0U;
765             if(CAN_EXTENDED_FRAME_ACCEPTED == id_filter_table[j].extended_frame) {
766                 val |= (uint32_t)FIFO_FILTER_ID_EXD_C0(id_filter_table[j].id);
767             } else {
768                 val |= (uint32_t)FIFO_FILTER_ID_STD_C0(id_filter_table[j].id);
769             }
770             j++;
771             if(CAN_EXTENDED_FRAME_ACCEPTED == id_filter_table[j].extended_frame) {
772                 val |= (uint32_t)FIFO_FILTER_ID_EXD_C1(id_filter_table[j].id);
773             } else {
774                 val |= (uint32_t)FIFO_FILTER_ID_STD_C1(id_filter_table[j].id);
775             }
776             j++;
777             if(CAN_EXTENDED_FRAME_ACCEPTED == id_filter_table[j].extended_frame) {
778                 val |= (uint32_t)FIFO_FILTER_ID_EXD_C2(id_filter_table[j].id);
779             } else {
780                 val |= (uint32_t)FIFO_FILTER_ID_STD_C2(id_filter_table[j].id);
781             }
782             j++;
783             if(CAN_EXTENDED_FRAME_ACCEPTED == id_filter_table[j].extended_frame) {
784                 val |= (uint32_t)FIFO_FILTER_ID_EXD_C3(id_filter_table[j].id);
785             } else {
786                 val |= (uint32_t)FIFO_FILTER_ID_STD_C3(id_filter_table[j].id);
787             }
788             j++;
789 
790             filter_table[i] = val;
791         }
792         break;
793     case(CAN_FIFO_FILTER_FORMAT_D):
794         /* all frames rejected */
795         break;
796     default:
797         /* should not get here */
798         break;
799     }
800 }
801 
802 /*!
803     \brief      read rx FIFO data
804     \param[in]  can_periph: CANx(x=0,1)
805     \param[out] rx_fifo: rx FIFO struct
806     \retval     none
807 */
can_rx_fifo_read(uint32_t can_periph,can_rx_fifo_struct * rx_fifo)808 void can_rx_fifo_read(uint32_t can_periph, can_rx_fifo_struct *rx_fifo)
809 {
810     uint32_t *rx_fifo_addr = (uint32_t *)rx_fifo;
811     uint32_t *can_mb = (uint32_t *)CAN_RAM(can_periph);
812 
813     /* read FIFO descriptor 0 */
814     rx_fifo_addr[0] = can_mb[0];
815     rx_fifo_addr[1] = can_mb[1];
816     rx_fifo->data[0] = can_mb[2];
817     rx_fifo->data[1] = can_mb[3];
818 
819     /* clear FIFO status */
820     CAN_STAT(can_periph) = CAN_STAT_MS5_RFNE;
821 
822     /* read FIFO id field */
823     if(rx_fifo->ide) {
824         rx_fifo->id = GET_FDES1_ID_EXD(rx_fifo->id);
825     } else {
826         rx_fifo->id = GET_FDES1_ID_STD(rx_fifo->id);
827     }
828 
829     /* read FIFO data */
830     can_data_to_little_endian_swap(rx_fifo->data, rx_fifo->data, rx_fifo->dlc);
831 }
832 
833 /*!
834     \brief      get rx FIFO filter matching number
835     \param[in]  can_periph: CANx(x=0,1)
836     \param[out] none
837     \retval     filter number
838 */
can_rx_fifo_filter_matching_number_get(uint32_t can_periph)839 uint32_t can_rx_fifo_filter_matching_number_get(uint32_t can_periph)
840 {
841     return GET_RFIFOIFMN_IDFMN(CAN_RFIFOIFMN(can_periph));
842 }
843 
844 /*!
845     \brief      clear rx FIFO
846     \param[in]  can_periph: CANx(x=0,1)
847     \param[out] none
848     \retval     none
849 */
can_rx_fifo_clear(uint32_t can_periph)850 void can_rx_fifo_clear(uint32_t can_periph)
851 {
852     CAN_STAT(can_periph) = CAN_STAT_MS0_RFC;
853 }
854 
855 /*!
856     \brief      get mailbox RAM address
857     \param[in]  can_periph: CANx(x=0,1)
858     \param[in]  index: mailbox index, 0-31
859     \param[out] none
860     \retval     pointer to the mailbox address
861 */
can_ram_address_get(uint32_t can_periph,uint32_t index)862 uint32_t *can_ram_address_get(uint32_t can_periph, uint32_t index)
863 {
864     uint32_t payload_size;
865     uint32_t *address;
866 
867     /* if CAN FD mode is enabled */
868     if(CAN_CTL0(can_periph) & CAN_CTL0_FDEN) {
869         payload_size = (uint32_t)1U << (GET_FDCTL_MDSZ(CAN_FDCTL(can_periph)) + 3U);
870     } else {
871         payload_size = 8U;
872     }
873     address = (uint32_t *)(uint32_t)(CAN_RAM(can_periph) + (payload_size + 8U) * index);
874 
875     return address;
876 }
877 
878 /*!
879     \brief      configure mailbox
880     \param[in]  can_periph: CANx(x=0,1)
881     \param[in]  index: mailbox index
882                 only one parameter can be selected which is shown as below:
883       \arg        0 - 31
884     \param[in]  mdpara: mailbox descriptor struct
885                   rtr: 0, 1
886                   ide: 0, 1
887                   id: 0 - 0x1FFFFFFF
888                   code: CAN_MB_RX_STATUS_INACTIVE, CAN_MB_RX_STATUS_FULL, CAN_MB_RX_STATUS_EMPTY,
889                         CAN_MB_RX_STATUS_OVERRUN, CAN_MB_RX_STATUS_RANSWER, CAN_MB_RX_STATUS_BUSY,
890                         CAN_MB_TX_STATUS_INACTIVE, CAN_MB_TX_STATUS_ABORT, CAN_MB_TX_STATUS_DATA
891                   data_bytes: 0 - 64
892                   data: point to the data
893                   esi: 0, 1
894                   fdf: 0, 1
895                   brs: 0, 1
896                   prio: 0 - 7
897     \param[out] none
898     \retval     none
899 */
can_mailbox_config(uint32_t can_periph,uint32_t index,can_mailbox_descriptor_struct * mdpara)900 void can_mailbox_config(uint32_t can_periph, uint32_t index, can_mailbox_descriptor_struct *mdpara)
901 {
902     uint32_t dlc;
903     uint32_t mdes0 = 0U;
904     uint32_t length;
905     uint32_t *mdes;
906 
907     /* clear mailbox status */
908     CAN_STAT(can_periph) = STAT_MS(index);
909 
910     /* get mailbox base address */
911     mdes = can_ram_address_get(can_periph, index);
912     mdes[0] = 0U;
913     mdes[1] = 0U;
914     mdes[2] = 0U;
915     mdes[3] = 0U;
916 
917     /* set RTR bit */
918     if(mdpara->rtr) {
919         mdes0 |= CAN_MDES0_RTR;
920     }
921 
922     /* set IDE bit and ID field */
923     if(mdpara->ide) {
924         mdes0 |= CAN_MDES0_IDE;
925         mdes0 |= CAN_MDES0_SRR;
926         mdes[1] |= MDES1_ID_EXD(mdpara->id);
927     } else {
928         mdes[1] |= MDES1_ID_STD(mdpara->id);
929     }
930 
931     /* set CODE field */
932     mdes0 |= MDES0_CODE(mdpara->code);
933 
934     if(mdpara->code != CAN_MB_RX_STATUS_EMPTY) {
935         /* copy user's buffer into the mailbox data area */
936         if(mdpara->data_bytes) {
937             dlc = can_dlc_value_compute(mdpara->data_bytes);
938             mdes0 |= MDES0_DLC(dlc);
939             length = (uint32_t)1U << (GET_FDCTL_MDSZ(CAN_FDCTL(can_periph)) + 3U);
940             if(mdpara->data_bytes < length) {
941                 length = mdpara->data_bytes;
942             }
943             can_data_to_big_endian_swap(&mdes[2], mdpara->data, length);
944         }
945 
946         /* prepare mailbox for transmission */
947         if(CAN_MB_TX_STATUS_DATA == mdpara->code) {
948             /* set ESI bit */
949             if(mdpara->esi) {
950                 mdes0 |= CAN_MDES0_ESI;
951             }
952             /* set FDF and BRS bit */
953             if(mdpara->fdf) {
954                 mdes0 |= CAN_MDES0_FDF;
955                 if(mdpara->brs) {
956                     mdes0 |= CAN_MDES0_BRS;
957                 }
958                 mdes0 &= ~CAN_MDES0_RTR;
959             }
960         }
961 
962         /* set PRIO field */
963         mdes[1] |= MDES1_PRIO(mdpara->prio);
964     }
965 
966     /* set mailbox descriptor 0 */
967     mdes[0] = mdes0;
968 }
969 
970 /*!
971     \brief      abort mailbox transmit
972     \param[in]  can_periph: CANx(x=0,1)
973     \param[in]  index: mailbox index
974                 only one parameter can be selected which is shown as below:
975       \arg        0 - 31
976     \param[out] none
977     \retval     none
978 */
can_mailbox_transmit_abort(uint32_t can_periph,uint32_t index)979 void can_mailbox_transmit_abort(uint32_t can_periph, uint32_t index)
980 {
981     uint32_t mdes0;
982     uint32_t *mdes;
983 
984     /* abort transmit mailbox */
985     mdes = can_ram_address_get(can_periph, index);
986     mdes0 = mdes[0];
987     mdes0 &= ~CAN_MDES0_CODE;
988     mdes0 |= MDES0_CODE(CAN_MB_TX_STATUS_ABORT);
989     mdes[0] = mdes0;
990 }
991 
992 /*!
993     \brief      inactive transmit mailbox
994     \param[in]  can_periph: CANx(x=0,1)
995     \param[in]  index: mailbox index
996                 only one parameter can be selected which is shown as below:
997       \arg        0 - 31
998     \param[out] none
999     \retval     none
1000 */
can_mailbox_transmit_inactive(uint32_t can_periph,uint32_t index)1001 void can_mailbox_transmit_inactive(uint32_t can_periph, uint32_t index)
1002 {
1003     uint32_t mdes0;
1004     uint32_t *mdes;
1005 
1006     /* inactive transmit mailbox */
1007     mdes = can_ram_address_get(can_periph, index);
1008     mdes0 = mdes[0];
1009     mdes0 &= ~CAN_MDES0_CODE;
1010     mdes0 |= MDES0_CODE(CAN_MB_TX_STATUS_INACTIVE);
1011     mdes[0] = mdes0;
1012 }
1013 
1014 /*!
1015     \brief      read receive mailbox data
1016     \param[in]  can_periph: CANx(x=0,1)
1017     \param[in]  index: mailbox index
1018                 only one parameter can be selected which is shown as below:
1019       \arg        0 - 31
1020     \param[out] mdpara: mailbox descriptor struct
1021     \retval     ERROR or SUCCESS
1022 */
can_mailbox_receive_data_read(uint32_t can_periph,uint32_t index,can_mailbox_descriptor_struct * mdpara)1023 ErrStatus can_mailbox_receive_data_read(uint32_t can_periph, uint32_t index, can_mailbox_descriptor_struct *mdpara)
1024 {
1025     uint32_t i;
1026     uint32_t cnt;
1027     uint32_t timeout;
1028     uint32_t *mdes = can_ram_address_get(can_periph, index);
1029     uint32_t *mdaddr = (uint32_t *)mdpara;
1030 
1031     /* wait mailbox data ready */
1032     timeout = CAN_DELAY;
1033     while((mdes[0] & MDES0_CODE(CAN_MB_RX_STATUS_BUSY)) && (timeout)) {
1034         timeout--;
1035     }
1036     if(mdes[0] & MDES0_CODE(CAN_MB_RX_STATUS_BUSY)) {
1037         return ERROR;
1038     }
1039 
1040     /* get mailbox descriptor 0 */
1041     mdaddr[0] = mdes[0];
1042     mdaddr[1] = mdes[1];
1043     mdpara->data_bytes = can_payload_size_compute(mdpara->dlc);
1044     cnt = (mdpara->data_bytes + 3U) / 4U;
1045     mdaddr = mdpara->data;
1046     mdes += 2U;
1047     for(i = 0U; i < cnt; i++) {
1048         mdaddr[i] = mdes[i];
1049     }
1050 
1051     /* clear mailbox status */
1052     CAN_STAT(can_periph) = STAT_MS(index);
1053     /* unlock mailbox */
1054     CAN_TIMER(can_periph);
1055 
1056     /* get mailbox ID */
1057     if(mdpara->ide) {
1058         mdpara->id = GET_MDES1_ID_EXD(mdpara->id);
1059     } else {
1060         mdpara->id = GET_MDES1_ID_STD(mdpara->id);
1061     }
1062 
1063     /* get mailbox data */
1064     if(mdpara->data_bytes) {
1065         can_data_to_little_endian_swap(mdpara->data, mdpara->data, mdpara->data_bytes);
1066     }
1067 
1068     return SUCCESS;
1069 }
1070 
1071 /*!
1072     \brief      lock the receive mailbox
1073     \param[in]  can_periph: CANx(x=0,1)
1074     \param[in]  index: mailbox index
1075                 only one parameter can be selected which is shown as below:
1076       \arg        0 - 31
1077     \param[out] none
1078     \retval     none
1079 */
can_mailbox_receive_lock(uint32_t can_periph,uint32_t index)1080 void can_mailbox_receive_lock(uint32_t can_periph, uint32_t index)
1081 {
1082     uint32_t *mdes;
1083 
1084     mdes = can_ram_address_get(can_periph, index);
1085     REG32((uint32_t)mdes);
1086 }
1087 
1088 /*!
1089     \brief      unlock the receive mailbox
1090     \param[in]  can_periph: CANx(x=0,1)
1091     \param[out] none
1092     \retval     none
1093 */
can_mailbox_receive_unlock(uint32_t can_periph)1094 void can_mailbox_receive_unlock(uint32_t can_periph)
1095 {
1096     CAN_TIMER(can_periph);
1097 }
1098 
1099 /*!
1100     \brief      inactive the receive mailbox
1101     \param[in]  can_periph: CANx(x=0,1)
1102     \param[in]  index: mailbox index
1103                 only one parameter can be selected which is shown as below:
1104       \arg        0 - 31
1105     \param[out] none
1106     \retval     none
1107 */
can_mailbox_receive_inactive(uint32_t can_periph,uint32_t index)1108 void can_mailbox_receive_inactive(uint32_t can_periph, uint32_t index)
1109 {
1110     uint32_t mdes0;
1111     uint32_t *mdes;
1112 
1113     /* inactive receive mailbox */
1114     mdes = can_ram_address_get(can_periph, index);
1115     mdes0 = mdes[0];
1116     mdes0 &= ~CAN_MDES0_CODE;
1117     mdes0 |= MDES0_CODE(CAN_MB_RX_STATUS_INACTIVE);
1118     mdes[0] = mdes0;
1119 }
1120 
1121 /*!
1122     \brief      get mailbox code value
1123     \param[in]  can_periph: CANx(x=0,1)
1124     \param[in]  index: mailbox index(0~31)
1125                 only one parameter can be selected which is shown as below:
1126       \arg        0 - 31
1127     \param[out] none
1128     \retval     mailbox code
1129 */
can_mailbox_code_get(uint32_t can_periph,uint32_t index)1130 uint32_t can_mailbox_code_get(uint32_t can_periph, uint32_t index)
1131 {
1132     uint32_t code;
1133     uint32_t *mdes;
1134 
1135     mdes = can_ram_address_get(can_periph, index);
1136     code = GET_MDES0_CODE(mdes[0]);
1137 
1138     return code;
1139 }
1140 
1141 /*!
1142     \brief      configure error counter
1143     \param[in]  can_periph: CANx(x=0,1)
1144     \param[in]  errcnt_struct
1145                   fd_data_phase_rx_errcnt: 0-255
1146                   fd_data_phase_tx_errcnt: 0-255
1147                   rx_errcnt: 0-255
1148                   tx_errcnt: 0-255
1149     \retval     none
1150 */
can_error_counter_config(uint32_t can_periph,can_error_counter_struct * errcnt_struct)1151 void can_error_counter_config(uint32_t can_periph, can_error_counter_struct *errcnt_struct)
1152 {
1153     CAN_ERR0(can_periph) = ERR0_REFCNT(errcnt_struct->fd_data_phase_rx_errcnt) | ERR0_TEFCNT(errcnt_struct->fd_data_phase_tx_errcnt) | \
1154                            ERR0_RECNT(errcnt_struct->rx_errcnt) | ERR0_TECNT(errcnt_struct->tx_errcnt);
1155 }
1156 
1157 /*!
1158     \brief      get error counter
1159     \param[in]  can_periph: CANx(x=0,1)
1160     \param[out] errcnt_struct
1161                   fd_data_phase_rx_errcnt: 0-255
1162                   fd_data_phase_tx_errcnt: 0-255
1163                   rx_errcnt: 0-255
1164                   tx_errcnt: 0-255
1165     \retval     none
1166 */
can_error_counter_get(uint32_t can_periph,can_error_counter_struct * errcnt_struct)1167 void can_error_counter_get(uint32_t can_periph, can_error_counter_struct *errcnt_struct)
1168 {
1169     uint32_t reg = 0U;
1170 
1171     reg = CAN_ERR0(can_periph);
1172     errcnt_struct->fd_data_phase_rx_errcnt = (uint8_t)GET_ERR0_REFCNT(reg);
1173     errcnt_struct->fd_data_phase_tx_errcnt = (uint8_t)GET_ERR0_TEFCNT(reg);
1174     errcnt_struct->rx_errcnt = (uint8_t)GET_ERR0_RECNT(reg);
1175     errcnt_struct->tx_errcnt = (uint8_t)GET_ERR0_TECNT(reg);
1176 }
1177 
1178 /*!
1179     \brief      get error state indicator
1180     \param[in]  can_periph: CANx(x=0,1)
1181     \param[out] none
1182     \retval     CAN_ERROR_STATE_ACTIVE, CAN_ERROR_STATE_PASSIVE or CAN_ERROR_STATE_BUS_OFF
1183 */
can_error_state_get(uint32_t can_periph)1184 can_error_state_enum can_error_state_get(uint32_t can_periph)
1185 {
1186     uint32_t reg;
1187 
1188     reg = GET_ERR1_ERRSI(CAN_ERR1(can_periph));
1189     if(reg >= (uint32_t)CAN_ERROR_STATE_BUS_OFF) {
1190         reg = (uint32_t)CAN_ERROR_STATE_BUS_OFF;
1191     }
1192 
1193     return (can_error_state_enum)reg;
1194 }
1195 
1196 /*!
1197     \brief      get mailbox CRC value
1198     \param[in]  can_periph: CANx(x=0,1)
1199     \param[out] crc_struct:
1200                   classical_frm_mb_number: 0 - 0x1F
1201                   classical_frm_transmitted_crc: 0 - 0x7FFF
1202                   classical_fd_frm_mb_number: 0 - 0x1F
1203                   classical_fd_frm_transmitted_crc: 0 - 0x1FFFFF
1204     \retval     none
1205 */
can_crc_get(uint32_t can_periph,can_crc_struct * crc_struct)1206 void can_crc_get(uint32_t can_periph, can_crc_struct *crc_struct)
1207 {
1208     uint32_t reg1 = 0U, reg2 = 0U;
1209 
1210     reg1 = CAN_CRCC(can_periph);
1211     reg2 = CAN_CRCCFD(can_periph);
1212     crc_struct->classical_frm_mb_number = GET_CRCC_ANTM(reg1);
1213     crc_struct->classical_frm_transmitted_crc = GET_CRCC_CRCTC(reg1);
1214     crc_struct->classical_fd_frm_mb_number = GET_CRCCFD_ANTM(reg2);
1215     crc_struct->classical_fd_frm_transmitted_crc = GET_CRCCFD_CRCTCI(reg2);
1216 }
1217 
1218 /*!
1219     \brief      configure Pretended Networking mode parameter
1220     \param[in]  can_periph: CANx(x=0,1)
1221     \param[in]  pnmod_config: Pretended Networking mode config struct
1222                   timeout_int: ENABLE, DISABLE
1223                   match_int: ENABLE, DISABLE
1224                   num_matches: 1 ~ 255
1225                   match_timeout: 0 ~ 0xFFFF
1226                   frame_filter: CAN_PN_FRAME_FILTERING_ID, CAN_PN_FRAME_FILTERING_ID_DATA
1227                                 CAN_PN_FRAME_FILTERING_ID_NMM, CAN_PN_FRAME_FILTERING_ID_DATA_NMM
1228                   id_filter: CAN_PN_ID_FILTERING_EXACT, CAN_PN_ID_FILTERING_GREATER
1229                              CAN_PN_ID_FILTERING_SMALLER, CAN_PN_ID_FILTERING_RANGE
1230                   data_filter: CAN_PN_DATA_FILTERING_EXACT, CAN_PN_DATA_FILTERING_GREATER
1231                                CAN_PN_DATA_FILTERING_SMALLER, CAN_PN_DATA_FILTERING_RANGE
1232     \param[out] none
1233     \retval     none
1234 */
can_pn_mode_config(uint32_t can_periph,can_pn_mode_config_struct * pnmod_config)1235 void can_pn_mode_config(uint32_t can_periph, can_pn_mode_config_struct *pnmod_config)
1236 {
1237     uint32_t tmp;
1238 
1239     /* configure specific Pretended Networking mode settings */
1240     tmp = CAN_PN_CTL0(can_periph);
1241     tmp &= ~(CAN_PN_CTL0_FFT | CAN_PN_CTL0_IDFT | CAN_PN_CTL0_DATAFT |
1242              CAN_PN_CTL0_NMM | CAN_PN_CTL0_WMIE | CAN_PN_CTL0_WTOIE);
1243     tmp |= (uint32_t)PN_CTL0_WTOIE(pnmod_config->timeout_int) | PN_CTL0_WMIE(pnmod_config->match_int) | \
1244            PN_CTL0_NMM(pnmod_config->num_matches) | PN_CTL0_DATAFT(pnmod_config->data_filter) | \
1245            PN_CTL0_IDFT(pnmod_config->id_filter) | PN_CTL0_FFT(pnmod_config->frame_filter);
1246 
1247     CAN_PN_CTL0(can_periph) = tmp;
1248 
1249     /* set timeout value */
1250     CAN_PN_TO(can_periph) &= ~CAN_PN_TO_WTO;
1251     CAN_PN_TO(can_periph) |= (uint32_t)PN_TO_WTO(pnmod_config->match_timeout);
1252 
1253     /* enable Pretended Networking mode */
1254     CAN_CTL0(can_periph) |= CAN_CTL0_PNMOD;
1255 }
1256 
1257 /*!
1258     \brief      configure Pretended Networking mode filter
1259     \param[in]  can_periph: CANx(x=0,1)
1260     \param[in]  expect: Pretended Networking mode struct of expected wakeup frame
1261                   remote_frame: SET, RESET
1262                   extended_frame: SET, RESET
1263                   id: 0x00000000~0x1FFFFFFF
1264                   dlc_high_threshold: 0~8
1265                   dlc_low_threshold: 0~8
1266                   payload[0]: 0x00000000~0xFFFFFFFF
1267                   payload[1]: 0x00000000~0xFFFFFFFF
1268     \param[in]  filter: Pretended Networking mode struct of filter data
1269                   remote_frame: SET, RESET
1270                   extended_frame: SET, RESET
1271                   id: 0x00000000~0x1FFFFFFF
1272                   dlc_high_threshold: 0~8
1273                   dlc_low_threshold: 0~8
1274                   payload[0]: 0x00000000~0xFFFFFFFF
1275                   payload[1]: 0x00000000~0xFFFFFFFF
1276     \param[out] none
1277     \retval     none
1278 */
can_pn_mode_filter_config(uint32_t can_periph,can_pn_mode_filter_struct * expect,can_pn_mode_filter_struct * filter)1279 void can_pn_mode_filter_config(uint32_t can_periph, can_pn_mode_filter_struct *expect, can_pn_mode_filter_struct *filter)
1280 {
1281     uint32_t reg, temp;
1282 
1283     /* set filter identifier 0 */
1284     reg = 0U;
1285     if((uint32_t)SET == expect->extended_frame) {
1286         reg |= CAN_PN_EID0_EIDE;
1287         reg |= (uint32_t)PN_EID0_EIDF_ELT_EXD(expect->id);
1288     } else {
1289         reg |= (uint32_t)PN_EID0_EIDF_ELT_STD(expect->id);
1290     }
1291     if((uint32_t)SET == expect->remote_frame) {
1292         reg |= CAN_PN_EID0_ERTR;
1293     }
1294     CAN_PN_EID0(can_periph) = reg;
1295 
1296     temp = CAN_PN_CTL0(can_periph);
1297     /* ID field 1 is used when ID filtering type is EXACT or RANGE */
1298     if(((temp & CAN_PN_CTL0_IDFT) == CAN_PN_ID_FILTERING_EXACT) ||
1299             ((temp & CAN_PN_CTL0_IDFT) == CAN_PN_ID_FILTERING_RANGE)) {
1300         /* set filter identifier 1 */
1301         reg = 0U;
1302         if((uint32_t)SET == filter->extended_frame) {
1303             reg |= CAN_PN_IFEID1_IDEFD;
1304             reg |= (uint32_t)PN_IFEID1_IDEFD_EXD(filter->id);
1305         } else {
1306             reg |= (uint32_t)PN_IFEID1_IDEFD_STD(filter->id);
1307         }
1308         if((uint32_t)SET == filter->remote_frame) {
1309             reg |= CAN_PN_IFEID1_RTRFD;
1310         }
1311         CAN_PN_IFEID1(can_periph) = reg;
1312     }
1313 
1314     /* data field is used when frame filtering type is not MATCH or MATCH NMM */
1315     if(((temp & CAN_PN_CTL0_FFT) == CAN_PN_FRAME_FILTERING_ID_DATA) ||
1316             ((temp & CAN_PN_CTL0_FFT) == CAN_PN_FRAME_FILTERING_ID_DATA_NMM)) {
1317         /* set filter data payload 0 */
1318         CAN_PN_EDLC(can_periph) = PN_EDLC_DLCEHT(expect->dlc_high_threshold) | PN_EDLC_DLCELT(expect->dlc_low_threshold);
1319         CAN_PN_EDL0(can_periph) = ((expect->payload[0] << 24U) & CAN_PN_EDL0_DB0ELT) |
1320                                   ((expect->payload[0] << 8U) & CAN_PN_EDL0_DB1ELT) |
1321                                   ((expect->payload[0] >> 8U) & CAN_PN_EDL0_DB2ELT) |
1322                                   ((expect->payload[0] >> 24U) & CAN_PN_EDL0_DB3ELT);
1323         CAN_PN_EDL1(can_periph) = ((expect->payload[1] << 24U) & CAN_PN_EDL1_DB4ELT) |
1324                                   ((expect->payload[1] << 8U) & CAN_PN_EDL1_DB5ELT) |
1325                                   ((expect->payload[1] >> 8U) & CAN_PN_EDL1_DB6ELT) |
1326                                   ((expect->payload[1] >> 24U) & CAN_PN_EDL1_DB7ELT);
1327 
1328         /* data field 1 is used when data filtering type is EXACT or RANGE */
1329         if(((temp & CAN_PN_CTL0_DATAFT) == CAN_PN_DATA_FILTERING_EXACT)
1330                 || ((temp & CAN_PN_CTL0_DATAFT) == CAN_PN_DATA_FILTERING_RANGE)) {
1331             /* set filter data payload 1 */
1332             CAN_PN_DF0EDH0(can_periph) = ((filter->payload[0] << 24U) & CAN_PN_DF0EDH0_DB0FD_EHT) |
1333                                          ((filter->payload[0] << 8U) & CAN_PN_DF0EDH0_DB1FD_EHT) |
1334                                          ((filter->payload[0] >> 8U) & CAN_PN_DF0EDH0_DB2FD_EHT) |
1335                                          ((filter->payload[0] >> 24U) & CAN_PN_DF0EDH0_DB3FD_EHT);
1336             CAN_PN_DF1EDH1(can_periph) = ((filter->payload[1] << 24U) & CAN_PN_DF1EDH1_DB4FD_EHT) |
1337                                          ((filter->payload[1] << 8U) & CAN_PN_DF1EDH1_DB5FD_EHT) |
1338                                          ((filter->payload[1] >> 8U) & CAN_PN_DF1EDH1_DB6FD_EHT) |
1339                                          ((filter->payload[1] >> 24U) & CAN_PN_DF1EDH1_DB7FD_EHT);
1340         }
1341     }
1342 }
1343 
1344 
1345 /*!
1346     \brief      get matching message counter of Pretended Networking mode
1347     \param[in]  can_periph: CANx(x=0,1)
1348     \param[out] none
1349     \retval     0~255 or -1
1350 */
can_pn_mode_num_of_match_get(uint32_t can_periph)1351 int32_t can_pn_mode_num_of_match_get(uint32_t can_periph)
1352 {
1353     int32_t ret = 0;
1354     uint32_t reg = 0U;
1355 
1356     reg = CAN_PN_STAT(can_periph);
1357     if(0U != (reg & CAN_PN_STAT_MMCNTS)) {
1358         ret = (int32_t)(uint32_t)GET_PN_STAT_MMCNT(reg);
1359     } else {
1360         ret = -1;
1361     }
1362     return ret;
1363 }
1364 
1365 /*!
1366     \brief      get matching message
1367     \param[in]  can_periph: CANx(x=0,1)
1368     \param[in]  index: Pretended Networking mailbox index
1369                 only one parameter can be selected which is shown as below:
1370       \arg        0 - 31
1371     \param[out] mdpara: wakeup message information
1372     \retval     none
1373 */
can_pn_mode_data_read(uint32_t can_periph,uint32_t index,can_mailbox_descriptor_struct * mdpara)1374 void can_pn_mode_data_read(uint32_t can_periph, uint32_t index, can_mailbox_descriptor_struct *mdpara)
1375 {
1376     uint32_t *mdaddr = (uint32_t *)mdpara;
1377     uint32_t *pnram = (uint32_t *)(uint32_t)(CAN_PN_RAM(can_periph) + index * 16U);
1378 
1379     mdaddr[0] = pnram[0];
1380     mdaddr[1] = pnram[1];
1381     /* get mailbox ID */
1382     if(0U != mdpara->ide) {
1383         mdpara->id = GET_MDES1_ID_EXD(mdpara->id);
1384     } else {
1385         mdpara->id = GET_MDES1_ID_STD(mdpara->id);
1386     }
1387     mdpara->data_bytes = mdpara->dlc;
1388     if(mdpara->data_bytes) {
1389         can_data_to_little_endian_swap(mdpara->data, &pnram[2], mdpara->data_bytes);
1390     }
1391 }
1392 
1393 /*!
1394     \brief      enable self reception
1395     \param[in]  can_periph: CANx(x=0,1)
1396     \param[out] none
1397     \retval     none
1398 */
can_self_reception_enable(uint32_t can_periph)1399 void can_self_reception_enable(uint32_t can_periph)
1400 {
1401     CAN_CTL0(can_periph) &= ~CAN_CTL0_SRDIS;
1402 }
1403 
1404 /*!
1405     \brief      disable self reception
1406     \param[in]  can_periph: CANx(x=0,1)
1407     \param[out] none
1408     \retval     none
1409 */
can_self_reception_disable(uint32_t can_periph)1410 void can_self_reception_disable(uint32_t can_periph)
1411 {
1412     CAN_CTL0(can_periph) |= CAN_CTL0_SRDIS;
1413 }
1414 
1415 /*!
1416     \brief      enable transmit abort
1417     \param[in]  can_periph: CANx(x=0,1)
1418     \param[out] none
1419     \retval     none
1420 */
can_transmit_abort_enable(uint32_t can_periph)1421 void can_transmit_abort_enable(uint32_t can_periph)
1422 {
1423     CAN_CTL0(can_periph) |= CAN_CTL0_MST;
1424 }
1425 
1426 /*!
1427     \brief      disable transmit abort
1428     \param[in]  can_periph: CANx(x=0,1)
1429     \param[out] none
1430     \retval     none
1431 */
can_transmit_abort_disable(uint32_t can_periph)1432 void can_transmit_abort_disable(uint32_t can_periph)
1433 {
1434     CAN_CTL0(can_periph) &= ~CAN_CTL0_MST;
1435 }
1436 
1437 /*!
1438     \brief      enable auto bus off recovery mode
1439     \param[in]  can_periph: CANx(x=0,1)
1440     \param[out] none
1441     \retval     none
1442 */
can_auto_busoff_recovery_enable(uint32_t can_periph)1443 void can_auto_busoff_recovery_enable(uint32_t can_periph)
1444 {
1445     CAN_CTL1(can_periph) &= ~CAN_CTL1_ABORDIS;
1446 }
1447 
1448 /*!
1449     \brief      disable auto bus off recovery mode
1450     \param[in]  can_periph: CANx(x=0,1)
1451     \param[out] none
1452     \retval     none
1453 */
can_auto_busoff_recovery_disable(uint32_t can_periph)1454 void can_auto_busoff_recovery_disable(uint32_t can_periph)
1455 {
1456     CAN_CTL1(can_periph) |= CAN_CTL1_ABORDIS;
1457 }
1458 
1459 /*!
1460     \brief      enable time sync mode
1461     \param[in]  can_periph: CANx(x=0,1)
1462     \param[out] none
1463     \retval     none
1464 */
can_time_sync_enable(uint32_t can_periph)1465 void can_time_sync_enable(uint32_t can_periph)
1466 {
1467     CAN_CTL1(can_periph) |= CAN_CTL1_TSYNC;
1468 }
1469 
1470 /*!
1471     \brief      disable time sync mode
1472     \param[in]  can_periph: CANx(x=0,1)
1473     \param[out] none
1474     \retval     none
1475 */
can_time_sync_disable(uint32_t can_periph)1476 void can_time_sync_disable(uint32_t can_periph)
1477 {
1478     CAN_CTL1(can_periph) &= ~CAN_CTL1_TSYNC;
1479 }
1480 
1481 /*!
1482     \brief      enable edge filter mode
1483     \param[in]  can_periph: CANx(x=0,1)
1484     \param[out] none
1485     \retval     none
1486 */
can_edge_filter_mode_enable(uint32_t can_periph)1487 void can_edge_filter_mode_enable(uint32_t can_periph)
1488 {
1489     CAN_CTL2(can_periph) &= ~CAN_CTL2_EFDIS;
1490 }
1491 
1492 /*!
1493     \brief      disable edge filter mode
1494     \param[in]  can_periph: CANx(x=0,1)
1495     \param[out] none
1496     \retval     none
1497 */
can_edge_filter_mode_disable(uint32_t can_periph)1498 void can_edge_filter_mode_disable(uint32_t can_periph)
1499 {
1500     CAN_CTL2(can_periph) |= CAN_CTL2_EFDIS;
1501 }
1502 
1503 /*!
1504     \brief      enable protocol exception detection mode
1505     \param[in]  can_periph: CANx(x=0,1)
1506     \param[out] none
1507     \retval     none
1508 */
can_ped_mode_enable(uint32_t can_periph)1509 void can_ped_mode_enable(uint32_t can_periph)
1510 {
1511     CAN_CTL2(can_periph) |= CAN_CTL2_PREEN;
1512 }
1513 
1514 /*!
1515     \brief      disable protocol exception detection mode
1516     \param[in]  can_periph: CANx(x=0,1)
1517     \param[out] none
1518     \retval     none
1519 */
can_ped_mode_disable(uint32_t can_periph)1520 void can_ped_mode_disable(uint32_t can_periph)
1521 {
1522     CAN_CTL2(can_periph) &= ~CAN_CTL2_PREEN;
1523 }
1524 
1525 /*!
1526     \brief      configure arbitation delay bits
1527     \param[in]  can_periph: CANx(x=0,1)
1528     \param[in]  delay_bits: delay bits
1529                 only one parameter can be selected which is shown as below:
1530       \arg        0 - 31
1531     \param[out] none
1532     \retval     none
1533 */
can_arbitation_delay_bits_config(uint32_t can_periph,uint32_t delay_bits)1534 void can_arbitation_delay_bits_config(uint32_t can_periph, uint32_t delay_bits)
1535 {
1536     CAN_CTL2(can_periph) &= ~CAN_CTL2_ASD;
1537     CAN_CTL2(can_periph) |= (uint32_t)CTL2_ASD(delay_bits);
1538 }
1539 
1540 /*!
1541     \brief      configure bit sampling mode
1542     \param[in]  can_periph: CANx(x=0,1)
1543     \param[in]  sampling_mode: bit sampling mode
1544                 only one parameter can be selected which is shown as below:
1545       \arg        CAN_BSP_MODE_ONE_SAMPLE: one sample for received bit
1546       \arg        CAN_BSP_MODE_TRHEE_SAMPLES: three samples for received bit
1547     \param[out] none
1548     \retval     none
1549 */
can_bsp_mode_config(uint32_t can_periph,uint32_t sampling_mode)1550 void can_bsp_mode_config(uint32_t can_periph, uint32_t sampling_mode)
1551 {
1552     if(CAN_BSP_MODE_ONE_SAMPLE == sampling_mode) {
1553         CAN_CTL1(can_periph) &= ~CAN_CTL1_BSPMOD;
1554     } else {
1555         CAN_CTL1(can_periph) |= CAN_CTL1_BSPMOD;
1556     }
1557 }
1558 
1559 /*!
1560     \brief      get CAN flag
1561     \param[in]  can_periph: CANx(x=0,1)
1562     \param[in]  flag: CAN flags, refer to can_flag_enum
1563                 only one parameter can be selected which is shown as below:
1564       \arg        CAN_FLAG_CAN_PN: Pretended Networking state flag
1565       \arg        CAN_FLAG_SOFT_RST: software reset flag
1566       \arg        CAN_FLAG_ERR_SUMMARY: error summary flag
1567       \arg        CAN_FLAG_BUSOFF: bus off flag
1568       \arg        CAN_FLAG_RECEIVING: receiving state flag
1569       \arg        CAN_FLAG_TRANSMITTING: transmitting state flag
1570       \arg        CAN_FLAG_IDLE: IDLE state flag
1571       \arg        CAN_FLAG_RX_WARNING: receive warning flag
1572       \arg        CAN_FLAG_TX_WARNING: transmit warning flag
1573       \arg        CAN_FLAG_STUFF_ERR: stuff error flag
1574       \arg        CAN_FLAG_FORM_ERR: form error flag
1575       \arg        CAN_FLAG_CRC_ERR: CRC error flag
1576       \arg        CAN_FLAG_ACK_ERR: ACK error flag
1577       \arg        CAN_FLAG_BIT_DOMINANT_ERR: bit dominant error flag
1578       \arg        CAN_FLAG_BIT_RECESSIVE_ERR: bit recessive error flag
1579       \arg        CAN_FLAG_SYNC_ERR: synchronization flag
1580       \arg        CAN_FLAG_BUSOFF_RECOVERY: bus off recovery flag
1581       \arg        CAN_FLAG_ERR_SUMMARY_FD: fd error summary flag
1582       \arg        CAN_FLAG_ERR_OVERRUN: error overrun flag
1583       \arg        CAN_FLAG_STUFF_ERR_FD: stuff error in FD data phase flag
1584       \arg        CAN_FLAG_FORM_ERR_FD: form error in FD data phase flag
1585       \arg        CAN_FLAG_CRC_ERR_FD: CRC error in FD data phase flag
1586       \arg        CAN_FLAG_BIT_DOMINANT_ERR_FD: bit dominant error in FD data phase flag
1587       \arg        CAN_FLAG_BIT_RECESSIVE_ERR_FD: bit recessive error in FD data phase flag
1588       \arg        CAN_FLAG_MBx(x=0~31): mailbox x flag
1589       \arg        CAN_FLAG_FIFO_AVAILABLE: fifo available flag
1590       \arg        CAN_FLAG_FIFO_WARNING: fifo warning flag
1591       \arg        CAN_FLAG_FIFO_OVERFLOW: fifo overflow flag
1592       \arg        CAN_FLAG_WAKEUP_MATCH: Pretended Networking match flag
1593       \arg        CAN_FLAG_WAKEUP_TIMEOUT: Pretended Networking timeout wakeup flag
1594       \arg        CAN_FLAG_TDC_OUT_OF_RANGE: transmitter delay is out of compensation range flag
1595     \param[out] none
1596     \retval     FlagStatus: SET or RESET
1597 */
can_flag_get(uint32_t can_periph,can_flag_enum flag)1598 FlagStatus can_flag_get(uint32_t can_periph, can_flag_enum flag)
1599 {
1600     if(CAN_REG_VAL(can_periph, flag) & BIT(CAN_BIT_POS(flag))) {
1601         return SET;
1602     } else {
1603         return RESET;
1604     }
1605 }
1606 
1607 /*!
1608     \brief      clear CAN flag
1609     \param[in]  can_periph: CANx(x=0,1)
1610     \param[in]  flag: CAN flags, refer to can_flag_enum
1611                 only one parameter can be selected which is shown as below:
1612       \arg        CAN_FLAG_ERR_SUMMARY: error summary flag
1613       \arg        CAN_FLAG_BUSOFF: bus off flag
1614       \arg        CAN_FLAG_BUSOFF_RECOVERY: bus off recovery flag
1615       \arg        CAN_FLAG_ERR_SUMMARY_FD: fd error summary flag
1616       \arg        CAN_FLAG_ERR_OVERRUN: error overrun flag
1617       \arg        CAN_FLAG_MBx(x=0~31): mailbox x flag
1618       \arg        CAN_FLAG_FIFO_AVAILABLE: fifo available flag
1619       \arg        CAN_FLAG_FIFO_WARNING: fifo warning flag
1620       \arg        CAN_FLAG_FIFO_OVERFLOW: fifo overflow flag
1621       \arg        CAN_FLAG_WAKEUP_MATCH: Pretended Networking match flag
1622       \arg        CAN_FLAG_WAKEUP_TIMEOUT: Pretended Networking timeout wakeup flag
1623       \arg        CAN_FLAG_TDC_OUT_OF_RANGE: transmitter delay is out of compensation range flag
1624     \param[out] none
1625     \retval     none
1626 */
can_flag_clear(uint32_t can_periph,can_flag_enum flag)1627 void can_flag_clear(uint32_t can_periph, can_flag_enum flag)
1628 {
1629     if(CAN_FLAG_TDC_OUT_OF_RANGE == flag) {
1630         CAN_FDCTL(can_periph) |= CAN_FDCTL_TDCS;
1631     } else {
1632         CAN_REG_VAL(can_periph, flag) = BIT(CAN_BIT_POS(flag));
1633     }
1634 }
1635 
1636 /*!
1637     \brief      enable CAN interrupt
1638     \param[in]  can_periph: CANx(x=0,1)
1639     \param[in]  interrupt: CAN interrupt, refer to can_interrupt_enum
1640                 only one parameter can be selected which is shown as below:
1641       \arg        CAN_INT_ERR_SUMMARY: error interrupt
1642       \arg        CAN_INT_RX_WARNING: receive warning interrupt
1643       \arg        CAN_INT_TX_WARNING: transmit warning interrupt
1644       \arg        CAN_INT_BUSOFF: bus off interrupt
1645       \arg        CAN_INT_BUSOFF_RECOVERY: bus off recovery interrupt
1646       \arg        CAN_INT_ERR_SUMMARY_FD: fd error interrupt
1647       \arg        CAN_INT_MBx(x=0~31): mailbox x interrupt
1648       \arg        CAN_INT_FIFO_AVAILABLE: fifo availabe interrupt
1649       \arg        CAN_INT_FIFO_WARNING: fifo warning interrupt
1650       \arg        CAN_INT_FIFO_OVERFLOW: fifo overflow interrupt
1651       \arg        CAN_INT_WAKEUP_MATCH: Pretended Networking match interrupt
1652       \arg        CAN_INT_WAKEUP_TIMEOUT: Pretended Networking timeout wakeup interrupt
1653     \param[out] none
1654     \retval     none
1655 */
can_interrupt_enable(uint32_t can_periph,can_interrupt_enum interrupt)1656 void can_interrupt_enable(uint32_t can_periph, can_interrupt_enum interrupt)
1657 {
1658     /* enable receive or transmit warning error interrupt should enable error warning in CTL0 register  */
1659     if((CAN_INT_RX_WARNING == interrupt)
1660             || (CAN_INT_TX_WARNING == interrupt)) {
1661         CAN_CTL0(can_periph) |= CAN_CTL0_WERREN;
1662     }
1663 
1664     CAN_REG_VAL(can_periph, interrupt) |= BIT(CAN_BIT_POS(interrupt));
1665 }
1666 
1667 /*!
1668     \brief      disable CAN interrupt
1669     \param[in]  can_periph: CANx(x=0,1)
1670     \param[in]  interrupt: CAN interrupt, refer to can_interrupt_enum
1671                 only one parameter can be selected which is shown as below:
1672       \arg        CAN_INT_ERR_SUMMARY: error interrupt
1673       \arg        CAN_INT_RX_WARNING: receive warning interrupt
1674       \arg        CAN_INT_TX_WARNING: transmit warning interrupt
1675       \arg        CAN_INT_BUSOFF: bus off interrupt
1676       \arg        CAN_INT_BUSOFF_RECOVERY: bus off recovery interrupt
1677       \arg        CAN_INT_ERR_SUMMARY_FD: fd error interrupt
1678       \arg        CAN_INT_MBx(x=0~31): mailbox x interrupt
1679       \arg        CAN_INT_FIFO_AVAILABLE: fifo available interrupt
1680       \arg        CAN_INT_FIFO_WARNING: fifo warning interrupt
1681       \arg        CAN_INT_FIFO_OVERFLOW: fifo overflow interrupt
1682       \arg        CAN_INT_WAKEUP_MATCH: Pretended Networking match interrupt
1683       \arg        CAN_INT_WAKEUP_TIMEOUT: Pretended Networking timeout wakeup interrupt
1684     \param[out] none
1685     \retval     none
1686 */
can_interrupt_disable(uint32_t can_periph,can_interrupt_enum interrupt)1687 void can_interrupt_disable(uint32_t can_periph, can_interrupt_enum interrupt)
1688 {
1689     CAN_REG_VAL(can_periph, interrupt) &= ~BIT(CAN_BIT_POS(interrupt));
1690 }
1691 
1692 /*!
1693     \brief      get CAN interrupt flag
1694     \param[in]  can_periph: CANx(x=0,1)
1695     \param[in]  int_flag: CAN interrupt flags, refer to can_interrupt_flag_enum
1696                 only one parameter can be selected which is shown as below:
1697       \arg        CAN_INT_FLAG_ERR_SUMMARY: error summary interrupt flag
1698       \arg        CAN_INT_FLAG_BUSOFF: bus off interrupt flag
1699       \arg        CAN_INT_FLAG_RX_WARNING: receive warning interrupt flag
1700       \arg        CAN_INT_FLAG_TX_WARNING: transmit warning interrupt flag
1701       \arg        CAN_INT_FLAG_BUSOFF_RECOVERY: bus off recovery interrupt flag
1702       \arg        CAN_INT_FLAG_ERR_SUMMARY_FD: fd error summary interrupt flag
1703       \arg        CAN_INT_FLAG_MBx(x=0~31): mailbox x interrupt flag
1704       \arg        CAN_INT_FLAG_FIFO_AVAILABLE: fifo available interrupt flag
1705       \arg        CAN_INT_FLAG_FIFO_WARNING: fifo warning interrupt flag
1706       \arg        CAN_INT_FLAG_FIFO_OVERFLOW: fifo overflow interrupt flag
1707       \arg        CAN_INT_FLAG_WAKEUP_MATCH: Pretended Networking match interrupt flag
1708       \arg        CAN_INT_FLAG_WAKEUP_TIMEOUT: Pretended Networking timeout wakeup interrupt flag
1709     \param[out] none
1710     \retval     FlagStatus: SET or RESET
1711 */
can_interrupt_flag_get(uint32_t can_periph,can_interrupt_flag_enum int_flag)1712 FlagStatus can_interrupt_flag_get(uint32_t can_periph, can_interrupt_flag_enum int_flag)
1713 {
1714     if(CAN_REG_VAL(can_periph, int_flag) & BIT(CAN_BIT_POS(int_flag))) {
1715         return SET;
1716     } else {
1717         return RESET;
1718     }
1719 }
1720 
1721 /*!
1722     \brief      clear CAN interrupt flag
1723     \param[in]  can_periph: CANx(x=0,1)
1724     \param[in]  int_flag: CAN interrupt flags, refer to can_interrupt_flag_enum
1725                 only one parameter can be selected which is shown as below:
1726       \arg        CAN_INT_FLAG_ERR_SUMMARY: error summary interrupt flag
1727       \arg        CAN_INT_FLAG_BUSOFF: bus off interrupt flag
1728       \arg        CAN_INT_FLAG_RX_WARNING: receive warning interrupt flag
1729       \arg        CAN_INT_FLAG_TX_WARNING: transmit warning interrupt flag
1730       \arg        CAN_INT_FLAG_BUSOFF_RECOVERY: bus off recovery interrupt flag
1731       \arg        CAN_INT_FLAG_ERR_SUMMARY_FD: fd error summary interrupt flag
1732       \arg        CAN_INT_FLAG_MBx(x=0~31): mailbox x interrupt flag
1733       \arg        CAN_INT_FLAG_FIFO_AVAILABLE: fifo availabe interrupt flag
1734       \arg        CAN_INT_FLAG_FIFO_WARNING: fifo warning interrupt flag
1735       \arg        CAN_INT_FLAG_FIFO_OVERFLOW: fifo overflow interrupt flag
1736       \arg        CAN_INT_FLAG_WAKEUP_MATCH: Pretended Networking match interrupt flag
1737       \arg        CAN_INT_FLAG_WAKEUP_TIMEOUT: Pretended Networking timeout wakeup interrupt flag
1738     \param[out] none
1739     \retval     none
1740 */
can_interrupt_flag_clear(uint32_t can_periph,can_interrupt_flag_enum int_flag)1741 void can_interrupt_flag_clear(uint32_t can_periph, can_interrupt_flag_enum int_flag)
1742 {
1743     CAN_REG_VAL(can_periph, int_flag) = BIT(CAN_BIT_POS(int_flag));
1744 }
1745 
1746 /*!
1747     \brief      computes the maximum payload size (in bytes), given a dlc
1748     \param[in]  dlc_value: dlc value
1749     \param[out] none
1750     \retval     payload_size
1751 */
can_payload_size_compute(uint32_t dlc_value)1752 static uint32_t can_payload_size_compute(uint32_t dlc_value)
1753 {
1754     uint8_t ret = 0U;
1755 
1756     if(dlc_value <= 15U) {
1757         ret = dlc_to_databytes[dlc_value];
1758     }
1759 
1760     return (uint32_t)ret;
1761 }
1762 
1763 /*!
1764     \brief      swap data to little endian
1765     \param[in]  src: data source address
1766     \param[in]  len: data length be byte
1767     \param[out] dest: data destination address
1768     \retval     none
1769 */
can_data_to_little_endian_swap(uint32_t dest[],uint32_t src[],uint32_t len)1770 static void can_data_to_little_endian_swap(uint32_t dest[], uint32_t src[], uint32_t len)
1771 {
1772     volatile uint32_t i = 0U;
1773     uint32_t cnt;
1774     uint32_t temp_src = 0U;
1775 
1776     /* get the word length of the data */
1777     cnt = (len + 3U) / 4U;
1778     /* change each word from big endian to little endian */
1779     for(i = 0U; i < cnt; i++) {
1780         temp_src = src[i];
1781         dest[i] = ((uint32_t)(temp_src >> 24U) & 0x000000FFU) |
1782                   ((uint32_t)(temp_src >> 8U) & 0x0000FF00U) |
1783                   ((uint32_t)(temp_src << 8U) & 0x00FF0000U) |
1784                   ((uint32_t)(temp_src << 24U) & 0xFF000000U);
1785     }
1786 
1787     cnt = len % 4U;
1788     if(cnt) {
1789         dest[i - 1U] &= ((uint32_t)1U << (cnt * 8U)) - 1U;
1790     }
1791 }
1792 
1793 /*!
1794     \brief      swap data to big endian
1795     \param[in]  src: data source address
1796     \param[in]  len: data length be byte
1797     \param[out] dest: data destination address
1798     \retval     none
1799 */
can_data_to_big_endian_swap(uint32_t dest[],uint32_t src[],uint32_t len)1800 static void can_data_to_big_endian_swap(uint32_t dest[], uint32_t src[], uint32_t len)
1801 {
1802     volatile uint32_t i = 0U;
1803     uint32_t cnt;
1804     uint32_t temp_src = 0U;
1805 
1806     /* get the word length of the data */
1807     cnt = (len + 3U) / 4U;
1808     for(i = 0U; i < cnt; i++) {
1809         /* change each word from little endian to big endian */
1810         temp_src = src[i];
1811         dest[i] = ((uint32_t)(temp_src >> 24U) & 0x000000FFU) |
1812                   ((uint32_t)(temp_src >> 8U) & 0x0000FF00U) |
1813                   ((uint32_t)(temp_src << 8U) & 0x00FF0000U) |
1814                   ((uint32_t)(temp_src << 24U) & 0xFF000000U);
1815     }
1816 
1817     cnt = len % 4U;
1818     if(cnt) {
1819         dest[i - 1U] &= ~(((uint32_t)1U << ((4U - cnt) * 8U)) - 1U);
1820     }
1821 }
1822 
1823 /*!
1824     \brief      computes the DLC field value, given a payload size (in bytes)
1825     \param[in]  payload_size: payload size
1826     \param[out] none
1827     \retval     DLC value
1828 */
can_dlc_value_compute(uint32_t payload_size)1829 static uint32_t can_dlc_value_compute(uint32_t payload_size)
1830 {
1831     uint32_t ret = 8U;
1832 
1833     if(payload_size <= 8U) {
1834         ret = payload_size;
1835     } else if(payload_size <= 24U) {
1836         ret = (payload_size - 9U) / 4U + 9U;
1837     } else if(payload_size <= 64U) {
1838         ret = (payload_size - 17U) / 16U + 13U;
1839     } else {
1840         ret = 8U;
1841     }
1842 
1843     return ret;
1844 }
1845