Skip to content

Commit d5b884f

Browse files
author
Vehicle Researcher
committed
Squashed 'panda/' changes from ef880b7..0dcd84d
0dcd84d Toyota safety: integer division bug 9a268f3 Toyota Safety: cleaner var types 8638650 bump panda version 9ab6a56 gmlan recv test a1a2d97 gmlan test 8efa389 detect ack f5fab4b nicer err ad4d423 add gmlan fail count bb41ff7 test 998f7c0 oops, set recessive 80051be autoretry on chime 813218d GM: allowing higher brakes in Volt, so decel can reach between 3 and 3.5 m/s2 74ad3d6 GM: max param definitions 38a9ea9 added gm safety for steering (#123) bf5db45 Safety: made the driver steer check common so it can be shared across multiple safety files ef079e6 Safety: made rate limit check also common dc3cc24 Safety: made common the max torque check as well dbc3568 removing extra spaces 1966bdf Safety: made real time rate limit check a shared function e214477 use timer for can bitbanging cb92733 minor bitbang refactor ed2920c support extended addressing in canbitbang 36df0996 move speed be46c7a Merge pull request #122 from commaai/gmbitbang 7edc88e put that back fa66e4b Revert "handle rollover" 2ce3a26a handle rollover 223a1fb cleanin it up 1ba7907 that space tho d917386 bitbanging works 74af441 can crc 932d727 bit stuffing support be22522 bros ok match bros 55da0b6 rigol yea, dj pauly d yea a577583 working on gmbitbang 875c2bd3 Cadillac: block OP messages if OP is on 7caba24 Addition to Bosch safety to support Hatchback (#111) 63ca46b modify before we forward bf70f51 Safety: increase buffer for sampled signals. TBD a violation feedback from board to prevent car faults b0541a8 Cadillac: monitoring the 4 torque messages independently cd1dba9 Cadillac: fixed bug in regression safety ca0b6be Cadillac: fixed typo. Need better regression tests to catch this d9f1e61 Cadillac: simplified the ignition code by removing the timeout logic and resetting controls_allowed = 0 at each init 293fd1a GM: using real ignition logic. Creedit to Jamezz 8fa507b GM: simplified max steer check logic, Cadillac: fixed can parsing bug c7e2c2d Cadillac (#119) 83bcaa3 small logic cleanup (#118) 9d92bf2 Cadillac: need to specify car name in const 79ab5af Toyota: moved common functions into safety header file 40c8dda Cadillac ignition: simplified logic 69be556 Cadillac: better ignition logic d176220 Ignition: made a default hook for GPIO bea5187 Cadillac: added max steer safety dbc11a1 Cadillac: always controls allowed for now ace232a Cadillac: ignition bug e2c89d6 Cadillac: changed ignition logic to be based on can presence 528f901 Cadillac: simpler ignition logic 4e79ecf Cadillac: added safety file placeholder git-subtree-dir: panda git-subtree-split: 0dcd84d
1 parent dcacbf6 commit d5b884f

24 files changed

+1291
-139
lines changed

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v1.1.1
1+
v1.1.2

board/drivers/can.h

+12-4
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,9 @@ void can_rx(uint8_t can_number) {
415415
to_push.RDLR = CAN->sFIFOMailBox[0].RDLR;
416416
to_push.RDHR = CAN->sFIFOMailBox[0].RDHR;
417417

418+
// modify RDTR for our API
419+
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4);
420+
418421
// forwarding (panda only)
419422
#ifdef PANDA
420423
int bus_fwd_num = can_forwarding[bus_number] != -1 ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push);
@@ -428,8 +431,6 @@ void can_rx(uint8_t can_number) {
428431
}
429432
#endif
430433

431-
// modify RDTR for our API
432-
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4);
433434
safety_rx_hook(&to_push);
434435

435436
#ifdef PANDA
@@ -460,14 +461,21 @@ void CAN3_SCE_IRQHandler() { can_sce(CAN3); }
460461

