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// Clock 42 MHz
25#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%
26// These have an 85.7% sample point
27#define CAN_BTR_50 (CAN_BTR_SJW(0) | CAN_BTR_BRP(59) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
28#define CAN_BTR_83 (CAN_BTR_SJW(0) | CAN_BTR_BRP(35) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
29#define CAN_BTR_100 (CAN_BTR_SJW(0) | CAN_BTR_BRP(29) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
30#define CAN_BTR_125 (CAN_BTR_SJW(0) | CAN_BTR_BRP(23) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
31#define CAN_BTR_250 (CAN_BTR_SJW(0) | CAN_BTR_BRP(11) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
32#define CAN_BTR_500 (CAN_BTR_SJW(0) | CAN_BTR_BRP(5) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
33#define CAN_BTR_666 (CAN_BTR_SJW(0) | CAN_BTR_BRP(2) | CAN_BTR_TS1(15) | CAN_BTR_TS2(3)) // sampling point 81.0%
34#define CAN_BTR_1k0 (CAN_BTR_SJW(0) | CAN_BTR_BRP(2) | CAN_BTR_TS1(10) | CAN_BTR_TS2(1))
35
36#elif defined(STM32F7XX)
37// Clock 54 MHz
38// These have an 88.9% sample point
39#define CAN_BTR_33 (CAN_BTR_SJW(0) | CAN_BTR_BRP(179)| CAN_BTR_TS1(6) | CAN_BTR_TS2(0))
40#define CAN_BTR_50 (CAN_BTR_SJW(0) | CAN_BTR_BRP(59) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
41#define CAN_BTR_83 (CAN_BTR_SJW(0) | CAN_BTR_BRP(35) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
42#define CAN_BTR_100 (CAN_BTR_SJW(0) | CAN_BTR_BRP(29) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
43#define CAN_BTR_125 (CAN_BTR_SJW(0) | CAN_BTR_BRP(23) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
44#define CAN_BTR_250 (CAN_BTR_SJW(0) | CAN_BTR_BRP(11) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
45#define CAN_BTR_500 (CAN_BTR_SJW(0) | CAN_BTR_BRP(5) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
46#define CAN_BTR_666 (CAN_BTR_SJW(0) | CAN_BTR_BRP(8) | CAN_BTR_TS1(6) | CAN_BTR_TS2(0))
47#define CAN_BTR_1k0 (CAN_BTR_SJW(0) | CAN_BTR_BRP(2) | CAN_BTR_TS1(14) | CAN_BTR_TS2(1))
48
49#elif defined(STM32H7XX)
50// FDCAN driver has different bit timing registers (yes, different format)
51// for the arbitration and data phases
52
53static_assert(STM32_FDCANCLK == 80'000'000, "CANFD baudrates calculated for 80MHz clock!");
54
55constexpr uint32_t CAN_NBTP_H7(uint32_t sjw, uint32_t prescaler, uint32_t seg1, uint32_t seg2) {
56 return ((sjw-1)<<24) | ((prescaler-1)<<16) | ((seg1-1)<<8) | (seg2-1);
57}
58constexpr uint32_t CAN_DBTP_H7(uint32_t sjw, uint32_t prescaler, uint32_t seg1, uint32_t seg2) {
59 return ((prescaler-1) << 16) | ((seg1-1) << 8) | ((seg2-1)<<4) | (sjw-1);
60}
61
62// 87.5% sample point
63#define CAN_NBTP_33 0x06950c01
64#define CAN_DBTP_33 0x00950D03 // TODO: validate!
65
66// 66% sample point, not ideal but best we can do without changing CAN clock
67#define CAN_NBTP_50 0x061F1F10
68#define CAN_DBTP_50 0x001F2003
69
70// 86.7% sample point
71#define CAN_NBTP_83 0x061F1803
72#define CAN_DBTP_83 0x001F1833
73
74// 88.0% sample point
75#define CAN_NBTP_100 0x061F1402
76#define CAN_DBTP_100 0x001F1423
77
78// 85.0% sample point
79#define CAN_NBTP_125 0x061F0F02
80#define CAN_DBTP_125 0x001F0F23
81
82// These have an 87.5% sample point
83#define CAN_NBTP_250 0x06130C01
84#define CAN_DBTP_250 0x00130C13
85
86#define CAN_NBTP_500 CAN_NBTP_H7(7, 10, 13, 2)
87#define CAN_DBTP_500 CAN_DBTP_H7(4, 10, 13, 2)
88static_assert(CAN_NBTP_500 == 0x06090C01);
89static_assert(CAN_DBTP_500 == 0x00090C13);
90
91#define CAN_NBTP_1k0 CAN_NBTP_H7(7, 5, 13, 2)
92#define CAN_DBTP_1k0 CAN_DBTP_H7(4, 5, 13, 2)
93static_assert(CAN_NBTP_1k0 == 0x06040C01);
94static_assert(CAN_DBTP_1k0 == 0x00040C13);
95
96// 86.7% sample point
97#define CAN_NBTP_666 CAN_NBTP_H7(7, 8, 12, 2)
98#define CAN_DBTP_666 CAN_DBTP_H7(4, 8, 12, 2)
99
100#else
101#error Please define CAN BTR settings for your MCU!
102#endif
103
104/*
105 * 500KBaud
106 * automatic wakeup
107 * automatic recover from abort mode
108 * See section 22.7.7 on the STM32 reference manual.
109 *
110 * 29 bit would be CAN_TI0R_EXID (?) but we do not mention it here
111 * CAN_TI0R_STID "Standard Identifier or Extended Identifier"? not mentioned as well
112 */
113#if defined(STM32F4XX) || defined(STM32F7XX)
114
115#define STM32FxMCR (CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP)
116
117static const CANConfig canConfig33 = {
118 .mcr = STM32FxMCR,
119 .btr = CAN_BTR_33
120};
121
122static const CANConfig canConfig50 = {
123 .mcr = STM32FxMCR,
124 .btr = CAN_BTR_50
125};
126
127static const CANConfig canConfig83 = {
128 .mcr = STM32FxMCR,
129 .btr = CAN_BTR_83
130};
131
132static const CANConfig canConfig100 = {
133 .mcr = STM32FxMCR,
134 .btr = CAN_BTR_100
135};
136
137static const CANConfig canConfig125 = {
138 .mcr = STM32FxMCR,
139 .btr = CAN_BTR_125
140};
141
142static const CANConfig canConfig250 = {
143 .mcr = STM32FxMCR,
144 .btr = CAN_BTR_250
145};
146
147static const CANConfig canConfig500 = {
148 .mcr = STM32FxMCR,
149 .btr = CAN_BTR_500
150};
151
152static const CANConfig canConfig666 = {
153 .mcr = STM32FxMCR,
154 .btr = CAN_BTR_666
155};
156
157static const CANConfig canConfig1000 = {
158 .mcr = STM32FxMCR,
159 .btr = CAN_BTR_1k0
160};
161
162#elif defined(STM32H7XX)
163static const CANConfig canConfig33 = {
164 .op_mode = OPMODE_CAN,
165 .NBTP = CAN_NBTP_33,
166 .DBTP = CAN_DBTP_33,
167 .TDCR = 0,
168 .CCCR = 0,
169 .TEST = 0,
170 .RXGFC = 0,
171};
172
173static const CANConfig canConfig50 = {
174 .op_mode = OPMODE_CAN,
175 .NBTP = CAN_NBTP_50,
176 .DBTP = CAN_DBTP_50,
177 .TDCR = 0,
178 .CCCR = 0,
179 .TEST = 0,
180 .RXGFC = 0,
181};
182
183static const CANConfig canConfig83 = {
184 .op_mode = OPMODE_CAN,
185 .NBTP = CAN_NBTP_83,
186 .DBTP = CAN_DBTP_83,
187 .TDCR = 0,
188 .CCCR = 0,
189 .TEST = 0,
190 .RXGFC = 0,
191};
192
193static const CANConfig canConfig100 = {
194 .op_mode = OPMODE_CAN,
195 .NBTP = CAN_NBTP_100,
196 .DBTP = CAN_DBTP_100,
197 .TDCR = 0,
198 .CCCR = 0,
199 .TEST = 0,
200 .RXGFC = 0,
201};
202
203static const CANConfig canConfig125 = {
204 .op_mode = OPMODE_CAN,
205 .NBTP = CAN_NBTP_125,
206 .DBTP = CAN_DBTP_125,
207 .TDCR = 0,
208 .CCCR = 0,
209 .TEST = 0,
210 .RXGFC = 0,
211};
212
213static const CANConfig canConfig250 = {
214 .op_mode = OPMODE_CAN,
215 .NBTP = CAN_NBTP_250,
216 .DBTP = CAN_DBTP_250,
217 .TDCR = 0,
218 .CCCR = 0,
219 .TEST = 0,
220 .RXGFC = 0,
221};
222
223static const CANConfig canConfig500 = {
224 .op_mode = OPMODE_CAN,
225 .NBTP = CAN_NBTP_500,
226 .DBTP = CAN_DBTP_500,
227 .TDCR = 0,
228 .CCCR = 0,
229 .TEST = 0,
230 .RXGFC = 0,
231};
232
233static const CANConfig canConfig666 = {
234 .op_mode = OPMODE_CAN,
235 .NBTP = CAN_NBTP_666,
236 .DBTP = CAN_DBTP_666,
237 .TDCR = 0,
238 .CCCR = 0,
239 .TEST = 0,
240 .RXGFC = 0,
241};
242
243static const CANConfig canConfig1000 = {
244 .op_mode = OPMODE_CAN,
245 .NBTP = CAN_NBTP_1k0,
246 .DBTP = CAN_DBTP_1k0,
247 .TDCR = 0,
248 .CCCR = 0,
249 .TEST = 0,
250 .RXGFC = 0,
251};
252#endif
253
255 return pin == Gpio::A11 || pin == Gpio::B8 || pin == Gpio::D0;
256}
257
259 return pin == Gpio::A12 || pin == Gpio::B9 || pin == Gpio::D1;
260}
261
263 return pin == Gpio::B5 || pin == Gpio::B12;
264}
265
267 return pin == Gpio::B6 || pin == Gpio::B13;
268}
269
270#if STM32_CAN_USE_CAN3
271// this is about STM32F413
273 return pin == Gpio::A8 || pin == Gpio::B3;
274}
275
277 return pin == Gpio::A15 || pin == Gpio::B4;
278}
279#elif STM32_CAN_USE_FDCAN3
280// STM32H723
281// See different AF for PD12/PD13 vs PF6/PF7 and PG9/PG10
282static bool isValidCan3RxPin(brain_pin_e pin) {
283 return pin == Gpio::D12 /* || pin == Gpio::F6 || pin == Gpio::G10 */;
284}
285
286static bool isValidCan3TxPin(brain_pin_e pin) {
287 return pin == Gpio::D13 /* || pin == Gpio::F7 || pin == Gpio::G9 */;
288}
289#else
291 return false;
292}
293
294static __attribute__((unused)) bool isValidCan3TxPin(brain_pin_e) {
295 return false;
296}
297#endif
298
300 // Note: different AF for CAN3 and CANFD3, so check for CAN1/CANFD1 and CAN2/CANFD2 only
301 // see startCanPins()
302 return isValidCan1TxPin(pin) || isValidCan2TxPin(pin) /* || isValidCan3TxPin(pin) */;
303}
304
306 return isValidCan1RxPin(pin) || isValidCan2RxPin(pin) /* || isValidCan3RxPin(pin) */;
307}
308
309CANDriver* detectCanDevice(brain_pin_e pinRx, brain_pin_e pinTx) {
310 if (pinRx == Gpio::Unassigned || pinTx == Gpio::Unassigned) {
311 return nullptr;
312 }
313#if STM32_CAN_USE_CAN1 || STM32_CAN_USE_FDCAN1
314 if (isValidCan1RxPin(pinRx) && isValidCan1TxPin(pinTx))
315 return &CAND1;
316#endif
317#if STM32_CAN_USE_CAN2 || STM32_CAN_USE_FDCAN2
318 if (isValidCan2RxPin(pinRx) && isValidCan2TxPin(pinTx))
319 return &CAND2;
320#endif
321#if STM32_CAN_USE_CAN3 || STM32_CAN_USE_FDCAN3
322 if (isValidCan3RxPin(pinRx) && isValidCan3TxPin(pinTx))
323 return &CAND3;
324#endif
325 criticalError("invalid CAN pins tx %s and rx %s", hwPortname(pinTx), hwPortname(pinRx));
326 return nullptr;
327}
328
330 switch (rate) {
331 case B33KBPS:
332 return &canConfig33;
333 case B50KBPS:
334 return &canConfig50;
335 case B83KBPS:
336 return &canConfig83;
337 case B100KBPS:
338 return &canConfig100;
339 case B125KBPS:
340 return &canConfig125;
341 case B250KBPS:
342 return &canConfig250;
343 case B666KBPS:
344 return &canConfig666;
345 case B1MBPS:
346 return &canConfig1000;
347 case B500KBPS:
348 default:
349 return &canConfig500;
350 }
351}
352
353void canHwInfo(CANDriver* cand) {
354 if (cand == NULL)
355 return;
356
357 if (cand->state != CAN_READY) {
358 efiPrintf("Interface is not ready");
359 return;
360 }
361
362#if STM32_CAN_USE_CAN1 || STM32_CAN_USE_CAN2
363 if (cand->can == NULL) {
364 efiPrintf("No device assigned!");
365 }
366
367 uint32_t esr = cand->can->ESR;
368 efiPrintf("Receive error counter %ld", (esr >> 24) & 0xff);
369 efiPrintf("Transmit error counter %ld", (esr >> 16) & 0xff);
370 efiPrintf("Last error %ld", (esr >> 4) & 0x7);
371 efiPrintf("Flags: %s %s %s",
372 (esr & 0x4) ? "BOFF" : "",
373 (esr & 0x2) ? "EPVF" : "",
374 (esr & 0x1) ? "EWGF" : "");
375#endif
376}
377
378#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, 1956, 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)
constexpr uint32_t CAN_NBTP_H7(uint32_t sjw, uint32_t prescaler, uint32_t seg1, uint32_t seg2)
Definition stm32_can.cpp:55
static const CANConfig canConfig666
static const CANConfig canConfig100
constexpr uint32_t CAN_DBTP_H7(uint32_t sjw, uint32_t prescaler, uint32_t seg1, uint32_t seg2)
Definition stm32_can.cpp:58
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
void canHwInfo(CANDriver *cand)
static bool isValidCan1TxPin(brain_pin_e pin)