rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
stm32_can.cpp
Go to the documentation of this file.
1/**
2 * @file stm32_common_can.cpp
3 * @brief Low level common STM32 code
4 *
5 * @date Mar 28, 2019
6 * @author Andrey Belomutskiy, (c) 2012-2020
7 */
8
9#include "pch.h"
10
11#if EFI_CAN_SUPPORT
12
13
14// Values below calculated with http://www.bittiming.can-wiki.info/
15// Pick ST micro bxCAN
16// Clock rate of 42mhz for f4, 54mhz for f7, 80mhz for h7
17
18// CAN_BTR_SJW(n), where n = SJW - 1
19// CAN_BTR_BRP(n), where n = prescaler - 1
20// CAN_BTR_TS1(n), where n = Seg 1 - 1
21// CAN_BTR_TS2(n), where n = Seg 2 - 1
22
23#ifdef STM32F4XX
24#define CAN_BTR_33 (CAN_BTR_SJW(0) | CAN_BTR_BRP(139)| CAN_BTR_TS1(6) | CAN_BTR_TS2(0)) // sampling point at 88.9%
25// These have an 85.7% sample point
26#define CAN_BTR_50 (CAN_BTR_SJW(0) | CAN_BTR_BRP(59) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
27#define CAN_BTR_83 (CAN_BTR_SJW(0) | CAN_BTR_BRP(35) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
28#define CAN_BTR_100 (CAN_BTR_SJW(0) | CAN_BTR_BRP(29) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
29#define CAN_BTR_125 (CAN_BTR_SJW(0) | CAN_BTR_BRP(23) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
30#define CAN_BTR_250 (CAN_BTR_SJW(0) | CAN_BTR_BRP(11) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
31#define CAN_BTR_500 (CAN_BTR_SJW(0) | CAN_BTR_BRP(5) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
32#define CAN_BTR_1k0 (CAN_BTR_SJW(0) | CAN_BTR_BRP(2) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
33#elif defined(STM32F7XX)
34#define CAN_BTR_33 (CAN_BTR_SJW(0) | CAN_BTR_BRP(179)| CAN_BTR_TS1(6) | CAN_BTR_TS2(0)) // sampling point at 88.9%
35// These have an 88.9% sample point
36#define CAN_BTR_50 (CAN_BTR_SJW(0) | CAN_BTR_BRP(59) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
37#define CAN_BTR_83 (CAN_BTR_SJW(0) | CAN_BTR_BRP(35) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
38#define CAN_BTR_100 (CAN_BTR_SJW(0) | CAN_BTR_BRP(29) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
39#define CAN_BTR_125 (CAN_BTR_SJW(0) | CAN_BTR_BRP(23) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
40#define CAN_BTR_250 (CAN_BTR_SJW(0) | CAN_BTR_BRP(11) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
41#define CAN_BTR_500 (CAN_BTR_SJW(0) | CAN_BTR_BRP(5) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
42#define CAN_BTR_1k0 (CAN_BTR_SJW(0) | CAN_BTR_BRP(2) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
43#elif defined(STM32H7XX)
44// FDCAN driver has different bit timing registers (yes, different format)
45// for the arbitration and data phases
46
47static_assert(STM32_FDCANCLK == 80'000'000, "CANFD baudrates calculated for 80MHz clock!");
48
49// 87.5% sample point
50#define CAN_NBTP_33 0x06950c01
51#define CAN_DBTP_33 0x00950D03 // TODO: validate!
52
53// 66% sample point, not ideal but best we can do without changing CAN clock
54#define CAN_NBTP_50 0x061F1F10
55#define CAN_DBTP_50 0x001F2003
56
57// 86.7% sample point
58#define CAN_NBTP_83 0x061F1803
59#define CAN_DBTP_83 0x001F1833
60
61// 88.0% sample point
62#define CAN_NBTP_100 0x061F1402
63#define CAN_DBTP_100 0x001F1423
64
65// 85.0% sample point
66#define CAN_NBTP_125 0x061F0F02
67#define CAN_DBTP_125 0x001F0F23
68
69// These have an 87.5% sample point
70#define CAN_NBTP_250 0x06130C01
71#define CAN_DBTP_250 0x00130C13
72
73#define CAN_NBTP_500 0x06090C01
74#define CAN_DBTP_500 0x00090C13
75
76#define CAN_NBTP_1k0 0x06040C01
77#define CAN_DBTP_1k0 0x00040C13
78#else
79#error Please define CAN BTR settings for your MCU!
80#endif
81
82/*
83 * 500KBaud
84 * automatic wakeup
85 * automatic recover from abort mode
86 * See section 22.7.7 on the STM32 reference manual.
87 *
88 * 29 bit would be CAN_TI0R_EXID (?) but we do not mention it here
89 * CAN_TI0R_STID "Standard Identifier or Extended Identifier"? not mentioned as well
90 */
91#if defined(STM32F4XX) || defined(STM32F7XX)
92
93#define STM32FxMCR (CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP)
94
95static const CANConfig canConfig33 = {
96 .mcr = STM32FxMCR,
97 .btr = CAN_BTR_33
98};
99
100static const CANConfig canConfig50 = {
101 .mcr = STM32FxMCR,
102 .btr = CAN_BTR_50
103};
104
105static const CANConfig canConfig83 = {
106 .mcr = STM32FxMCR,
107 .btr = CAN_BTR_83
108};
109
110static const CANConfig canConfig100 = {
111 .mcr = STM32FxMCR,
112 .btr = CAN_BTR_100
113};
114
115static const CANConfig canConfig125 = {
116 .mcr = STM32FxMCR,
117 .btr = CAN_BTR_125
118};
119
120static const CANConfig canConfig250 = {
121 .mcr = STM32FxMCR,
122 .btr = CAN_BTR_250
123};
124
125static const CANConfig canConfig500 = {
126 .mcr = STM32FxMCR,
127 .btr = CAN_BTR_500
128};
129
130static const CANConfig canConfig1000 = {
131 .mcr = STM32FxMCR,
132 .btr = CAN_BTR_1k0
133};
134
135#elif defined(STM32H7XX)
136static const CANConfig canConfig33 = {
137 .op_mode = OPMODE_CAN,
138 .NBTP = CAN_NBTP_33,
139 .DBTP = CAN_DBTP_33,
140 .TDCR = 0,
141 .CCCR = 0,
142 .TEST = 0,
143 .RXGFC = 0,
144};
145
146static const CANConfig canConfig50 = {
147 .op_mode = OPMODE_CAN,
148 .NBTP = CAN_NBTP_50,
149 .DBTP = CAN_DBTP_50,
150 .TDCR = 0,
151 .CCCR = 0,
152 .TEST = 0,
153 .RXGFC = 0,
154};
155
156static const CANConfig canConfig83 = {
157 .op_mode = OPMODE_CAN,
158 .NBTP = CAN_NBTP_83,
159 .DBTP = CAN_DBTP_83,
160 .TDCR = 0,
161 .CCCR = 0,
162 .TEST = 0,
163 .RXGFC = 0,
164};
165
166static const CANConfig canConfig100 = {
167 .op_mode = OPMODE_CAN,
168 .NBTP = CAN_NBTP_100,
169 .DBTP = CAN_DBTP_100,
170 .TDCR = 0,
171 .CCCR = 0,
172 .TEST = 0,
173 .RXGFC = 0,
174};
175
176static const CANConfig canConfig125 = {
177 .op_mode = OPMODE_CAN,
178 .NBTP = CAN_NBTP_125,
179 .DBTP = CAN_DBTP_125,
180 .TDCR = 0,
181 .CCCR = 0,
182 .TEST = 0,
183 .RXGFC = 0,
184};
185
186static const CANConfig canConfig250 = {
187 .op_mode = OPMODE_CAN,
188 .NBTP = CAN_NBTP_250,
189 .DBTP = CAN_DBTP_250,
190 .TDCR = 0,
191 .CCCR = 0,
192 .TEST = 0,
193 .RXGFC = 0,
194};
195
196static const CANConfig canConfig500 = {
197 .op_mode = OPMODE_CAN,
198 .NBTP = CAN_NBTP_500,
199 .DBTP = CAN_DBTP_500,
200 .TDCR = 0,
201 .CCCR = 0,
202 .TEST = 0,
203 .RXGFC = 0,
204};
205
206static const CANConfig canConfig1000 = {
207 .op_mode = OPMODE_CAN,
208 .NBTP = CAN_NBTP_1k0,
209 .DBTP = CAN_DBTP_1k0,
210 .TDCR = 0,
211 .CCCR = 0,
212 .TEST = 0,
213 .RXGFC = 0,
214};
215#endif
216
218 return pin == Gpio::A11 || pin == Gpio::B8 || pin == Gpio::D0;
219}
220
222 return pin == Gpio::A12 || pin == Gpio::B9 || pin == Gpio::D1;
223}
224
226 return pin == Gpio::B5 || pin == Gpio::B12;
227}
228
230 return pin == Gpio::B6 || pin == Gpio::B13;
231}
232
233#if STM32_CAN_USE_CAN3
234// this is about STM32F413
236 return pin == Gpio::A8 || pin == Gpio::B3;
237}
238
240 return pin == Gpio::A15 || pin == Gpio::B4;
241}
242#elif STM32_CAN_USE_FDCAN3
243// STM32H723
244// See different AF for PD12/PD13 vs PF6/PF7 and PG9/PG10
245static bool isValidCan3RxPin(brain_pin_e pin) {
246 return pin == Gpio::D12 /* || pin == Gpio::F6 || pin == Gpio::G10 */;
247}
248
249static bool isValidCan3TxPin(brain_pin_e pin) {
250 return pin == Gpio::D13 /* || pin == Gpio::F7 || pin == Gpio::G9 */;
251}
252#else
254 return false;
255}
256
257static __attribute__((unused)) bool isValidCan3TxPin(brain_pin_e) {
258 return false;
259}
260#endif
261
263 // Note: different AF for CAN3 and CANFD3, so check for CAN1/CANFD1 and CAN2/CANFD2 only
264 // see startCanPins()
265 return isValidCan1TxPin(pin) || isValidCan2TxPin(pin) /* || isValidCan3TxPin(pin) */;
266}
267
269 return isValidCan1RxPin(pin) || isValidCan2RxPin(pin) /* || isValidCan3RxPin(pin) */;
270}
271
272CANDriver* detectCanDevice(brain_pin_e pinRx, brain_pin_e pinTx) {
273 if (pinRx == Gpio::Unassigned || pinTx == Gpio::Unassigned) {
274 return nullptr;
275 }
276#if STM32_CAN_USE_CAN1 || STM32_CAN_USE_FDCAN1
277 if (isValidCan1RxPin(pinRx) && isValidCan1TxPin(pinTx))
278 return &CAND1;
279#endif
280#if STM32_CAN_USE_CAN2 || STM32_CAN_USE_FDCAN2
281 if (isValidCan2RxPin(pinRx) && isValidCan2TxPin(pinTx))
282 return &CAND2;
283#endif
284#if STM32_CAN_USE_CAN3 || STM32_CAN_USE_FDCAN3
285 if (isValidCan3RxPin(pinRx) && isValidCan3TxPin(pinTx))
286 return &CAND3;
287#endif
288 criticalError("invalid CAN pins tx %s and rx %s", hwPortname(pinTx), hwPortname(pinRx));
289 return nullptr;
290}
291
293 switch (rate) {
294 case B33KBPS:
295 return &canConfig33;
296 case B50KBPS:
297 return &canConfig50;
298 case B83KBPS:
299 return &canConfig83;
300 case B100KBPS:
301 return &canConfig100;
302 case B125KBPS:
303 return &canConfig125;
304 case B250KBPS:
305 return &canConfig250;
306 case B1MBPS:
307 return &canConfig1000;
308 case B500KBPS:
309 default:
310 return &canConfig500;
311 }
312}
313
314void canHwInfo(CANDriver* cand) {
315 if (cand == NULL)
316 return;
317
318 if (cand->state != CAN_READY) {
319 efiPrintf("Interface is not ready");
320 return;
321 }
322
323#if STM32_CAN_USE_CAN1 || STM32_CAN_USE_CAN2
324 if (cand->can == NULL) {
325 efiPrintf("No device assigned!");
326 }
327
328 uint32_t esr = cand->can->ESR;
329 efiPrintf("Receive error counter %ld", (esr >> 24) & 0xff);
330 efiPrintf("Transmit error counter %ld", (esr >> 16) & 0xff);
331 efiPrintf("Last error %ld", (esr >> 4) & 0x7);
332 efiPrintf("Flags: %s %s %s",
333 (esr & 0x4) ? "BOFF" : "",
334 (esr & 0x2) ? "EPVF" : "",
335 (esr & 0x1) ? "EWGF" : "");
336#endif
337}
338
339#endif /* EFI_CAN_SUPPORT */
uint32_t rate
Definition bluetooth.cpp:39
typedef __attribute__
Ignition Mode.
@ Unassigned
const char * hwPortname(brain_pin_e brainPin)
can_baudrate_e
esr("WBO: ESR", SensorCategory.SENSOR_INPUTS, FieldType.INT16, 1948, 1.0, 0.0, 10000.0, "ohm")
brain_pin_e pin
Definition stm32_adc.cpp:15
static bool isValidCan2RxPin(brain_pin_e pin)
CANDriver * detectCanDevice(brain_pin_e pinRx, brain_pin_e pinTx)
static const CANConfig canConfig500
bool isValidCanRxPin(brain_pin_e pin)
static const CANConfig canConfig125
static const CANConfig canConfig1000
static const CANConfig canConfig83
static const CANConfig canConfig50
static const CANConfig canConfig250
static bool isValidCan3RxPin(brain_pin_e pin)
static const CANConfig canConfig100
static bool isValidCan1RxPin(brain_pin_e pin)
bool isValidCanTxPin(brain_pin_e pin)
static bool isValidCan2TxPin(brain_pin_e pin)
const CANConfig * findCanConfig(can_baudrate_e rate)
static bool isValidCan3TxPin(brain_pin_e pin)
static const CANConfig canConfig33
Definition stm32_can.cpp:95
void canHwInfo(CANDriver *cand)
static bool isValidCan1TxPin(brain_pin_e pin)