461462
#endif
462463

464+
#include "canbitbang.h"
465+
463466
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) {
464467
if (safety_tx_hook(to_push) && !can_autobaud_enabled[bus_number]) {
465468
if (bus_number < BUS_MAX) {
466469
// add CAN packet to send queue
467470
// bus number isn't passed through
468471
to_push->RDTR &= 0xF;
469-
can_push(can_queues[bus_number], to_push);
470-
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
472+
if (bus_number == 3 && can_num_lookup[3] == 0xFF) {
473+
// TODO: why uint8 bro? only int8?
474+
bitbang_gmlan(to_push);
475+
} else {
476+
can_push(can_queues[bus_number], to_push);
477+
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
478+
}
471479
}
472480
}
473481
}

board/drivers/canbitbang.h

+203
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
#define MAX_BITS_CAN_PACKET (200)
2+
3+
// returns out_len
4+
int do_bitstuff(char *out, char *in, int in_len) {
5+
int last_bit = -1;
6+
int bit_cnt = 0;
7+
int j = 0;
8+
for (int i = 0; i < in_len; i++) {
9+
char bit = in[i];
10+
out[j++] = bit;
11+
12+
// do the stuffing
13+
if (bit == last_bit) {
14+
bit_cnt++;
15+
if (bit_cnt == 5) {
16+
// 5 in a row the same, do stuff
17+
last_bit = !bit;
18+
out[j++] = last_bit;
19+
bit_cnt = 1;
20+
}
21+
} else {
22+
// this is a new bit
23+
last_bit = bit;
24+
bit_cnt = 1;
25+
}
26+
}
27+
return j;
28+
}
29+
30+
int append_crc(char *in, int in_len) {
31+
int crc = 0;
32+
for (int i = 0; i < in_len; i++) {
33+
crc <<= 1;
34+
if (in[i] ^ ((crc>>15)&1)) {
35+
crc = crc ^ 0x4599;
36+
}
37+
crc &= 0x7fff;
38+
}
39+
for (int i = 14; i >= 0; i--) {
40+
in[in_len++] = (crc>>i)&1;
41+
}
42+
return in_len;
43+
}
44+
45+
int append_bits(char *in, int in_len, char *app, int app_len) {
46+
for (int i = 0; i < app_len; i++) {
47+
in[in_len++] = app[i];
48+
}
49+
return in_len;
50+
}
51+
52+
int append_int(char *in, int in_len, int val, int val_len) {
53+
for (int i = val_len-1; i >= 0; i--) {
54+
in[in_len++] = (val&(1<<i)) != 0;
55+
}
56+
return in_len;
57+
}
58+
59+
int get_bit_message(char *out, CAN_FIFOMailBox_TypeDef *to_bang) {
60+
char pkt[MAX_BITS_CAN_PACKET];
61+
char footer[] = {
62+
1, // CRC delimiter
63+
1, // ACK
64+
1, // ACK delimiter
65+
1,1,1,1,1,1,1, // EOF
66+
1,1,1, // IFS
67+
};
68+
69+
int len = 0;
70+
71+
// test packet
72+
int dlc_len = to_bang->RDTR & 0xF;
73+
len = append_int(pkt, len, 0, 1); // Start-of-frame
74+
75+
if (to_bang->RIR & 4) {
76+
// extended identifier
77+
len = append_int(pkt, len, to_bang->RIR >> 21, 11); // Identifier
78+
len = append_int(pkt, len, 3, 2); // SRR+IDE
79+
len = append_int(pkt, len, (to_bang->RIR >> 3) & ((1<<18)-1), 18); // Identifier
80+
len = append_int(pkt, len, 0, 3); // RTR+r1+r0
81+
} else {
82+
// standard identifier
83+
len = append_int(pkt, len, to_bang->RIR >> 21, 11); // Identifier
84+
len = append_int(pkt, len, 0, 3); // RTR+IDE+reserved
85+
}
86+
87+
len = append_int(pkt, len, dlc_len, 4); // Data length code
88+
89+
// append data
90+
for (int i = 0; i < dlc_len; i++) {
91+
unsigned char dat = ((unsigned char *)(&(to_bang->RDLR)))[i];
92+
len = append_int(pkt, len, dat, 8);
93+
}
94+
95+
// append crc
96+
len = append_crc(pkt, len);
97+
98+
// do bitstuffing
99+
len = do_bitstuff(out, pkt, len);
100+
101+
// append footer
102+
len = append_bits(out, len, footer, sizeof(footer));
103+
return len;
104+
}
105+
106+
// hardware stuff below this line
107+
108+
#ifdef PANDA
109+
110+
void set_bitbanged_gmlan(int val) {
111+
if (val) {
112+
GPIOB->ODR |= (1 << 13);
113+
} else {
114+
GPIOB->ODR &= ~(1 << 13);
115+
}
116+
}
117+
118+
char pkt_stuffed[MAX_BITS_CAN_PACKET];
119+
int gmlan_sending = -1;
120+
int gmlan_sendmax = -1;
121+
122+
int gmlan_silent_count = 0;
123+
int gmlan_fail_count = 0;
124+
#define REQUIRED_SILENT_TIME 10
125+
#define MAX_FAIL_COUNT 10
126+
127+
void TIM4_IRQHandler(void) {
128+
if (TIM4->SR & TIM_SR_UIF && gmlan_sendmax != -1) {
129+
int read = get_gpio_input(GPIOB, 12);
130+
if (gmlan_silent_count < REQUIRED_SILENT_TIME) {
131+
if (read == 0) {
132+
gmlan_silent_count = 0;
133+
} else {
134+
gmlan_silent_count++;
135+
}
136+
} else if (gmlan_silent_count == REQUIRED_SILENT_TIME) {
137+
int retry = 0;
138+
// in send loop
139+
if (gmlan_sending > 0 && // not first bit
140+
(read == 0 && pkt_stuffed[gmlan_sending-1] == 1) && // bus wrongly dominant
141+
gmlan_sending != (gmlan_sendmax-11)) { //not ack bit
142+
puts("GMLAN ERR: bus driven at ");
143+
puth(gmlan_sending);
144+
puts("\n");
145+
retry = 1;
146+
} else if (read == 1 && gmlan_sending == (gmlan_sendmax-11)) { // recessive during ACK
147+
puts("GMLAN ERR: didn't recv ACK\n");
148+
retry = 1;
149+
}
150+
if (retry) {
151+
// reset sender (retry after 7 silent)
152+
set_bitbanged_gmlan(1); // recessive
153+
gmlan_silent_count = 0;
154+
gmlan_sending = 0;
155+
gmlan_fail_count++;
156+
if (gmlan_fail_count == MAX_FAIL_COUNT) {
157+
puts("GMLAN ERR: giving up send\n");
158+
}
159+
} else {
160+
set_bitbanged_gmlan(pkt_stuffed[gmlan_sending]);
161+
gmlan_sending++;
162+
}
163+
}
164+
if (gmlan_sending == gmlan_sendmax || gmlan_fail_count == MAX_FAIL_COUNT) {
165+
set_bitbanged_gmlan(1); // recessive
166+
set_gpio_mode(GPIOB, 13, MODE_INPUT);
167+
TIM4->DIER = 0; // no update interrupt
168+
TIM4->CR1 = 0; // disable timer
169+
gmlan_sendmax = -1; // exit
170+
}
171+
}
172+
TIM4->SR = 0;
173+
}
174+
175+
void bitbang_gmlan(CAN_FIFOMailBox_TypeDef *to_bang) {
176+
// TODO: make failure less silent
177+
if (gmlan_sendmax != -1) return;
178+
179+
int len = get_bit_message(pkt_stuffed, to_bang);
180+
gmlan_fail_count = 0;
181+
gmlan_silent_count = 0;
182+
gmlan_sending = 0;
183+
gmlan_sendmax = len;
184+
185+
// setup for bitbang loop
186+
set_bitbanged_gmlan(1); // recessive
187+
set_gpio_mode(GPIOB, 13, MODE_OUTPUT);
188+
189+
// setup
190+
TIM4->PSC = 48-1; // tick on 1 us
191+
TIM4->CR1 = TIM_CR1_CEN; // enable
192+
TIM4->ARR = 30-1; // 33.3 kbps
193+
194+
// in case it's disabled
195+
NVIC_EnableIRQ(TIM4_IRQn);
196+
197+
// run the interrupt
198+
TIM4->DIER = TIM_DIER_UIE; // update interrupt
199+
TIM4->SR = 0;
200+
}
201+
202+
#endif
203+

