libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
fdcan.c
Go to the documentation of this file.
1/** @addtogroup fdcan_file FDCAN peripheral API
2 *
3 * @ingroup peripheral_apis
4 *
5 * @brief <b>libopencm3 STM32 FDCAN</b>
6 *
7 * @version 1.0.0
8 *
9 * @author @htmlonly &copy; @endhtmlonly 2021 Eduard Drusa <ventyl86 at netkosice dot sk>
10 *
11 * Devices can have up to three FDCAN peripherals residing in one FDCAN block. The peripherals
12 * support both CAN 2.0 A and B standard and Bosch FDCAN standard. FDCAN frame format and
13 * bitrate switching is supported. The peripheral has several filters for incoming messages that
14 * can be distributed between two FIFOs and three transmit mailboxes. For transmitted messages
15 * it is possible to opt for event notification once message is transmitted.
16 *
17 * LGPL License Terms @ref lgpl_license
18*/
19
20/*
21 * This file is part of the libopencm3 project.
22 *
23 * Copyright (C) 2021 Eduard Drusa <ventyl86 at netkosice dot sk>
24 *
25 * This library is free software: you can redistribute it and/or modify
26 * it under the terms of the GNU Lesser General Public License as published by
27 * the Free Software Foundation, either version 3 of the License, or
28 * (at your option) any later version.
29 *
30 * This library is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU Lesser General Public License for more details.
34 *
35 * You should have received a copy of the GNU Lesser General Public License
36 * along with this library. If not, see <http://www.gnu.org/licenses/>.
37 */
38
41#include <stddef.h>
42
43/* --- FD-CAN functions ----------------------------------------------------- */
44
45/** @ingroup fdcan_file */
46/**@{
47 * */
48
49/** Returns actual size of FIFO entry in FIFO for given CAN port and FIFO.
50 *
51 * Obtains value of FIFO entry length. For G4 it returns constant value as
52 * G4 has FIFO element length hardcoded.
53 * @param [in] canport FDCAN block base address. See @ref fdcan_block. Unused.
54 * @param [in] fifo_id ID of FIFO whole length is queried. Unused.
55 * @returns Length of FIFO entry length covering frame header and frame payload.
56 */
57unsigned fdcan_get_fifo_element_size(uint32_t canport, unsigned fifo_id)
58{
59 /* Silences compiler. Variables are present for API compatibility
60 * with STM32H7
61 */
62 (void) (canport);
63 (void) (fifo_id);
64 return sizeof(struct fdcan_rx_fifo_element);
65}
66
67/** Returns actual size of transmit entry in transmit queue/FIFO for given CAN port.
68 *
69 * Obtains value of entry length in transmit queue/FIFO. For G4 it returns constant value
70 * as G4 has transmit buffer entries of fixed length.
71 *
72 * @param [in] canport FDCAN block base address. See @ref fdcan_block. Unused.
73 * @returns Length of FIFO entry length covering frame header and frame payload.
74 */
75unsigned fdcan_get_txbuf_element_size(uint32_t canport)
76{
77 /* Silences compiler. Variables are present for API compatibility
78 * with STM32H7
79 */
80 (void) (canport);
81 return sizeof(struct fdcan_tx_buffer_element);
82}
83
84/** Configure amount of filters and initialize filtering block.
85 *
86 * This function allows to configure global amount of filters present.
87 * FDCAN block will only ever check as many filters as this function configures.
88 * Function will also clear all filter blocks to zero values. This function
89 * can be only called after @ref fdcan_init has already been called and
90 * @ref fdcan_start has not been called yet as registers holding filter
91 * count are write-protected unless FDCAN block is in INIT mode. It is possible
92 * to reconfigure filters (@ref fdcan_set_std_filter and @ref fdcan_set_ext_filter)
93 * after FDCAN block has already been started.
94 *
95 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
96 * @param [in] std_filt requested amount of standard ID filter rules (0-28)
97 * @param [in] ext_filt requested amount of extended ID filter rules (0-8)
98 */
99void fdcan_init_filter(uint32_t canport, uint8_t std_filt, uint8_t ext_filt)
100{
101 struct fdcan_standard_filter *lfssa = fdcan_get_flssa_addr(canport);
102 struct fdcan_extended_filter *lfesa = fdcan_get_flesa_addr(canport);
103
104 /* Only perform initialization of message RAM if there are
105 * any filters required
106 */
107 if (std_filt > 0) {
108 FDCAN_RXGFC(canport) =
110 | (std_filt << FDCAN_RXGFC_LSS_SHIFT);
111
112
113 for (int q = 0; q < FDCAN_SFT_MAX_NR; ++q) {
114 lfssa[q].type_id1_conf_id2 = 0;
115 }
116 } else {
117 /* Reset filter count to zero */
118 FDCAN_RXGFC(canport) =
120 }
121
122 if (ext_filt > 0) {
123 FDCAN_RXGFC(canport) =
125 | (ext_filt << FDCAN_RXGFC_LSE_SHIFT);
126
127 for (int q = 0; q < FDCAN_EFT_MAX_NR; ++q) {
128 lfesa[q].conf_id1 = 0;
129 lfesa[q].type_id2 = 0;
130 }
131 } else {
132 /* Reset filter count to zero */
133 FDCAN_RXGFC(canport) =
135 }
136}
137
138/** Enable FDCAN operation after FDCAN block has been set up.
139 *
140 * This function will disable FDCAN configuration effectively
141 * allowing FDCAN to sync up with the bus. After calling this function
142 * it is not possible to reconfigure amount of filter rules, yet
143 * it is possible to configure rules themselves. FDCAN block operation
144 * state can be checked using @ref fdcan_get_init_state.
145 *
146 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
147 * @param [in] timeout Amount of empty busy loops, which routine should wait for FDCAN
148 * confirming that it left INIT mode. If set to 0, function will return
149 * immediately.
150 * @returns Operation error status. See @ref fdcan_error.
151 * @note If this function returns with timeout, it usually means that
152 * FDCAN_clk is not set up properly.
153 */
154int fdcan_start(uint32_t canport, uint32_t timeout)
155{
156 /* Error here usually means, that FDCAN_clk is not set up
157 * correctly, or at all. This usually can't be seen above
158 * when INIT is set to 1, because default value for INIT is
159 * 1 as long as one has FDCAN_pclk configured properly.
160 **/
161 if (fdcan_cccr_init_cfg(canport, false, timeout) != 0) {
162 return FDCAN_E_TIMEOUT;
163 }
164
165 return FDCAN_E_OK;
166}
167
168/** Configure FDCAN FIFO lock mode
169 *
170 * This function allows to choose between locked and overewrite mode of FIFOs. In locked mode,
171 * whenever FIFO is full and new frame arrives, which would normally been stored into given
172 * FIFO, then frame is dropped. If overwrite mode is active, then most recent message in FIFO
173 * is rewritten by frame just received.
174 * @param [in] canport FDCAN block base address. See @ref fdcan_block.
175 * @param [in] locked true activates locked mode, false activates overwrite mode
176 */
177void fdcan_set_fifo_locked_mode(uint32_t canport, bool locked)
178{
179 if (locked) {
181 } else {
183 }
184}
185
186/** @} */
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_extended_filter * fdcan_get_flesa_addr(uint32_t canport)
Returns extended filter start address in message RAM.
Definition: fdcan_common.c:136
#define FDCAN_RXGFC_F1OM
Definition: g4/fdcan.h:74
#define FDCAN_RXGFC_LSE_SHIFT
LSE[3:0]: List size of extended ID filters.
Definition: g4/fdcan.h:81
#define FDCAN_RXGFC_LSS_SHIFT
LSS[4:0]: List size of standard ID filters.
Definition: g4/fdcan.h:77
#define FDCAN_RXGFC_LSS_MASK
Definition: g4/fdcan.h:78
#define FDCAN_SFT_MAX_NR
Amount of standard filters allocated in Message RAM This number may vary between devices.
Definition: g4/fdcan.h:105
#define FDCAN_RXGFC_F0OM
Definition: g4/fdcan.h:75
#define FDCAN_RXGFC_LSE_MASK
Definition: g4/fdcan.h:82
#define FDCAN_RXGFC(can_base)
Definition: g4/fdcan.h:48
#define FDCAN_EFT_MAX_NR
Amount of extended filters allocated in Message RAM This number may vary between devices.
Definition: g4/fdcan.h:111
#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
void fdcan_set_fifo_locked_mode(uint32_t canport, bool locked)
Configure FDCAN FIFO lock mode.
Definition: fdcan.c:177
int fdcan_start(uint32_t canport, uint32_t timeout)
Enable FDCAN operation after FDCAN block has been set up.
Definition: fdcan.c:154
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_init_filter(uint32_t canport, uint8_t std_filt, uint8_t ext_filt)
Configure amount of filters and initialize filtering block.
Definition: fdcan.c:99
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
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
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