mirror of https://github.com/commaai/panda.git
parent
ffb3109e28
commit
2f3e2825e5
|
@ -12,6 +12,7 @@ typedef struct {
|
|||
uint32_t can_data_speed;
|
||||
bool canfd_enabled;
|
||||
bool brs_enabled;
|
||||
bool canfd_non_iso;
|
||||
} bus_config_t;
|
||||
|
||||
uint32_t safety_tx_blocked = 0;
|
||||
|
@ -155,10 +156,10 @@ void can_clear(can_ring *q) {
|
|||
// Helpers
|
||||
// Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3
|
||||
bus_config_t bus_config[] = {
|
||||
{ .bus_lookup = 0U, .can_num_lookup = 0U, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_enabled = false, .brs_enabled = false },
|
||||
{ .bus_lookup = 1U, .can_num_lookup = 1U, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_enabled = false, .brs_enabled = false },
|
||||
{ .bus_lookup = 2U, .can_num_lookup = 2U, .can_speed = 5000U, .can_data_speed = 20000U, .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 },
|
||||
{ .bus_lookup = 0U, .can_num_lookup = 0U, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false },
|
||||
{ .bus_lookup = 1U, .can_num_lookup = 1U, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false },
|
||||
{ .bus_lookup = 2U, .can_num_lookup = 2U, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false },
|
||||
{ .bus_lookup = 0xFFU, .can_num_lookup = 0xFFU, .can_speed = 333U, .can_data_speed = 333U, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false },
|
||||
};
|
||||
|
||||
#define CANIF_FROM_CAN_NUM(num) (cans[num])
|
||||
|
|
|
@ -20,6 +20,7 @@ bool can_set_speed(uint8_t can_number) {
|
|||
CANx,
|
||||
bus_config[bus_number].can_speed,
|
||||
bus_config[bus_number].can_data_speed,
|
||||
bus_config[bus_number].canfd_non_iso,
|
||||
can_loopback,
|
||||
(unsigned int)(can_silent) & (1U << can_number)
|
||||
);
|
||||
|
|
|
@ -28,7 +28,7 @@ struct __attribute__((packed)) health_t {
|
|||
uint8_t safety_rx_checks_invalid;
|
||||
};
|
||||
|
||||
#define CAN_HEALTH_PACKET_VERSION 2
|
||||
#define CAN_HEALTH_PACKET_VERSION 3
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t bus_off;
|
||||
uint32_t bus_off_cnt;
|
||||
|
@ -50,4 +50,5 @@ typedef struct __attribute__((packed)) {
|
|||
uint16_t can_data_speed;
|
||||
uint8_t canfd_enabled;
|
||||
uint8_t brs_enabled;
|
||||
uint8_t canfd_non_iso;
|
||||
} can_health_t;
|
||||
|
|
|
@ -254,6 +254,7 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
|||
can_health[req->param1].can_data_speed = (bus_config[req->param1].can_data_speed / 10U);
|
||||
can_health[req->param1].canfd_enabled = bus_config[req->param1].canfd_enabled;
|
||||
can_health[req->param1].brs_enabled = bus_config[req->param1].brs_enabled;
|
||||
can_health[req->param1].canfd_non_iso = bus_config[req->param1].canfd_non_iso;
|
||||
resp_len = sizeof(can_health[req->param1]);
|
||||
(void)memcpy(resp, &can_health[req->param1], resp_len);
|
||||
}
|
||||
|
@ -534,7 +535,7 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
|||
heartbeat_disabled = true;
|
||||
}
|
||||
break;
|
||||
// **** 0xde: set CAN FD data bitrate
|
||||
// **** 0xf9: set CAN FD data bitrate
|
||||
case 0xf9:
|
||||
if ((req->param1 < CAN_CNT) &&
|
||||
current_board->has_canfd &&
|
||||
|
@ -546,18 +547,18 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
|
|||
UNUSED(ret);
|
||||
}
|
||||
break;
|
||||
// **** 0xfa: check if CAN FD and BRS are enabled
|
||||
case 0xfa:
|
||||
if (req->param1 < CAN_CNT) {
|
||||
resp[0] = bus_config[req->param1].canfd_enabled;
|
||||
resp[1] = bus_config[req->param1].brs_enabled;
|
||||
resp_len = 2;
|
||||
}
|
||||
break;
|
||||
// **** 0xfb: allow highest power saving mode (stop) to be entered
|
||||
case 0xfb:
|
||||
deepsleep_allowed = true;
|
||||
break;
|
||||
// **** 0xfc: set CAN FD non-ISO mode
|
||||
case 0xfc:
|
||||
if ((req->param1 < CAN_CNT) && current_board->has_canfd) {
|
||||
bus_config[req->param1].canfd_non_iso = (req->param2 != 0U);
|
||||
bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1));
|
||||
UNUSED(ret);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
puts("NO HANDLER ");
|
||||
puth(req->request);
|
||||
|
|
|
@ -84,7 +84,7 @@ bool fdcan_exit_init(FDCAN_GlobalTypeDef *CANx) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool llcan_set_speed(FDCAN_GlobalTypeDef *CANx, uint32_t speed, uint32_t data_speed, bool loopback, bool silent) {
|
||||
bool llcan_set_speed(FDCAN_GlobalTypeDef *CANx, uint32_t speed, uint32_t data_speed, bool non_iso, bool loopback, bool silent) {
|
||||
UNUSED(speed);
|
||||
bool ret = fdcan_request_init(CANx);
|
||||
|
||||
|
@ -97,6 +97,7 @@ bool llcan_set_speed(FDCAN_GlobalTypeDef *CANx, uint32_t speed, uint32_t data_sp
|
|||
CANx->TEST &= ~(FDCAN_TEST_LBCK);
|
||||
CANx->CCCR &= ~(FDCAN_CCCR_MON);
|
||||
CANx->CCCR &= ~(FDCAN_CCCR_ASM);
|
||||
CANx->CCCR &= ~(FDCAN_CCCR_NISO);
|
||||
|
||||
// TODO: add as a separate safety mode
|
||||
// Enable ASM restricted operation(for debug or automatic bitrate switching)
|
||||
|
@ -130,6 +131,11 @@ bool llcan_set_speed(FDCAN_GlobalTypeDef *CANx, uint32_t speed, uint32_t data_sp
|
|||
|
||||
CANx->DBTP = (((sjw & 0xFU)-1U)<<FDCAN_DBTP_DSJW_Pos) | (((seg1 & 0x1FU)-1U)<<FDCAN_DBTP_DTSEG1_Pos) | (((seg2 & 0xFU)-1U)<<FDCAN_DBTP_DTSEG2_Pos) | (((prescaler & 0x1FU)-1U)<<FDCAN_DBTP_DBRP_Pos);
|
||||
|
||||
if (non_iso) {
|
||||
// FD non-ISO mode
|
||||
CANx->CCCR |= FDCAN_CCCR_NISO;
|
||||
}
|
||||
|
||||
// Silent loopback is known as internal loopback in the docs
|
||||
if (loopback) {
|
||||
CANx->CCCR |= FDCAN_CCCR_TEST;
|
||||
|
|
|
@ -186,9 +186,9 @@ class Panda:
|
|||
|
||||
CAN_PACKET_VERSION = 2
|
||||
HEALTH_PACKET_VERSION = 11
|
||||
CAN_HEALTH_PACKET_VERSION = 2
|
||||
CAN_HEALTH_PACKET_VERSION = 3
|
||||
HEALTH_STRUCT = struct.Struct("<IIIIIIIIIBBBBBBHBBBHfBB")
|
||||
CAN_HEALTH_STRUCT = struct.Struct("<BIBBBBBBBBIIIIIIHHBB")
|
||||
CAN_HEALTH_STRUCT = struct.Struct("<BIBBBBBBBBIIIIIIHHBBB")
|
||||
|
||||
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)
|
||||
|
@ -509,6 +509,7 @@ class Panda:
|
|||
"can_data_speed": a[17],
|
||||
"canfd_enabled": a[18],
|
||||
"brs_enabled": a[19],
|
||||
"canfd_non_iso": a[20],
|
||||
}
|
||||
|
||||
# ******************* control *******************
|
||||
|
@ -626,14 +627,8 @@ class Panda:
|
|||
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_canfd_non_iso(self, bus, non_iso):
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xfc, bus, int(non_iso), b'')
|
||||
|
||||
def set_uart_baud(self, uart, rate):
|
||||
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe4, uart, int(rate / 300), b'')
|
||||
|
|
|
@ -15,38 +15,41 @@ if os.getenv("H7_PANDAS_EXCLUDE"):
|
|||
#TODO: REMOVE, temporary list of CAN FD lengths, one in panda python lib MUST be used
|
||||
DLC_TO_LEN = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48]
|
||||
|
||||
_panda_serials = []
|
||||
def panda_reset():
|
||||
panda_serials = []
|
||||
|
||||
if JUNGLE_SERIAL:
|
||||
panda_jungle = PandaJungle(JUNGLE_SERIAL)
|
||||
panda_jungle.set_panda_power(False)
|
||||
time.sleep(2)
|
||||
panda_jungle.set_panda_power(True)
|
||||
time.sleep(4)
|
||||
|
||||
def panda_init(serial, enable_canfd=False):
|
||||
for serial in Panda.list():
|
||||
if serial not in H7_PANDAS_EXCLUDE:
|
||||
p = Panda(serial=serial)
|
||||
if p.get_type() in H7_HW_TYPES:
|
||||
assert p.recover(timeout=30)
|
||||
panda_serials.append(serial)
|
||||
p.close()
|
||||
|
||||
if len(panda_serials) < 2:
|
||||
print("Minimum two H7 type pandas should be connected.")
|
||||
assert False
|
||||
|
||||
return panda_serials
|
||||
|
||||
def panda_init(serial, enable_canfd=False, enable_non_iso=False):
|
||||
p = Panda(serial=serial)
|
||||
p.set_power_save(False)
|
||||
for bus in range(3):
|
||||
if enable_canfd:
|
||||
p.set_can_data_speed_kbps(bus, 2000)
|
||||
if enable_non_iso:
|
||||
p.set_canfd_non_iso(bus, True)
|
||||
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
|
||||
return p
|
||||
|
||||
if JUNGLE_SERIAL:
|
||||
panda_jungle = PandaJungle(JUNGLE_SERIAL)
|
||||
panda_jungle.set_panda_power(False)
|
||||
time.sleep(2)
|
||||
panda_jungle.set_panda_power(True)
|
||||
time.sleep(4)
|
||||
|
||||
for serial in Panda.list():
|
||||
if serial not in H7_PANDAS_EXCLUDE:
|
||||
p = Panda(serial=serial)
|
||||
if p.get_type() in H7_HW_TYPES:
|
||||
assert p.recover(timeout=30)
|
||||
_panda_serials.append(serial)
|
||||
p.close()
|
||||
|
||||
if len(_panda_serials) < 2:
|
||||
print("Minimum two H7 type pandas should be connected.")
|
||||
assert False
|
||||
|
||||
|
||||
def canfd_test(p_send, p_recv):
|
||||
for _ in range(100):
|
||||
sent_msgs = defaultdict(set)
|
||||
|
@ -78,27 +81,46 @@ def canfd_test(p_send, p_recv):
|
|||
p_recv.set_safety_mode(Panda.SAFETY_SILENT)
|
||||
p_send.set_power_save(True)
|
||||
p_recv.set_power_save(True)
|
||||
p_send.close()
|
||||
p_recv.close()
|
||||
print("Got all messages intact")
|
||||
|
||||
|
||||
p_send = panda_init(_panda_serials[0], enable_canfd=False)
|
||||
p_recv = panda_init(_panda_serials[1], enable_canfd=True)
|
||||
def setup_test(enable_non_iso=False):
|
||||
panda_serials = panda_reset()
|
||||
|
||||
# Check that sending panda CAN FD and BRS are turned off
|
||||
for bus in range(3):
|
||||
canfd, brs = p_send.get_canfd_status(bus)
|
||||
assert not canfd
|
||||
assert not brs
|
||||
p_send = panda_init(panda_serials[0], enable_canfd=False, enable_non_iso=enable_non_iso)
|
||||
p_recv = panda_init(panda_serials[1], enable_canfd=True, enable_non_iso=enable_non_iso)
|
||||
|
||||
# Receiving panda sends dummy CAN FD message that should enable CAN FD on sender side
|
||||
for bus in range(3):
|
||||
p_recv.can_send(0x200, b"dummymessage", bus)
|
||||
p_recv.can_recv()
|
||||
# Check that sending panda CAN FD and BRS are turned off
|
||||
for bus in range(3):
|
||||
health = p_send.can_health(bus)
|
||||
assert not health["canfd_enabled"]
|
||||
assert not health["brs_enabled"]
|
||||
assert health["canfd_non_iso"] == enable_non_iso
|
||||
|
||||
# Check if all tested buses on sending panda have swithed to CAN FD with BRS
|
||||
for bus in range(3):
|
||||
canfd, brs = p_send.get_canfd_status(bus)
|
||||
assert canfd
|
||||
assert brs
|
||||
# Receiving panda sends dummy CAN FD message that should enable CAN FD on sender side
|
||||
for bus in range(3):
|
||||
p_recv.can_send(0x200, b"dummymessage", bus)
|
||||
p_recv.can_recv()
|
||||
|
||||
canfd_test(p_send, p_recv)
|
||||
# Check if all tested buses on sending panda have swithed to CAN FD with BRS
|
||||
for bus in range(3):
|
||||
health = p_send.can_health(bus)
|
||||
assert health["canfd_enabled"]
|
||||
assert health["brs_enabled"]
|
||||
assert health["canfd_non_iso"] == enable_non_iso
|
||||
|
||||
return p_send, p_recv
|
||||
|
||||
def main():
|
||||
print("[TEST CAN-FD]")
|
||||
p_send, p_recv = setup_test()
|
||||
canfd_test(p_send, p_recv)
|
||||
|
||||
print("[TEST CAN-FD non-ISO]")
|
||||
p_send, p_recv = setup_test(enable_non_iso=True)
|
||||
canfd_test(p_send, p_recv)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
Loading…
Reference in New Issue