board/gpio.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ void periph_init() {
119119
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
120120
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
121121
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
122-
//RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
122+
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
123123
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
124124
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
125125
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;

board/safety.h

+100
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,24 @@
1+
// sample struct that keeps 3 samples in memory
2+
struct sample_t {
3+
int values[6];
4+
int min;
5+
int max;
6+
} sample_t_default = {{0}, 0, 0};
7+
18
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
29
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
310
int safety_tx_lin_hook(int lin_num, uint8_t *data, int len);
411
int safety_ignition_hook();
12+
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last);
13+
int to_signed(int d, int bits);
14+
void update_sample(struct sample_t *sample, int sample_new);
15+
int max_limit_check(int val, const int MAX);
16+
int dist_to_meas_check(int val, int val_last, struct sample_t *val_meas,
17+
const int MAX_RATE_UP, const int MAX_RATE_DOWN, const int MAX_ERROR);
18+
int driver_limit_check(int val, int val_last, struct sample_t *val_driver,
19+
const int MAX, const int MAX_RATE_UP, const int MAX_RATE_DOWN,
20+
const int MAX_ALLOWANCE, const int DRIVER_FACTOR);
21+
int rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA);
522

623
typedef void (*safety_hook_init)(int16_t param);
724
typedef void (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push);
@@ -31,6 +48,7 @@ int controls_allowed = 0;
3148
#endif
3249
#include "safety/safety_gm.h"
3350
#include "safety/safety_ford.h"
51+
#include "safety/safety_cadillac.h"
3452
#include "safety/safety_elm327.h"
3553

