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
47// 87.5% sample point
48#define CAN_NBTP_33 0x06950c01
49#define CAN_DBTP_33 0x00950D03 // TODO: validate!
50
51// 66% sample point, not ideal but best we can do without changing CAN clock
52#define CAN_NBTP_50 0x061F1F10
53#define CAN_DBTP_50 0x001F2003
54
55// 86.7% sample point
56#define CAN_NBTP_83 0x061F1803
57#define CAN_DBTP_83 0x001F1833
58
59// 88.0% sample point
60#define CAN_NBTP_100 0x061F1402
61#define CAN_DBTP_100 0x001F1423
62
63// 85.0% sample point
64#define CAN_NBTP_125 0x061F0F02
65#define CAN_DBTP_125 0x001F0F23
66
67// These have an 87.5% sample point
68#define CAN_NBTP_250 0x06130C01
69#define CAN_DBTP_250 0x00130C13
70
71#define CAN_NBTP_500 0x06090C01
72#define CAN_DBTP_500 0x00090C13
73
74#define CAN_NBTP_1k0 0x06040C01
75#define CAN_DBTP_1k0 0x00040C13
76#else
77#error Please define CAN BTR settings for your MCU!
78#endif
79
80/*
81 * 500KBaud
82 * automatic wakeup
83 * automatic recover from abort mode
84 * See section 22.7.7 on the STM32 reference manual.
85 *
86 * 29 bit would be CAN_TI0R_EXID (?) but we do not mention it here
87 * CAN_TI0R_STID "Standard Identifier or Extended Identifier"? not mentioned as well
88 */
89#if defined(STM32F4XX) || defined(STM32F7XX)
90
91#define STM32FxMCR (CAN_MCR_ABOM | CAN_MCR_AWUM | CAN_MCR_TXFP)
92
93static const CANConfig canConfig33 = {
94 .mcr = STM32FxMCR,
95 .btr = CAN_BTR_33
96};
97
98static const CANConfig canConfig50 = {
99 .mcr = STM32FxMCR,
100 .btr = CAN_BTR_50
101};
102
103static const CANConfig canConfig83 = {
104 .mcr = STM32FxMCR,
105 .btr = CAN_BTR_83
106};
107
108static const CANConfig canConfig100 = {
109 .mcr = STM32FxMCR,
110 .btr = CAN_BTR_100
111};
112
113static const CANConfig canConfig125 = {
114 .mcr = STM32FxMCR,
115 .btr = CAN_BTR_125
116};
117
118static const CANConfig canConfig250 = {
119 .mcr = STM32FxMCR,
120 .btr = CAN_BTR_250
121};
122
123static const CANConfig canConfig500 = {
124 .mcr = STM32FxMCR,
125 .btr = CAN_BTR_500
126};
127
128static const CANConfig canConfig1000 = {
129 .mcr = STM32FxMCR,
130 .btr = CAN_BTR_1k0
131};
132
133#elif defined(STM32H7XX)
134static const CANConfig canConfig33 = {
135 .op_mode = OPMODE_CAN,
136 .NBTP = CAN_NBTP_33,
137 .DBTP = CAN_DBTP_33,
138 .TDCR = 0,
139 .CCCR = 0,
140 .TEST = 0,
141 .RXGFC = 0,
142};
143
144static const CANConfig canConfig50 = {
145 .op_mode = OPMODE_CAN,
146 .NBTP = CAN_NBTP_50,
147 .DBTP = CAN_DBTP_50,
148 .TDCR = 0,
149 .CCCR = 0,
150 .TEST = 0,
151 .RXGFC = 0,
152};
153
154static const CANConfig canConfig83 = {
155 .op_mode = OPMODE_CAN,
156 .NBTP = CAN_NBTP_83,
157 .DBTP = CAN_DBTP_83,
158 .TDCR = 0,
159 .CCCR = 0,
160 .TEST = 0,
161 .RXGFC = 0,
162};
163
164static const CANConfig canConfig100 = {
165 .op_mode = OPMODE_CAN,
166 .NBTP = CAN_NBTP_100,
167 .DBTP = CAN_DBTP_100,
168 .TDCR = 0,
169 .CCCR = 0,
170 .TEST = 0,
171 .RXGFC = 0,
172};
173
174static const CANConfig canConfig125 = {
175 .op_mode = OPMODE_CAN,
176 .NBTP = CAN_NBTP_125,
177 .DBTP = CAN_DBTP_125,
178 .TDCR = 0,
179 .CCCR = 0,
180 .TEST = 0,
181 .RXGFC = 0,
182};
183
184static const CANConfig canConfig250 = {
185 .op_mode = OPMODE_CAN,
186 .NBTP = CAN_NBTP_250,
187 .DBTP = CAN_DBTP_250,
188 .TDCR = 0,
189 .CCCR = 0,
190 .TEST = 0,
191 .RXGFC = 0,
192};
193
194static const CANConfig canConfig500 = {
195 .op_mode = OPMODE_CAN,
196 .NBTP = CAN_NBTP_500,
197 .DBTP = CAN_DBTP_500,
198 .TDCR = 0,
199 .CCCR = 0,
200 .TEST = 0,
201 .RXGFC = 0,
202};
203
204static const CANConfig canConfig1000 = {
205 .op_mode = OPMODE_CAN,
206 .NBTP = CAN_NBTP_1k0,
207 .DBTP = CAN_DBTP_1k0,
208 .TDCR = 0,
209 .CCCR = 0,
210 .TEST = 0,
211 .RXGFC = 0,
212};
213#endif
214
216 return pin == Gpio::A11 || pin == Gpio::B8 || pin == Gpio::D0;
217}
218
220 return pin == Gpio::A12 || pin == Gpio::B9 || pin == Gpio::D1;
221}
222
224 return pin == Gpio::B5 || pin == Gpio::B12;
225}
226
228 return pin == Gpio::B6 || pin == Gpio::B13;
229}
230
231#if STM32_CAN_USE_CAN3 || STM32_CAN_USE_FDCAN3
233 return pin == Gpio::A8 || pin == Gpio::B3;
234}
235
237 return pin == Gpio::A15 || pin == Gpio::B4;
238}
239#endif
240
244
248
249CANDriver* detectCanDevice(brain_pin_e pinRx, brain_pin_e pinTx) {
250 if (pinRx == Gpio::Unassigned || pinTx == Gpio::Unassigned) {
251 return nullptr;
252 }
253#if STM32_CAN_USE_CAN1 || STM32_CAN_USE_FDCAN1
254 if (isValidCan1RxPin(pinRx) && isValidCan1TxPin(pinTx))
255 return &CAND1;
256#endif
257#if STM32_CAN_USE_CAN2 || STM32_CAN_USE_FDCAN2
258 if (isValidCan2RxPin(pinRx) && isValidCan2TxPin(pinTx))
259 return &CAND2;
260#endif
261#if STM32_CAN_USE_CAN3 || STM32_CAN_USE_FDCAN3
262 if (isValidCan3RxPin(pinRx) && isValidCan3TxPin(pinTx))
263 return &CAND3;
264#endif
265 criticalError("invalid CAN pins tx %s and rx %s", hwPortname(pinTx), hwPortname(pinRx));
266 return nullptr;
267}
268
270 switch (rate) {
271 case B33KBPS:
272 return &canConfig33;
273 case B50KBPS:
274 return &canConfig50;
275 case B83KBPS:
276 return &canConfig83;
277 case B100KBPS:
278 return &canConfig100;
279 case B125KBPS:
280 return &canConfig125;
281 case B250KBPS:
282 return &canConfig250;
283 case B1MBPS:
284 return &canConfig1000;
285 case B500KBPS:
286 default:
287 return &canConfig500;
288 }
289}
290
291void canHwInfo(CANDriver* cand) {
292 if (cand == NULL)
293 return;
294
295 if (cand->state != CAN_READY) {
296 efiPrintf("Interface is not ready");
297 return;
298 }
299
300#if STM32_CAN_USE_CAN1 || STM32_CAN_USE_CAN2
301 if (cand->can == NULL) {
302 efiPrintf("No device assigned!");
303 }
304
305 uint32_t esr = cand->can->ESR;
306 efiPrintf("Receive error counter %ld", (esr >> 24) & 0xff);
307 efiPrintf("Transmit error counter %ld", (esr >> 16) & 0xff);
308 efiPrintf("Last error %ld", (esr >> 4) & 0x7);
309 efiPrintf("Flags: %s %s %s",
310 (esr & 0x4) ? "BOFF" : "",
311 (esr & 0x2) ? "EPVF" : "",
312 (esr & 0x1) ? "EWGF" : "");
313#endif
314}
315
316#endif /* EFI_CAN_SUPPORT */
uint32_t rate
Definition bluetooth.cpp:39
@ Unassigned
const char * hwPortname(brain_pin_e brainPin)
can_baudrate_e
esr("WBO: ESR", SensorCategory.SENSOR_INPUTS, FieldType.INT16, 1940, 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
Definition stm32_can.cpp:98
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:93
void canHwInfo(CANDriver *cand)
static bool isValidCan1TxPin(brain_pin_e pin)