openpilot v0.8.11 release

This commit is contained in:
Vehicle Researcher
2021-11-19 15:24:51 -08:00
parent 93e8dbb8b5
commit bf338bf5e9
328 changed files with 9240 additions and 3951 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
# flake8: noqa
# pylint: skip-file
from .python import Panda, PandaWifiStreaming, PandaDFU, flash_release, \
BASEDIR, ensure_st_up_to_date, PandaSerial, \
DEFAULT_FW_FN, DEFAULT_H7_FW_FN, MCU_TYPE_H7, MCU_TYPE_F4
BASEDIR, ensure_st_up_to_date, PandaSerial, pack_can_buffer, unpack_can_buffer, \
DEFAULT_FW_FN, DEFAULT_H7_FW_FN, MCU_TYPE_H7, MCU_TYPE_F4, DLC_TO_LEN, LEN_TO_DLC
from .python.config import BOOTSTUB_ADDRESS, BLOCK_SIZE_FX, APP_ADDRESS_FX, \
BLOCK_SIZE_H7, APP_ADDRESS_H7, DEVICE_SERIAL_NUMBER_ADDR_H7, \
+29
View File
@@ -0,0 +1,29 @@
#include "dlc_to_len.h"
#define CAN_PACKET_VERSION 2
typedef struct {
unsigned char reserved : 1;
unsigned char bus : 3;
unsigned char data_len_code : 4;
unsigned char rejected : 1;
unsigned char returned : 1;
unsigned char extended : 1;
unsigned int addr : 29;
unsigned char data[CANPACKET_DATA_SIZE_MAX];
} __attribute__((packed, aligned(4))) CANPacket_t;
#define GET_BUS(msg) ((msg)->bus)
#define GET_LEN(msg) (dlc_to_len[(msg)->data_len_code])
#define GET_ADDR(msg) ((msg)->addr)
// Flasher and pedal use raw mailbox access
#define GET_MAILBOX_BYTE(msg, b) (((int)(b) > 3) ? (((msg)->RDHR >> (8U * ((unsigned int)(b) % 4U))) & 0xFFU) : (((msg)->RDLR >> (8U * (unsigned int)(b))) & 0xFFU))
#define GET_MAILBOX_BYTES_04(msg) ((msg)->RDLR)
#define GET_MAILBOX_BYTES_48(msg) ((msg)->RDHR)
#define CAN_INIT_TIMEOUT_MS 500U
#define CANPACKET_HEAD_SIZE 5U
#define WORD_TO_BYTE_ARRAY(dst8, src32) 0[dst8] = ((src32) & 0xFF); 1[dst8] = (((src32) >> 8) & 0xFF); 2[dst8] = (((src32) >> 16) & 0xFF); 3[dst8] = (((src32) >> 24) & 0xFF)
#define BYTE_ARRAY_TO_WORD(dst32, src8) ((dst32) = 0[src8] | (1[src8] << 8) | (2[src8] << 16) | (3[src8] << 24))
-10
View File
@@ -34,16 +34,6 @@
#define MAX_RESP_LEN 0x40U
#define GET_BUS(msg) (((msg)->RDTR >> 4) & 0xFF)
#define GET_LEN(msg) ((msg)->RDTR & 0xF)
#define GET_ADDR(msg) ((((msg)->RIR & 4) != 0) ? ((msg)->RIR >> 3) : ((msg)->RIR >> 21))
#define GET_BYTE(msg, b) (((int)(b) > 3) ? (((msg)->RDHR >> (8U * ((unsigned int)(b) % 4U))) & 0xFFU) : (((msg)->RDLR >> (8U * (unsigned int)(b))) & 0xFFU))
#define GET_BYTES_04(msg) ((msg)->RDLR)
#define GET_BYTES_48(msg) ((msg)->RDHR)
#define GET_FLAG(value, mask) (((__typeof__(mask))(value) & (mask)) == (mask))
#define CAN_INIT_TIMEOUT_MS 500U
#include <stdbool.h>
#ifdef STM32H7
#include "stm32h7/stm32h7_config.h"
+1
View File
@@ -0,0 +1 @@
unsigned char dlc_to_len[] = {0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 12U, 16U, 20U, 24U, 32U, 48U, 64U};
+44 -31
View File
@@ -9,7 +9,7 @@ bool can_set_speed(uint8_t can_number) {
CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
ret &= llcan_set_speed(CAN, can_speed[bus_number], can_loopback, (unsigned int)(can_silent) & (1U << can_number));
ret &= llcan_set_speed(CAN, bus_config[bus_number].can_speed, can_loopback, (unsigned int)(can_silent) & (1U << can_number));
return ret;
}
@@ -17,7 +17,7 @@ bool can_set_speed(uint8_t can_number) {
void can_set_gmlan(uint8_t bus) {
if(current_board->has_hw_gmlan){
// first, disable GMLAN on prev bus
uint8_t prev_bus = can_num_lookup[3];
uint8_t prev_bus = bus_config[3].can_num_lookup;
if (bus != prev_bus) {
switch (prev_bus) {
case 1:
@@ -26,9 +26,9 @@ void can_set_gmlan(uint8_t bus) {
puth(prev_bus + 1U);
puts("\n");
current_board->set_can_mode(CAN_MODE_NORMAL);
bus_lookup[prev_bus] = prev_bus;
can_num_lookup[prev_bus] = prev_bus;
can_num_lookup[3] = -1;
bus_config[prev_bus].bus_lookup = prev_bus;
bus_config[prev_bus].can_num_lookup = prev_bus;
bus_config[3].can_num_lookup = -1;
bool ret = can_init(prev_bus);
UNUSED(ret);
break;
@@ -46,9 +46,9 @@ void can_set_gmlan(uint8_t bus) {
puth(bus + 1U);
puts("\n");
current_board->set_can_mode((bus == 1U) ? CAN_MODE_GMLAN_CAN2 : CAN_MODE_GMLAN_CAN3);
bus_lookup[bus] = 3;
can_num_lookup[bus] = -1;
can_num_lookup[3] = bus;
bus_config[bus].bus_lookup = 3;
bus_config[bus].can_num_lookup = -1;
bus_config[3].can_num_lookup = bus;
bool ret = can_init(bus);
UNUSED(ret);
break;
@@ -101,18 +101,23 @@ void process_can(uint8_t can_number) {
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
// check for empty mailbox
CAN_FIFOMailBox_TypeDef to_send;
CANPacket_t to_send;
if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) {
// add successfully transmitted message to my fifo
if ((CAN->TSR & CAN_TSR_RQCP0) == CAN_TSR_RQCP0) {
can_txd_cnt += 1;
if ((CAN->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) {
CAN_FIFOMailBox_TypeDef to_push;
to_push.RIR = CAN->sTxMailBox[0].TIR;
to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000FU) | ((CAN_BUS_RET_FLAG | bus_number) << 4);
to_push.RDLR = CAN->sTxMailBox[0].TDLR;
to_push.RDHR = CAN->sTxMailBox[0].TDHR;
CANPacket_t to_push;
to_push.returned = 1U;
to_push.rejected = 0U;
to_push.extended = (CAN->sTxMailBox[0].TIR >> 2) & 0x1U;
to_push.addr = (to_push.extended != 0) ? (CAN->sTxMailBox[0].TIR >> 3) : (CAN->sTxMailBox[0].TIR >> 21);
to_push.data_len_code = CAN->sTxMailBox[0].TDTR & 0xFU;
to_push.bus = bus_number;
WORD_TO_BYTE_ARRAY(&to_push.data[0], CAN->sTxMailBox[0].TDLR);
WORD_TO_BYTE_ARRAY(&to_push.data[4], CAN->sTxMailBox[0].TDHR);
can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U;
}
@@ -136,10 +141,12 @@ void process_can(uint8_t can_number) {
if (can_pop(can_queues[bus_number], &to_send)) {
can_tx_cnt += 1;
// only send if we have received a packet
CAN->sTxMailBox[0].TDLR = to_send.RDLR;
CAN->sTxMailBox[0].TDHR = to_send.RDHR;
CAN->sTxMailBox[0].TDTR = to_send.RDTR;
CAN->sTxMailBox[0].TIR = to_send.RIR;
CAN->sTxMailBox[0].TIR = ((to_send.extended != 0) ? (to_send.addr << 3) : (to_send.addr << 21)) | (to_send.extended << 2);
CAN->sTxMailBox[0].TDTR = to_send.data_len_code;
BYTE_ARRAY_TO_WORD(CAN->sTxMailBox[0].TDLR, &to_send.data[0]);
BYTE_ARRAY_TO_WORD(CAN->sTxMailBox[0].TDHR, &to_send.data[4]);
// Send request TXRQ
CAN->sTxMailBox[0].TIR |= 0x1U;
usb_cb_ep3_out_complete();
}
@@ -161,23 +168,29 @@ void can_rx(uint8_t can_number) {
pending_can_live = 1;
// add to my fifo
CAN_FIFOMailBox_TypeDef to_push;
to_push.RIR = CAN->sFIFOMailBox[0].RIR;
to_push.RDTR = CAN->sFIFOMailBox[0].RDTR;
to_push.RDLR = CAN->sFIFOMailBox[0].RDLR;
to_push.RDHR = CAN->sFIFOMailBox[0].RDHR;
CANPacket_t to_push;
// modify RDTR for our API
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4);
to_push.returned = 0U;
to_push.rejected = 0U;
to_push.extended = (CAN->sFIFOMailBox[0].RIR >> 2) & 0x1U;
to_push.addr = (to_push.extended != 0) ? (CAN->sFIFOMailBox[0].RIR >> 3) : (CAN->sFIFOMailBox[0].RIR >> 21);
to_push.data_len_code = CAN->sFIFOMailBox[0].RDTR & 0xFU;
to_push.bus = bus_number;
WORD_TO_BYTE_ARRAY(&to_push.data[0], CAN->sFIFOMailBox[0].RDLR);
WORD_TO_BYTE_ARRAY(&to_push.data[4], CAN->sFIFOMailBox[0].RDHR);
// forwarding (panda only)
int bus_fwd_num = (can_forwarding[bus_number] != -1) ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push);
int bus_fwd_num = safety_fwd_hook(bus_number, &to_push);
if (bus_fwd_num != -1) {
CAN_FIFOMailBox_TypeDef to_send;
to_send.RIR = to_push.RIR | 1; // TXRQ
to_send.RDTR = to_push.RDTR;
to_send.RDLR = to_push.RDLR;
to_send.RDHR = to_push.RDHR;
CANPacket_t to_send;
to_send.returned = 0U;
to_send.rejected = 0U;
to_send.extended = to_push.extended; // TXRQ
to_send.addr = to_push.addr;
to_send.bus = to_push.bus;
to_send.data_len_code = to_push.data_len_code;
(void)memcpy(to_send.data, to_push.data, dlc_to_len[to_push.data_len_code]);
can_send(&to_send, bus_fwd_num, true);
}
+51 -35
View File
@@ -2,11 +2,19 @@ typedef struct {
volatile uint32_t w_ptr;
volatile uint32_t r_ptr;
uint32_t fifo_size;
CAN_FIFOMailBox_TypeDef *elems;
CANPacket_t *elems;
} can_ring;
#define CAN_BUS_RET_FLAG 0x80U
#define CAN_BUS_NUM_MASK 0x7FU
typedef struct {
uint8_t bus_lookup;
uint8_t can_num_lookup;
uint32_t can_speed;
uint32_t can_data_speed;
bool canfd_enabled;
bool brs_enabled;
} bus_config_t;
#define CAN_BUS_NUM_MASK 0x3FU
#define BUS_MAX 4U
@@ -21,8 +29,6 @@ extern int pending_can_live;
// must reinit after changing these
extern int can_loopback;
extern int can_silent;
extern uint32_t can_speed[4];
extern uint32_t can_data_speed[3];
// Ignition detected from CAN meessages
bool ignition_can = false;
@@ -43,14 +49,19 @@ void process_can(uint8_t can_number);
// ********************* instantiate queues *********************
#define can_buffer(x, size) \
CAN_FIFOMailBox_TypeDef elems_##x[size]; \
can_ring can_##x = { .w_ptr = 0, .r_ptr = 0, .fifo_size = (size), .elems = (CAN_FIFOMailBox_TypeDef *)&(elems_##x) };
CANPacket_t elems_##x[size]; \
can_ring can_##x = { .w_ptr = 0, .r_ptr = 0, .fifo_size = (size), .elems = (CANPacket_t *)&(elems_##x) };
#ifdef STM32H7
__attribute__((section(".ram_d1"))) can_buffer(rx_q, 0x1000)
__attribute__((section(".ram_d1"))) can_buffer(txgmlan_q, 0x1A0)
#else
can_buffer(rx_q, 0x1000)
can_buffer(tx1_q, 0x100)
can_buffer(tx2_q, 0x100)
can_buffer(tx3_q, 0x100)
can_buffer(txgmlan_q, 0x100)
can_buffer(txgmlan_q, 0x1A0)
#endif
can_buffer(tx1_q, 0x1A0)
can_buffer(tx2_q, 0x1A0)
can_buffer(tx3_q, 0x1A0)
// FIXME:
// cppcheck-suppress misra-c2012-9.3
can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q, &can_txgmlan_q};
@@ -63,7 +74,7 @@ int can_err_cnt = 0;
int can_overflow_cnt = 0;
// ********************* interrupt safe queue *********************
bool can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
bool can_pop(can_ring *q, CANPacket_t *elem) {
bool ret = 0;
ENTER_CRITICAL();
@@ -81,7 +92,7 @@ bool can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
return ret;
}
bool can_push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) {
bool can_push(can_ring *q, CANPacket_t *elem) {
bool ret = false;
uint32_t next_w_ptr;
@@ -150,20 +161,21 @@ void can_clear(can_ring *q) {
// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc);
// bus_lookup: Translates from 'can number' to 'bus number'.
// can_num_lookup: Translates from 'bus number' to 'can number'.
// can_forwarding: Given a bus num, lookup bus num to forward to. -1 means no forward.
// Helpers
// Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3
uint8_t bus_lookup[] = {0,1,2};
uint8_t can_num_lookup[] = {0,1,2,-1};
int8_t can_forwarding[] = {-1,-1,-1,-1};
uint32_t can_speed[] = {5000, 5000, 5000, 333};
uint32_t can_data_speed[] = {5000, 5000, 5000}; //For CAN FD with BRS only
bus_config_t bus_config[] = {
{ .bus_lookup = 0U, .can_num_lookup = 0U, .can_speed = 5000U, .can_data_speed = 5000U, .canfd_enabled = false, .brs_enabled = false },
{ .bus_lookup = 1U, .can_num_lookup = 1U, .can_speed = 5000U, .can_data_speed = 5000U, .canfd_enabled = false, .brs_enabled = false },
{ .bus_lookup = 2U, .can_num_lookup = 2U, .can_speed = 5000U, .can_data_speed = 5000U, .canfd_enabled = false, .brs_enabled = false },
{ .bus_lookup = 0xFFU, .can_num_lookup = 0xFFU, .can_speed = 333U, .can_data_speed = 333U, .canfd_enabled = false, .brs_enabled = false },
};
#define CAN_MAX 3U
#define CANIF_FROM_CAN_NUM(num) (cans[num])
#define BUS_NUM_FROM_CAN_NUM(num) (bus_lookup[num])
#define CAN_NUM_FROM_BUS_NUM(num) (can_num_lookup[num])
#define BUS_NUM_FROM_CAN_NUM(num) (bus_config[num].bus_lookup)
#define CAN_NUM_FROM_BUS_NUM(num) (bus_config[num].can_num_lookup)
void can_init_all(void) {
bool ret = true;
@@ -175,13 +187,13 @@ void can_init_all(void) {
}
void can_flip_buses(uint8_t bus1, uint8_t bus2){
bus_lookup[bus1] = bus2;
bus_lookup[bus2] = bus1;
can_num_lookup[bus1] = bus2;
can_num_lookup[bus2] = bus1;
bus_config[bus1].bus_lookup = bus2;
bus_config[bus2].bus_lookup = bus1;
bus_config[bus1].can_num_lookup = bus2;
bus_config[bus2].can_num_lookup = bus1;
}
void ignition_can_hook(CAN_FIFOMailBox_TypeDef *to_push) {
void ignition_can_hook(CANPacket_t *to_push) {
int bus = GET_BUS(to_push);
int addr = GET_ADDR(to_push);
int len = GET_LEN(to_push);
@@ -189,23 +201,30 @@ void ignition_can_hook(CAN_FIFOMailBox_TypeDef *to_push) {
ignition_can_cnt = 0U; // reset counter
if (bus == 0) {
// GM exception
// TODO: verify on all supported GM models that we can reliably detect ignition using only this signal,
// since the 0x1F1 signal can briefly go low immediately after ignition
if ((addr == 0x160) && (len == 5)) {
// this message isn't all zeros when ignition is on
ignition_cadillac = GET_BYTES_04(to_push) != 0;
}
// GM exception
if ((addr == 0x1F1) && (len == 8)) {
// Bit 5 is ignition "on"
bool ignition_gm = ((GET_BYTE(to_push, 0) & 0x20) != 0);
ignition_can = ignition_gm || ignition_cadillac;
}
// Tesla exception
if ((addr == 0x348) && (len == 8)) {
// GTW_status
ignition_can = (GET_BYTE(to_push, 0) & 0x1) != 0;
}
// Mazda exception
if ((addr == 0x9E) && (len == 8)) {
ignition_can = (GET_BYTE(to_push, 0) >> 4) == 0xDU;
}
}
}
@@ -217,22 +236,19 @@ bool can_tx_check_min_slots_free(uint32_t min) {
(can_slots_empty(&can_txgmlan_q) >= min);
}
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number, bool skip_tx_hook) {
void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook) {
if (skip_tx_hook || safety_tx_hook(to_push) != 0) {
if (bus_number < BUS_MAX) {
// add CAN packet to send queue
// bus number isn't passed through
to_push->RDTR &= 0xF;
if ((bus_number == 3U) && (can_num_lookup[3] == 0xFFU)) {
if ((bus_number == 3U) && (bus_config[3].can_num_lookup == 0xFFU)) {
gmlan_send_errs += bitbang_gmlan(to_push) ? 0U : 1U;
} else {
can_fwd_errs += can_push(can_queues[bus_number], to_push) ? 0U : 1U;
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
}
}
} else {
to_push->rejected = 1U;
can_send_errs += can_push(&can_rx_q, to_push) ? 0U : 1U;
}
}
void can_set_forwarding(int from, int to) {
can_forwarding[from] = to;
}
+56 -39
View File
@@ -5,6 +5,11 @@
#define BUS_OFF_FAIL_LIMIT 2U
uint8_t bus_off_err[] = {0U, 0U, 0U};
typedef struct {
volatile uint32_t header[2];
volatile uint32_t data_word[CANPACKET_DATA_SIZE_MAX/4U];
} canfd_fifo;
FDCAN_GlobalTypeDef *cans[] = {FDCAN1, FDCAN2, FDCAN3};
bool can_set_speed(uint8_t can_number) {
@@ -12,7 +17,7 @@ bool can_set_speed(uint8_t can_number) {
FDCAN_GlobalTypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
ret &= llcan_set_speed(CANx, can_speed[bus_number], can_data_speed[bus_number], can_loopback, (unsigned int)(can_silent) & (1U << can_number));
ret &= llcan_set_speed(CANx, bus_config[bus_number].can_speed, bus_config[bus_number].can_data_speed, can_loopback, (unsigned int)(can_silent) & (1U << can_number));
return ret;
}
@@ -42,36 +47,41 @@ void process_can(uint8_t can_number) {
FDCAN_GlobalTypeDef *CANx = CANIF_FROM_CAN_NUM(can_number);
uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number);
CANx->IR |= FDCAN_IR_TFE; // Clear Tx FIFO Empty flag
if ((CANx->TXFQS & FDCAN_TXFQS_TFQF) == 0) {
CAN_FIFOMailBox_TypeDef to_send;
CANPacket_t to_send;
if (can_pop(can_queues[bus_number], &to_send)) {
can_tx_cnt += 1;
uint32_t TxFIFOSA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET) + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_SIZE);
uint8_t tx_index = (CANx->TXFQS >> FDCAN_TXFQS_TFQPI_Pos) & 0x1F;
// only send if we have received a packet
CAN_FIFOMailBox_TypeDef *fifo;
fifo = (CAN_FIFOMailBox_TypeDef *)(TxFIFOSA + (tx_index * FDCAN_TX_FIFO_EL_SIZE));
canfd_fifo *fifo;
fifo = (canfd_fifo *)(TxFIFOSA + (tx_index * FDCAN_TX_FIFO_EL_SIZE));
// Convert from "mailbox type"
fifo->RIR = ((to_send.RIR & 0x6) << 28) | (to_send.RIR >> 3); // identifier format and frame type | identifier
//REDEBUG: enable CAN FD and BRS for test purposes
//fifo->RDTR = ((to_send.RDTR & 0xF) << 16) | ((to_send.RDTR) >> 16) | (1U << 21) | (1U << 20); // DLC (length) | timestamp | enable CAN FD | enable BRS
fifo->RDTR = ((to_send.RDTR & 0xF) << 16) | ((to_send.RDTR) >> 16); // DLC (length) | timestamp
fifo->RDLR = to_send.RDLR;
fifo->RDHR = to_send.RDHR;
CANx->TXBAR = (1UL << tx_index);
fifo->header[0] = (to_send.extended << 30) | ((to_send.extended != 0) ? (to_send.addr) : (to_send.addr << 18));
fifo->header[1] = (to_send.data_len_code << 16) | (bus_config[can_number].canfd_enabled << 21) | (bus_config[can_number].brs_enabled << 20);
uint8_t data_len_w = (dlc_to_len[to_send.data_len_code] / 4U);
data_len_w += ((dlc_to_len[to_send.data_len_code] % 4) > 0) ? 1U : 0U;
for (unsigned int i = 0; i < data_len_w; i++) {
BYTE_ARRAY_TO_WORD(fifo->data_word[i], &to_send.data[i*4]);
}
CANx->TXBAR = (1UL << tx_index);
// Send back to USB
can_txd_cnt += 1;
CAN_FIFOMailBox_TypeDef to_push;
to_push.RIR = to_send.RIR;
to_push.RDTR = (to_send.RDTR & 0xFFFF000FU) | ((CAN_BUS_RET_FLAG | bus_number) << 4);
to_push.RDLR = to_send.RDLR;
to_push.RDHR = to_send.RDHR;
CANPacket_t to_push;
to_push.returned = 1U;
to_push.rejected = 0U;
to_push.extended = to_send.extended;
to_push.addr = to_send.addr;
to_push.bus = to_send.bus;
to_push.data_len_code = to_send.data_len_code;
(void)memcpy(to_push.data, to_send.data, dlc_to_len[to_push.data_len_code]);
can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U;
usb_cb_ep3_out_complete();
@@ -123,29 +133,37 @@ void can_rx(uint8_t can_number) {
rx_fifo_idx = (uint8_t)((CANx->RXF0S >> FDCAN_RXF0S_F0GI_Pos) & 0x3F);
uint32_t RxFIFO0SA = FDCAN_START_ADDRESS + (can_number * FDCAN_OFFSET);
CAN_FIFOMailBox_TypeDef to_push;
CAN_FIFOMailBox_TypeDef *fifo;
CANPacket_t to_push;
canfd_fifo *fifo;
// getting address
fifo = (CAN_FIFOMailBox_TypeDef *)(RxFIFO0SA + (rx_fifo_idx * FDCAN_RX_FIFO_0_EL_SIZE));
fifo = (canfd_fifo *)(RxFIFO0SA + (rx_fifo_idx * FDCAN_RX_FIFO_0_EL_SIZE));
// Need to convert real CAN frame format to mailbox "type"
to_push.RIR = ((fifo->RIR >> 28) & 0x6) | (fifo->RIR << 3); // identifier format and frame type | identifier
to_push.RDTR = ((fifo->RDTR >> 16) & 0xF) | (fifo->RDTR << 16); // DLC (length) | timestamp
to_push.RDLR = fifo->RDLR;
to_push.RDHR = fifo->RDHR;
to_push.returned = 0U;
to_push.rejected = 0U;
to_push.extended = (fifo->header[0] >> 30) & 0x1U;
to_push.addr = ((to_push.extended != 0) ? (fifo->header[0] & 0x1FFFFFFFU) : ((fifo->header[0] >> 18) & 0x7FFU));
to_push.bus = bus_number;
to_push.data_len_code = ((fifo->header[1] >> 16) & 0xFU);
// modify RDTR for our API
to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4);
uint8_t data_len_w = (dlc_to_len[to_push.data_len_code] / 4U);
data_len_w += ((dlc_to_len[to_push.data_len_code] % 4) > 0) ? 1U : 0U;
for (unsigned int i = 0; i < data_len_w; i++) {
WORD_TO_BYTE_ARRAY(&to_push.data[i*4], fifo->data_word[i]);
}
// forwarding (panda only)
int bus_fwd_num = (can_forwarding[bus_number] != -1) ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push);
int bus_fwd_num = safety_fwd_hook(bus_number, &to_push);
if (bus_fwd_num != -1) {
CAN_FIFOMailBox_TypeDef to_send;
to_send.RIR = to_push.RIR;
to_send.RDTR = to_push.RDTR;
to_send.RDLR = to_push.RDLR;
to_send.RDHR = to_push.RDHR;
CANPacket_t to_send;
to_send.returned = 0U;
to_send.rejected = 0U;
to_send.extended = to_push.extended;
to_send.addr = to_push.addr;
to_send.bus = to_push.bus;
to_send.data_len_code = to_push.data_len_code;
(void)memcpy(to_send.data, to_push.data, dlc_to_len[to_push.data_len_code]);
can_send(&to_send, bus_fwd_num, true);
}
@@ -155,7 +173,7 @@ void can_rx(uint8_t can_number) {
current_board->set_led(LED_BLUE, true);
can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U;
// update read index
// update read index
CANx->RXF0A = rx_fifo_idx;
}
@@ -165,10 +183,9 @@ void can_rx(uint8_t can_number) {
#endif
CANx->IR |= (FDCAN_IR_PEA | FDCAN_IR_PED | FDCAN_IR_RF0L | FDCAN_IR_RF0F | FDCAN_IR_EW | FDCAN_IR_MRAF | FDCAN_IR_TOO); // Clean all error flags
can_err_cnt += 1;
} else {
} else {
}
}
void FDCAN1_IT0_IRQ_Handler(void) { can_rx(0); }
+8 -9
View File
@@ -75,7 +75,7 @@ int append_int(char *in, int in_len, int val, int val_len) {
return in_len_copy;
}
int get_bit_message(char *out, CAN_FIFOMailBox_TypeDef *to_bang) {
int get_bit_message(char *out, CANPacket_t *to_bang) {
char pkt[MAX_BITS_CAN_PACKET];
char footer[] = {
1, // CRC delimiter
@@ -88,18 +88,18 @@ int get_bit_message(char *out, CAN_FIFOMailBox_TypeDef *to_bang) {
int len = 0;
// test packet
int dlc_len = to_bang->RDTR & 0xF;
int dlc_len = GET_LEN(to_bang);
len = append_int(pkt, len, 0, 1); // Start-of-frame
if ((to_bang->RIR & 4) != 0) {
if (to_bang->extended != 0) {
// extended identifier
len = append_int(pkt, len, to_bang->RIR >> 21, 11); // Identifier
len = append_int(pkt, len, GET_ADDR(to_bang) >> 18, 11); // Identifier
len = append_int(pkt, len, 3, 2); // SRR+IDE
len = append_int(pkt, len, (to_bang->RIR >> 3) & ((1U << 18) - 1U), 18); // Identifier
len = append_int(pkt, len, (GET_ADDR(to_bang)) & ((1U << 18) - 1U), 18); // Identifier
len = append_int(pkt, len, 0, 3); // RTR+r1+r0
} else {
// standard identifier
len = append_int(pkt, len, to_bang->RIR >> 21, 11); // Identifier
len = append_int(pkt, len, GET_ADDR(to_bang), 11); // Identifier
len = append_int(pkt, len, 0, 3); // RTR+IDE+reserved
}
@@ -107,8 +107,7 @@ int get_bit_message(char *out, CAN_FIFOMailBox_TypeDef *to_bang) {
// append data
for (int i = 0; i < dlc_len; i++) {
unsigned char dat = ((unsigned char *)(&(to_bang->RDLR)))[i];
len = append_int(pkt, len, dat, 8);
len = append_int(pkt, len, to_bang->data[i], 8);
}
// append crc
@@ -269,7 +268,7 @@ void TIM12_IRQ_Handler(void) {
TIM12->SR = 0;
}
bool bitbang_gmlan(CAN_FIFOMailBox_TypeDef *to_bang) {
bool bitbang_gmlan(CANPacket_t *to_bang) {
gmlan_send_ok = true;
gmlan_alt_mode = BITBANG;
+4 -3
View File
@@ -23,7 +23,8 @@ typedef union _USB_Setup {
}
USB_Setup_TypeDef;
#define MAX_CAN_MSGS_PER_BULK_TRANSFER 4U
#define MAX_CAN_MSGS_PER_BULK_TRANSFER 51U
#define MAX_EP1_CHUNK_PER_BULK_TRANSFER 16256 // max data stream chunk in bytes, shouldn't be higher than 16320 or counter will overflow
bool usb_eopf_detected = false;
@@ -493,7 +494,7 @@ void usb_setup(void) {
USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP;
USBx_OUTEP(2)->DOEPINT = 0xFF;
USBx_OUTEP(3)->DOEPTSIZ = (1U << 19) | 0x40U;
USBx_OUTEP(3)->DOEPTSIZ = (32U << 19) | 0x800U;
USBx_OUTEP(3)->DOEPCTL = (0x40U & USB_OTG_DOEPCTL_MPSIZ) | (2U << 18) |
USB_OTG_DOEPCTL_SD0PID_SEVNFRM | USB_OTG_DOEPCTL_USBAEP;
USBx_OUTEP(3)->DOEPINT = 0xFF;
@@ -934,7 +935,7 @@ void usb_irqhandler(void) {
void usb_outep3_resume_if_paused(void) {
ENTER_CRITICAL();
if (!outep3_processing && (USBx_OUTEP(3)->DOEPCTL & USB_OTG_DOEPCTL_NAKSTS) != 0) {
USBx_OUTEP(3)->DOEPTSIZ = (1U << 19) | 0x40U;
USBx_OUTEP(3)->DOEPTSIZ = (32U << 19) | 0x800U;
USBx_OUTEP(3)->DOEPCTL |= USB_OTG_DOEPCTL_EPENA | USB_OTG_DOEPCTL_CNAK;
}
EXIT_CRITICAL();
+1 -1
View File
@@ -183,7 +183,7 @@ void CAN1_RX0_IRQ_Handler(void) {
if ((CAN->sFIFOMailBox[0].RIR>>21) == CAN_BL_INPUT) {
uint8_t dat[8];
for (int i = 0; i < 8; i++) {
dat[i] = GET_BYTE(&CAN->sFIFOMailBox[0], i);
dat[i] = GET_MAILBOX_BYTE(&CAN->sFIFOMailBox[0], i);
}
uint8_t odat[8];
uint8_t type = dat[0] & 0xF0;
+1 -1
View File
@@ -1,3 +1,3 @@
#!/bin/bash
sudo apt-get install gcc-arm-none-eabi python-pip
sudo apt-get install dfu-util gcc-arm-none-eabi python3-pip
sudo pip install libusb1 pycryptodome requests
+1 -1
View File
@@ -1,7 +1,7 @@
#!/bin/bash
# Need formula for gcc
sudo easy_install pip
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew tap ArmMbed/homebrew-formulae
brew install python dfu-util arm-none-eabi-gcc
pip install --user libusb1 pycryptodome requests
+30 -7
View File
@@ -14,13 +14,36 @@ void *memset(void *str, int c, unsigned int n) {
return str;
}
void *memcpy(void *dest, const void *src, unsigned int n) {
uint8_t *d = dest;
const uint8_t *s = src;
for (unsigned int i = 0; i < n; i++) {
*d = *s;
d++;
s++;
#define UNALIGNED(X, Y) \
(((uint32_t)(X) & (sizeof(uint32_t) - 1U)) | ((uint32_t)(Y) & (sizeof(uint32_t) - 1U)))
void *memcpy(void *dest, const void *src, unsigned int len) {
unsigned int n = len;
uint8_t *d8 = dest;
const uint8_t *s8 = src;
if ((n >= 4U) && !UNALIGNED(s8, d8)) {
uint32_t *d32 = (uint32_t *)d8; // cppcheck-suppress misra-c2012-11.3 ; already checked that it's properly aligned
const uint32_t *s32 = (const uint32_t *)s8; // cppcheck-suppress misra-c2012-11.3 ; already checked that it's properly aligned
while(n >= 16U) {
*d32 = *s32; d32++; s32++;
*d32 = *s32; d32++; s32++;
*d32 = *s32; d32++; s32++;
*d32 = *s32; d32++; s32++;
n -= 16U;
}
while(n >= 4U) {
*d32 = *s32; d32++; s32++;
n -= 4U;
}
d8 = (uint8_t *)d32;
s8 = (const uint8_t *)s32;
}
while (n-- > 0U) {
*d8 = *s8; d8++; s8++;
}
return dest;
}
+20 -39
View File
@@ -20,11 +20,14 @@
#include "drivers/bxcan.h"
#endif
#include "usb_protocol.h"
#include "obj/gitversion.h"
extern int _app_start[0xc000]; // Only first 3 sectors of size 0x4000 are used
// When changing this struct, boardd and python/__init__.py needs to be kept up to date!
#define HEALTH_PACKET_VERSION 1
struct __attribute__((packed)) health_t {
uint32_t uptime_pkt;
uint32_t voltage_pkt;
@@ -192,15 +195,7 @@ int get_rtc_pkt(void *dat) {
return sizeof(t);
}
int usb_cb_ep1_in(void *usbdata, int len, bool hardwired) {
UNUSED(hardwired);
CAN_FIFOMailBox_TypeDef *reply = (CAN_FIFOMailBox_TypeDef *)usbdata;
int ilen = 0;
while (ilen < MIN(len/0x10, 4) && can_pop(&can_rx_q, &reply[ilen])) {
ilen++;
}
return ilen*0x10;
}
// send on serial, first byte to select the ring
void usb_cb_ep2_out(void *usbdata, int len, bool hardwired) {
@@ -218,23 +213,6 @@ void usb_cb_ep2_out(void *usbdata, int len, bool hardwired) {
}
}
// send on CAN
void usb_cb_ep3_out(void *usbdata, int len, bool hardwired) {
UNUSED(hardwired);
int dpkt = 0;
uint32_t *d32 = (uint32_t *)usbdata;
for (dpkt = 0; dpkt < (len / 4); dpkt += 4) {
CAN_FIFOMailBox_TypeDef to_push;
to_push.RDHR = d32[dpkt + 3];
to_push.RDLR = d32[dpkt + 2];
to_push.RDTR = d32[dpkt + 1];
to_push.RIR = d32[dpkt];
uint8_t bus_number = (to_push.RDTR >> 4) & CAN_BUS_NUM_MASK;
can_send(&to_push, bus_number, false);
}
}
void usb_cb_ep3_out_complete(void) {
if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_BULK_TRANSFER)) {
usb_outep3_resume_if_paused();
@@ -454,24 +432,17 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
set_safety_mode(setup->b.wValue.w, (uint16_t) setup->b.wIndex.w);
}
break;
// **** 0xdd: enable can forwarding
// **** 0xdd: get healthpacket and CANPacket versions
case 0xdd:
// wValue = Can Bus Num to forward from
// wIndex = Can Bus Num to forward to
if ((setup->b.wValue.w < BUS_MAX) && (setup->b.wIndex.w < BUS_MAX) &&
(setup->b.wValue.w != setup->b.wIndex.w)) { // set forwarding
can_set_forwarding(setup->b.wValue.w, setup->b.wIndex.w & CAN_BUS_NUM_MASK);
} else if((setup->b.wValue.w < BUS_MAX) && (setup->b.wIndex.w == 0xFFU)){ //Clear Forwarding
can_set_forwarding(setup->b.wValue.w, -1);
} else {
puts("Invalid CAN bus forwarding\n");
}
resp[0] = HEALTH_PACKET_VERSION;
resp[1] = CAN_PACKET_VERSION;
resp_len = 2;
break;
// **** 0xde: set can bitrate
case 0xde:
if (setup->b.wValue.w < BUS_MAX) {
// TODO: add sanity check, ideally check if value is correct(from array of correct values)
can_speed[setup->b.wValue.w] = setup->b.wIndex.w;
bus_config[setup->b.wValue.w].can_speed = setup->b.wIndex.w;
bool ret = can_init(CAN_NUM_FROM_BUS_NUM(setup->b.wValue.w));
UNUSED(ret);
}
@@ -628,11 +599,21 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
case 0xf9:
if (setup->b.wValue.w < CAN_MAX) {
// TODO: add sanity check, ideally check if value is correct(from array of correct values)
can_data_speed[setup->b.wValue.w] = setup->b.wIndex.w;
bus_config[setup->b.wValue.w].can_data_speed = setup->b.wIndex.w;
bus_config[setup->b.wValue.w].canfd_enabled = (setup->b.wIndex.w >= bus_config[setup->b.wValue.w].can_speed) ? true : false;
bus_config[setup->b.wValue.w].brs_enabled = (setup->b.wIndex.w > bus_config[setup->b.wValue.w].can_speed) ? true : false;
bool ret = can_init(CAN_NUM_FROM_BUS_NUM(setup->b.wValue.w));
UNUSED(ret);
}
break;
// **** 0xfa: check if CAN FD and BRS are enabled
case 0xfa:
if (setup->b.wValue.w < CAN_MAX) {
resp[0] = bus_config[setup->b.wValue.w].canfd_enabled;
resp[1] = bus_config[setup->b.wValue.w].brs_enabled;
resp_len = 2;
}
break;
default:
puts("NO HANDLER ");
puth(setup->b.bRequest);
+4 -4
View File
@@ -132,11 +132,11 @@ void CAN1_RX0_IRQ_Handler(void) {
int address = CAN->sFIFOMailBox[0].RIR >> 21;
if (address == CAN_GAS_INPUT) {
// softloader entry
if (GET_BYTES_04(&CAN->sFIFOMailBox[0]) == 0xdeadface) {
if (GET_BYTES_48(&CAN->sFIFOMailBox[0]) == 0x0ab00b1e) {
if (GET_MAILBOX_BYTES_04(&CAN->sFIFOMailBox[0]) == 0xdeadface) {
if (GET_MAILBOX_BYTES_48(&CAN->sFIFOMailBox[0]) == 0x0ab00b1e) {
enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC;
NVIC_SystemReset();
} else if (GET_BYTES_48(&CAN->sFIFOMailBox[0]) == 0x02b00b1e) {
} else if (GET_MAILBOX_BYTES_48(&CAN->sFIFOMailBox[0]) == 0x02b00b1e) {
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
NVIC_SystemReset();
} else {
@@ -147,7 +147,7 @@ void CAN1_RX0_IRQ_Handler(void) {
// normal packet
uint8_t dat[8];
for (int i=0; i<8; i++) {
dat[i] = GET_BYTE(&CAN->sFIFOMailBox[0], i);
dat[i] = GET_MAILBOX_BYTE(&CAN->sFIFOMailBox[0], i);
}
uint16_t value_0 = (dat[0] << 8) | dat[1];
uint16_t value_1 = (dat[2] << 8) | dat[3];
+14 -15
View File
@@ -5,7 +5,6 @@
#include "safety/safety_honda.h"
#include "safety/safety_toyota.h"
#include "safety/safety_tesla.h"
#include "safety/safety_gm_ascm.h"
#include "safety/safety_gm.h"
#include "safety/safety_ford.h"
#include "safety/safety_hyundai.h"
@@ -39,26 +38,27 @@
#define SAFETY_SUBARU_LEGACY 22U
#define SAFETY_HYUNDAI_LEGACY 23U
#define SAFETY_HYUNDAI_COMMUNITY 24U
#define SAFETY_STELLANTIS 25U
uint16_t current_safety_mode = SAFETY_SILENT;
int16_t current_safety_param = 0;
const safety_hooks *current_hooks = &nooutput_hooks;
const addr_checks *current_rx_checks = &default_rx_checks;
int safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
int safety_rx_hook(CANPacket_t *to_push) {
return current_hooks->rx(to_push);
}
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return current_hooks->tx(to_send);
int safety_tx_hook(CANPacket_t *to_send) {
return (relay_malfunction ? -1 : current_hooks->tx(to_send));
}
int safety_tx_lin_hook(int lin_num, uint8_t *data, int len) {
return current_hooks->tx_lin(lin_num, data, len);
}
int safety_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
return current_hooks->fwd(bus_num, to_fwd);
int safety_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
return (relay_malfunction ? -1 : current_hooks->fwd(bus_num, to_fwd));
}
// Given a CRC-8 poly, generate a static lookup table to use with a fast CRC-8
@@ -76,7 +76,7 @@ void gen_crc_lookup_table(uint8_t poly, uint8_t crc_lut[]) {
}
}
bool msg_allowed(CAN_FIFOMailBox_TypeDef *to_send, const CanMsg msg_list[], int len) {
bool msg_allowed(CANPacket_t *to_send, const CanMsg msg_list[], int len) {
int addr = GET_ADDR(to_send);
int bus = GET_BUS(to_send);
int length = GET_LEN(to_send);
@@ -97,7 +97,7 @@ uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) {
return ts - ts_last;
}
int get_addr_check_index(CAN_FIFOMailBox_TypeDef *to_push, AddrCheckStruct addr_list[], const int len) {
int get_addr_check_index(CANPacket_t *to_push, AddrCheckStruct addr_list[], const int len) {
int bus = GET_BUS(to_push);
int addr = GET_ADDR(to_push);
int length = GET_LEN(to_push);
@@ -171,11 +171,11 @@ void update_addr_timestamp(AddrCheckStruct addr_list[], int index) {
}
}
bool addr_safety_check(CAN_FIFOMailBox_TypeDef *to_push,
bool addr_safety_check(CANPacket_t *to_push,
const addr_checks *rx_checks,
uint8_t (*get_checksum)(CAN_FIFOMailBox_TypeDef *to_push),
uint8_t (*compute_checksum)(CAN_FIFOMailBox_TypeDef *to_push),
uint8_t (*get_counter)(CAN_FIFOMailBox_TypeDef *to_push)) {
uint8_t (*get_checksum)(CANPacket_t *to_push),
uint8_t (*compute_checksum)(CANPacket_t *to_push),
uint8_t (*get_counter)(CANPacket_t *to_push)) {
int index = get_addr_check_index(to_push, rx_checks->check, rx_checks->len);
update_addr_timestamp(rx_checks->check, index);
@@ -241,7 +241,6 @@ const safety_hook_config safety_hook_registry[] = {
{SAFETY_TOYOTA, &toyota_hooks},
{SAFETY_ELM327, &elm327_hooks},
{SAFETY_GM, &gm_hooks},
{SAFETY_HONDA_BOSCH_GIRAFFE, &honda_bosch_giraffe_hooks},
{SAFETY_HONDA_BOSCH_HARNESS, &honda_bosch_harness_hooks},
{SAFETY_HYUNDAI, &hyundai_hooks},
{SAFETY_CHRYSLER, &chrysler_hooks},
@@ -250,13 +249,12 @@ const safety_hook_config safety_hook_registry[] = {
{SAFETY_NISSAN, &nissan_hooks},
{SAFETY_NOOUTPUT, &nooutput_hooks},
{SAFETY_HYUNDAI_LEGACY, &hyundai_legacy_hooks},
{SAFETY_MAZDA, &mazda_hooks},
#ifdef ALLOW_DEBUG
{SAFETY_TESLA, &tesla_hooks},
{SAFETY_MAZDA, &mazda_hooks},
{SAFETY_SUBARU_LEGACY, &subaru_legacy_hooks},
{SAFETY_VOLKSWAGEN_PQ, &volkswagen_pq_hooks},
{SAFETY_ALLOUTPUT, &alloutput_hooks},
{SAFETY_GM_ASCM, &gm_ascm_hooks},
{SAFETY_FORD, &ford_hooks},
#endif
};
@@ -274,6 +272,7 @@ int set_safety_hooks(uint16_t mode, int16_t param) {
cruise_engaged_prev = false;
vehicle_speed = 0;
vehicle_moving = false;
acc_main_on = false;
desired_torque_last = 0;
rt_torque_last = 0;
ts_angle_last = 0;
+15 -19
View File
@@ -18,12 +18,12 @@ AddrCheckStruct chrysler_addr_checks[] = {
#define CHRYSLER_ADDR_CHECK_LEN (sizeof(chrysler_addr_checks) / sizeof(chrysler_addr_checks[0]))
addr_checks chrysler_rx_checks = {chrysler_addr_checks, CHRYSLER_ADDR_CHECK_LEN};
static uint8_t chrysler_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t chrysler_get_checksum(CANPacket_t *to_push) {
int checksum_byte = GET_LEN(to_push) - 1;
return (uint8_t)(GET_BYTE(to_push, checksum_byte));
}
static uint8_t chrysler_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t chrysler_compute_checksum(CANPacket_t *to_push) {
/* This function does not want the checksum byte in the input data.
jeep chrysler canbus checksum from http://illmatics.com/Remote%20Car%20Hacking.pdf */
uint8_t checksum = 0xFFU;
@@ -56,12 +56,12 @@ static uint8_t chrysler_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
return ~checksum;
}
static uint8_t chrysler_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t chrysler_get_counter(CANPacket_t *to_push) {
// Well defined counter only for 8 bytes messages
return (uint8_t)(GET_BYTE(to_push, 6) >> 4);
}
static int chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int chrysler_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &chrysler_rx_checks,
chrysler_get_checksum, chrysler_compute_checksum,
@@ -117,7 +117,7 @@ static int chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
return valid;
}
static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int chrysler_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
@@ -126,10 +126,6 @@ static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
tx = 0;
}
if (relay_malfunction) {
tx = 0;
}
// LKA STEER
if (addr == 0x292) {
int desired_torque = ((GET_BYTE(to_send, 0) & 0x7U) << 8) + GET_BYTE(to_send, 1) - 1024U;
@@ -186,21 +182,21 @@ static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return tx;
}
static int chrysler_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int chrysler_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
int bus_fwd = -1;
int addr = GET_ADDR(to_fwd);
if (!relay_malfunction) {
// forward CAN 0 -> 2 so stock LKAS camera sees messages
if (bus_num == 0) {
bus_fwd = 2;
}
// forward all messages from camera except LKAS_COMMAND and LKAS_HUD
if ((bus_num == 2) && (addr != 658) && (addr != 678)) {
bus_fwd = 0;
}
// forward CAN 0 -> 2 so stock LKAS camera sees messages
if (bus_num == 0) {
bus_fwd = 2;
}
// forward all messages from camera except LKAS_COMMAND and LKAS_HUD
if ((bus_num == 2) && (addr != 658) && (addr != 678)) {
bus_fwd = 0;
}
return bus_fwd;
}
+26 -5
View File
@@ -3,7 +3,7 @@ const addr_checks default_rx_checks = {
.len = 0,
};
int default_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
int default_rx_hook(CANPacket_t *to_push) {
UNUSED(to_push);
return true;
}
@@ -17,7 +17,7 @@ static const addr_checks* nooutput_init(int16_t param) {
return &default_rx_checks;
}
static int nooutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int nooutput_tx_hook(CANPacket_t *to_send) {
UNUSED(to_send);
return false;
}
@@ -29,7 +29,7 @@ static int nooutput_tx_lin_hook(int lin_num, uint8_t *data, int len) {
return false;
}
static int default_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int default_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
UNUSED(bus_num);
UNUSED(to_fwd);
return -1;
@@ -45,14 +45,19 @@ const safety_hooks nooutput_hooks = {
// *** all output safety mode ***
// Enables passthrough mode where relay is open and bus 0 gets forwarded to bus 2 and vice versa
const uint16_t ALLOUTPUT_PARAM_PASSTHROUGH = 1;
bool alloutput_passthrough = false;
static const addr_checks* alloutput_init(int16_t param) {
UNUSED(param);
alloutput_passthrough = GET_FLAG(param, ALLOUTPUT_PARAM_PASSTHROUGH);
controls_allowed = true;
relay_malfunction_reset();
return &default_rx_checks;
}
static int alloutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int alloutput_tx_hook(CANPacket_t *to_send) {
UNUSED(to_send);
return true;
}
@@ -64,10 +69,26 @@ static int alloutput_tx_lin_hook(int lin_num, uint8_t *data, int len) {
return true;
}
static int alloutput_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
UNUSED(to_fwd);
int bus_fwd = -1;
if (alloutput_passthrough) {
if (bus_num == 0) {
bus_fwd = 2;
}
if (bus_num == 2) {
bus_fwd = 0;
}
}
return bus_fwd;
}
const safety_hooks alloutput_hooks = {
.init = alloutput_init,
.rx = default_rx_hook,
.tx = alloutput_tx_hook,
.tx_lin = alloutput_tx_lin_hook,
.fwd = default_fwd_hook,
.fwd = alloutput_fwd_hook,
};
+1 -1
View File
@@ -1,4 +1,4 @@
static int elm327_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int elm327_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
+2 -6
View File
@@ -8,7 +8,7 @@
// brake > 0mph
static int ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int ford_rx_hook(CANPacket_t *to_push) {
int addr = GET_ADDR(to_push);
int bus = GET_BUS(to_push);
@@ -65,7 +65,7 @@ static int ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// else
// block all commands that produce actuation
static int ford_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int ford_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
@@ -79,10 +79,6 @@ static int ford_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
bool current_controls_allowed = controls_allowed && !(pedal_pressed);
if (relay_malfunction) {
tx = 0;
}
// STEER: safety check
if (addr == 0x3CA) {
if (!current_controls_allowed) {
+2 -6
View File
@@ -34,7 +34,7 @@ AddrCheckStruct gm_addr_checks[] = {
#define GM_RX_CHECK_LEN (sizeof(gm_addr_checks) / sizeof(gm_addr_checks[0]))
addr_checks gm_rx_checks = {gm_addr_checks, GM_RX_CHECK_LEN};
static int gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int gm_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &gm_rx_checks, NULL, NULL, NULL);
@@ -104,7 +104,7 @@ static int gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// else
// block all commands that produce actuation
static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int gm_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
@@ -113,10 +113,6 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
tx = 0;
}
if (relay_malfunction) {
tx = 0;
}
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
// and the the latching controls_allowed flag is True
int pedal_pressed = brake_pressed_prev && vehicle_moving;
-43
View File
@@ -1,43 +0,0 @@
// BUS 0 is on the LKAS module (ASCM) side
// BUS 2 is on the actuator (EPS) side
static int gm_ascm_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
int bus_fwd = -1;
if (bus_num == 0) {
int addr = GET_ADDR(to_fwd);
bus_fwd = 2;
// do not propagate lkas messages from ascm to actuators, unless supercruise is on
// block 0x152 and 0x154, which are the lkas command from ASCM1 and ASCM2
// block 0x315 and 0x2cb, which are the brake and accel commands from ASCM1
//if ((addr == 0x152) || (addr == 0x154) || (addr == 0x315) || (addr == 0x2cb)) {
if ((addr == 0x152) || (addr == 0x154)) {
bool supercruise_on = (GET_BYTE(to_fwd, 4) & 0x10) != 0; // bit 36
if (!supercruise_on) {
bus_fwd = -1;
}
}
if ((addr == 0x151) || (addr == 0x153) || (addr == 0x314)) {
// on the chassis bus, the OBDII port is on the module side, so we need to read
// the lkas messages sent by openpilot (put on unused 0x151 ane 0x153 addrs) and send it to
// the actuator as 0x152 and 0x154
uint32_t fwd_addr = addr + 1;
to_fwd->RIR = (fwd_addr << 21) | (to_fwd->RIR & 0x1fffff);
}
}
if (bus_num == 2) {
bus_fwd = 0;
}
return bus_fwd;
}
const safety_hooks gm_ascm_hooks = {
.init = nooutput_init,
.rx = default_rx_hook,
.tx = alloutput_tx_hook,
.tx_lin = nooutput_tx_lin_hook,
.fwd = gm_ascm_fwd_hook,
};
+71 -76
View File
@@ -7,9 +7,7 @@
// brake rising edge
// brake > 0mph
const CanMsg HONDA_N_TX_MSGS[] = {{0xE4, 0, 5}, {0x194, 0, 4}, {0x1FA, 0, 8}, {0x200, 0, 6}, {0x30C, 0, 8}, {0x33D, 0, 5}};
const CanMsg HONDA_BG_TX_MSGS[] = {{0xE4, 2, 5}, {0xE5, 2, 8}, {0x296, 0, 4}, {0x33D, 2, 5}}; // Bosch Giraffe
const CanMsg HONDA_BH_TX_MSGS[] = {{0xE4, 0, 5}, {0xE5, 0, 8}, {0x296, 1, 4}, {0x33D, 0, 5}}; // Bosch Harness
const CanMsg HONDA_BG_LONG_TX_MSGS[] = {{0xE4, 0, 5}, {0x1DF, 0, 8}, {0x1EF, 0, 8}, {0x1FA, 0, 8}, {0x30C, 0, 8}, {0x33D, 0, 5}, {0x39F, 0, 8}, {0x18DAB0F1, 0, 8}}; // Bosch Giraffe w/ gas and brakes
const CanMsg HONDA_BH_LONG_TX_MSGS[] = {{0xE4, 1, 5}, {0x1DF, 1, 8}, {0x1EF, 1, 8}, {0x1FA, 1, 8}, {0x30C, 1, 8}, {0x33D, 1, 5}, {0x39F, 1, 8}, {0x18DAB0F1, 1, 8}}; // Bosch Harness w/ gas and brakes
// Roughly calculated using the offsets in openpilot +5%:
@@ -24,14 +22,24 @@ const int HONDA_BOSCH_NO_GAS_VALUE = -30000; // value sent when not requesting g
const int HONDA_BOSCH_GAS_MAX = 2000;
const int HONDA_BOSCH_ACCEL_MIN = -350; // max braking == -3.5m/s2
// Nidec and Bosch giraffe have pt on bus 0
AddrCheckStruct honda_addr_checks[] = {
// Nidec has the powertrain bus on bus 0
AddrCheckStruct honda_nidec_addr_checks[] = {
{.msg = {{0x1A6, 0, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U},
{0x296, 0, 4, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U},{ 0 }}},
{0x296, 0, 4, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U}, { 0 }}},
{.msg = {{0x158, 0, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
{.msg = {{0x17C, 0, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
};
#define HONDA_ADDR_CHECKS_LEN (sizeof(honda_addr_checks) / sizeof(honda_addr_checks[0]))
#define HONDA_NIDEC_ADDR_CHECKS_LEN (sizeof(honda_nidec_addr_checks) / sizeof(honda_nidec_addr_checks[0]))
// For Nidecs with main on signal on 0x326
AddrCheckStruct honda_nidec_alt_addr_checks[] = {
{.msg = {{0x1A6, 0, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U},
{0x296, 0, 4, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U}, { 0 }}},
{.msg = {{0x158, 0, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
{.msg = {{0x17C, 0, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
{.msg = {{0x326, 0, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 100000U}, { 0 }, { 0 }}},
};
#define HONDA_NIDEC_ALT_ADDR_CHECKS_LEN (sizeof(honda_nidec_alt_addr_checks) / sizeof(honda_nidec_alt_addr_checks[0]))
// Bosch harness has pt on bus 1
AddrCheckStruct honda_bh_addr_checks[] = {
@@ -39,26 +47,28 @@ AddrCheckStruct honda_bh_addr_checks[] = {
{.msg = {{0x158, 1, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U}, { 0 }, { 0 }}},
{.msg = {{0x17C, 1, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
{0x1BE, 1, 3, .check_checksum = true, .max_counter = 3U, .expected_timestep = 20000U}, { 0 }}},
{.msg = {{0x326, 1, 8, .check_checksum = true, .max_counter = 3U, .expected_timestep = 100000U}, { 0 }, { 0 }}},
};
#define HONDA_BH_ADDR_CHECKS_LEN (sizeof(honda_bh_addr_checks) / sizeof(honda_bh_addr_checks[0]))
const uint16_t HONDA_PARAM_ALT_BRAKE = 1;
const uint16_t HONDA_PARAM_BOSCH_LONG = 2;
const uint16_t HONDA_PARAM_NIDEC_ALT = 4;
int honda_brake = 0;
bool honda_alt_brake_msg = false;
bool honda_fwd_brake = false;
bool honda_bosch_long = false;
enum {HONDA_N_HW, HONDA_BG_HW, HONDA_BH_HW} honda_hw = HONDA_N_HW;
addr_checks honda_rx_checks = {honda_addr_checks, HONDA_ADDR_CHECKS_LEN};
enum {HONDA_N_HW, HONDA_BH_HW} honda_hw = HONDA_N_HW;
addr_checks honda_rx_checks = {honda_nidec_addr_checks, HONDA_NIDEC_ADDR_CHECKS_LEN};
static uint8_t honda_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t honda_get_checksum(CANPacket_t *to_push) {
int checksum_byte = GET_LEN(to_push) - 1;
return (uint8_t)(GET_BYTE(to_push, checksum_byte)) & 0xFU;
}
static uint8_t honda_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t honda_compute_checksum(CANPacket_t *to_push) {
int len = GET_LEN(to_push);
uint8_t checksum = 0U;
unsigned int addr = GET_ADDR(to_push);
@@ -75,12 +85,12 @@ static uint8_t honda_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
return (8U - checksum) & 0xFU;
}
static uint8_t honda_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t honda_get_counter(CANPacket_t *to_push) {
int counter_byte = GET_LEN(to_push) - 1;
return ((uint8_t)(GET_BYTE(to_push, counter_byte)) >> 4U) & 0x3U;
}
static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int honda_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &honda_rx_checks,
honda_get_checksum, honda_compute_checksum, honda_get_counter);
@@ -96,17 +106,30 @@ static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
vehicle_moving = GET_BYTE(to_push, 0) | GET_BYTE(to_push, 1);
}
// check ACC main state
// 0x326 for all Bosch and some Nidec, 0x1A6 for some Nidec
if ((addr == 0x326) || (addr == 0x1A6)) {
acc_main_on = GET_BIT(to_push, (addr == 0x326) ? 28 : 47);
if (!acc_main_on) {
controls_allowed = 0;
}
}
// state machine to enter and exit controls
// 0x1A6 for the ILX, 0x296 for the Civic Touring
if ((addr == 0x1A6) || (addr == 0x296)) {
// check for button presses
int button = (GET_BYTE(to_push, 0) & 0xE0) >> 5;
switch (button) {
case 1: // main
case 2: // cancel
controls_allowed = 0;
break;
case 3: // set
case 4: // resume
controls_allowed = 1;
if (acc_main_on) {
controls_allowed = 1;
}
break;
default:
break; // any other button is irrelevant
@@ -186,17 +209,13 @@ static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
// else
// block all commands that produce actuation
static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int honda_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
int bus = GET_BUS(to_send);
if ((honda_hw == HONDA_BG_HW) && !honda_bosch_long) {
tx = msg_allowed(to_send, HONDA_BG_TX_MSGS, sizeof(HONDA_BG_TX_MSGS)/sizeof(HONDA_BG_TX_MSGS[0]));
} else if ((honda_hw == HONDA_BG_HW) && honda_bosch_long) {
tx = msg_allowed(to_send, HONDA_BG_LONG_TX_MSGS, sizeof(HONDA_BG_LONG_TX_MSGS)/sizeof(HONDA_BG_LONG_TX_MSGS[0]));
} else if ((honda_hw == HONDA_BH_HW) && !honda_bosch_long) {
if ((honda_hw == HONDA_BH_HW) && !honda_bosch_long) {
tx = msg_allowed(to_send, HONDA_BH_TX_MSGS, sizeof(HONDA_BH_TX_MSGS)/sizeof(HONDA_BH_TX_MSGS[0]));
} else if ((honda_hw == HONDA_BH_HW) && honda_bosch_long) {
tx = msg_allowed(to_send, HONDA_BH_LONG_TX_MSGS, sizeof(HONDA_BH_LONG_TX_MSGS)/sizeof(HONDA_BH_LONG_TX_MSGS[0]));
@@ -204,10 +223,6 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
tx = msg_allowed(to_send, HONDA_N_TX_MSGS, sizeof(HONDA_N_TX_MSGS)/sizeof(HONDA_N_TX_MSGS[0]));
}
if (relay_malfunction) {
tx = 0;
}
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
// and the the latching controls_allowed flag is True
int pedal_pressed = brake_pressed_prev && vehicle_moving;
@@ -296,9 +311,9 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
// Only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address
if (addr == 0x18DAB0F1) {
if ((GET_BYTES_04(to_send) != 0x00803E02) || (GET_BYTES_48(to_send) != 0x0)) {
tx = 0;
}
if ((GET_BYTES_04(to_send) != 0x00803E02) || (GET_BYTES_48(to_send) != 0x0)) {
tx = 0;
}
}
// 1 allows the message through
@@ -313,23 +328,12 @@ static const addr_checks* honda_nidec_init(int16_t param) {
honda_hw = HONDA_N_HW;
honda_alt_brake_msg = false;
honda_bosch_long = false;
honda_rx_checks = (addr_checks){honda_addr_checks, HONDA_ADDR_CHECKS_LEN};
return &honda_rx_checks;
}
static const addr_checks* honda_bosch_giraffe_init(int16_t param) {
controls_allowed = false;
relay_malfunction_reset();
honda_hw = HONDA_BG_HW;
// Checking for alternate brake override from safety parameter
honda_alt_brake_msg = GET_FLAG(param, HONDA_PARAM_ALT_BRAKE);
// radar disabled so allow gas/brakes
#ifdef ALLOW_DEBUG
honda_bosch_long = GET_FLAG(param, HONDA_PARAM_BOSCH_LONG);
#endif
honda_rx_checks = (addr_checks){honda_addr_checks, HONDA_ADDR_CHECKS_LEN};
if (GET_FLAG(param, HONDA_PARAM_NIDEC_ALT)) {
honda_rx_checks = (addr_checks){honda_nidec_alt_addr_checks, HONDA_NIDEC_ALT_ADDR_CHECKS_LEN};
} else {
honda_rx_checks = (addr_checks){honda_nidec_addr_checks, HONDA_NIDEC_ADDR_CHECKS_LEN};
}
return &honda_rx_checks;
}
@@ -349,48 +353,47 @@ static const addr_checks* honda_bosch_harness_init(int16_t param) {
return &honda_rx_checks;
}
static int honda_nidec_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int honda_nidec_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
// fwd from car to camera. also fwd certain msgs from camera to car
// 0xE4 is steering on all cars except CRV and RDX, 0x194 for CRV and RDX,
// 0x1FA is brake control, 0x30C is acc hud, 0x33D is lkas hud,
int bus_fwd = -1;
if (!relay_malfunction) {
if (bus_num == 0) {
bus_fwd = 2;
}
if (bus_num == 2) {
// block stock lkas messages and stock acc messages (if OP is doing ACC)
int addr = GET_ADDR(to_fwd);
bool is_lkas_msg = (addr == 0xE4) || (addr == 0x194) || (addr == 0x33D);
bool is_acc_hud_msg = addr == 0x30C;
bool is_brake_msg = addr == 0x1FA;
bool block_fwd = is_lkas_msg || is_acc_hud_msg || (is_brake_msg && !honda_fwd_brake);
if (!block_fwd) {
bus_fwd = 0;
}
if (bus_num == 0) {
bus_fwd = 2;
}
if (bus_num == 2) {
// block stock lkas messages and stock acc messages (if OP is doing ACC)
int addr = GET_ADDR(to_fwd);
bool is_lkas_msg = (addr == 0xE4) || (addr == 0x194) || (addr == 0x33D);
bool is_acc_hud_msg = addr == 0x30C;
bool is_brake_msg = addr == 0x1FA;
bool block_fwd = is_lkas_msg || is_acc_hud_msg || (is_brake_msg && !honda_fwd_brake);
if (!block_fwd) {
bus_fwd = 0;
}
}
return bus_fwd;
}
static int honda_bosch_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int honda_bosch_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
int bus_fwd = -1;
int bus_rdr_cam = (honda_hw == HONDA_BH_HW) ? 2 : 1; // radar bus, camera side
int bus_rdr_car = (honda_hw == HONDA_BH_HW) ? 0 : 2; // radar bus, car side
if (!relay_malfunction) {
if (bus_num == bus_rdr_car) {
bus_fwd = bus_rdr_cam;
}
if (bus_num == bus_rdr_cam) {
int addr = GET_ADDR(to_fwd);
int is_lkas_msg = (addr == 0xE4) || (addr == 0xE5) || (addr == 0x33D);
if (!is_lkas_msg) {
bus_fwd = bus_rdr_car;
}
if (bus_num == bus_rdr_car) {
bus_fwd = bus_rdr_cam;
}
if (bus_num == bus_rdr_cam) {
int addr = GET_ADDR(to_fwd);
int is_lkas_msg = (addr == 0xE4) || (addr == 0xE5) || (addr == 0x33D);
if (!is_lkas_msg) {
bus_fwd = bus_rdr_car;
}
}
return bus_fwd;
}
@@ -402,14 +405,6 @@ const safety_hooks honda_nidec_hooks = {
.fwd = honda_nidec_fwd_hook,
};
const safety_hooks honda_bosch_giraffe_hooks = {
.init = honda_bosch_giraffe_init,
.rx = honda_rx_hook,
.tx = honda_tx_hook,
.tx_lin = nooutput_tx_lin_hook,
.fwd = honda_bosch_fwd_hook,
};
const safety_hooks honda_bosch_harness_hooks = {
.init = honda_bosch_harness_init,
.rx = honda_rx_hook,
+13 -17
View File
@@ -69,7 +69,7 @@ bool hyundai_longitudinal = false;
addr_checks hyundai_rx_checks = {hyundai_addr_checks, HYUNDAI_ADDR_CHECK_LEN};
static uint8_t hyundai_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t hyundai_get_counter(CANPacket_t *to_push) {
int addr = GET_ADDR(to_push);
uint8_t cnt;
@@ -89,7 +89,7 @@ static uint8_t hyundai_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
return cnt;
}
static uint8_t hyundai_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t hyundai_get_checksum(CANPacket_t *to_push) {
int addr = GET_ADDR(to_push);
uint8_t chksum;
@@ -107,7 +107,7 @@ static uint8_t hyundai_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
return chksum;
}
static uint8_t hyundai_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t hyundai_compute_checksum(CANPacket_t *to_push) {
int addr = GET_ADDR(to_push);
uint8_t chksum = 0;
@@ -143,7 +143,7 @@ static uint8_t hyundai_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
return chksum;
}
static int hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int hyundai_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &hyundai_rx_checks,
hyundai_get_checksum, hyundai_compute_checksum,
@@ -223,7 +223,7 @@ static int hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
return valid;
}
static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int hyundai_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
@@ -234,10 +234,6 @@ static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
tx = msg_allowed(to_send, HYUNDAI_TX_MSGS, sizeof(HYUNDAI_TX_MSGS)/sizeof(HYUNDAI_TX_MSGS[0]));
}
if (relay_malfunction) {
tx = 0;
}
// FCA11: Block any potential actuation
if (addr == 909) {
int CR_VSM_DecCmd = GET_BYTE(to_send, 1);
@@ -342,19 +338,19 @@ static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return tx;
}
static int hyundai_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int hyundai_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
int bus_fwd = -1;
int addr = GET_ADDR(to_fwd);
// forward cam to ccan and viceversa, except lkas cmd
if (!relay_malfunction) {
if (bus_num == 0) {
bus_fwd = 2;
}
if ((bus_num == 2) && (addr != 832) && (addr != 1157)) {
bus_fwd = 0;
}
if (bus_num == 0) {
bus_fwd = 2;
}
if ((bus_num == 2) && (addr != 832) && (addr != 1157)) {
bus_fwd = 0;
}
return bus_fwd;
}
+28 -41
View File
@@ -1,5 +1,6 @@
// CAN msgs we care about
#define MAZDA_LKAS 0x243
#define MAZDA_LKAS_HUD 0x440
#define MAZDA_CRZ_CTRL 0x21c
#define MAZDA_CRZ_BTNS 0x09d
#define MAZDA_STEER_TORQUE 0x240
@@ -23,12 +24,7 @@
#define MAZDA_DRIVER_TORQUE_FACTOR 1
#define MAZDA_MAX_TORQUE_ERROR 350
// lkas enable speed 52kph, disable at 45kph
#define MAZDA_LKAS_ENABLE_SPEED 5200
#define MAZDA_LKAS_DISABLE_SPEED 4500
const CanMsg MAZDA_TX_MSGS[] = {{MAZDA_LKAS, 0, 8}, {MAZDA_CRZ_BTNS, 0, 8}};
bool mazda_lkas_allowed = false;
const CanMsg MAZDA_TX_MSGS[] = {{MAZDA_LKAS, 0, 8}, {MAZDA_CRZ_BTNS, 0, 8}, {MAZDA_LKAS_HUD, 0, 8}};
AddrCheckStruct mazda_addr_checks[] = {
{.msg = {{MAZDA_CRZ_CTRL, 0, 8, .expected_timestep = 20000U}, { 0 }, { 0 }}},
@@ -41,7 +37,7 @@ AddrCheckStruct mazda_addr_checks[] = {
addr_checks mazda_rx_checks = {mazda_addr_checks, MAZDA_ADDR_CHECKS_LEN};
// track msgs coming from OP so that we know what CAM msgs to drop and what to forward
static int mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int mazda_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &mazda_rx_checks, NULL, NULL, NULL);
if (valid && (GET_BUS(to_push) == MAZDA_MAIN)) {
int addr = GET_ADDR(to_push);
@@ -49,17 +45,7 @@ static int mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
if (addr == MAZDA_ENGINE_DATA) {
// sample speed: scale by 0.01 to get kph
int speed = (GET_BYTE(to_push, 2) << 8) | GET_BYTE(to_push, 3);
vehicle_moving = speed > 10; // moving when speed > 0.1 kph
// Enable LKAS at 52kph going up, disable at 45kph going down
if (speed > MAZDA_LKAS_ENABLE_SPEED) {
mazda_lkas_allowed = true;
} else if (speed < MAZDA_LKAS_DISABLE_SPEED) {
mazda_lkas_allowed = false;
} else {
// Misra-able appeasment block!
}
}
if (addr == MAZDA_STEER_TORQUE) {
@@ -73,13 +59,7 @@ static int mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
bool cruise_engaged = GET_BYTE(to_push, 0) & 8;
if (cruise_engaged) {
if (!cruise_engaged_prev) {
// do not engage until we hit the speed at which lkas is on
if (mazda_lkas_allowed) {
controls_allowed = 1;
} else {
controls_allowed = 0;
cruise_engaged = false;
}
controls_allowed = 1;
}
} else {
controls_allowed = 0;
@@ -100,7 +80,7 @@ static int mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
return valid;
}
static int mazda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int mazda_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
int bus = GET_BUS(to_send);
@@ -109,10 +89,6 @@ static int mazda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
tx = 0;
}
if (relay_malfunction) {
tx = 0;
}
// Check if msg is sent on the main BUS
if (bus == MAZDA_MAIN) {
@@ -162,24 +138,36 @@ static int mazda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
tx = 0;
}
}
// cruise buttons check
if (addr == MAZDA_CRZ_BTNS) {
// allow resume spamming while controls allowed, but
// only allow cancel while contrls not allowed
bool cancel_cmd = (GET_BYTE(to_send, 0) == 0x1U);
if (!controls_allowed && !cancel_cmd) {
tx = 0;
}
}
}
return tx;
}
static int mazda_fwd_hook(int bus, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int mazda_fwd_hook(int bus, CANPacket_t *to_fwd) {
int bus_fwd = -1;
if (!relay_malfunction) {
int addr = GET_ADDR(to_fwd);
if (bus == MAZDA_MAIN) {
bus_fwd = MAZDA_CAM;
} else if (bus == MAZDA_CAM) {
if (!(addr == MAZDA_LKAS)) {
bus_fwd = MAZDA_MAIN;
}
} else {
bus_fwd = -1;
int addr = GET_ADDR(to_fwd);
if (bus == MAZDA_MAIN) {
bus_fwd = MAZDA_CAM;
} else if (bus == MAZDA_CAM) {
bool block = (addr == MAZDA_LKAS) || (addr == MAZDA_LKAS_HUD);
if (!block) {
bus_fwd = MAZDA_MAIN;
}
} else {
// don't fwd
}
return bus_fwd;
}
@@ -187,7 +175,6 @@ static const addr_checks* mazda_init(int16_t param) {
UNUSED(param);
controls_allowed = false;
relay_malfunction_reset();
mazda_lkas_allowed = false;
return &mazda_rx_checks;
}
+14 -16
View File
@@ -11,7 +11,14 @@ const struct lookup_t NISSAN_LOOKUP_ANGLE_RATE_DOWN = {
const int NISSAN_DEG_TO_CAN = 100;
const CanMsg NISSAN_TX_MSGS[] = {{0x169, 0, 8}, {0x2b1, 0, 8}, {0x4cc, 0, 8}, {0x20b, 2, 6}, {0x20b, 1, 6}, {0x280, 2, 8}};
const CanMsg NISSAN_TX_MSGS[] = {
{0x169, 0, 8}, // LKAS
{0x2b1, 0, 8}, // PROPILOT_HUD
{0x4cc, 0, 8}, // PROPILOT_HUD_INFO_MSG
{0x20b, 2, 6}, // CRUISE_THROTTLE (X-Trail)
{0x20b, 1, 6}, // CRUISE_THROTTLE (Altima)
{0x280, 2, 8} // CANCEL_MSG (Leaf)
};
// Signals duplicated below due to the fact that these messages can come in on either CAN bus, depending on car model.
AddrCheckStruct nissan_addr_checks[] = {
@@ -34,7 +41,7 @@ addr_checks nissan_rx_checks = {nissan_addr_checks, NISSAN_ADDR_CHECK_LEN};
// EPS Location. false = V-CAN, true = C-CAN
bool nissan_alt_eps = false;
static int nissan_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int nissan_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &nissan_rx_checks, NULL, NULL, NULL);
@@ -71,12 +78,12 @@ static int nissan_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
}
// X-trail 0x454, Leaf 0x1cc
if ((addr == 0x454) || (addr == 0x1cc)) {
// X-trail 0x454, Leaf 0x239
if ((addr == 0x454) || (addr == 0x239)) {
if (addr == 0x454){
brake_pressed = (GET_BYTE(to_push, 2) & 0x80) != 0;
} else {
brake_pressed = GET_BYTE(to_push, 0) > 3;
brake_pressed = ((GET_BYTE(to_push, 4) >> 5) & 1) != 0;
}
}
@@ -99,7 +106,7 @@ static int nissan_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
static int nissan_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int nissan_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
bool violation = 0;
@@ -108,10 +115,6 @@ static int nissan_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
tx = 0;
}
if (relay_malfunction) {
tx = 0;
}
// steer cmd checks
if (addr == 0x169) {
int desired_angle = ((GET_BYTE(to_send, 0) << 10) | (GET_BYTE(to_send, 1) << 2) | ((GET_BYTE(to_send, 2) >> 6) & 0x3));
@@ -163,7 +166,7 @@ static int nissan_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
static int nissan_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int nissan_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
int bus_fwd = -1;
int addr = GET_ADDR(to_fwd);
@@ -182,11 +185,6 @@ static int nissan_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
}
}
if (relay_malfunction) {
bus_fwd = -1;
}
// fallback to do not forward
return bus_fwd;
}
+37 -47
View File
@@ -35,17 +35,17 @@ AddrCheckStruct subaru_l_addr_checks[] = {
{.msg = {{0x144, 0, 8, .expected_timestep = 50000U}, { 0 }, { 0 }}},
};
#define SUBARU_L_ADDR_CHECK_LEN (sizeof(subaru_l_addr_checks) / sizeof(subaru_l_addr_checks[0]))
addr_checks subaru_l_rx_checks = {subaru_addr_checks, SUBARU_L_ADDR_CHECK_LEN};
addr_checks subaru_l_rx_checks = {subaru_l_addr_checks, SUBARU_L_ADDR_CHECK_LEN};
static uint8_t subaru_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t subaru_get_checksum(CANPacket_t *to_push) {
return (uint8_t)GET_BYTE(to_push, 0);
}
static uint8_t subaru_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t subaru_get_counter(CANPacket_t *to_push) {
return (uint8_t)(GET_BYTE(to_push, 1) & 0xF);
}
static uint8_t subaru_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t subaru_compute_checksum(CANPacket_t *to_push) {
int addr = GET_ADDR(to_push);
int len = GET_LEN(to_push);
uint8_t checksum = (uint8_t)(addr) + (uint8_t)((unsigned int)(addr) >> 8U);
@@ -55,7 +55,7 @@ static uint8_t subaru_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
return checksum;
}
static int subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int subaru_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &subaru_rx_checks,
subaru_get_checksum, subaru_compute_checksum, subaru_get_counter);
@@ -102,7 +102,7 @@ static int subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
return valid;
}
static int subaru_legacy_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int subaru_legacy_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &subaru_l_rx_checks, NULL, NULL, NULL);
@@ -148,7 +148,7 @@ static int subaru_legacy_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
return valid;
}
static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int subaru_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
@@ -156,10 +156,6 @@ static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
tx = 0;
}
if (relay_malfunction) {
tx = 0;
}
// steer cmd checks
if (addr == 0x122) {
int desired_torque = ((GET_BYTES_04(to_send) >> 16) & 0x1FFF);
@@ -212,7 +208,7 @@ static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return tx;
}
static int subaru_legacy_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int subaru_legacy_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
@@ -220,10 +216,6 @@ static int subaru_legacy_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
tx = 0;
}
if (relay_malfunction) {
tx = 0;
}
// steer cmd checks
if (addr == 0x164) {
int desired_torque = ((GET_BYTES_04(to_send) >> 8) & 0x1FFF);
@@ -276,48 +268,46 @@ static int subaru_legacy_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return tx;
}
static int subaru_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int subaru_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
int bus_fwd = -1;
if (!relay_malfunction) {
if (bus_num == 0) {
bus_fwd = 2; // Camera CAN
}
if (bus_num == 2) {
// Global platform
// 0x122 ES_LKAS
// 0x221 ES_Distance
// 0x322 ES_LKAS_State
int addr = GET_ADDR(to_fwd);
int block_msg = ((addr == 0x122) || (addr == 0x221) || (addr == 0x322));
if (!block_msg) {
bus_fwd = 0; // Main CAN
}
if (bus_num == 0) {
bus_fwd = 2; // Camera CAN
}
if (bus_num == 2) {
// Global platform
// 0x122 ES_LKAS
// 0x221 ES_Distance
// 0x322 ES_LKAS_State
int addr = GET_ADDR(to_fwd);
int block_msg = ((addr == 0x122) || (addr == 0x221) || (addr == 0x322));
if (!block_msg) {
bus_fwd = 0; // Main CAN
}
}
// fallback to do not forward
return bus_fwd;
}
static int subaru_legacy_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int subaru_legacy_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
int bus_fwd = -1;
if (!relay_malfunction) {
if (bus_num == 0) {
bus_fwd = 2; // Camera CAN
}
if (bus_num == 2) {
// Preglobal platform
// 0x161 is ES_CruiseThrottle
// 0x164 is ES_LKAS
int addr = GET_ADDR(to_fwd);
int block_msg = ((addr == 0x161) || (addr == 0x164));
if (!block_msg) {
bus_fwd = 0; // Main CAN
}
if (bus_num == 0) {
bus_fwd = 2; // Camera CAN
}
if (bus_num == 2) {
// Preglobal platform
// 0x161 is ES_CruiseThrottle
// 0x164 is ES_LKAS
int addr = GET_ADDR(to_fwd);
int block_msg = ((addr == 0x161) || (addr == 0x164));
if (!block_msg) {
bus_fwd = 0; // Main CAN
}
}
// fallback to do not forward
return bus_fwd;
}
+96 -49
View File
@@ -7,18 +7,29 @@ const struct lookup_t TESLA_LOOKUP_ANGLE_RATE_DOWN = {
{5., 3.5, .8}};
const int TESLA_DEG_TO_CAN = 10;
const float TESLA_MAX_ACCEL = 2.0; // m/s^2
const float TESLA_MIN_ACCEL = -3.5; // m/s^2
const int TESLA_FLAG_POWERTRAIN = 1;
const int TESLA_FLAG_LONGITUDINAL_CONTROL = 2;
const CanMsg TESLA_TX_MSGS[] = {
{0x488, 0, 4}, // DAS_steeringControl
{0x45, 0, 8}, // STW_ACTN_RQ
{0x45, 2, 8}, // STW_ACTN_RQ
{0x2b9, 0, 8}, // DAS_control
};
#define TESLA_TX_LEN (sizeof(TESLA_TX_MSGS) / sizeof(TESLA_TX_MSGS[0]))
const CanMsg TESLA_PT_TX_MSGS[] = {
{0x2bf, 0, 8}, // DAS_control
};
#define TESLA_PT_TX_LEN (sizeof(TESLA_PT_TX_MSGS) / sizeof(TESLA_PT_TX_MSGS[0]))
AddrCheckStruct tesla_addr_checks[] = {
{.msg = {{0x370, 0, 8, .expected_timestep = 40000U}, { 0 }, { 0 }}}, // EPAS_sysStatus (25Hz)
{.msg = {{0x108, 0, 8, .expected_timestep = 10000U}, { 0 }, { 0 }}}, // DI_torque1 (100Hz)
{.msg = {{0x118, 0, 6, .expected_timestep = 10000U}, { 0 }, { 0 }}}, // DI_torque2 (100Hz)
{.msg = {{0x155, 0, 8, .expected_timestep = 20000U}, { 0 }, { 0 }}}, // ESP_B (50Hz)
{.msg = {{0x20a, 0, 8, .expected_timestep = 20000U}, { 0 }, { 0 }}}, // BrakeMessage (50Hz)
{.msg = {{0x368, 0, 8, .expected_timestep = 100000U}, { 0 }, { 0 }}}, // DI_state (10Hz)
{.msg = {{0x318, 0, 8, .expected_timestep = 100000U}, { 0 }, { 0 }}}, // GTW_carState (10Hz)
@@ -26,10 +37,20 @@ AddrCheckStruct tesla_addr_checks[] = {
#define TESLA_ADDR_CHECK_LEN (sizeof(tesla_addr_checks) / sizeof(tesla_addr_checks[0]))
addr_checks tesla_rx_checks = {tesla_addr_checks, TESLA_ADDR_CHECK_LEN};
bool autopilot_enabled = false;
AddrCheckStruct tesla_pt_addr_checks[] = {
{.msg = {{0x106, 0, 8, .expected_timestep = 10000U}, { 0 }, { 0 }}}, // DI_torque1 (100Hz)
{.msg = {{0x116, 0, 6, .expected_timestep = 10000U}, { 0 }, { 0 }}}, // DI_torque2 (100Hz)
{.msg = {{0x1f8, 0, 8, .expected_timestep = 20000U}, { 0 }, { 0 }}}, // BrakeMessage (50Hz)
{.msg = {{0x256, 0, 8, .expected_timestep = 100000U}, { 0 }, { 0 }}}, // DI_state (10Hz)
};
#define TESLA_PT_ADDR_CHECK_LEN (sizeof(tesla_pt_addr_checks) / sizeof(tesla_pt_addr_checks[0]))
addr_checks tesla_pt_rx_checks = {tesla_pt_addr_checks, TESLA_PT_ADDR_CHECK_LEN};
static int tesla_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
bool valid = addr_safety_check(to_push, &tesla_rx_checks,
bool tesla_longitudinal = false;
bool tesla_powertrain = false; // Are we the second panda intercepting the powertrain bus?
static int tesla_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, tesla_powertrain ? (&tesla_pt_rx_checks) : (&tesla_rx_checks),
NULL, NULL, NULL);
if(valid) {
@@ -37,30 +58,32 @@ static int tesla_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
int addr = GET_ADDR(to_push);
if(bus == 0) {
if(addr == 0x370) {
// Steering angle: (0.1 * val) - 819.2 in deg.
// Store it 1/10 deg to match steering request
int angle_meas_new = (((GET_BYTE(to_push, 4) & 0x3F) << 8) | GET_BYTE(to_push, 5)) - 8192;
update_sample(&angle_meas, angle_meas_new);
if (!tesla_powertrain) {
if(addr == 0x370) {
// Steering angle: (0.1 * val) - 819.2 in deg.
// Store it 1/10 deg to match steering request
int angle_meas_new = (((GET_BYTE(to_push, 4) & 0x3F) << 8) | GET_BYTE(to_push, 5)) - 8192;
update_sample(&angle_meas, angle_meas_new);
}
}
if(addr == 0x155) {
// Vehicle speed: (0.01 * val) * KPH_TO_MPS
vehicle_speed = ((GET_BYTE(to_push, 5) << 8) | (GET_BYTE(to_push, 6))) * 0.01 / 3.6;
vehicle_moving = vehicle_speed > 0.;
if(addr == (tesla_powertrain ? 0x116 : 0x118)) {
// Vehicle speed: ((0.05 * val) - 25) * MPH_TO_MPS
vehicle_speed = (((((GET_BYTE(to_push, 3) & 0x0F) << 8) | (GET_BYTE(to_push, 2))) * 0.05) - 25) * 0.447;
vehicle_moving = ABS(vehicle_speed) > 0.1;
}
if(addr == 0x108) {
if(addr == (tesla_powertrain ? 0x106 : 0x108)) {
// Gas pressed
gas_pressed = (GET_BYTE(to_push, 6) != 0);
}
if(addr == 0x20a) {
if(addr == (tesla_powertrain ? 0x1f8 : 0x20a)) {
// Brake pressed
brake_pressed = (((GET_BYTE(to_push, 0) & 0x0C) >> 2) != 1);
}
if(addr == 0x368) {
if(addr == (tesla_powertrain ? 0x256 : 0x368)) {
// Cruise state
int cruise_state = (GET_BYTE(to_push, 1) >> 4);
bool cruise_engaged = (cruise_state == 2) || // ENABLED
@@ -79,42 +102,31 @@ static int tesla_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
}
}
if (bus == 2) {
if (addr == 0x399) {
// Autopilot status
int autopilot_status = (GET_BYTE(to_push, 0) & 0xF);
autopilot_enabled = (autopilot_status == 3) || // ACTIVE_1
(autopilot_status == 4) || // ACTIVE_2
(autopilot_status == 5); // ACTIVE_NAVIGATE_ON_AUTOPILOT
if (autopilot_enabled) {
controls_allowed = 0;
}
}
if (tesla_powertrain) {
// 0x2bf: DAS_control should not be received on bus 0
generic_rx_checks((addr == 0x2bf) && (bus == 0));
} else {
// 0x488: DAS_steeringControl should not be received on bus 0
generic_rx_checks((addr == 0x488) && (bus == 0));
}
// 0x488: DAS_steeringControl should not be received on bus 0
generic_rx_checks((addr == 0x488) && (bus == 0));
}
return valid;
}
static int tesla_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int tesla_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
bool violation = false;
if(!msg_allowed(to_send, TESLA_TX_MSGS, sizeof(TESLA_TX_MSGS) / sizeof(TESLA_TX_MSGS[0]))) {
if(!msg_allowed(to_send,
tesla_powertrain ? TESLA_PT_TX_MSGS : TESLA_TX_MSGS,
tesla_powertrain ? TESLA_PT_TX_LEN : TESLA_TX_LEN)) {
tx = 0;
}
if(relay_malfunction) {
tx = 0;
}
if(addr == 0x488) {
if(!tesla_powertrain && (addr == 0x488)) {
// Steering control: (0.1 * val) - 1638.35 in deg.
// We use 1/10 deg as a unit here
int raw_angle_can = (((GET_BYTE(to_send, 0) & 0x7F) << 8) | GET_BYTE(to_send, 1));
@@ -150,7 +162,7 @@ static int tesla_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
}
if(addr == 0x45) {
if(!tesla_powertrain && (addr == 0x45)) {
// No button other than cancel can be sent by us
int control_lever_status = (GET_BYTE(to_send, 0) & 0x3F);
if((control_lever_status != 0) && (control_lever_status != 1)) {
@@ -158,6 +170,33 @@ static int tesla_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
}
}
if(addr == (tesla_powertrain ? 0x2bf : 0x2b9)) {
// DAS_control: longitudinal control message
if (tesla_longitudinal) {
// No AEB events may be sent by openpilot
int aeb_event = GET_BYTE(to_send, 2) & 0x03;
if (aeb_event != 0) {
violation = true;
}
// Don't allow any acceleration limits above the safety limits
int raw_accel_max = ((GET_BYTE(to_send, 6) & 0x1F) << 4) | (GET_BYTE(to_send, 5) >> 4);
int raw_accel_min = ((GET_BYTE(to_send, 5) & 0x0F) << 5) | (GET_BYTE(to_send, 4) >> 3);
float accel_max = (0.04 * raw_accel_max) - 15;
float accel_min = (0.04 * raw_accel_min) - 15;
if ((accel_max > TESLA_MAX_ACCEL) || (accel_min > TESLA_MAX_ACCEL)){
violation = true;
}
if ((accel_max < TESLA_MIN_ACCEL) || (accel_min < TESLA_MIN_ACCEL)){
violation = true;
}
} else {
violation = true;
}
}
if(violation) {
controls_allowed = 0;
tx = 0;
@@ -166,35 +205,43 @@ static int tesla_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return tx;
}
static int tesla_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int tesla_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
int bus_fwd = -1;
int addr = GET_ADDR(to_fwd);
if(bus_num == 0) {
// Chassis to autopilot
// Chassis/PT to autopilot
bus_fwd = 2;
}
if(bus_num == 2) {
// Autopilot to chassis
bool block_msg = ((addr == 0x488) && !autopilot_enabled);
// Autopilot to chassis/PT
int das_control_addr = (tesla_powertrain ? 0x2bf : 0x2b9);
bool block_msg = false;
if (!tesla_powertrain && (addr == 0x488)) {
block_msg = true;
}
if (tesla_longitudinal && (addr == das_control_addr)) {
block_msg = true;
}
if(!block_msg) {
bus_fwd = 0;
}
}
if(relay_malfunction) {
bus_fwd = -1;
}
return bus_fwd;
}
static const addr_checks* tesla_init(int16_t param) {
UNUSED(param);
tesla_powertrain = GET_FLAG(param, TESLA_FLAG_POWERTRAIN);
tesla_longitudinal = GET_FLAG(param, TESLA_FLAG_LONGITUDINAL_CONTROL);
controls_allowed = 0;
relay_malfunction_reset();
return &tesla_rx_checks;
return tesla_powertrain ? (&tesla_pt_rx_checks) : (&tesla_rx_checks);
}
const safety_hooks tesla_hooks = {
+21 -24
View File
@@ -44,7 +44,7 @@ addr_checks toyota_rx_checks = {toyota_addr_checks, TOYOTA_ADDR_CHECKS_LEN};
// global actuation limit states
int toyota_dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file
static uint8_t toyota_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t toyota_compute_checksum(CANPacket_t *to_push) {
int addr = GET_ADDR(to_push);
int len = GET_LEN(to_push);
uint8_t checksum = (uint8_t)(addr) + (uint8_t)((unsigned int)(addr) >> 8U) + (uint8_t)(len);
@@ -54,12 +54,12 @@ static uint8_t toyota_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
return checksum;
}
static uint8_t toyota_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t toyota_get_checksum(CANPacket_t *to_push) {
int checksum_byte = GET_LEN(to_push) - 1;
return (uint8_t)(GET_BYTE(to_push, checksum_byte));
}
static int toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int toyota_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &toyota_rx_checks,
toyota_get_checksum, toyota_compute_checksum, NULL);
@@ -134,7 +134,7 @@ static int toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
return valid;
}
static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int toyota_tx_hook(CANPacket_t *to_send) {
int tx = 1;
int addr = GET_ADDR(to_send);
@@ -144,10 +144,6 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
tx = 0;
}
if (relay_malfunction) {
tx = 0;
}
// Check if msg is sent on BUS 0
if (bus == 0) {
@@ -251,26 +247,27 @@ static const addr_checks* toyota_init(int16_t param) {
return &toyota_rx_checks;
}
static int toyota_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int toyota_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
int bus_fwd = -1;
if (!relay_malfunction) {
if (bus_num == 0) {
bus_fwd = 2;
}
if (bus_num == 2) {
int addr = GET_ADDR(to_fwd);
// block stock lkas messages and stock acc messages (if OP is doing ACC)
// in TSS2, 0x191 is LTA which we need to block to avoid controls collision
int is_lkas_msg = ((addr == 0x2E4) || (addr == 0x412) || (addr == 0x191));
// in TSS2 the camera does ACC as well, so filter 0x343
int is_acc_msg = (addr == 0x343);
int block_msg = is_lkas_msg || is_acc_msg;
if (!block_msg) {
bus_fwd = 0;
}
if (bus_num == 0) {
bus_fwd = 2;
}
if (bus_num == 2) {
int addr = GET_ADDR(to_fwd);
// block stock lkas messages and stock acc messages (if OP is doing ACC)
// in TSS2, 0x191 is LTA which we need to block to avoid controls collision
int is_lkas_msg = ((addr == 0x2E4) || (addr == 0x412) || (addr == 0x191));
// in TSS2 the camera does ACC as well, so filter 0x343
int is_acc_msg = (addr == 0x343);
int block_msg = is_lkas_msg || is_acc_msg;
if (!block_msg) {
bus_fwd = 0;
}
}
return bus_fwd;
}
+30 -31
View File
@@ -58,22 +58,22 @@ int volkswagen_lane_msg = 0;
uint8_t volkswagen_crc8_lut_8h2f[256]; // Static lookup table for CRC8 poly 0x2F, aka 8H2F/AUTOSAR
static uint8_t volkswagen_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t volkswagen_get_checksum(CANPacket_t *to_push) {
return (uint8_t)GET_BYTE(to_push, 0);
}
static uint8_t volkswagen_mqb_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t volkswagen_mqb_get_counter(CANPacket_t *to_push) {
// MQB message counters are consistently found at LSB 8.
return (uint8_t)GET_BYTE(to_push, 1) & 0xFU;
}
static uint8_t volkswagen_pq_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t volkswagen_pq_get_counter(CANPacket_t *to_push) {
// Few PQ messages have counters, and their offsets are inconsistent. This
// function works only for Lenkhilfe_3 at this time.
return (uint8_t)(GET_BYTE(to_push, 1) & 0xF0U) >> 4;
}
static uint8_t volkswagen_mqb_compute_crc(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t volkswagen_mqb_compute_crc(CANPacket_t *to_push) {
int addr = GET_ADDR(to_push);
int len = GET_LEN(to_push);
@@ -108,7 +108,7 @@ static uint8_t volkswagen_mqb_compute_crc(CAN_FIFOMailBox_TypeDef *to_push) {
return crc ^ 0xFFU;
}
static uint8_t volkswagen_pq_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
static uint8_t volkswagen_pq_compute_checksum(CANPacket_t *to_push) {
int len = GET_LEN(to_push);
uint8_t checksum = 0U;
@@ -140,7 +140,7 @@ static const addr_checks* volkswagen_pq_init(int16_t param) {
return &volkswagen_pq_rx_checks;
}
static int volkswagen_mqb_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int volkswagen_mqb_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &volkswagen_mqb_rx_checks,
volkswagen_get_checksum, volkswagen_mqb_compute_crc, volkswagen_mqb_get_counter);
@@ -200,7 +200,7 @@ static int volkswagen_mqb_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
return valid;
}
static int volkswagen_pq_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
static int volkswagen_pq_rx_hook(CANPacket_t *to_push) {
bool valid = addr_safety_check(to_push, &volkswagen_pq_rx_checks,
volkswagen_get_checksum, volkswagen_pq_compute_checksum, volkswagen_pq_get_counter);
@@ -297,11 +297,11 @@ static bool volkswagen_steering_check(int desired_torque) {
return violation;
}
static int volkswagen_mqb_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int volkswagen_mqb_tx_hook(CANPacket_t *to_send) {
int addr = GET_ADDR(to_send);
int tx = 1;
if (!msg_allowed(to_send, VOLKSWAGEN_MQB_TX_MSGS, VOLKSWAGEN_MQB_TX_MSGS_LEN) || relay_malfunction) {
if (!msg_allowed(to_send, VOLKSWAGEN_MQB_TX_MSGS, VOLKSWAGEN_MQB_TX_MSGS_LEN)) {
tx = 0;
}
@@ -333,11 +333,11 @@ static int volkswagen_mqb_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return tx;
}
static int volkswagen_pq_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
static int volkswagen_pq_tx_hook(CANPacket_t *to_send) {
int addr = GET_ADDR(to_send);
int tx = 1;
if (!msg_allowed(to_send, VOLKSWAGEN_PQ_TX_MSGS, VOLKSWAGEN_PQ_TX_MSGS_LEN) || relay_malfunction) {
if (!msg_allowed(to_send, VOLKSWAGEN_PQ_TX_MSGS, VOLKSWAGEN_PQ_TX_MSGS_LEN)) {
tx = 0;
}
@@ -370,31 +370,30 @@ static int volkswagen_pq_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
return tx;
}
static int volkswagen_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
static int volkswagen_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
int addr = GET_ADDR(to_fwd);
int bus_fwd = -1;
if (!relay_malfunction) {
switch (bus_num) {
case 0:
// Forward all traffic from the Extended CAN onward
bus_fwd = 2;
break;
case 2:
if ((addr == volkswagen_torque_msg) || (addr == volkswagen_lane_msg)) {
// OP takes control of the Heading Control Assist and Lane Departure Warning messages from the camera
bus_fwd = -1;
} else {
// Forward all remaining traffic from Extended CAN devices to J533 gateway
bus_fwd = 0;
}
break;
default:
// No other buses should be in use; fallback to do-not-forward
switch (bus_num) {
case 0:
// Forward all traffic from the Extended CAN onward
bus_fwd = 2;
break;
case 2:
if ((addr == volkswagen_torque_msg) || (addr == volkswagen_lane_msg)) {
// OP takes control of the Heading Control Assist and Lane Departure Warning messages from the camera
bus_fwd = -1;
break;
}
} else {
// Forward all remaining traffic from Extended CAN devices to J533 gateway
bus_fwd = 0;
}
break;
default:
// No other buses should be in use; fallback to do-not-forward
bus_fwd = -1;
break;
}
return bus_fwd;
}
+18 -11
View File
@@ -1,3 +1,9 @@
#define GET_BIT(msg, b) (((msg)->data[(int)((b) / 8)] >> ((b) % 8)) & 0x1)
#define GET_BYTE(msg, b) ((msg)->data[(b)])
#define GET_BYTES_04(msg) ((msg)->data[0] | ((msg)->data[1] << 8) | ((msg)->data[2] << 16) | ((msg)->data[3] << 24))
#define GET_BYTES_48(msg) ((msg)->data[4] | ((msg)->data[5] << 8) | ((msg)->data[6] << 16) | ((msg)->data[7] << 24))
#define GET_FLAG(value, mask) (((__typeof__(mask))(value) & (mask)) == (mask))
const int MAX_WRONG_COUNTERS = 5;
const uint8_t MAX_MISSED_MSGS = 10U;
@@ -48,8 +54,8 @@ typedef struct {
int len;
} addr_checks;
int safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
int safety_rx_hook(CANPacket_t *to_push);
int safety_tx_hook(CANPacket_t *to_send);
int safety_tx_lin_hook(int lin_num, uint8_t *data, int len);
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last);
int to_signed(int d, int bits);
@@ -63,25 +69,25 @@ bool driver_limit_check(int val, int val_last, struct sample_t *val_driver,
bool rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA);
float interpolate(struct lookup_t xy, float x);
void gen_crc_lookup_table(uint8_t poly, uint8_t crc_lut[]);
bool msg_allowed(CAN_FIFOMailBox_TypeDef *to_send, const CanMsg msg_list[], int len);
int get_addr_check_index(CAN_FIFOMailBox_TypeDef *to_push, AddrCheckStruct addr_list[], const int len);
bool msg_allowed(CANPacket_t *to_send, const CanMsg msg_list[], int len);
int get_addr_check_index(CANPacket_t *to_push, AddrCheckStruct addr_list[], const int len);
void update_counter(AddrCheckStruct addr_list[], int index, uint8_t counter);
void update_addr_timestamp(AddrCheckStruct addr_list[], int index);
bool is_msg_valid(AddrCheckStruct addr_list[], int index);
bool addr_safety_check(CAN_FIFOMailBox_TypeDef *to_push,
bool addr_safety_check(CANPacket_t *to_push,
const addr_checks *rx_checks,
uint8_t (*get_checksum)(CAN_FIFOMailBox_TypeDef *to_push),
uint8_t (*compute_checksum)(CAN_FIFOMailBox_TypeDef *to_push),
uint8_t (*get_counter)(CAN_FIFOMailBox_TypeDef *to_push));
uint8_t (*get_checksum)(CANPacket_t *to_push),
uint8_t (*compute_checksum)(CANPacket_t *to_push),
uint8_t (*get_counter)(CANPacket_t *to_push));
void generic_rx_checks(bool stock_ecu_detected);
void relay_malfunction_set(void);
void relay_malfunction_reset(void);
typedef const addr_checks* (*safety_hook_init)(int16_t param);
typedef int (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push);
typedef int (*tx_hook)(CAN_FIFOMailBox_TypeDef *to_send);
typedef int (*rx_hook)(CANPacket_t *to_push);
typedef int (*tx_hook)(CANPacket_t *to_send);
typedef int (*tx_lin_hook)(int lin_num, uint8_t *data, int len);
typedef int (*fwd_hook)(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd);
typedef int (*fwd_hook)(int bus_num, CANPacket_t *to_fwd);
typedef struct {
safety_hook_init init;
@@ -105,6 +111,7 @@ bool brake_pressed_prev = false;
bool cruise_engaged_prev = false;
float vehicle_speed = 0;
bool vehicle_moving = false;
bool acc_main_on = false; // referred to as "ACC off" in ISO 15622:2018
// for safety modes with torque steering control
int desired_torque_last = 0; // last desired steer torque
+4
View File
@@ -38,6 +38,10 @@
#define PROVISION_CHUNK_ADDRESS 0x1FFF79E0U
#define DEVICE_SERIAL_NUMBER_ADDRESS 0x1FFF79C0U
#define CANPACKET_DATA_SIZE_MAX 8U
#include "can_definitions.h"
#ifndef BOOTSTUB
#ifdef PANDA
#include "main_declarations.h"
+22 -14
View File
@@ -1,8 +1,8 @@
void clock_init(void) {
//Set power mode to direct SMPS power supply(depends on the board layout)
register_set(&(PWR->CR3), PWR_CR3_SMPSEN, 0xFU); // powered only by SMPS
//Set VOS level to VOS0. (VOS3 to 170Mhz, VOS2 to 300Mhz, VOS1 to 400Mhz, VOS0 to 550Mhz)
register_set(&(PWR->D3CR), PWR_D3CR_VOS_1, 0xC000U); //VOS2
//Set VOS level (VOS3 to 170Mhz, VOS2 to 300Mhz, VOS1 to 400Mhz, VOS0 to 550Mhz)
register_set(&(PWR->D3CR), PWR_D3CR_VOS_1 | PWR_D3CR_VOS_0, 0xC000U); //VOS1, needed for 80Mhz CAN FD
while ((PWR->CSR1 & PWR_CSR1_ACTVOSRDY) == 0);
while ((PWR->CSR1 & PWR_CSR1_ACTVOS) != (PWR->D3CR & PWR_D3CR_VOS)); // check that VOS level was actually set
// Configure Flash ACR register LATENCY and WRHIGHFREQ (VOS0 range!)
@@ -10,12 +10,12 @@ void clock_init(void) {
// enable external oscillator HSE
register_set_bits(&(RCC->CR), RCC_CR_HSEON);
while ((RCC->CR & RCC_CR_HSERDY) == 0);
// Specify the frequency source for PLL1, divider for DIVM1, divider for DIVM2 : HSE, 5, 5
register_set(&(RCC->PLLCKSELR), RCC_PLLCKSELR_PLLSRC_HSE | RCC_PLLCKSELR_DIVM1_0 | RCC_PLLCKSELR_DIVM1_2 | RCC_PLLCKSELR_DIVM2_0 | RCC_PLLCKSELR_DIVM2_2, 0x3F3F3U);
// Specify the frequency source for PLL1, divider for DIVM1, DIVM2, DIVM3 : HSE, 5, 5, 5
register_set(&(RCC->PLLCKSELR), RCC_PLLCKSELR_PLLSRC_HSE | RCC_PLLCKSELR_DIVM1_0 | RCC_PLLCKSELR_DIVM1_2 | RCC_PLLCKSELR_DIVM2_0 | RCC_PLLCKSELR_DIVM2_2 | RCC_PLLCKSELR_DIVM3_0 | RCC_PLLCKSELR_DIVM3_2, 0x3F3F3F3U);
// *** PLL1 start ***
// Specify multiplier N and dividers P, Q, R for PLL1 : 48, 1, 5, 2
register_set(&(RCC->PLL1DIVR), 0x104002FU, 0x7F7FFFFFU);
// Specify multiplier N and dividers P, Q, R for PLL1 : 48, 1, 3, 2 (clock 240Mhz, PLL1Q 80Mhz for CAN FD)
register_set(&(RCC->PLL1DIVR), 0x102002FU, 0x7F7FFFFFU);
// Specify the input and output frequency ranges, enable dividers for PLL1
register_set(&(RCC->PLLCFGR), RCC_PLLCFGR_PLL1RGE_2 | RCC_PLLCFGR_DIVP1EN | RCC_PLLCFGR_DIVQ1EN | RCC_PLLCFGR_DIVR1EN, 0x7000CU);
// Enable PLL1
@@ -23,6 +23,16 @@ void clock_init(void) {
while((RCC->CR & RCC_CR_PLL1RDY) == 0);
// *** PLL1 end ***
// *** PLL3 start ***
// Specify multiplier N and dividers P, Q, R for PLL1 : 48, 2, 5, 2 (PLL3Q 48Mhz for USB FS)
register_set(&(RCC->PLL3DIVR), 0x104022FU, 0x7F7FFFFFU);
// Specify the input and output frequency ranges, enable dividers for PLL1
register_set(&(RCC->PLLCFGR), RCC_PLLCFGR_PLL3RGE_2 | RCC_PLLCFGR_DIVP3EN | RCC_PLLCFGR_DIVQ3EN | RCC_PLLCFGR_DIVR3EN, 0x1C00C00U);
// Enable PLL1
register_set_bits(&(RCC->CR), RCC_CR_PLL3ON);
while((RCC->CR & RCC_CR_PLL3RDY) == 0);
// *** PLL1 end ***
//////////////OTHER CLOCKS////////////////////
// RCC HCLK Clock Source / RCC APB3 Clock Source / RCC SYS Clock Source
register_set(&(RCC->D1CFGR), RCC_D1CFGR_HPRE_DIV2 | RCC_D1CFGR_D1PPRE_DIV2 | RCC_D1CFGR_D1CPRE_DIV1, 0xF7FU);
@@ -30,8 +40,6 @@ void clock_init(void) {
register_set(&(RCC->D2CFGR), RCC_D2CFGR_D2PPRE1_DIV2 | RCC_D2CFGR_D2PPRE2_DIV2, 0x770U);
// RCC APB4 Clock Source
register_set(&(RCC->D3CFGR), RCC_D3CFGR_D3PPRE_DIV2, 0x70U);
// PLL2P for ADC
register_clear_bits(&(RCC->D3CFGR), RCC_D3CCIPR_ADCSEL);
// Set SysClock source to PLL
register_set(&(RCC->CFGR), RCC_CFGR_SW_PLL1, 0x7U);
@@ -41,12 +49,12 @@ void clock_init(void) {
register_set_bits(&(RCC->AHB4ENR), RCC_APB4ENR_SYSCFGEN);
//////////////END OTHER CLOCKS////////////////////
// Configure clock source for USB
register_set(&(RCC->D2CCIP2R), RCC_D2CCIP2R_USBSEL_0, RCC_D2CCIP2R_USBSEL); //PLL1Q
// Configure clock source for FDCAN
register_set(&(RCC->D2CCIP1R), RCC_D2CCIP1R_FDCANSEL_0, RCC_D2CCIP1R_FDCANSEL); //PLL1Q
// Configure clock source for ADC1,2,3
register_set(&(RCC->D3CCIPR), RCC_D3CCIPR_ADCSEL_1, RCC_D3CCIPR_ADCSEL); //per_ck(currently HSE)
// Configure clock source for USB (PLL3Q at 48Mhz)
register_set(&(RCC->D2CCIP2R), RCC_D2CCIP2R_USBSEL_1, RCC_D2CCIP2R_USBSEL);
// Configure clock source for FDCAN (PLL1Q at 80Mhz)
register_set(&(RCC->D2CCIP1R), RCC_D2CCIP1R_FDCANSEL_0, RCC_D2CCIP1R_FDCANSEL);
// Configure clock source for ADC1,2,3 (per_ck(currently HSE))
register_set(&(RCC->D3CCIPR), RCC_D3CCIPR_ADCSEL_1, RCC_D3CCIPR_ADCSEL);
//Enable the Clock Security System
register_set_bits(&(RCC->CR), RCC_CR_CSSHSEON);
//Enable Vdd33usb supply level detector
+13 -20
View File
@@ -4,28 +4,28 @@
#define FDCAN_OFFSET_W 853UL // words for each FDCAN module
#define FDCAN_END_ADDRESS 0x4000D3FCUL // Message RAM has a width of 4 Bytes
// With this settings we can go up to 6Mbit/s
// With this settings we can go up to 5Mbit/s
#define CAN_SYNC_JW 1U // 1 to 4
#define CAN_PHASE_SEG1 6U // =(PROP_SEG + PHASE_SEG1) , 1 to 16
#define CAN_PHASE_SEG2 1U // 1 to 8
#define CAN_PCLK 48000U // Sourced from PLL1Q
#define CAN_PCLK 80000U // Sourced from PLL1Q
#define CAN_QUANTA (1U + CAN_PHASE_SEG1 + CAN_PHASE_SEG2)
// Valid speeds in kbps and their prescalers:
// 10=600, 20=300, 50=120, 83.333=72, 100=60, 125=48, 250=24, 500=12, 1000=6, 2000=3, 3000=2, 6000=1
// 10=1000, 20=500, 50=200, 83.333=120, 100=100, 125=80, 250=40, 500=20, 1000=10, 2000=5, 5000=2
#define can_speed_to_prescaler(x) (CAN_PCLK / CAN_QUANTA * 10U / (x))
// RX FIFO 0
#define FDCAN_RX_FIFO_0_EL_CNT 32UL
#define FDCAN_RX_FIFO_0_EL_CNT 24UL
#define FDCAN_RX_FIFO_0_HEAD_SIZE 8UL // bytes
#define FDCAN_RX_FIFO_0_DATA_SIZE 8UL // bytes
#define FDCAN_RX_FIFO_0_DATA_SIZE 64UL // bytes
#define FDCAN_RX_FIFO_0_EL_SIZE (FDCAN_RX_FIFO_0_HEAD_SIZE + FDCAN_RX_FIFO_0_DATA_SIZE)
#define FDCAN_RX_FIFO_0_EL_W_SIZE (FDCAN_RX_FIFO_0_EL_SIZE / 4UL)
#define FDCAN_RX_FIFO_0_OFFSET 0UL
// TX FIFO
#define FDCAN_TX_FIFO_EL_CNT 32UL
#define FDCAN_TX_FIFO_EL_CNT 16UL
#define FDCAN_TX_FIFO_HEAD_SIZE 8UL // bytes
#define FDCAN_TX_FIFO_DATA_SIZE 8UL // bytes
#define FDCAN_TX_FIFO_DATA_SIZE 64UL // bytes
#define FDCAN_TX_FIFO_EL_SIZE (FDCAN_TX_FIFO_HEAD_SIZE + FDCAN_TX_FIFO_DATA_SIZE)
#define FDCAN_TX_FIFO_EL_W_SIZE (FDCAN_TX_FIFO_EL_SIZE / 4UL)
#define FDCAN_TX_FIFO_OFFSET (FDCAN_RX_FIFO_0_OFFSET + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_W_SIZE))
@@ -33,13 +33,6 @@
#define CAN_NAME_FROM_CANIF(CAN_DEV) (((CAN_DEV)==FDCAN1) ? "FDCAN1" : (((CAN_DEV) == FDCAN2) ? "FDCAN2" : "FDCAN3"))
#define CAN_NUM_FROM_CANIF(CAN_DEV) (((CAN_DEV)==FDCAN1) ? 0UL : (((CAN_DEV) == FDCAN2) ? 1UL : 2UL))
// For backwards compatibility with safety code
typedef struct {
__IO uint32_t RIR; /*!< CAN receive FIFO mailbox identifier register */
__IO uint32_t RDTR; /*!< CAN receive FIFO mailbox data length control and time stamp register */
__IO uint32_t RDLR; /*!< CAN receive FIFO mailbox data low register */
__IO uint32_t RDHR; /*!< CAN receive FIFO mailbox data high register */
} CAN_FIFOMailBox_TypeDef;
void puts(const char *a);
@@ -138,10 +131,10 @@ bool llcan_init(FDCAN_GlobalTypeDef *CANx) {
// Set TX mode to FIFO
CANx->TXBC &= ~(FDCAN_TXBC_TFQM);
// Configure TX element size (for now 8 bytes, no need to change)
//CANx->TXESC |= 0x000U;
//Configure RX FIFO0, FIFO1, RX buffer element sizes (no need for now, using classic 8 bytes)
register_set(&(CANx->RXESC), 0x0U, (FDCAN_RXESC_F0DS | FDCAN_RXESC_F1DS | FDCAN_RXESC_RBDS));
// Configure TX element data size
CANx->TXESC |= 0x7U << FDCAN_TXESC_TBDS_Pos; // 64 bytes
//Configure RX FIFO0 element data size
CANx->RXESC |= 0x7U << FDCAN_RXESC_F0DS_Pos;
// Disable filtering, accept all valid frames received
CANx->XIDFC &= ~(FDCAN_XIDFC_LSE); // No extended filters
CANx->SIDFC &= ~(FDCAN_SIDFC_LSS); // No standard filters
@@ -154,13 +147,13 @@ bool llcan_init(FDCAN_GlobalTypeDef *CANx) {
uint32_t TxFIFOSA = RxFIFO0SA + (FDCAN_RX_FIFO_0_EL_CNT * FDCAN_RX_FIFO_0_EL_SIZE);
// RX FIFO 0
CANx->RXF0C = (FDCAN_RX_FIFO_0_OFFSET + (can_number * FDCAN_OFFSET_W)) << FDCAN_RXF0C_F0SA_Pos;
CANx->RXF0C |= (FDCAN_RX_FIFO_0_OFFSET + (can_number * FDCAN_OFFSET_W)) << FDCAN_RXF0C_F0SA_Pos;
CANx->RXF0C |= FDCAN_RX_FIFO_0_EL_CNT << FDCAN_RXF0C_F0S_Pos;
// RX FIFO 0 switch to non-blocking (overwrite) mode
CANx->RXF0C |= FDCAN_RXF0C_F0OM;
// TX FIFO (mode set earlier)
CANx->TXBC = (FDCAN_TX_FIFO_OFFSET + (can_number * FDCAN_OFFSET_W)) << FDCAN_TXBC_TBSA_Pos;
CANx->TXBC |= (FDCAN_TX_FIFO_OFFSET + (can_number * FDCAN_OFFSET_W)) << FDCAN_TXBC_TBSA_Pos;
CANx->TXBC |= FDCAN_TX_FIFO_EL_CNT << FDCAN_TXBC_TFQS_Pos;
// Flush allocated RAM
+4
View File
@@ -34,6 +34,10 @@
#define PROVISION_CHUNK_ADDRESS 0x080FFFE0U
#define DEVICE_SERIAL_NUMBER_ADDRESS 0x080FFFC0U
#define CANPACKET_DATA_SIZE_MAX 64U
#include "can_definitions.h"
#ifndef BOOTSTUB
#include "main_declarations.h"
#else
+6
View File
@@ -180,6 +180,12 @@ SECTIONS
. = ALIGN(8);
} >DTCMRAM
.ram_d1 (NOLOAD) :
{
. = ALIGN(4);
*(.ram_d1*)
} >RAM_D1
.ARM.attributes 0 : { *(.ARM.attributes) }
}
+108
View File
@@ -0,0 +1,108 @@
typedef struct {
uint8_t ptr;
uint8_t tail_size;
uint8_t data[72];
uint8_t counter;
} usb_asm_buffer;
usb_asm_buffer ep1_buffer = {.ptr = 0, .tail_size = 0, .counter = 0};
uint32_t total_rx_size = 0;
int usb_cb_ep1_in(void *usbdata, int len, bool hardwired) {
UNUSED(hardwired);
uint8_t pos = 1;
uint8_t *usbdata8 = (uint8_t *)usbdata;
usbdata8[0] = ep1_buffer.counter;
// Send tail of previous message if it is in buffer
if (ep1_buffer.ptr > 0) {
if (ep1_buffer.ptr <= 63U) {
(void)memcpy(&usbdata8[pos], ep1_buffer.data, ep1_buffer.ptr);
pos += ep1_buffer.ptr;
ep1_buffer.ptr = 0;
} else {
(void)memcpy(&usbdata8[pos], ep1_buffer.data, 63U);
ep1_buffer.ptr = ep1_buffer.ptr - 63U;
(void)memcpy(ep1_buffer.data, &ep1_buffer.data[63U], ep1_buffer.ptr);
pos += 63U;
}
}
if (total_rx_size > MAX_EP1_CHUNK_PER_BULK_TRANSFER) {
total_rx_size = 0;
ep1_buffer.counter = 0;
} else {
CANPacket_t can_packet;
while ((pos < len) && can_pop(&can_rx_q, &can_packet)) {
uint8_t pckt_len = CANPACKET_HEAD_SIZE + dlc_to_len[can_packet.data_len_code];
if ((pos + pckt_len) <= len) {
(void)memcpy(&usbdata8[pos], &can_packet, pckt_len);
pos += pckt_len;
} else {
(void)memcpy(&usbdata8[pos], &can_packet, len - pos);
ep1_buffer.ptr = pckt_len - (len - pos);
//(void)memcpy(ep1_buffer.data, ((uint8_t*)&can_packet + (len - pos)), ep1_buffer.ptr);
// cppcheck-suppress objectIndex
(void)memcpy(ep1_buffer.data, &((uint8_t*)&can_packet)[(len - pos)], ep1_buffer.ptr);
pos = len;
}
}
ep1_buffer.counter++;
total_rx_size += pos;
}
if (pos != len) {
ep1_buffer.counter = 0;
total_rx_size = 0;
}
if (pos <= 1) { pos = 0; }
return pos;
}
usb_asm_buffer ep3_buffer = {.ptr = 0, .tail_size = 0, .counter = 0};
// send on CAN
void usb_cb_ep3_out(void *usbdata, int len, bool hardwired) {
UNUSED(hardwired);
uint8_t *usbdata8 = (uint8_t *)usbdata;
// Got first packet from a stream, resetting buffer and counter
if (usbdata8[0] == 0) {
ep3_buffer.counter = 0;
ep3_buffer.ptr = 0;
ep3_buffer.tail_size = 0;
}
// Assembling can message with data from buffer
if (usbdata8[0] == ep3_buffer.counter) {
uint8_t pos = 1;
ep3_buffer.counter++;
if (ep3_buffer.ptr != 0) {
if (ep3_buffer.tail_size <= 63U) {
CANPacket_t to_push;
(void)memcpy(&ep3_buffer.data[ep3_buffer.ptr], &usbdata8[pos], ep3_buffer.tail_size);
(void)memcpy(&to_push, ep3_buffer.data, ep3_buffer.ptr + ep3_buffer.tail_size);
can_send(&to_push, to_push.bus, false);
pos += ep3_buffer.tail_size;
ep3_buffer.ptr = 0;
ep3_buffer.tail_size = 0;
} else {
(void)memcpy(&ep3_buffer.data[ep3_buffer.ptr], &usbdata8[pos], len - pos);
ep3_buffer.tail_size -= 63U;
ep3_buffer.ptr += 63U;
pos += 63U;
}
}
while (pos < len) {
uint8_t pckt_len = CANPACKET_HEAD_SIZE + dlc_to_len[(usbdata8[pos] >> 4U)];
if ((pos + pckt_len) <= (uint8_t)len) {
CANPacket_t to_push;
(void)memcpy(&to_push, &usbdata8[pos], pckt_len);
can_send(&to_push, to_push.bus, false);
pos += pckt_len;
} else {
(void)memcpy(ep3_buffer.data, &usbdata8[pos], len - pos);
ep3_buffer.ptr = len - pos;
ep3_buffer.tail_size = pckt_len - ep3_buffer.ptr;
pos += ep3_buffer.ptr;
}
}
}
}
+143 -38
View File
@@ -8,6 +8,7 @@ import os
import time
import traceback
import sys
from functools import wraps
from .dfu import PandaDFU, MCU_TYPE_F2, MCU_TYPE_F4, MCU_TYPE_H7 # pylint: disable=import-error
from .flash_release import flash_release # noqa pylint: disable=import-error
from .update import ensure_st_up_to_date # noqa pylint: disable=import-error
@@ -15,28 +16,105 @@ from .serial import PandaSerial # noqa pylint: disable=import-error
from .isotp import isotp_send, isotp_recv # pylint: disable=import-error
from .config import DEFAULT_FW_FN, DEFAULT_H7_FW_FN # noqa pylint: disable=import-error
__version__ = '0.0.9'
__version__ = '0.0.10'
BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")
DEBUG = os.getenv("PANDADEBUG") is not None
def parse_can_buffer(dat):
ret = []
for j in range(0, len(dat), 0x10):
ddat = dat[j:j + 0x10]
f1, f2 = struct.unpack("II", ddat[0:8])
extended = 4
if f1 & extended:
address = f1 >> 3
else:
address = f1 >> 21
dddat = ddat[8:8 + (f2 & 0xF)]
CANPACKET_HEAD_SIZE = 0x5
DLC_TO_LEN = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64]
LEN_TO_DLC = {length: dlc for (dlc, length) in enumerate(DLC_TO_LEN)}
def pack_can_buffer(arr):
snds = [b'']
idx = 0
for address, _, dat, bus in arr:
assert len(dat) in LEN_TO_DLC
if DEBUG:
print(f" R 0x{address:x}: 0x{dddat.hex()}")
ret.append((address, f2 >> 16, dddat, (f2 >> 4) & 0xFF))
print(f" W 0x{address:x}: 0x{dat.hex()}")
extended = 1 if address >= 0x800 else 0
data_len_code = LEN_TO_DLC[len(dat)]
header = bytearray(5)
word_4b = address << 3 | extended << 2
header[0] = (data_len_code << 4) | (bus << 1)
header[1] = word_4b & 0xFF
header[2] = (word_4b >> 8) & 0xFF
header[3] = (word_4b >> 16) & 0xFF
header[4] = (word_4b >> 24) & 0xFF
snds[idx] += header + dat
if len(snds[idx]) > 256: # Limit chunks to 256 bytes
snds.append(b'')
idx += 1
#Apply counter to each 64 byte packet
for idx in range(len(snds)):
tx = b''
counter = 0
for i in range (0, len(snds[idx]), 63):
tx += bytes([counter]) + snds[idx][i:i+63]
counter += 1
snds[idx] = tx
return snds
def unpack_can_buffer(dat):
ret = []
counter = 0
tail = bytearray()
for i in range(0, len(dat), 64):
if counter != dat[i]:
print("CAN: LOST RECV PACKET COUNTER")
break
counter+=1
chunk = tail + dat[i+1:i+64]
tail = bytearray()
pos = 0
while pos<len(chunk):
data_len = DLC_TO_LEN[(chunk[pos]>>4)]
pckt_len = CANPACKET_HEAD_SIZE + data_len
if pckt_len <= len(chunk[pos:]):
header = chunk[pos:pos+CANPACKET_HEAD_SIZE]
if len(header) < 5:
print("CAN: MALFORMED USB RECV PACKET")
break
bus = (header[0] >> 1) & 0x7
address = (header[4] << 24 | header[3] << 16 | header[2] << 8 | header[1]) >> 3
returned = (header[1] >> 1) & 0x1
rejected = header[1] & 0x1
data = chunk[pos + CANPACKET_HEAD_SIZE:pos + CANPACKET_HEAD_SIZE + data_len]
if returned:
bus += 128
if rejected:
bus += 192
if DEBUG:
print(f" R 0x{address:x}: 0x{data.hex()}")
ret.append((address, 0, data, bus))
pos += pckt_len
else:
tail = chunk[pos:]
break
return ret
def ensure_health_packet_version(fn):
@wraps(fn)
def wrapper(self, *args, **kwargs):
if self.health_version < self.HEALTH_PACKET_VERSION:
raise RuntimeError("Panda firmware has outdated health packet definition. Reflash panda firmware.")
elif self.health_version > self.HEALTH_PACKET_VERSION:
raise RuntimeError("Panda python library has outdated health packet definition. Update panda python library.")
return fn(self, *args, **kwargs)
return wrapper
def ensure_can_packet_version(fn):
@wraps(fn)
def wrapper(self, *args, **kwargs):
if self.can_version < self.CAN_PACKET_VERSION:
raise RuntimeError("Panda firmware has outdated CAN packet definition. Reflash panda firmware.")
elif self.can_version > self.CAN_PACKET_VERSION:
raise RuntimeError("Panda python library has outdated CAN packet definition. Update panda python library.")
return fn(self, *args, **kwargs)
return wrapper
class PandaWifiStreaming(object):
def __init__(self, ip="192.168.0.10", port=1338):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
@@ -55,7 +133,7 @@ class PandaWifiStreaming(object):
try:
dat, addr = self.sock.recvfrom(0x200 * 0x10)
if addr == (self.ip, self.port):
ret += parse_can_buffer(dat)
ret += unpack_can_buffer(dat)
except socket.error as e:
if e.errno != 35 and e.errno != 11:
traceback.print_exc()
@@ -140,6 +218,9 @@ class Panda(object):
HW_TYPE_DOS = b'\x06'
HW_TYPE_RED_PANDA = b'\x07'
CAN_PACKET_VERSION = 2
HEALTH_PACKET_VERSION = 1
F2_DEVICES = [HW_TYPE_PEDAL]
F4_DEVICES = [HW_TYPE_WHITE_PANDA, HW_TYPE_GREY_PANDA, HW_TYPE_BLACK_PANDA, HW_TYPE_UNO, HW_TYPE_DOS]
H7_DEVICES = [HW_TYPE_RED_PANDA]
@@ -150,7 +231,13 @@ class Panda(object):
FLAG_HONDA_ALT_BRAKE = 1
FLAG_HONDA_BOSCH_LONG = 2
FLAG_HONDA_NIDEC_ALT = 4
FLAG_HYUNDAI_EV_GAS = 1
FLAG_HYUNDAI_HYBRID_GAS = 2
FLAG_HYUNDAI_LONG = 4
FLAG_TESLA_POWERTRAIN = 1
FLAG_TESLA_LONG_CONTROL = 2
def __init__(self, serial=None, claim=True):
self._serial = serial
@@ -201,6 +288,7 @@ class Panda(object):
break
context = usb1.USBContext() # New context needed so new devices show up
assert(self._handle is not None)
self.health_version, self.can_version = self.get_packets_versions()
print("connected")
def reset(self, enter_bootstub=False, enter_bootloader=False):
@@ -239,6 +327,8 @@ class Panda(object):
if not success:
raise Exception("reconnect failed")
@staticmethod
def flash_static(handle, code):
# confirm flasher is present
@@ -342,6 +432,7 @@ class Panda(object):
# ******************* health *******************
@ensure_health_packet_version
def health(self):
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd2, 0, 0, 44)
a = struct.unpack("<IIIIIIIIBBBBBBBHBBB", dat)
@@ -392,6 +483,15 @@ class Panda(object):
def get_type(self):
return self._handle.controlRead(Panda.REQUEST_IN, 0xc1, 0, 0, 0x40)
# Returns tuple with health packet version and CAN packet/USB packet version
def get_packets_versions(self):
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xdd, 0, 0, 2)
if dat:
a = struct.unpack("BB", dat)
return (a[0], a[1])
else:
return (0, 0)
def is_white(self):
return self.get_type() == Panda.HW_TYPE_WHITE_PANDA
@@ -409,7 +509,7 @@ class Panda(object):
def is_dos(self):
return self.get_type() == Panda.HW_TYPE_DOS
def is_red(self):
return self.get_type() == Panda.HW_TYPE_RED_PANDA
@@ -429,12 +529,18 @@ class Panda(object):
def has_canfd(self):
return self._mcu_type in Panda.H7_DEVICES
def is_internal(self):
return self.get_type() in [Panda.HW_TYPE_UNO, Panda.HW_TYPE_DOS]
def get_serial(self):
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd0, 0, 0, 0x20)
hashsig, calc_hash = dat[0x1c:], hashlib.sha1(dat[0:0x1c]).digest()[0:4]
assert(hashsig == calc_hash)
return [dat[0:0x10].decode("utf8"), dat[0x10:0x10 + 10].decode("utf8")]
def get_usb_serial(self):
return self._serial
def get_secret(self):
return self._handle.controlRead(Panda.REQUEST_IN, 0xd0, 1, 0, 0x10)
@@ -459,10 +565,6 @@ class Panda(object):
self.set_heartbeat_disabled()
self.set_power_save(0)
def set_can_forwarding(self, from_bus, to_bus):
# TODO: This feature may not work correctly with saturated buses
self._handle.controlWrite(Panda.REQUEST_OUT, 0xdd, from_bus, to_bus, b'')
def set_gmlan(self, bus=2):
# TODO: check panda type
if bus is None:
@@ -488,6 +590,15 @@ class Panda(object):
def set_can_data_speed_kbps(self, bus, speed):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf9, bus, int(speed * 10), b'')
# CAN FD and BRS status
def get_canfd_status(self, bus):
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xfa, bus, 0, 2)
if dat:
a = struct.unpack("BB", dat)
return (a[0], a[1])
else:
return (None, None)
def set_uart_baud(self, uart, rate):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe4, uart, int(rate / 300), b'')
@@ -505,29 +616,22 @@ class Panda(object):
# Timeout is in ms. If set to 0, the timeout is infinite.
CAN_SEND_TIMEOUT_MS = 10
@ensure_can_packet_version
def can_send_many(self, arr, timeout=CAN_SEND_TIMEOUT_MS):
snds = []
transmit = 1
extended = 4
for addr, _, dat, bus in arr:
assert len(dat) <= 8
if DEBUG:
print(f" W 0x{addr:x}: 0x{dat.hex()}")
if addr >= 0x800:
rir = (addr << 3) | transmit | extended
else:
rir = (addr << 21) | transmit
snd = struct.pack("II", rir, len(dat) | (bus << 4)) + dat
snd = snd.ljust(0x10, b'\x00')
snds.append(snd)
snds = pack_can_buffer(arr)
while True:
try:
if self.wifi:
for s in snds:
self._handle.bulkWrite(3, s)
else:
self._handle.bulkWrite(3, b''.join(snds), timeout=timeout)
for tx in snds:
while True:
bs = self._handle.bulkWrite(3, tx, timeout=timeout)
tx = tx[bs:]
if len(tx) == 0:
break
print("CAN: PARTIAL SEND MANY, RETRYING")
break
except (usb1.USBErrorIO, usb1.USBErrorOverflow):
print("CAN: BAD SEND MANY, RETRYING")
@@ -535,16 +639,17 @@ class Panda(object):
def can_send(self, addr, dat, bus, timeout=CAN_SEND_TIMEOUT_MS):
self.can_send_many([[addr, None, dat, bus]], timeout=timeout)
@ensure_can_packet_version
def can_recv(self):
dat = bytearray()
while True:
try:
dat = self._handle.bulkRead(1, 0x10 * 256)
dat = self._handle.bulkRead(1, 16384) # Max receive batch size + 2 extra reserve frames
break
except (usb1.USBErrorIO, usb1.USBErrorOverflow):
print("CAN: BAD RECV, RETRYING")
time.sleep(0.1)
return parse_can_buffer(dat)
return unpack_can_buffer(dat)
def can_clear(self, bus):
"""Clears all messages from the specified internal CAN ringbuffer as
+362
View File
@@ -0,0 +1,362 @@
#!/usr/bin/env python3
import sys
import time
import struct
from enum import IntEnum, Enum
class COMMAND_CODE(IntEnum):
CONNECT = 0x01
SET_MTA = 0x02
DNLOAD = 0x03
UPLOAD = 0x04
TEST = 0x05
START_STOP = 0x06
DISCONNECT = 0x07
START_STOP_ALL = 0x08
GET_ACTIVE_CAL_PAGE = 0x09
SET_S_STATUS = 0x0C
GET_S_STATUS = 0x0D
BUILD_CHKSUM = 0x0E
SHORT_UP = 0x0F
CLEAR_MEMORY = 0x10
SELECT_CAL_PAGE = 0x11
GET_SEED = 0x12
UNLOCK = 0x13
GET_DAQ_SIZE = 0x14
SET_DAQ_PTR = 0x15
WRITE_DAQ = 0x16
EXCHANGE_ID = 0x17
PROGRAM = 0x18
MOVE = 0x19
GET_CCP_VERSION = 0x1B
DIAG_SERVICE = 0x20
ACTION_SERVICE = 0x21
PROGRAM_6 = 0x22
DNLOAD_6 = 0x23
COMMAND_RETURN_CODES = {
0x00: "acknowledge / no error",
0x01: "DAQ processor overload",
0x10: "command processor busy",
0x11: "DAQ processor busy",
0x12: "internal timeout",
0x18: "key request",
0x19: "session status request",
0x20: "cold start request",
0x21: "cal. data init. request",
0x22: "DAQ list init. request",
0x23: "code update request",
0x30: "unknown command",
0x31: "command syntax",
0x32: "parameter(s) out of range",
0x33: "access denied",
0x34: "overload",
0x35: "access locked",
0x36: "resource/function not available",
}
class BYTE_ORDER(Enum):
LITTLE_ENDIAN = '<'
BIG_ENDIAN = '>'
class CommandTimeoutError(Exception):
pass
class CommandCounterError(Exception):
pass
class CommandResponseError(Exception):
def __init__(self, message, return_code):
super().__init__()
self.message = message
self.return_code = return_code
def __str__(self):
return self.message
class CcpClient():
def __init__(self, panda, tx_addr: int, rx_addr: int, bus: int=0, byte_order: BYTE_ORDER=BYTE_ORDER.BIG_ENDIAN, debug=False):
self.tx_addr = tx_addr
self.rx_addr = rx_addr
self.can_bus = bus
self.byte_order = byte_order
self.debug = debug
self._panda = panda
self._command_counter = -1
def _send_cro(self, cmd: int, dat: bytes = b"") -> None:
self._command_counter = (self._command_counter + 1) & 0xFF
tx_data = (bytes([cmd, self._command_counter]) + dat).ljust(8, b"\x00")
if self.debug:
print(f"CAN-TX: {hex(self.tx_addr)} - 0x{bytes.hex(tx_data)}")
assert len(tx_data) == 8, "data is not 8 bytes"
self._panda.can_clear(self.can_bus)
self._panda.can_clear(0xFFFF)
self._panda.can_send(self.tx_addr, tx_data, self.can_bus)
def _recv_dto(self, timeout: float) -> bytes:
start_time = time.time()
while time.time() - start_time < timeout:
msgs = self._panda.can_recv() or []
if len(msgs) >= 256:
print("CAN RX buffer overflow!!!", file=sys.stderr)
for rx_addr, _, rx_data, rx_bus in msgs:
if rx_bus == self.can_bus and rx_addr == self.rx_addr:
rx_data = bytes(rx_data) # convert bytearray to bytes
if self.debug:
print(f"CAN-RX: {hex(rx_addr)} - 0x{bytes.hex(rx_data)}")
assert len(rx_data) == 8, f"message length not 8: {len(rx_data)}"
pid = rx_data[0]
if pid == 0xFF or pid == 0xFE:
err = rx_data[1]
err_desc = COMMAND_RETURN_CODES.get(err, "unknown error")
ctr = rx_data[2]
dat = rx_data[3:]
if pid == 0xFF and self._command_counter != ctr:
raise CommandCounterError(f"counter invalid: {ctr} != {self._command_counter}")
if err >= 0x10 and err <= 0x12:
if self.debug:
print(f"CCP-WAIT: {hex(err)} - {err_desc}")
start_time = time.time()
continue
if err >= 0x30:
raise CommandResponseError(f"{hex(err)} - {err_desc}", err)
else:
dat = rx_data[1:]
return dat
time.sleep(0.001)
raise CommandTimeoutError("timeout waiting for response")
# commands
def connect(self, station_addr: int) -> None:
if station_addr > 65535:
raise ValueError("station address must be less than 65536")
# NOTE: station address is always little endian
self._send_cro(COMMAND_CODE.CONNECT, struct.pack("<H", station_addr))
self._recv_dto(0.025)
def exchange_station_ids(self, device_id_info: bytes = b"") -> dict:
self._send_cro(COMMAND_CODE.EXCHANGE_ID, device_id_info)
resp = self._recv_dto(0.025)
return { # TODO: define a type
"id_length": resp[0],
"data_type": resp[1],
"available": resp[2],
"protected": resp[3],
}
def get_seed(self, resource_mask: int) -> bytes:
if resource_mask > 255:
raise ValueError("resource mask must be less than 256")
self._send_cro(COMMAND_CODE.GET_SEED)
resp = self._recv_dto(0.025)
# protected = resp[0] == 0
seed = resp[1:]
return seed
def unlock(self, key: bytes) -> int:
if len(key) > 6:
raise ValueError("max key size is 6 bytes")
self._send_cro(COMMAND_CODE.UNLOCK, key)
resp = self._recv_dto(0.025)
status = resp[0]
return status
def set_memory_transfer_address(self, mta_num: int, addr_ext: int, addr: int) -> None:
if mta_num > 255:
raise ValueError("MTA number must be less than 256")
if addr_ext > 255:
raise ValueError("address extension must be less than 256")
self._send_cro(COMMAND_CODE.SET_MTA, bytes([mta_num, addr_ext]) + struct.pack(f"{self.byte_order.value}I", addr))
self._recv_dto(0.025)
def download(self, data: bytes) -> int:
if len(data) > 5:
raise ValueError("max data size is 5 bytes")
self._send_cro(COMMAND_CODE.DNLOAD, bytes([len(data)]) + data)
resp = self._recv_dto(0.025)
# mta_addr_ext = resp[0]
mta_addr = struct.unpack(f"{self.byte_order.value}I", resp[1:5])[0]
return mta_addr
def download_6_bytes(self, data: bytes) -> int:
if len(data) != 6:
raise ValueError("data size must be 6 bytes")
self._send_cro(COMMAND_CODE.DNLOAD_6, data)
resp = self._recv_dto(0.025)
# mta_addr_ext = resp[0]
mta_addr = struct.unpack(f"{self.byte_order.value}I", resp[1:5])[0]
return mta_addr
def upload(self, size: int) -> bytes:
if size > 5:
raise ValueError("size must be less than 6")
self._send_cro(COMMAND_CODE.UPLOAD, bytes([size]))
return self._recv_dto(0.025)
def short_upload(self, size: int, addr_ext: int, addr: int) -> bytes:
if size > 5:
raise ValueError("size must be less than 6")
if addr_ext > 255:
raise ValueError("address extension must be less than 256")
self._send_cro(COMMAND_CODE.SHORT_UP, bytes([size, addr_ext]) + struct.pack(f"{self.byte_order.value}I", addr))
return self._recv_dto(0.025)
def select_calibration_page(self) -> None:
self._send_cro(COMMAND_CODE.SELECT_CAL_PAGE)
self._recv_dto(0.025)
def get_daq_list_size(self, list_num: int, can_id: int = 0) -> dict:
if list_num > 255:
raise ValueError("list number must be less than 256")
self._send_cro(COMMAND_CODE.GET_DAQ_SIZE, bytes([list_num, 0]) + struct.pack(f"{self.byte_order.value}I", can_id))
resp = self._recv_dto(0.025)
return { # TODO: define a type
"list_size": resp[0],
"first_pid": resp[1],
}
def set_daq_list_pointer(self, list_num: int, odt_num: int, element_num: int) -> None:
if list_num > 255:
raise ValueError("list number must be less than 256")
if odt_num > 255:
raise ValueError("ODT number must be less than 256")
if element_num > 255:
raise ValueError("element number must be less than 256")
self._send_cro(COMMAND_CODE.SET_DAQ_PTR, bytes([list_num, odt_num, element_num]))
self._recv_dto(0.025)
def write_daq_list_entry(self, size: int, addr_ext: int, addr: int) -> None:
if size > 255:
raise ValueError("size must be less than 256")
if addr_ext > 255:
raise ValueError("address extension must be less than 256")
self._send_cro(COMMAND_CODE.WRITE_DAQ, bytes([size, addr_ext]) + struct.pack(f"{self.byte_order.value}I", addr))
self._recv_dto(0.025)
def start_stop_transmission(self, mode: int, list_num: int, odt_num: int, channel_num: int, rate_prescaler: int = 0) -> None:
if mode > 255:
raise ValueError("mode must be less than 256")
if list_num > 255:
raise ValueError("list number must be less than 256")
if odt_num > 255:
raise ValueError("ODT number must be less than 256")
if channel_num > 255:
raise ValueError("channel number must be less than 256")
if rate_prescaler > 65535:
raise ValueError("rate prescaler must be less than 65536")
self._send_cro(COMMAND_CODE.START_STOP, bytes([mode, list_num, odt_num, channel_num]) + struct.pack(f"{self.byte_order.value}H", rate_prescaler))
self._recv_dto(0.025)
def disconnect(self, station_addr: int, temporary: bool = False) -> None:
if station_addr > 65535:
raise ValueError("station address must be less than 65536")
# NOTE: station address is always little endian
self._send_cro(COMMAND_CODE.DISCONNECT, bytes([int(not temporary), 0x00]) + struct.pack("<H", station_addr))
self._recv_dto(0.025)
def set_session_status(self, status: int) -> None:
if status > 255:
raise ValueError("status must be less than 256")
self._send_cro(COMMAND_CODE.SET_S_STATUS, bytes([status]))
self._recv_dto(0.025)
def get_session_status(self) -> dict:
self._send_cro(COMMAND_CODE.GET_S_STATUS)
resp = self._recv_dto(0.025)
return { # TODO: define a type
"status": resp[0],
"info": resp[2] if resp[1] else None,
}
def build_checksum(self, size: int) -> bytes:
self._send_cro(COMMAND_CODE.BUILD_CHKSUM, struct.pack(f"{self.byte_order.value}I", size))
resp = self._recv_dto(30.0)
chksum_size = resp[0]
assert chksum_size <= 4, "checksum more than 4 bytes"
chksum = resp[1:1+chksum_size]
return chksum
def clear_memory(self, size: int) -> None:
self._send_cro(COMMAND_CODE.CLEAR_MEMORY, struct.pack(f"{self.byte_order.value}I", size))
self._recv_dto(30.0)
def program(self, size: int, data: bytes) -> int:
if size > 5:
raise ValueError("size must be less than 6")
if len(data) > 5:
raise ValueError("max data size is 5 bytes")
self._send_cro(COMMAND_CODE.PROGRAM, bytes([size]) + data)
resp = self._recv_dto(0.1)
# mta_addr_ext = resp[0]
mta_addr = struct.unpack(f"{self.byte_order.value}I", resp[1:5])[0]
return mta_addr
def program_6_bytes(self, data: bytes) -> int:
if len(data) != 6:
raise ValueError("data size must be 6 bytes")
self._send_cro(COMMAND_CODE.PROGRAM_6, data)
resp = self._recv_dto(0.1)
# mta_addr_ext = resp[0]
mta_addr = struct.unpack(f"{self.byte_order.value}I", resp[1:5])[0]
return mta_addr
def move_memory_block(self, size: int) -> None:
self._send_cro(COMMAND_CODE.MOVE, struct.pack(f"{self.byte_order.value}I", size))
self._recv_dto(0.025)
def diagnostic_service(self, service_num: int, data: bytes = b"") -> dict:
if service_num > 65535:
raise ValueError("service number must be less than 65536")
if len(data) > 4:
raise ValueError("max data size is 4 bytes")
self._send_cro(COMMAND_CODE.DIAG_SERVICE, struct.pack(f"{self.byte_order.value}H", service_num) + data)
resp = self._recv_dto(0.025)
return { # TODO: define a type
"length": resp[0],
"type": resp[1],
}
def action_service(self, service_num: int, data: bytes = b"") -> dict:
if service_num > 65535:
raise ValueError("service number must be less than 65536")
if len(data) > 4:
raise ValueError("max data size is 4 bytes")
self._send_cro(COMMAND_CODE.ACTION_SERVICE, struct.pack(f"{self.byte_order.value}H", service_num) + data)
resp = self._recv_dto(0.025)
return { # TODO: define a type
"length": resp[0],
"type": resp[1],
}
def test_availability(self, station_addr: int) -> None:
if station_addr > 65535:
raise ValueError("station address must be less than 65536")
# NOTE: station address is always little endian
self._send_cro(COMMAND_CODE.TEST, struct.pack("<H", station_addr))
self._recv_dto(0.025)
def start_stop_synchronised_transmission(self, mode: int) -> None:
if mode > 255:
raise ValueError("mode must be less than 256")
self._send_cro(COMMAND_CODE.START_STOP_ALL, bytes([mode]))
self._recv_dto(0.025)
def get_active_calibration_page(self):
self._send_cro(COMMAND_CODE.GET_ACTIVE_CAL_PAGE)
resp = self._recv_dto(0.025)
# cal_addr_ext = resp[0]
cal_addr = struct.unpack(f"{self.byte_order.value}I", resp[1:5])[0]
return cal_addr
def get_version(self, desired_version: float = 2.1) -> float:
major, minor = map(int, str(desired_version).split("."))
self._send_cro(COMMAND_CODE.GET_CCP_VERSION, bytes([major, minor]))
resp = self._recv_dto(0.025)
return float(f"{resp[0]}.{resp[1]}")
+8 -5
View File
@@ -586,13 +586,16 @@ class UdsClient():
power_down_time = resp[0]
return power_down_time
def security_access(self, access_type: ACCESS_TYPE, security_key: bytes = None):
def security_access(self, access_type: ACCESS_TYPE, security_key: bytes = b'', data_record: bytes = b''):
request_seed = access_type % 2 != 0
if request_seed and security_key is not None:
if request_seed and len(security_key) != 0:
raise ValueError('security_key not allowed')
if not request_seed and security_key is None:
if not request_seed and len(security_key) == 0:
raise ValueError('security_key is missing')
resp = self._uds_request(SERVICE_TYPE.SECURITY_ACCESS, subfunction=access_type, data=security_key)
if not request_seed and len(data_record) != 0:
raise ValueError('data_record not allowed')
data = security_key + data_record
resp = self._uds_request(SERVICE_TYPE.SECURITY_ACCESS, subfunction=access_type, data=data)
if request_seed:
security_seed = resp
return security_seed
@@ -792,7 +795,7 @@ class UdsClient():
return resp
def input_output_control_by_identifier(self, data_identifier_type: DATA_IDENTIFIER_TYPE, control_parameter_type: CONTROL_PARAMETER_TYPE,
control_option_record: bytes, control_enable_mask_record: bytes = b''):
control_option_record: bytes = b'', control_enable_mask_record: bytes = b''):
data = struct.pack('!H', data_identifier_type) + bytes([control_parameter_type]) + control_option_record + control_enable_mask_record
resp = self._uds_request(SERVICE_TYPE.INPUT_OUTPUT_CONTROL_BY_IDENTIFIER, subfunction=None, data=data)
resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None