3654
const safety_hooks *current_hooks = &nooutput_hooks;
@@ -68,6 +86,7 @@ typedef struct {
6886
#define SAFETY_GM 3
6987
#define SAFETY_HONDA_BOSCH 4
7088
#define SAFETY_FORD 5
89+
#define SAFETY_CADILLAC 6
7190
#define SAFETY_TOYOTA_IPAS 0x1335
7291
#define SAFETY_TOYOTA_NOLIMITS 0x1336
7392
#define SAFETY_ALLOUTPUT 0x1337
@@ -80,6 +99,7 @@ const safety_hook_config safety_hook_registry[] = {
8099
{SAFETY_TOYOTA, &toyota_hooks},
81100
{SAFETY_GM, &gm_hooks},
82101
{SAFETY_FORD, &ford_hooks},
102+
{SAFETY_CADILLAC, &cadillac_hooks},
83103
{SAFETY_TOYOTA_NOLIMITS, &toyota_nolimits_hooks},
84104
#ifdef PANDA
85105
{SAFETY_TOYOTA_IPAS, &toyota_ipas_hooks},
@@ -101,3 +121,83 @@ int safety_set_mode(uint16_t mode, int16_t param) {
101121
return -1;
102122
}
103123

124+
// compute the time elapsed (in microseconds) from 2 counter samples
125+
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) {
126+
return ts > ts_last ? ts - ts_last : (0xFFFFFFFF - ts_last) + 1 + ts;
127+
}
128+
129+
// convert a trimmed integer to signed 32 bit int
130+
int to_signed(int d, int bits) {
131+
if (d >= (1 << (bits - 1))) {
132+
d -= (1 << bits);
133+
}
134+
return d;
135+
}
136+
137+
// given a new sample, update the smaple_t struct
138+
void update_sample(struct sample_t *sample, int sample_new) {
139+
for (int i = sizeof(sample->values)/sizeof(sample->values[0]) - 1; i > 0; i--) {
140+
sample->values[i] = sample->values[i-1];
141+
}
142+
sample->values[0] = sample_new;
143+
144+
// get the minimum and maximum measured samples
145+
sample->min = sample->max = sample->values[0];
146+
for (int i = 1; i < sizeof(sample->values)/sizeof(sample->values[0]); i++) {
147+
if (sample->values[i] < sample->min) sample->min = sample->values[i];
148+
if (sample->values[i] > sample->max) sample->max = sample->values[i];
149+
}
150+
}
151+
152+
int max_limit_check(int val, const int MAX) {
153+
return (val > MAX) | (val < -MAX);
154+
}
155+
156+
// check that commanded value isn't too far from measured
157+
int dist_to_meas_check(int val, int val_last, struct sample_t *val_meas,
158+
const int MAX_RATE_UP, const int MAX_RATE_DOWN, const int MAX_ERROR) {
159+
160+
// *** val rate limit check ***
161+
int16_t highest_allowed_val = max(val_last, 0) + MAX_RATE_UP;
162+
int16_t lowest_allowed_val = min(val_last, 0) - MAX_RATE_UP;
163+
164+
// if we've exceeded the meas val, we must start moving toward 0
165+
highest_allowed_val = min(highest_allowed_val, max(val_last - MAX_RATE_DOWN, max(val_meas->max, 0) + MAX_ERROR));
166+
lowest_allowed_val = max(lowest_allowed_val, min(val_last + MAX_RATE_DOWN, min(val_meas->min, 0) - MAX_ERROR));
167+
168+
// check for violation
169+
return (val < lowest_allowed_val) || (val > highest_allowed_val);
170+
}
171+
172+
// check that commanded value isn't fighting against driver
173+
int driver_limit_check(int val, int val_last, struct sample_t *val_driver,
174+
const int MAX, const int MAX_RATE_UP, const int MAX_RATE_DOWN,
175+
const int MAX_ALLOWANCE, const int DRIVER_FACTOR) {
176+
177+
int highest_allowed = max(val_last, 0) + MAX_RATE_UP;
178+
int lowest_allowed = min(val_last, 0) - MAX_RATE_UP;
179+
180+
int driver_max_limit = MAX + (MAX_ALLOWANCE + val_driver->max) * DRIVER_FACTOR;
181+
int driver_min_limit = -MAX + (-MAX_ALLOWANCE + val_driver->min) * DRIVER_FACTOR;
182+
183+
// if we've exceeded the applied torque, we must start moving toward 0
184+
highest_allowed = min(highest_allowed, max(val_last - MAX_RATE_DOWN,
185+
max(driver_max_limit, 0)));
186+
lowest_allowed = max(lowest_allowed, min(val_last + MAX_RATE_DOWN,
187+
min(driver_min_limit, 0)));
188+
189+
// check for violation
190+
return (val < lowest_allowed) || (val > highest_allowed);
191+
}
192+
193+
194+
// real time check, mainly used for steer torque rate limiter
195+
int rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA) {
196+
197+
// *** torque real time rate limit check ***
198+
int16_t highest_val = max(val_last, 0) + MAX_RT_DELTA;
199+
int16_t lowest_val = min(val_last, 0) - MAX_RT_DELTA;
200+
201+
// check for violation
202+
return (val < lowest_val) || (val > highest_val);
203+
}

0 commit comments

Comments
 (0)