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