libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
fdcan_common.c
Go to the documentation of this file.
1/*
2 * This file is part of the libopencm3 project.
3 *
4 * Copyright (C) 2021 Eduard Drusa <ventyl86 at netkosice dot sk>
5 *
6 * This library is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this library. If not, see <http://www.gnu.org/licenses/>.
18 */
19
22#include <stddef.h>
23
24
25/* --- FD-CAN internal functions -------------------------------------------- */
26
27/** Routine implementing FDCAN_CCCR's INIT bit manipulation.
28 *
29 * This routine will change INIT bit and wait for it to actually
30 * change its value. If change won't happen before timeout,
31 * error is signalized. If INIT bit already has value which
32 * should be set, this function will return immediately.
33 *
34 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
35 * @param [in] set new value of INIT, true means set
36 * @param [in] timeout Amount of busyloop cycles, function will wait for FDCAN
37 * to switch it's state. If set to 0, then function returns immediately.
38 * @returns FDCAN_E_OK on success, FDCAN_E_TIMEOUT if INIT bit value
39 * didn't change before timeout has expired.
40 */
41int fdcan_cccr_init_cfg(uint32_t canport, bool set, uint32_t timeout)
42{
43 uint32_t expected;
44 uint32_t wait_ack;
45
46 if (set) {
47 if ((FDCAN_CCCR(canport) & FDCAN_CCCR_INIT) == FDCAN_CCCR_INIT) {
48 /* Already there, sir */
49 return FDCAN_E_OK;
50 }
51
52 FDCAN_CCCR(canport) |= FDCAN_CCCR_INIT;
53 expected = FDCAN_CCCR_INIT;
54 } else {
55 if ((FDCAN_CCCR(canport) & FDCAN_CCCR_INIT) == 0) {
56 /* Already there, sir */
57 return FDCAN_E_OK;
58 }
59
60 FDCAN_CCCR(canport) &= ~FDCAN_CCCR_INIT;
61 expected = 0;
62 }
63
64 /* Wait, until INIT bit is acknowledged */
65 wait_ack = timeout;
66 while ((wait_ack--) &&
67 ((FDCAN_CCCR(canport) & FDCAN_CCCR_INIT) == expected));
68
69 if ((FDCAN_CCCR(canport) & FDCAN_CCCR_INIT) == expected) {
70 return FDCAN_E_OK;
71 } else {
72 return FDCAN_E_TIMEOUT;
73 }
74}
75
76/** Return ID of next free Tx buffer.
77 *
78 * Examines transmit buffer allocation in message RAM
79 * and returns ID of buffer, which is free.
80 *
81 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
82 * @returns Non-negative number ID of Tx buffer which is free,
83 * or FDCAN_E_BUSY if no Tx buffer is available
84 */
85static int fdcan_get_free_txbuf(uint32_t canport)
86{
87 if ((FDCAN_TXBRP(canport) & FDCAN_TXBRP_TRP0) == 0) {
88 return 0;
89 } else if ((FDCAN_TXBRP(canport) & FDCAN_TXBRP_TRP1) == 0) {
90 return 1;
91 } else if ((FDCAN_TXBRP(canport) & FDCAN_TXBRP_TRP2) == 0) {
92 return 2;
93 }
94
95 return FDCAN_E_BUSY;
96}
97
98/** Returns fill state and next available get index from receive FIFO.
99 *
100 * Examines FDCAN receive FIFO and returns fill status of FIFO and ID of
101 * next message available for reading. If fill status is 0 (FIFO is empty),
102 * then get index is undefined.
103 *
104 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
105 * @param [in] fifo_id ID of fifo queried (currently 0 or 1)
106 * @param [out] get_index Address of buffer where next get index will be stored
107 * @param [out] pending_frames Address of buffer where amount of pending frame will be stored.
108 */
109static void fdcan_get_fill_rxfifo(uint32_t canport, uint8_t fifo_id, unsigned *get_index,
110 unsigned *pending_frames)
111{
112 *get_index = (FDCAN_RXFIS(canport, fifo_id) >> FDCAN_RXFIFO_GI_SHIFT)
114
115 *pending_frames = (FDCAN_RXFIS(canport, fifo_id) >> FDCAN_RXFIFO_FL_SHIFT)
117}
118
119/** Returns standard filter start address in message RAM
120 *
121 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
122 * @returns Base address of standard filter configuration block.
123 */
125{
126 struct fdcan_standard_filter *lfssa = (struct fdcan_standard_filter *)
127 (CAN_MSG_BASE + FDCAN_LFSSA_OFFSET(canport));
128 return lfssa;
129}
130
131/** Returns extended filter start address in message RAM
132 *
133 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
134 * @returns Base address of extended filter configuration block.
135 */
137{
138 struct fdcan_extended_filter *lfesa = (struct fdcan_extended_filter *)
139 (CAN_MSG_BASE + FDCAN_LFESA_OFFSET(canport));
140 return lfesa;
141}
142
143/** Returns a pointer to an RX FIFO element in message RAM
144 *
145 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
146 * @param [in] fifo_id ID of FIFO whose address is requested
147 * @param [in] element_id the element number in the fifo we're requesting
148 * @returns a pointer to the individual element in the message ram
149 */
151 unsigned fifo_id, unsigned element_id)
152{
153 struct fdcan_rx_fifo_element *rxfifo = (struct fdcan_rx_fifo_element *)
154 (CAN_MSG_BASE + FDCAN_RXFIFO_OFFSET(canport, fifo_id)
155 + (element_id * fdcan_get_fifo_element_size(canport, fifo_id))
156 );
157 return rxfifo;
158}
159
160/** Returns transmit event start address in message RAM
161 *
162 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
163 * @returns Base address of transmit event block.
164 */
166{
167 struct fdcan_tx_event_element *rxfifo = (struct fdcan_tx_event_element *)
168 (CAN_MSG_BASE + FDCAN_TXEVT_OFFSET(canport));
169 return rxfifo;
170}
171
172/** Returns a pointer to an TX FIFO element in message RAM
173 *
174 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
175 * @param [in] element_id the element number in the fifo we're requesting
176 * @returns a pointer to the individual element in the message ram
177 */
178struct fdcan_tx_buffer_element *fdcan_get_txbuf_addr(uint32_t canport, unsigned element_id)
179{
180 struct fdcan_tx_buffer_element *rxfifo = (struct fdcan_tx_buffer_element *)
182 + (element_id * fdcan_get_txbuf_element_size(canport))
183 );
184
185 return rxfifo;
186}
187
188/** Converts frame length to DLC value.
189 *
190 * Works for both CAN and FDCAN frame lengths. If length
191 * is invalid value, then returns 0xFF.
192 *
193 * @param [in] length intended frame payload length in bytes
194 * @returns DLC value representing lengths or 0xFF if length cannot
195 * be encoded into DLC format (applies only to FDCAN frame lengths)
196 */
197uint32_t fdcan_length_to_dlc(uint8_t length)
198{
199 if (length <= 8) {
200 return length;
201 } else if (length <= 24) {
202 if ((length % 4) != 0) {
203 return 0xFF;
204 }
205 return 8 + ((length - 8) / 4);
206 } else {
207 if ((length % 16) != 0) {
208 return 0xFF;
209 }
210 return 11 + (length / 16);
211 }
212}
213
214/** Converts DLC value into frame payload length.
215 *
216 * Works for both CAN and FDCAN DLC values.
217 *
218 * @param [in] dlc DLC value
219 * @returns data payload length in bytes
220 */
221uint8_t fdcan_dlc_to_length(uint32_t dlc)
222{
223 if (dlc <= 8) {
224 return dlc;
225 } else if (dlc <= 12) {
226 return 8 + ((dlc - 8) * 4);
227 } else {
228 return 16 + ((dlc - 12) * 16);
229 }
230}
231
232/* --- FD-CAN functions ----------------------------------------------------- */
233
234/** @ingroup fdcan_file */
235/**@{
236 * */
237
238/** Put FDCAN block into INIT mode for setup
239 *
240 * Initialize the selected CAN peripheral block. This function will switch CAN block
241 * into initialization mode. CAN block is then left in initialization mode in order to
242 * perform setup, which can't be adjusted once FDCAN block is started. It is mandatory
243 * to call at least @ref fdcan_set_can function to configure basic timing values for
244 * CAN 2.0 operation. Functions which only have effect, if FDCAN block is in INIT mode
245 * are:
246 * * @ref fdcan_set_can
247 * * @ref fdcan_set_fdcan
248 * * @ref fdcan_init_filter
249 * * @ref fdcan_set_test
250 *
251 * You can check if FDCAN block is in INIT mode or it is started using
252 * @ref fdcan_get_init_state.
253 *
254 * @param[in] canport CAN register base address. See @ref fdcan_block.
255 * @param [in] timeout Amount of empty busy loops, which routine should wait for FDCAN
256 * confirming that it entered INIT mode. If set to 0, function will
257 * return immediately.
258 * @returns Operation error status. See @ref fdcan_error.
259 */
260int fdcan_init(uint32_t canport, uint32_t timeout)
261{
262 if (fdcan_cccr_init_cfg(canport, true, timeout) != 0) {
263 return FDCAN_E_TIMEOUT;
264 }
265
266 FDCAN_CCCR(canport) |= FDCAN_CCCR_CCE;
267
268 return FDCAN_E_OK;
269}
270
271/** Set essential FDCAN block parameters for plain CAN operation
272 *
273 * Allows configuration of prescalers and essential transmit and FIFO behavior
274 * used during transmission in plain CAN 2.0 mode. In this mode FDCAN frame format
275 * is not available nor is possible to use fast bitrates.
276 * This function does neither enable FD-CAN mode after reset nor disable it
277 * after re-entering INIT mode of previously configured block. Timing values set
278 * here are valid for both arbitration phase of all frames and for data phase of
279 * both CAN and FDCAN frames, which don't use bitrate switching. This function can
280 * only be called after FDCAN block has been switched into INIT mode.
281 * It is possible to receive FDCAN frames even if FDCAN block is configured only using
282 * this function as long as bitrate switching is not used.
283 *
284 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
285 * @param [in] auto_retry_disable Disable automatic frame retransmission on error
286 * @param [in] rx_fifo_locked Enable FIFO locked mode. Upon FIFO overflow all received
287 * messages are discarded.
288 * @param [in] tx_queue_mode Enable transmission queue mode. Otherwise transmission
289 * works in FIFO mode.
290 * @param [in] silent Enable silent mode. Transmitter stays recessive all the time.
291 * @param [in] n_sjw Resynchronization time quanta jump width
292 * @param [in] n_ts1 Time segment 1 time quanta
293 * @param [in] n_ts2 Time segment 2 time quanta
294 * @param [in] n_br_presc Arbitration phase / CAN mode bitrate prescaler
295 */
296void fdcan_set_can(uint32_t canport, bool auto_retry_disable, bool rx_fifo_locked,
297 bool tx_queue_mode, bool silent, uint32_t n_sjw, uint32_t n_ts1, uint32_t n_ts2,
298 uint32_t n_br_presc)
299{
300 FDCAN_NBTP(canport) = (n_sjw << FDCAN_NBTP_NSJW_SHIFT)
301 | (n_ts1 << FDCAN_NBTP_NTSEG1_SHIFT)
302 | (n_ts2 << FDCAN_NBTP_NTSEG2_SHIFT)
303 | (n_br_presc << FDCAN_NBTP_NBRP_SHIFT);
304
305 if (tx_queue_mode) {
306 FDCAN_TXBC(canport) |= FDCAN_TXBC_TFQM;
307 } else {
308 FDCAN_TXBC(canport) &= ~FDCAN_TXBC_TFQM;
309 }
310
311 if (auto_retry_disable) {
312 FDCAN_CCCR(canport) |= FDCAN_CCCR_DAR;
313 } else {
314 FDCAN_CCCR(canport) &= ~FDCAN_CCCR_DAR;
315 }
316
317 if (silent) {
318 FDCAN_CCCR(canport) |= FDCAN_CCCR_MON;
319 } else {
320 FDCAN_CCCR(canport) &= ~FDCAN_CCCR_MON;
321 }
322
323 fdcan_set_fifo_locked_mode(canport, rx_fifo_locked);
324}
325
326/** Set FDCAN block parameters for FDCAN transmission
327 *
328 * Enables and configures parameters related to FDCAN transmission. This function
329 * allows configuration of bitrate switching, FDCAN frame format and fast mode
330 * timing. This function can only be called if FDCAN block is in INIT mode.
331 * It is safe to call this function on previously configured block in order
332 * to enable/disable/change FDCAN mode parameters. Non-FDCAN parameters won't
333 * be affected.
334 *
335 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
336 * @param [in] brs_enable Enable FDCAN bitrate switching for fast mode operation
337 * @param [in] fd_op_enable Enable transmission of FDCAN-formatted frames
338 * @param [in] f_sjw Resynchronization time quanta jump width in fast mode
339 * @param [in] f_ts1 Time segment 1 time quanta in fast mode
340 * @param [in] f_ts2 Time segment 2 time quanta in fast mode
341 * @param [in] f_br_presc Fast mode operation bitrate prescaler
342 */
343void fdcan_set_fdcan(uint32_t canport, bool brs_enable, bool fd_op_enable,
344 uint32_t f_sjw, uint32_t f_ts1, uint32_t f_ts2, uint32_t f_br_presc)
345{
346 FDCAN_DBTP(canport) = (f_sjw << FDCAN_DBTP_DSJW_SHIFT)
347 | (f_ts1 << FDCAN_DBTP_DTSEG1_SHIFT)
348 | (f_ts2 << FDCAN_DBTP_DTSEG2_SHIFT)
349 | (f_br_presc << FDCAN_DBTP_DBRP_SHIFT);
350
351 if (fd_op_enable) {
352 FDCAN_CCCR(canport) |= FDCAN_CCCR_FDOE;
353 } else {
354 FDCAN_CCCR(canport) &= ~FDCAN_CCCR_FDOE;
355 }
356
357 if (brs_enable) {
358 FDCAN_CCCR(canport) |= FDCAN_CCCR_BRSE;
359 } else {
360 FDCAN_CCCR(canport) &= ~FDCAN_CCCR_BRSE;
361 }
362}
363
364/** Set FDCAN block testing features.
365 *
366 * Configures self-test functions of FDCAN block. It is safe to call
367 * this function on fully configured interface. This function can
368 * only be called after FDCAN block is put into INIT mode.
369 *
370 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
371 * @param [in] testing Enables testing mode of FDCAN block
372 * @param [in] loopback Enables transmission loopback
373 */
374void fdcan_set_test(uint32_t canport, bool testing, bool loopback)
375{
376 if (testing) {
377 FDCAN_CCCR(canport) |= FDCAN_CCCR_TEST;
378 if (loopback) {
379 FDCAN_TEST(canport) |= FDCAN_TEST_LBCK;
380 } else {
381 FDCAN_TEST(canport) &= ~FDCAN_TEST_LBCK;
382 }
383 } else {
384 FDCAN_CCCR(canport) &= ~FDCAN_CCCR_TEST;
385 /* FDCAN_TEST is automatically reset to default values by
386 * FDCAN at this point */
387 }
388}
389
390/** Return current FDCAN block operation state.
391 *
392 * This function effectively returns value of FDCAN_CCCR's INIT bit.
393 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
394 * @returns 1 if FDCAN block is in INIT mode, 0 if it is already started.
395 */
396int fdcan_get_init_state(uint32_t canport)
397{
398 return ((FDCAN_CCCR(canport) & FDCAN_CCCR_INIT) == FDCAN_CCCR_INIT);
399}
400
401/** Configure filter rule for standard ID frames.
402 *
403 * Sets up filter rule for frames having standard ID. Each FDCAN block can
404 * have its own set of filtering rules. It is only possible to configure as
405 * many filters as was configured previously using @ref fdcan_init_filter.
406 *
407 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
408 * @param [in] nr number of filter to be configured
409 * @param [in] id_list_mode Mode in which id1 and id2 are used to match the rule.
410 * See @ref fdcan_sft.
411 * @param [in] id1 standard ID for matching. Used as exact value, lower bound or bit
412 * pattern depending on matching mode selected
413 * @param [in] id2 standard ID or bitmask. Used as exact value, upper bound or bit mask
414 * depending on matching mode selected
415 * @param [in] action Action performed if filtering rule matches frame ID.
416 * See @ref fdcan_sfec.
417 */
418void fdcan_set_std_filter(uint32_t canport, uint32_t nr,
419 uint8_t id_list_mode, uint32_t id1, uint32_t id2,
420 uint8_t action)
421{
422 struct fdcan_standard_filter *lfssa = fdcan_get_flssa_addr(canport);
423
424 /* id_list_mode and action are passed unguarded. Simply use
425 * defines and it will be OK. id1 and id2 are masked for
426 * correct size, because it is way too simple to pass ID
427 * larger than 11 bits unintentionally. It then leads to all
428 * kind of extremely weird errors while excessive ID bits
429 * overflow into flags. This tends to be extremely time
430 * consuming to debug.
431 */
432 lfssa[nr].type_id1_conf_id2 =
433 (id_list_mode << FDCAN_SFT_SHIFT)
434 | (action << FDCAN_SFEC_SHIFT)
436 | ((id2 & FDCAN_SFID2_MASK) << FDCAN_SFID2_SHIFT);
437
438 return;
439}
440
441/** Configure filter rule for extended ID frames.
442 *
443 * Sets up filter rule for frames having extended ID. Each FDCAN block can
444 * have its own set of filtering rules. It is only possible to configure as
445 * many filters as was configured previously using @ref fdcan_init_filter.
446 *
447 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
448 * @param [in] nr number of filter to be configured
449 * @param [in] id_list_mode mode in which id1 and id2 are used to match the rule.
450 * See @ref fdcan_eft.
451 * @param [in] id1 extended ID for matching. Used as exact value, lower bound or bit
452 * pattern depending on matching mode selected
453 * @param [in] id2 extended ID or bitmask. Used as exact value, upper bound or bit mask
454 * depending on matching mode selected
455 * @param [in] action Action performed if filtering rule matches frame ID.
456 * See @ref fdcan_efec.
457 */
458void fdcan_set_ext_filter(uint32_t canport, uint32_t nr,
459 uint8_t id_list_mode, uint32_t id1, uint32_t id2,
460 uint8_t action)
461{
462 struct fdcan_extended_filter *lfesa = fdcan_get_flesa_addr(canport);
463
464 lfesa[nr].conf_id1 =
465 (action << FDCAN_EFEC_SHIFT)
466 | ((id1 & FDCAN_EFID1_MASK) << FDCAN_EFID1_SHIFT);
467
468 lfesa[nr].type_id2 =
469 (id_list_mode << FDCAN_EFT_SHIFT)
470 | ((id2 & FDCAN_EFID2_MASK) << FDCAN_EFID2_SHIFT);
471}
472
473/** Transmit Message using FDCAN
474 *
475 * @param [in] canport CAN block register base. See @ref fdcan_block.
476 * @param [in] id Message ID
477 * @param [in] ext Extended message ID
478 * @param [in] rtr Request transmit
479 * @param [in] fdcan_fmt Use FDCAN format
480 * @param [in] btr_switch Switch bitrate for data portion of frame
481 * @param [in] length Message payload length. Must be valid CAN or FDCAN frame length
482 * @param [in] data Message payload data
483 * @returns int 0, 1 or 2 on success and depending on which outgoing mailbox got
484 * selected. Otherwise returns error code. For error codes, see @ref fdcan_error.
485 */
486int fdcan_transmit(uint32_t canport, uint32_t id, bool ext, bool rtr,
487 bool fdcan_fmt, bool btr_switch, uint8_t length, const uint8_t *data)
488{
489 int mailbox;
490 uint32_t dlc, flags = 0;
491
492 mailbox = fdcan_get_free_txbuf(canport);
493
494 if (mailbox == FDCAN_E_BUSY) {
495 return mailbox;
496 }
497
498 struct fdcan_tx_buffer_element *tx_buffer = fdcan_get_txbuf_addr(canport, mailbox);
499
500 /* Early check: if FDCAN message lentgh is > 8, it must be
501 * a multiple of 4 *and* fdcan format must be enabled.
502 */
503 dlc = fdcan_length_to_dlc(length);
504
505 if (dlc == 0xFF) {
506 return FDCAN_E_INVALID;
507 }
508
509 if (ext) {
512 } else {
513 tx_buffer->identifier_flags =
515 }
516
517 if (rtr) {
518 tx_buffer->identifier_flags |= FDCAN_FIFO_RTR;
519 }
520
521 if (fdcan_fmt) {
522 flags |= FDCAN_FIFO_FDF;
523 }
524
525 if (btr_switch) {
526 flags |= FDCAN_FIFO_BRS;
527 }
528
529 tx_buffer->evt_fmt_dlc_res =
530 (dlc << FDCAN_FIFO_DLC_SHIFT) | flags;
531
532 for (int q = 0; q < length; q += 4) {
533 tx_buffer->data[q / 4] = *((uint32_t *) &data[q]);
534 }
535
536 FDCAN_TXBAR(canport) |= 1 << mailbox;
537
538 return mailbox;
539}
540
541/** Receive Message from FDCAN FIFO
542 *
543 * Reads one message from receive FIFO. Returns message ID, type of ID, message length
544 * and message payload. It is mandatory to provide valid pointers to suitably sized buffers
545 * for these outputs. Additionally, it is optinally possible to provide non-zero pointer to
546 * obtain filter identification, request of transmission flag and message timestamp.
547 * If pointers provided for optional outputs are NULL, then no information is returned
548 * for given pointer.
549 *
550 * @param [in] canport FDCAN block base address. See @ref fdcan_block
551 * @param [in] fifo_id FIFO id.
552 * @param [in] release Release the FIFO automatically after copying data out
553 * @param [out] id Returned message ID. Mandatory.
554 * @param [out] ext Returned type of the message ID (true if extended). Mandatory.
555 * @param [out] rtr Returnes flag if request of transmission was requested. Optional.
556 * @param [out] fmi Returned ID of the filter which matched this frame. Optional.
557 * @param [out] length Length of message payload in bytes. Mandatory.
558 * @param [out] data Buffer for storage of message payload data. Mandatory.
559 * @param [out] timestamp Returned timestamp of received frame. Optional.
560 * @returns Operation error status. See @ref fdcan_error.
561 */
562int fdcan_receive(uint32_t canport, uint8_t fifo_id, bool release, uint32_t *id,
563 bool *ext, bool *rtr, uint8_t *fmi, uint8_t *length,
564 uint8_t *data, uint16_t *timestamp)
565{
566 unsigned pending_frames, get_index, dlc, len;
567
568 fdcan_get_fill_rxfifo(canport, fifo_id, &get_index, &pending_frames);
569
570 if (pending_frames == 0) {
571 return FDCAN_E_NOTAVAIL;
572 }
573
574 const struct fdcan_rx_fifo_element *fifo = fdcan_get_rxfifo_addr(canport,
575 fifo_id, get_index);
576
579
580 len = fdcan_dlc_to_length(dlc);
581
582 *length = len;
584 *ext = true;
587 } else {
588 *ext = false;
591 }
592
593 if (timestamp) {
594 *timestamp = (uint16_t) (fifo->filt_fmt_dlc_ts >> FDCAN_FIFO_RXTS_SHIFT)
596 }
597
598 if (fmi) {
599 *fmi = (uint8_t) (fifo->filt_fmt_dlc_ts >> FDCAN_FIFO_MM_SHIFT)
601 }
602
603 if (rtr) {
604 *rtr = ((fifo->identifier_flags & FDCAN_FIFO_RTR) == FDCAN_FIFO_RTR);
605 }
606
607 for (unsigned int q = 0; q < len; q += 4) {
608 *((uint32_t *) &data[q]) = fifo->data[q / 4];
609 }
610
611 if (release) {
612 FDCAN_RXFIA(canport, fifo_id) = get_index << FDCAN_RXFIFO_AI_SHIFT;
613 }
614
615 return FDCAN_E_OK;
616}
617
618/** Release receive oldest FIFO entry.
619 *
620 * This function will mask oldest entry in FIFO as released making
621 * space for another received frame. This function can be used if
622 * fdcan_receive was called using release = false. If used in other
623 * case, then messages can get lost.
624 *
625 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
626 * @param [in] fifo_id ID of FIFO where release should be performed (0 or 1)
627 */
628void fdcan_release_fifo(uint32_t canport, uint8_t fifo_id)
629{
630 unsigned pending_frames, get_index;
631
632 get_index = (FDCAN_RXFIS(canport, fifo_id) >> FDCAN_RXFIFO_GI_SHIFT)
634
635 pending_frames = (FDCAN_RXFIS(canport, fifo_id) >> FDCAN_RXFIFO_FL_SHIFT)
637
638 if (pending_frames) {
639 FDCAN_RXFIA(canport, fifo_id) |= get_index << FDCAN_RXFIFO_AI_SHIFT;
640 }
641}
642
643/** Enable IRQ from FDCAN block.
644 *
645 * This routine configures FDCAN to enable certain IRQ.
646 * Each FDCAN block supports two IRQs.
647 *
648 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
649 * @param [in] irq number of IRQ to be enabled (currently 0 or 1)
650 */
651void fdcan_enable_irq(uint32_t canport, uint32_t irq)
652{
653 FDCAN_ILE(canport) |= irq & (FDCAN_ILE_INT0 | FDCAN_ILE_INT1);
654}
655
656/** Disable IRQ from FDCAN block.
657 *
658 * This routine configures FDCAN to disable certain IRQ.
659 * Each FDCAN block supports two IRQs.
660 *
661 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
662 * @param [in] irq number of IRQ to be enabled (currently 0 or 1)
663 */
664void fdcan_disable_irq(uint32_t canport, uint32_t irq)
665{
666 FDCAN_ILE(canport) &= ~(irq & (FDCAN_ILE_INT0 | FDCAN_ILE_INT1));
667}
668
669/** Check if there is free transmit buffer.
670 *
671 * @param [in] canport FDCAN port. See @ref fdcan_block.
672 * @returns true if there is at least one free transmit buffer for new message
673 * to be sent, false otherwise.
674 */
675bool fdcan_available_tx(uint32_t canport)
676{
677 return (fdcan_get_free_txbuf(canport) != FDCAN_E_BUSY);
678}
679
680/** Tell if there is message waiting in receive FIFO.
681 *
682 * @param [in] canport FDCAN port. See @ref fdcan_block.
683 * @param [in] fifo Rx FIFO number, 0 or 1
684 * @returns true if there is at least one message waiting in given receive FIFO,
685 * false otherwise.
686 */
687bool fdcan_available_rx(uint32_t canport, uint8_t fifo)
688{
689 unsigned pending_frames;
690
691 pending_frames = (FDCAN_RXFIS(canport, fifo) >> FDCAN_RXFIFO_FL_SHIFT)
693
694 return (pending_frames != 0);
695}
696
697/**@}*/
698
699
struct fdcan_tx_buffer_element * fdcan_get_txbuf_addr(uint32_t canport, unsigned element_id)
Returns a pointer to an TX FIFO element in message RAM.
Definition: fdcan_common.c:178
uint8_t fdcan_dlc_to_length(uint32_t dlc)
Converts DLC value into frame payload length.
Definition: fdcan_common.c:221
int fdcan_cccr_init_cfg(uint32_t canport, bool set, uint32_t timeout)
Routine implementing FDCAN_CCCR's INIT bit manipulation.
Definition: fdcan_common.c:41
struct fdcan_standard_filter * fdcan_get_flssa_addr(uint32_t canport)
Returns standard filter start address in message RAM.
Definition: fdcan_common.c:124
struct fdcan_rx_fifo_element * fdcan_get_rxfifo_addr(uint32_t canport, unsigned fifo_id, unsigned element_id)
Returns a pointer to an RX FIFO element in message RAM.
Definition: fdcan_common.c:150
static int fdcan_get_free_txbuf(uint32_t canport)
Return ID of next free Tx buffer.
Definition: fdcan_common.c:85
static void fdcan_get_fill_rxfifo(uint32_t canport, uint8_t fifo_id, unsigned *get_index, unsigned *pending_frames)
Returns fill state and next available get index from receive FIFO.
Definition: fdcan_common.c:109
struct fdcan_tx_event_element * fdcan_get_txevt_addr(uint32_t canport)
Returns transmit event start address in message RAM.
Definition: fdcan_common.c:165
struct fdcan_extended_filter * fdcan_get_flesa_addr(uint32_t canport)
Returns extended filter start address in message RAM.
Definition: fdcan_common.c:136
uint32_t fdcan_length_to_dlc(uint8_t length)
Converts frame length to DLC value.
Definition: fdcan_common.c:197
#define FDCAN_CCCR_MON
Definition: fdcan.h:156
#define FDCAN_CCCR_FDOE
Definition: fdcan.h:159
#define FDCAN_CCCR_CCE
Definition: fdcan.h:152
#define FDCAN_CCCR_DAR
Definition: fdcan.h:157
#define FDCAN_CCCR_TEST
Definition: fdcan.h:158
#define FDCAN_CCCR_BRSE
Definition: fdcan.h:160
#define FDCAN_CCCR_INIT
Definition: fdcan.h:151
#define FDCAN_RXFIFO_FL_MASK
Definition: g4/fdcan.h:84
#define FDCAN_LFSSA_OFFSET(can_base)
Definition: g4/fdcan.h:113
#define FDCAN_DBTP_DTSEG1_SHIFT
DTSEG1[4:0]: Data time segment before sample point.
Definition: fdcan.h:124
#define FDCAN_TXBRP(can_base)
Definition: g4/fdcan.h:52
#define FDCAN_TXBAR(can_base)
Definition: g4/fdcan.h:53
#define FDCAN_SFID1_MASK
Definition: fdcan.h:576
#define FDCAN_TXEVT_OFFSET(can_base)
Definition: g4/fdcan.h:121
#define CAN_MSG_BASE
Definition: g4/fdcan.h:42
#define FDCAN_SFEC_SHIFT
Definition: fdcan.h:539
#define FDCAN_NBTP_NTSEG1_SHIFT
NTSEG1[7:0]: Nominal timing segment before sample point length.
Definition: fdcan.h:183
#define FDCAN_FIFO_RXTS_SHIFT
Definition: fdcan.h:724
#define FDCAN_FIFO_EID_SHIFT
Definition: fdcan.h:708
#define FDCAN_RXFIFO_GI_MASK
Definition: g4/fdcan.h:85
#define FDCAN_TEST(can_base)
Definition: fdcan.h:49
#define FDCAN_FIFO_SID_SHIFT
Definition: fdcan.h:711
#define FDCAN_TXBUF_OFFSET(can_base)
Definition: g4/fdcan.h:123
#define FDCAN_DBTP_DSJW_SHIFT
DSJW[3:0]: Synchronization jump width.
Definition: fdcan.h:116
#define FDCAN_EFID2_MASK
Definition: fdcan.h:654
#define FDCAN_FIFO_EID_MASK
Definition: fdcan.h:709
#define FDCAN_EFID1_SHIFT
Definition: fdcan.h:626
#define FDCAN_DBTP_DBRP_SHIFT
DBRP[4:0]: Data bit rate prescaler.
Definition: fdcan.h:128
#define FDCAN_FIFO_MM_SHIFT
Definition: fdcan.h:717
#define FDCAN_NBTP(can_base)
Definition: fdcan.h:52
#define FDCAN_RXFIFO_AI_SHIFT
Rx FIFOs acknowledge index.
Definition: fdcan.h:389
#define FDCAN_DBTP(can_base)
Definition: fdcan.h:48
#define FDCAN_DBTP_DTSEG2_SHIFT
DTSEG2[3:0]: Data time segment after sample point.
Definition: fdcan.h:120
#define FDCAN_SFID1_SHIFT
Definition: fdcan.h:575
#define FDCAN_ILE_INT0
Definition: fdcan.h:338
#define FDCAN_FIFO_MM_MASK
Definition: fdcan.h:718
#define FDCAN_FIFO_DLC_SHIFT
Definition: fdcan.h:714
#define FDCAN_RXFIA(can_base, fifo_id)
Generic access to Rx FIFO acknowledge registers.
Definition: fdcan.h:81
#define FDCAN_NBTP_NTSEG2_SHIFT
NTSEG2[6:0]: Nominal timing segment after sample point length.
Definition: fdcan.h:179
#define FDCAN_SFID2_MASK
Definition: fdcan.h:579
#define FDCAN_RXFIFO_OFFSET(can_base, fifo_id)
Definition: g4/fdcan.h:118
#define FDCAN_NBTP_NBRP_SHIFT
NBRP[8:0]: Norminal timing bit rate prescaler.
Definition: fdcan.h:187
#define FDCAN_EFT_SHIFT
Definition: fdcan.h:629
#define FDCAN_ILE(can_base)
Definition: fdcan.h:63
#define FDCAN_TXBC_TFQM
Definition: fdcan.h:414
#define FDCAN_LFESA_OFFSET(can_base)
Definition: g4/fdcan.h:114
#define FDCAN_FIFO_DLC_MASK
Definition: fdcan.h:715
#define FDCAN_RXFIFO_GI_SHIFT
Get index of Rx FIFOs.
Definition: fdcan.h:365
#define FDCAN_ILE_INT1
Definition: fdcan.h:339
#define FDCAN_FIFO_RXTS_MASK
Definition: fdcan.h:725
#define FDCAN_EFEC_SHIFT
Definition: fdcan.h:592
#define FDCAN_RXFIS(can_base, fifo_id)
Generic access to Rx FIFO status registers.
Definition: fdcan.h:70
#define FDCAN_NBTP_NSJW_SHIFT
NSJW[6:0]: Norminal timing resynchronization jumb width.
Definition: fdcan.h:191
#define FDCAN_TEST_LBCK
Definition: fdcan.h:133
#define FDCAN_TXBC(can_base)
Definition: fdcan.h:87
#define FDCAN_SFID2_SHIFT
Definition: fdcan.h:578
#define FDCAN_EFID1_MASK
Definition: fdcan.h:627
#define FDCAN_FIFO_SID_MASK
Definition: fdcan.h:712
#define FDCAN_CCCR(can_base)
Definition: fdcan.h:51
#define FDCAN_SFT_SHIFT
Definition: fdcan.h:517
#define FDCAN_RXFIFO_FL_SHIFT
Fill level of Rx FIFOs.
Definition: fdcan.h:362
#define FDCAN_EFID2_SHIFT
Definition: fdcan.h:653
#define FDCAN_E_BUSY
Device is busy: Transmit buffer is full, unable to queue additional message or device is outside of I...
Definition: fdcan.h:746
#define FDCAN_E_TIMEOUT
Timeout waiting for FDCAN block to accept INIT bit change.
Definition: fdcan.h:739
#define FDCAN_E_OK
No error.
Definition: fdcan.h:733
#define FDCAN_E_NOTAVAIL
Receive buffer is empty, unable to read any new message.
Definition: fdcan.h:749
#define FDCAN_E_INVALID
Value provided was invalid (FIFO index, FDCAN block base address, length, etc.)
Definition: fdcan.h:742
#define FDCAN_FIFO_RTR
Definition: fdcan.h:702
#define FDCAN_FIFO_FDF
Definition: fdcan.h:704
#define FDCAN_FIFO_BRS
Definition: fdcan.h:705
#define FDCAN_FIFO_XTD
Definition: fdcan.h:701
int fdcan_init(uint32_t canport, uint32_t timeout)
Put FDCAN block into INIT mode for setup.
Definition: fdcan_common.c:260
void fdcan_set_fifo_locked_mode(uint32_t canport, bool locked)
Configure FDCAN FIFO lock mode.
Definition: fdcan.c:177
bool fdcan_available_tx(uint32_t canport)
Check if there is free transmit buffer.
Definition: fdcan_common.c:675
void fdcan_disable_irq(uint32_t canport, uint32_t irq)
Disable IRQ from FDCAN block.
Definition: fdcan_common.c:664
void fdcan_release_fifo(uint32_t canport, uint8_t fifo_id)
Release receive oldest FIFO entry.
Definition: fdcan_common.c:628
void fdcan_set_std_filter(uint32_t canport, uint32_t nr, uint8_t id_list_mode, uint32_t id1, uint32_t id2, uint8_t action)
Configure filter rule for standard ID frames.
Definition: fdcan_common.c:418
void fdcan_set_test(uint32_t canport, bool testing, bool loopback)
Set FDCAN block testing features.
Definition: fdcan_common.c:374
int fdcan_receive(uint32_t canport, uint8_t fifo_id, bool release, uint32_t *id, bool *ext, bool *rtr, uint8_t *fmi, uint8_t *length, uint8_t *data, uint16_t *timestamp)
Receive Message from FDCAN FIFO.
Definition: fdcan_common.c:562
void fdcan_set_fdcan(uint32_t canport, bool brs_enable, bool fd_op_enable, uint32_t f_sjw, uint32_t f_ts1, uint32_t f_ts2, uint32_t f_br_presc)
Set FDCAN block parameters for FDCAN transmission.
Definition: fdcan_common.c:343
bool fdcan_available_rx(uint32_t canport, uint8_t fifo)
Tell if there is message waiting in receive FIFO.
Definition: fdcan_common.c:687
void fdcan_enable_irq(uint32_t canport, uint32_t irq)
Enable IRQ from FDCAN block.
Definition: fdcan_common.c:651
int fdcan_get_init_state(uint32_t canport)
Return current FDCAN block operation state.
Definition: fdcan_common.c:396
unsigned fdcan_get_fifo_element_size(uint32_t canport, unsigned fifo_id)
Returns actual size of FIFO entry in FIFO for given CAN port and FIFO.
Definition: fdcan.c:57
void fdcan_set_ext_filter(uint32_t canport, uint32_t nr, uint8_t id_list_mode, uint32_t id1, uint32_t id2, uint8_t action)
Configure filter rule for extended ID frames.
Definition: fdcan_common.c:458
int fdcan_transmit(uint32_t canport, uint32_t id, bool ext, bool rtr, bool fdcan_fmt, bool btr_switch, uint8_t length, const uint8_t *data)
Transmit Message using FDCAN.
Definition: fdcan_common.c:486
unsigned fdcan_get_txbuf_element_size(uint32_t canport)
Returns actual size of transmit entry in transmit queue/FIFO for given CAN port.
Definition: fdcan.c:75
void fdcan_set_can(uint32_t canport, bool auto_retry_disable, bool rx_fifo_locked, bool tx_queue_mode, bool silent, uint32_t n_sjw, uint32_t n_ts1, uint32_t n_ts2, uint32_t n_br_presc)
Set essential FDCAN block parameters for plain CAN operation.
Definition: fdcan_common.c:296
#define FDCAN_TXBRP_TRP2
Definition: fdcan.h:432
#define FDCAN_TXBRP_TRP1
Definition: fdcan.h:431
#define FDCAN_TXBRP_TRP0
Definition: fdcan.h:430
Structure describing extended ID filters.
Definition: fdcan.h:585
uint32_t type_id2
Aggregate of filter type and extended ID or mask.
Definition: fdcan.h:589
uint32_t conf_id1
Aggregate of filter action and extended ID.
Definition: fdcan.h:587
Structure describing receive FIFO element.
Definition: fdcan.h:661
uint32_t filt_fmt_dlc_ts
Aggregate of filter match ID, transfer format, DLC and timestamp.
Definition: fdcan.h:665
uint32_t identifier_flags
Aggregate of message identifier and flags.
Definition: fdcan.h:663
uint32_t data[64/sizeof(uint32_t)]
Message payload data.
Definition: fdcan.h:667
Structure describing standard ID filter.
Definition: fdcan.h:512
uint32_t type_id1_conf_id2
Aggregate of filter type, filter action and two IDs
Definition: fdcan.h:514
Structure describing transmit buffer element.
Definition: fdcan.h:687
uint32_t data[64/sizeof(uint32_t)]
Message payload data.
Definition: fdcan.h:694
uint32_t evt_fmt_dlc_res
Aggregate of event ID, transfer format and DLC.
Definition: fdcan.h:692
uint32_t identifier_flags
Aggregate of message identifier and flags.
Definition: fdcan.h:689
Structure describing transmit event element.
Definition: fdcan.h:674