Skip to content

Commit 6908feb

Browse files
committed
Chevy Volt safety
Resets controls_allowed not only gas and brake, but on pressing regen paddle as well. Radar configuration, dashboard status, and chime messages are always allowed through.
1 parent 8203cc8 commit 6908feb

File tree

2 files changed

+184
-0
lines changed

2 files changed

+184
-0
lines changed

board/safety.h

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ int controls_allowed = 0;
2121
#include "safety/safety_defaults.h"
2222
#include "safety/safety_honda.h"
2323
#include "safety/safety_toyota.h"
24+
#include "safety/safety_gm.h"
2425
#include "safety/safety_elm327.h"
2526

2627
const safety_hooks *current_hooks = &nooutput_hooks;
@@ -46,6 +47,7 @@ typedef struct {
4647
#define SAFETY_HONDA 1
4748
#define SAFETY_TOYOTA 2
4849
#define SAFETY_TOYOTA_NOLIMITS 0x1336
50+
#define SAFETY_GM 3
4951
#define SAFETY_ALLOUTPUT 0x1337
5052
#define SAFETY_ELM327 0xE327
5153

@@ -54,6 +56,7 @@ const safety_hook_config safety_hook_registry[] = {
5456
{SAFETY_HONDA, &honda_hooks},
5557
{SAFETY_TOYOTA, &toyota_hooks},
5658
{SAFETY_TOYOTA_NOLIMITS, &toyota_nolimits_hooks},
59+
{SAFETY_GM, &gm_hooks},
5760
{SAFETY_ALLOUTPUT, &alloutput_hooks},
5861
{SAFETY_ELM327, &elm327_hooks},
5962
};

board/safety/safety_gm.h

+181
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
// board enforces
2+
// in-state
3+
// accel set/resume
4+
// out-state
5+
// cancel button
6+
// regen paddle
7+
// accel rising edge
8+
// brake rising edge
9+
// brake > 0mph
10+
11+
// gm_: poor man's namespacing
12+
int gm_brake_prev = 0;
13+
int gm_gas_prev = 0;
14+
int gm_speed = 0;
15+
16+
// silence everything if stock ECUs are still online
17+
int gm_ascm_detected = 0;
18+
19+
static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
20+
21+
uint32_t addr;
22+
if (to_push->RIR & 4) {
23+
// Extended
24+
// Not looked at, but have to be separated
25+
// to avoid address collision
26+
addr = to_push->RIR >> 3;
27+
} else {
28+
// Normal
29+
addr = to_push->RIR >> 21;
30+
}
31+
32+
// sample speed, really only care if car is moving or not
33+
// rear left wheel speed
34+
if (addr == 842) {
35+
gm_speed = to_push->RDLR & 0xFFFF;
36+
}
37+
38+
// check if stock ASCM ECU is still online
39+
int bus_number = (to_push->RDTR >> 4) & 0xFF;
40+
if (bus_number == 0 && addr == 715) {
41+
gm_ascm_detected = 1;
42+
controls_allowed = 0;
43+
}
44+
45+
// ACC steering wheel buttons
46+
if (addr == 481) {
47+
int buttons = (to_push->RDHR >> 12) & 0x7;
48+
// res/set - enable, cancel button - disable
49+
if (buttons == 2 || buttons == 3) {
50+
controls_allowed = 1;
51+
} else if (buttons == 6) {
52+
controls_allowed = 0;
53+
}
54+
}
55+
56+
// exit controls on rising edge of brake press or on brake press when
57+
// speed > 0
58+
if (addr == 241) {
59+
int brake = (to_push->RDLR & 0xFF00) >> 8;
60+
// Brake pedal's potentiometer returns near-zero reading
61+
// even when pedal is not pressed
62+
if (brake <= 5) {
63+
brake = 0;
64+
}
65+
if (brake && (!gm_brake_prev || gm_speed)) {
66+
controls_allowed = 0;
67+
}
68+
gm_brake_prev = brake;
69+
}
70+
71+
// exit controls on rising edge of gas press
72+
if (addr == 417) {
73+
int gas = to_push->RDHR & 0xFF0000;
74+
if (gas && !(gm_gas_prev)) {
75+
controls_allowed = 0;
76+
}
77+
gm_gas_prev = gas;
78+
}
79+
80+
// exit controls on regen paddle
81+
if (addr == 189) {
82+
int regen = to_push->RDLR & 0x20;
83+
if (regen) {
84+
controls_allowed = 0;
85+
}
86+
}
87+
}
88+
89+
// all commands: gas/regen, friction brake and steering
90+
// if controls_allowed and no pedals pressed
91+
// allow all commands up to limit
92+
// else
93+
// block all commands that produce actuation
94+
95+
static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
96+
97+
// There can be only one! (ASCM)
98+
if (gm_ascm_detected) {
99+
return 0;
100+
}
101+
102+
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
103+
// and the the latching controls_allowed flag is True
104+
int pedal_pressed = gm_gas_prev || (gm_brake_prev && gm_speed);
105+
int current_controls_allowed = controls_allowed && !(pedal_pressed);
106+
107+
uint32_t addr;
108+
if (to_send->RIR & 4) {
109+
// Extended
110+
addr = to_send->RIR >> 3;
111+
} else {
112+
// Normal
113+
addr = to_send->RIR >> 21;
114+
}
115+
116+
// BRAKE: safety check
117+
if (addr == 789) {
118+
int rdlr = to_send->RDLR;
119+
int brake = ((rdlr & 0xF) << 8) + ((rdlr & 0xFF00) >> 8);
120+
brake = (0x1000 - brake) & 0xFFF;
121+
if (current_controls_allowed) {
122+
if (brake > 255) return 0;
123+
} else {
124+
if (brake != 0) return 0;
125+
}
126+
}
127+
128+
// LKA STEER: safety check
129+
if (addr == 384) {
130+
int rdlr = to_send->RDLR;
131+
int steer = ((rdlr & 0x7) << 8) + ((rdlr & 0xFF00) >> 8);
132+
int max_steer = 255;
133+
if (current_controls_allowed) {
134+
// Signed arithmetic
135+
if (steer & 0x400) {
136+
if (steer < (0x800 - max_steer)) return 0;
137+
} else {
138+
if (steer > max_steer) return 0;
139+
}
140+
} else {
141+
if (steer != 0) return 0;
142+
}
143+
}
144+
145+
// PARK ASSIST STEER: unlimited torque, no thanks
146+
if (addr == 823) return 0;
147+
148+
// GAS/REGEN: safety check
149+
if (addr == 715) {
150+
int rdlr = to_send->RDLR;
151+
int gas_regen = ((rdlr & 0x7F0000) >> 11) + ((rdlr & 0xF8000000) >> 27);
152+
int apply = rdlr & 1;
153+
if (current_controls_allowed) {
154+
if (gas_regen > 3072) return 0;
155+
} else {
156+
// Disabled message is !engaed with gas
157+
// value that corresponds to max regen.
158+
if (apply || gas_regen != 1404) return 0;
159+
}
160+
}
161+
162+
// 1 allows the message through
163+
return true;
164+
}
165+
166+
static int gm_tx_lin_hook(int lin_num, uint8_t *data, int len) {
167+
// LIN is not used in Volt
168+
return false;
169+
}
170+
171+
static void gm_init(int16_t param) {
172+
controls_allowed = 0;
173+
}
174+
175+
const safety_hooks gm_hooks = {
176+
.init = gm_init,
177+
.rx = gm_rx_hook,
178+
.tx = gm_tx_hook,
179+
.tx_lin = gm_tx_lin_hook,
180+
};
181+

0 commit comments

Comments
 (0)