quick garbage collection pass (#2231)

* remove DPANDA

* -22

* lil more

* canfd

* lil more

* update cppcheck

* uart cleanup

* always harness

* sbu sense

* lil more

* enable spi

* rm ENABLE_SPI
This commit is contained in:
Adeeb Shihadeh
2025-07-19 21:05:12 -07:00
committed by GitHub
parent edd4146635
commit 5ac6305a95
42 changed files with 105 additions and 440 deletions

1
.gitignore vendored
View File

@@ -26,6 +26,7 @@ compile_commands.json
# CTU info files generated by Cppcheck
*.*.ctu-info
cppcheck-addon-ctu-file-list
# safety coverage-related files
*.gcda

View File

@@ -1,18 +1,4 @@
import os
import copy
Import('build_project', 'base_project_f4', 'base_project_h7')
build_projects = {
"panda": base_project_f4,
"panda_h7": base_project_h7,
}
for project_name, project in build_projects.items():
flags = [
"-DPANDA",
]
if ("ENABLE_SPI" in os.environ or "h7" in project_name):
flags.append('-DENABLE_SPI')
build_project(project_name, project, flags)
build_project("panda", base_project_f4, [])
build_project("panda_h7", base_project_h7, [])

View File

@@ -14,7 +14,6 @@ typedef void (*board_init)(void);
typedef void (*board_init_bootloader)(void);
typedef void (*board_enable_can_transceiver)(uint8_t transceiver, bool enabled);
typedef void (*board_set_can_mode)(uint8_t mode);
typedef bool (*board_check_ignition)(void);
typedef uint32_t (*board_read_voltage_mV)(void);
typedef uint32_t (*board_read_current_mA)(void);
typedef void (*board_set_ir_power)(uint8_t percentage);
@@ -30,7 +29,6 @@ struct board {
const uint8_t led_pin[3];
const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM
const bool has_spi;
const bool has_canfd;
const uint16_t fan_max_rpm;
const uint16_t avdd_mV;
const bool fan_stall_recovery;
@@ -40,7 +38,6 @@ struct board {
board_init_bootloader init_bootloader;
board_enable_can_transceiver enable_can_transceiver;
board_set_can_mode set_can_mode;
board_check_ignition check_ignition;
board_read_voltage_mV read_voltage_mV;
board_read_current_mA read_current_mA;
board_set_ir_power set_ir_power;
@@ -54,23 +51,12 @@ struct board {
// ******************* Definitions ********************
// These should match the enums in cereal/log.capnp and __init__.py
#define HW_TYPE_UNKNOWN 0U
//#define HW_TYPE_WHITE_PANDA 1U
//#define HW_TYPE_GREY_PANDA 2U
//#define HW_TYPE_BLACK_PANDA 3U
//#define HW_TYPE_PEDAL 4U
//#define HW_TYPE_UNO 5U
#define HW_TYPE_DOS 6U
#define HW_TYPE_RED_PANDA 7U
#define HW_TYPE_RED_PANDA_V2 8U
#define HW_TYPE_TRES 9U
#define HW_TYPE_CUATRO 10U
// USB power modes (from cereal.log.health)
#define USB_POWER_NONE 0U
#define USB_POWER_CLIENT 1U
#define USB_POWER_CDP 2U
#define USB_POWER_DCP 3U
// CAN modes
#define CAN_MODE_NORMAL 0U
#define CAN_MODE_OBD_CAN2 1U

View File

@@ -102,7 +102,6 @@ static void cuatro_init(void) {
}
static harness_configuration cuatro_harness_config = {
.has_harness = true,
.GPIO_SBU1 = GPIOC,
.GPIO_SBU2 = GPIOA,
.GPIO_relay_SBU1 = GPIOA,
@@ -118,7 +117,6 @@ static harness_configuration cuatro_harness_config = {
board board_cuatro = {
.harness_config = &cuatro_harness_config,
.has_spi = true,
.has_canfd = true,
.fan_max_rpm = 12500U,
.fan_max_pwm = 99U, // it can go up to 14k RPM, but 99% -> 100% is very non-linear
.avdd_mV = 1800U,
@@ -131,7 +129,6 @@ board board_cuatro = {
.led_pin = {6, 7, 9},
.led_pwm_channels = {1, 2, 4},
.set_can_mode = tres_set_can_mode,
.check_ignition = red_check_ignition,
.read_voltage_mV = cuatro_read_voltage_mV,
.read_current_mA = cuatro_read_current_mA,
.set_fan_enabled = cuatro_set_fan_enabled,

View File

@@ -62,11 +62,6 @@ static void dos_set_can_mode(uint8_t mode) {
}
}
static bool dos_check_ignition(void){
// ignition is checked through harness
return harness_check_ignition();
}
static void dos_set_ir_power(uint8_t percentage){
pwm_set(TIM4, 2, percentage);
}
@@ -114,7 +109,6 @@ static void dos_init(void) {
}
static harness_configuration dos_harness_config = {
.has_harness = true,
.GPIO_SBU1 = GPIOC,
.GPIO_SBU2 = GPIOC,
.GPIO_relay_SBU1 = GPIOC,
@@ -129,12 +123,7 @@ static harness_configuration dos_harness_config = {
board board_dos = {
.harness_config = &dos_harness_config,
#ifdef ENABLE_SPI
.has_spi = true,
#else
.has_spi = false,
#endif
.has_canfd = false,
.fan_max_rpm = 6500U,
.fan_max_pwm = 100U,
.avdd_mV = 3300U,
@@ -146,7 +135,6 @@ board board_dos = {
.led_GPIO = {GPIOC, GPIOC, GPIOC},
.led_pin = {9, 7, 6},
.set_can_mode = dos_set_can_mode,
.check_ignition = dos_check_ignition,
.read_voltage_mV = dos_read_voltage_mV,
.read_current_mA = unused_read_current,
.set_fan_enabled = dos_set_fan_enabled,

View File

@@ -67,11 +67,6 @@ static void red_set_can_mode(uint8_t mode) {
}
}
static bool red_check_ignition(void) {
// ignition is checked through harness
return harness_check_ignition();
}
static uint32_t red_read_voltage_mV(void){
return adc_get_mV(2) * 11U; // TODO: is this correct?
}
@@ -104,7 +99,6 @@ static void red_init(void) {
}
static harness_configuration red_harness_config = {
.has_harness = true,
.GPIO_SBU1 = GPIOC,
.GPIO_SBU2 = GPIOA,
.GPIO_relay_SBU1 = GPIOC,
@@ -121,7 +115,6 @@ board board_red = {
.set_bootkick = unused_set_bootkick,
.harness_config = &red_harness_config,
.has_spi = false,
.has_canfd = true,
.fan_max_rpm = 0U,
.fan_max_pwm = 100U,
.avdd_mV = 3300U,
@@ -133,7 +126,6 @@ board board_red = {
.led_GPIO = {GPIOE, GPIOE, GPIOE},
.led_pin = {4, 3, 2},
.set_can_mode = red_set_can_mode,
.check_ignition = red_check_ignition,
.read_voltage_mV = red_read_voltage_mV,
.read_current_mA = unused_read_current,
.set_fan_enabled = unused_set_fan_enabled,

View File

@@ -133,7 +133,6 @@ static void tres_init(void) {
}
static harness_configuration tres_harness_config = {
.has_harness = true,
.GPIO_SBU1 = GPIOC,
.GPIO_SBU2 = GPIOA,
.GPIO_relay_SBU1 = GPIOA,
@@ -149,7 +148,6 @@ static harness_configuration tres_harness_config = {
board board_tres = {
.harness_config = &tres_harness_config,
.has_spi = true,
.has_canfd = true,
.fan_max_rpm = 6600U,
.fan_max_pwm = 100U,
.avdd_mV = 1800U,
@@ -161,7 +159,6 @@ board board_tres = {
.led_GPIO = {GPIOE, GPIOE, GPIOE},
.led_pin = {4, 3, 2},
.set_can_mode = tres_set_can_mode,
.check_ignition = red_check_ignition,
.read_voltage_mV = red_read_voltage_mV,
.read_current_mA = unused_read_current,
.set_fan_enabled = tres_set_fan_enabled,

View File

@@ -1,6 +1,5 @@
#pragma once
#if defined(ENABLE_SPI) || defined(BOOTSTUB)
uint8_t crc_checksum(const uint8_t *dat, int len, const uint8_t poly) {
uint8_t crc = 0xFFU;
int i;
@@ -18,4 +17,3 @@ uint8_t crc_checksum(const uint8_t *dat, int len, const uint8_t poly) {
}
return crc;
}
#endif

View File

@@ -139,9 +139,9 @@ bus_config_t bus_config[BUS_CONFIG_ARRAY_SIZE] = {
void can_init_all(void) {
for (uint8_t i=0U; i < PANDA_CAN_CNT; i++) {
if (!current_board->has_canfd) {
#ifndef CANFD
bus_config[i].can_data_speed = 0U;
}
#endif
can_clear(can_queues[i]);
(void)can_init(i);
}

View File

@@ -4,31 +4,29 @@ struct harness_t harness;
// The ignition relay is only used for testing purposes
void set_intercept_relay(bool intercept, bool ignition_relay) {
if (current_board->harness_config->has_harness) {
bool drive_relay = intercept;
if (harness.status == HARNESS_STATUS_NC) {
// no harness, no relay to drive
drive_relay = false;
}
bool drive_relay = intercept;
if (harness.status == HARNESS_STATUS_NC) {
// no harness, no relay to drive
drive_relay = false;
}
if (drive_relay || ignition_relay) {
harness.relay_driven = true;
}
if (drive_relay || ignition_relay) {
harness.relay_driven = true;
}
// wait until we're not reading the analog voltages anymore
while (harness.sbu_adc_lock) {}
// wait until we're not reading the analog voltages anymore
while (harness.sbu_adc_lock) {}
if (harness.status == HARNESS_STATUS_NORMAL) {
set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !ignition_relay);
set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !drive_relay);
} else {
set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !drive_relay);
set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !ignition_relay);
}
if (harness.status == HARNESS_STATUS_NORMAL) {
set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !ignition_relay);
set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !drive_relay);
} else {
set_gpio_output(current_board->harness_config->GPIO_relay_SBU1, current_board->harness_config->pin_relay_SBU1, !drive_relay);
set_gpio_output(current_board->harness_config->GPIO_relay_SBU2, current_board->harness_config->pin_relay_SBU2, !ignition_relay);
}
if (!(drive_relay || ignition_relay)) {
harness.relay_driven = false;
}
if (!(drive_relay || ignition_relay)) {
harness.relay_driven = false;
}
}
@@ -56,7 +54,7 @@ static uint8_t harness_detect_orientation(void) {
#ifndef BOOTSTUB
// We can't detect orientation if the relay is being driven
if (!harness.relay_driven && current_board->harness_config->has_harness) {
if (!harness.relay_driven) {
harness.sbu_adc_lock = true;
set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_ANALOG);
set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_ANALOG);

View File

@@ -14,7 +14,6 @@ struct harness_t {
extern struct harness_t harness;
struct harness_configuration {
const bool has_harness;
GPIO_TypeDef * const GPIO_SBU1;
GPIO_TypeDef * const GPIO_SBU2;
GPIO_TypeDef * const GPIO_relay_SBU1;

View File

@@ -16,7 +16,6 @@ uint8_t spi_buf_tx[SPI_BUF_SIZE];
uint16_t spi_checksum_error_count = 0;
#if defined(ENABLE_SPI) || defined(BOOTSTUB)
static uint8_t spi_state = SPI_STATE_HEADER;
static uint16_t spi_data_len_mosi;
static bool spi_can_tx_ready = false;
@@ -234,8 +233,3 @@ void spi_tx_done(bool reset) {
void can_tx_comms_resume_spi(void) {
spi_can_tx_ready = true;
}
#else
void can_tx_comms_resume_spi(void) {
return;
}
#endif

View File

@@ -45,8 +45,6 @@ void llspi_mosi_dma(uint8_t *addr, int len);
void llspi_miso_dma(uint8_t *addr, int len);
void can_tx_comms_resume_spi(void);
#if defined(ENABLE_SPI) || defined(BOOTSTUB)
void spi_init(void);
void spi_rx_done(void);
void spi_tx_done(bool reset);
#endif

View File

@@ -1,7 +1,5 @@
#include "uart_declarations.h"
// IRQs: USART2, USART3, UART5
// ***************************** Definitions *****************************
#define UART_BUFFER(x, size_rx, size_tx, uart_ptr, callback_ptr, overwrite_mode) \
@@ -112,15 +110,6 @@ bool put_char(uart_ring *q, char elem) {
return ret;
}
void clear_uart_buff(uart_ring *q) {
ENTER_CRITICAL();
q->w_ptr_tx = 0;
q->r_ptr_tx = 0;
q->w_ptr_rx = 0;
q->r_ptr_rx = 0;
EXIT_CRITICAL();
}
// ************************ High-level debug functions **********************
void putch(const char a) {
// misra-c2012-17.7: serial debug function, ok to ignore output
@@ -145,14 +134,14 @@ void puth(unsigned int i) {
puthx(i, 8U);
}
#if defined(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG)
void puth4(unsigned int i) {
#if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG)
static void puth4(unsigned int i) {
puthx(i, 4U);
}
#endif
#if defined(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG_USB) || defined(DEBUG_COMMS)
void hexdump(const void *a, int l) {
#if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG_USB) || defined(DEBUG_COMMS)
static void hexdump(const void *a, int l) {
if (a != NULL) {
for (int i=0; i < l; i++) {
if ((i != 0) && ((i & 0xf) == 0)) print("\n");

View File

@@ -1,7 +1,5 @@
#pragma once
// IRQs: USART2, USART3, UART5
// ***************************** Definitions *****************************
#define FIFO_SIZE_INT 0x400U
@@ -33,7 +31,9 @@ void putch(const char a);
void print(const char *a);
void puthx(uint32_t i, uint8_t len);
void puth(unsigned int i);
#if defined(ENABLE_SPI) || defined(BOOTSTUB) || defined(DEBUG)
void puth4(unsigned int i);
#if defined(DEBUG_SPI) || defined(BOOTSTUB) || defined(DEBUG)
static void puth4(unsigned int i);
#endif
#if defined(DEBUG_SPI) || defined(DEBUG_USB) || defined(DEBUG_COMMS)
static void hexdump(const void *a, int l);
#endif
void hexdump(const void *a, int l);

View File

@@ -57,9 +57,7 @@ void early_initialization(void) {
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
led_init();
#ifdef PANDA
current_board->init_bootloader();
#endif
led_set(LED_GREEN, 1);
jump_to_bootloader();
}

View File

@@ -7,7 +7,6 @@
#define CANFD
#define ALLOW_DEBUG
#define PANDA
#define ENTER_CRITICAL() 0
#define EXIT_CRITICAL() 0

View File

@@ -134,15 +134,12 @@ void soft_flasher_start(void) {
gpio_usb_init();
led_init();
// enable USB
// enable comms
usb_init();
#ifdef ENABLE_SPI
if (current_board->has_spi) {
gpio_spi_init();
spi_init();
}
#endif
// green LED on for flashing
led_set(LED_GREEN, 1);

View File

@@ -1,17 +1,11 @@
import os
import copy
Import('build_project', 'base_project_h7')
build_projects = {
"panda_jungle_h7": base_project_h7,
}
flags = [
"-DPANDA_JUNGLE",
]
if os.getenv("FINAL_PROVISIONING"):
flags += ["-DFINAL_PROVISIONING"]
for project_name, project in build_projects.items():
flags = [
"-DPANDA_JUNGLE",
]
if os.getenv("FINAL_PROVISIONING"):
flags += ["-DFINAL_PROVISIONING"]
build_project(project_name, project, flags)
build_project("panda_jungle_h7", base_project_h7, flags)

View File

@@ -2,6 +2,7 @@
typedef void (*board_init)(void);
typedef void (*board_board_tick)(void);
typedef bool (*board_get_button)(void);
typedef void (*board_init_bootloader)(void);
typedef void (*board_set_panda_power)(bool enabled);
typedef void (*board_set_panda_individual_power)(uint8_t port_num, bool enabled);
typedef void (*board_set_ignition)(bool enabled);
@@ -17,12 +18,11 @@ struct board {
GPIO_TypeDef * const led_GPIO[3];
const uint8_t led_pin[3];
const uint8_t led_pwm_channels[3]; // leave at 0 to disable PWM
const bool has_canfd;
const bool has_sbu_sense;
const uint16_t avdd_mV;
board_init init;
board_board_tick board_tick;
board_get_button get_button;
board_init_bootloader init_bootloader;
board_set_panda_power set_panda_power;
board_set_panda_individual_power set_panda_individual_power;
board_set_ignition set_ignition;
@@ -40,7 +40,6 @@ struct board {
// ******************* Definitions ********************
#define HW_TYPE_UNKNOWN 0U
//#define HW_TYPE_V1 1U
#define HW_TYPE_V2 2U
// CAN modes
@@ -59,18 +58,3 @@ struct board {
uint8_t harness_orientation = HARNESS_ORIENTATION_NONE;
uint8_t can_mode = CAN_MODE_NORMAL;
uint8_t ignition = 0U;
void unused_set_individual_ignition(uint8_t bitmask) {
UNUSED(bitmask);
}
void unused_board_enable_header_pin(uint8_t pin_num, bool enabled) {
UNUSED(pin_num);
UNUSED(enabled);
}
void unused_set_panda_individual_power(uint8_t port_num, bool enabled) {
UNUSED(port_num);
UNUSED(enabled);
}

View File

@@ -287,10 +287,9 @@ void board_v2_init(void) {
void board_v2_tick(void) {}
board board_v2 = {
.has_canfd = true,
.has_sbu_sense = true,
.avdd_mV = 3300U,
.init = &board_v2_init,
.init_bootloader = &board_v2_tick,
.led_GPIO = {GPIOE, GPIOE, GPIOE},
.led_pin = {4, 3, 2},
.board_tick = &board_v2_tick,

View File

@@ -11,20 +11,16 @@
#include "board/provision.h"
#include "board/health.h"
#include "jungle_health.h"
#include "board/jungle/jungle_health.h"
#include "board/drivers/can_common.h"
#ifdef STM32H7
#include "board/drivers/fdcan.h"
#else
#include "board/drivers/bxcan.h"
#endif
#include "board/drivers/fdcan.h"
#include "board/obj/gitversion.h"
#include "board/can_comms.h"
#include "main_comms.h"
#include "board/jungle/main_comms.h"
// ********************* Serial debugging *********************
@@ -106,17 +102,15 @@ void tick_handler(void) {
current_board->set_individual_ignition(ignition_bitmask);
// SBU voltage reporting
if (current_board->has_sbu_sense) {
for (uint8_t i = 0U; i < 6U; i++) {
CANPacket_t pkt = { 0 };
pkt.data_len_code = 8U;
pkt.addr = 0x100U + i;
*(uint16_t *) &pkt.data[0] = current_board->get_sbu_mV(i + 1U, SBU1);
*(uint16_t *) &pkt.data[2] = current_board->get_sbu_mV(i + 1U, SBU2);
pkt.data[4] = (ignition_bitmask >> i) & 1U;
can_set_checksum(&pkt);
can_send(&pkt, 0U, false);
}
for (uint8_t i = 0U; i < 6U; i++) {
CANPacket_t pkt = { 0 };
pkt.data_len_code = 8U;
pkt.addr = 0x100U + i;
*(uint16_t *) &pkt.data[0] = current_board->get_sbu_mV(i + 1U, SBU1);
*(uint16_t *) &pkt.data[2] = current_board->get_sbu_mV(i + 1U, SBU2);
pkt.data[4] = (ignition_bitmask >> i) & 1U;
can_set_checksum(&pkt);
can_send(&pkt, 0U, false);
}
#else
// toggle ignition on button press

View File

@@ -219,11 +219,6 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
print("Clearing CAN CAN ring buffer failed: wrong bus number\n");
}
break;
// **** 0xf2: Clear debug ring buffer.
case 0xf2:
print("Clearing debug queue.\n");
clear_uart_buff(get_ring_by_number(0));
break;
// **** 0xf4: Set CAN transceiver enable pin
case 0xf4:
current_board->enable_can_transceiver(req->param1, req->param2 > 0U);
@@ -240,7 +235,6 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
// **** 0xf9: set CAN FD data bitrate
case 0xf9:
if ((req->param1 < PANDA_CAN_CNT) &&
current_board->has_canfd &&
is_speed_valid(req->param2, data_speeds, sizeof(data_speeds)/sizeof(data_speeds[0]))) {
bus_config[req->param1].can_data_speed = req->param2;
bus_config[req->param1].canfd_enabled = (req->param2 >= bus_config[req->param1].can_speed);
@@ -251,7 +245,7 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
break;
// **** 0xfc: set CAN FD non-ISO mode
case 0xfc:
if ((req->param1 < PANDA_CAN_CNT) && current_board->has_canfd) {
if (req->param1 < PANDA_CAN_CNT) {
bus_config[req->param1].canfd_non_iso = (req->param2 != 0U);
bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1));
UNUSED(ret);

View File

@@ -32,29 +32,10 @@
// ********************* Serial debugging *********************
static bool check_started(void) {
bool started = current_board->check_ignition() || ignition_can;
return started;
}
void debug_ring_callback(uart_ring *ring) {
char rcv;
while (get_char(ring, &rcv)) {
(void)put_char(ring, rcv); // misra-c2012-17.7: cast to void is ok: debug function
// only allow bootloader entry on debug builds
#ifdef ALLOW_DEBUG
// jump to DFU flash
if (rcv == 'z') {
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
NVIC_SystemReset();
}
#endif
// normal reset
if (rcv == 'x') {
NVIC_SystemReset();
}
}
}
@@ -77,31 +58,26 @@ void set_safety_mode(uint16_t mode, uint16_t param) {
switch (mode_copy) {
case SAFETY_SILENT:
set_intercept_relay(false, false);
if (current_board->harness_config->has_harness) {
current_board->set_can_mode(CAN_MODE_NORMAL);
}
current_board->set_can_mode(CAN_MODE_NORMAL);
can_silent = ALL_CAN_SILENT;
break;
case SAFETY_NOOUTPUT:
set_intercept_relay(false, false);
if (current_board->harness_config->has_harness) {
current_board->set_can_mode(CAN_MODE_NORMAL);
}
current_board->set_can_mode(CAN_MODE_NORMAL);
can_silent = ALL_CAN_LIVE;
break;
case SAFETY_ELM327:
set_intercept_relay(false, false);
heartbeat_counter = 0U;
heartbeat_lost = false;
if (current_board->harness_config->has_harness) {
// Clear any pending messages in the can core (i.e. sending while comma power is unplugged)
// TODO: rewrite using hardware queues rather than fifo to cancel specific messages
can_clear_send(CANIF_FROM_CAN_NUM(1), 1);
if (param == 0U) {
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
} else {
current_board->set_can_mode(CAN_MODE_NORMAL);
}
// Clear any pending messages in the can core (i.e. sending while comma power is unplugged)
// TODO: rewrite using hardware queues rather than fifo to cancel specific messages
can_clear_send(CANIF_FROM_CAN_NUM(1), 1);
if (param == 0U) {
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
} else {
current_board->set_can_mode(CAN_MODE_NORMAL);
}
can_silent = ALL_CAN_LIVE;
break;
@@ -109,9 +85,7 @@ void set_safety_mode(uint16_t mode, uint16_t param) {
set_intercept_relay(true, false);
heartbeat_counter = 0U;
heartbeat_lost = false;
if (current_board->harness_config->has_harness) {
current_board->set_can_mode(CAN_MODE_NORMAL);
}
current_board->set_can_mode(CAN_MODE_NORMAL);
can_silent = ALL_CAN_LIVE;
break;
}
@@ -199,7 +173,8 @@ static void tick_handler(void) {
const bool recent_heartbeat = heartbeat_counter == 0U;
// tick drivers at 1Hz
bootkick_tick(check_started(), recent_heartbeat);
bool started = harness_check_ignition() || ignition_can;
bootkick_tick(started, recent_heartbeat);
// increase heartbeat counter and cap it at the uint32 limit
if (heartbeat_counter < UINT32_MAX) {
@@ -235,7 +210,7 @@ static void tick_handler(void) {
if (!heartbeat_disabled) {
// if the heartbeat has been gone for a while, go to SILENT safety mode and enter power save
if (heartbeat_counter >= (check_started() ? HEARTBEAT_IGNITION_CNT_ON : HEARTBEAT_IGNITION_CNT_OFF)) {
if (heartbeat_counter >= (started ? HEARTBEAT_IGNITION_CNT_ON : HEARTBEAT_IGNITION_CNT_OFF)) {
print("device hasn't sent a heartbeat for 0x");
puth(heartbeat_counter);
print(" seconds. Safety is set to SILENT mode.\n");
@@ -322,9 +297,7 @@ int main(void) {
// init board
current_board->init();
current_board->set_can_mode(CAN_MODE_NORMAL);
if (current_board->harness_config->has_harness) {
harness_init();
}
harness_init();
// panda has an FPU, let's use it!
enable_fpu();
@@ -355,12 +328,10 @@ int main(void) {
// enable USB (right before interrupts or enum can fail!)
usb_init();
#ifdef ENABLE_SPI
if (current_board->has_spi) {
gpio_spi_init();
spi_init();
}
#endif
led_set(LED_RED, false);
led_set(LED_GREEN, false);

View File

@@ -12,8 +12,7 @@ static int get_health_pkt(void *dat) {
health->voltage_pkt = current_board->read_voltage_mV();
health->current_pkt = current_board->read_current_mA();
// Use the GPIO pin to determine ignition or use a CAN based logic
health->ignition_line_pkt = (uint8_t)(current_board->check_ignition());
health->ignition_line_pkt = (uint8_t)(harness_check_ignition());
health->ignition_can_pkt = ignition_can;
health->controls_allowed_pkt = controls_allowed;
@@ -29,7 +28,9 @@ static int get_health_pkt(void *dat) {
health->heartbeat_lost_pkt = heartbeat_lost;
health->safety_rx_checks_invalid_pkt = safety_rx_checks_invalid;
#ifndef STM32F4
health->spi_checksum_error_count_pkt = spi_checksum_error_count;
#endif
health->fault_status_pkt = fault_status;
health->faults_pkt = faults;
@@ -97,7 +98,7 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
resp[1] = ((fan_state.rpm & 0xFF00U) >> 8U);
resp_len = 2;
break;
// **** 0xc0: reset communications
// **** 0xc0: reset communications state
case 0xc0:
comms_can_reset();
break;
@@ -212,17 +213,14 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
break;
// **** 0xdb: set OBD CAN multiplexing mode
case 0xdb:
if (current_board->harness_config->has_harness) {
if (req->param1 == 1U) {
// Enable OBD CAN
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
} else {
// Disable OBD CAN
current_board->set_can_mode(CAN_MODE_NORMAL);
}
if (req->param1 == 1U) {
// Enable OBD CAN
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
} else {
// Disable OBD CAN
current_board->set_can_mode(CAN_MODE_NORMAL);
}
break;
// **** 0xdc: set safety mode
case 0xdc:
set_safety_mode(req->param1, (uint16_t)req->param2);
@@ -263,47 +261,6 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
++resp_len;
}
break;
// **** 0xe1: uart set baud rate
case 0xe1:
ur = get_ring_by_number(req->param1);
if (!ur) {
break;
}
uart_set_baud(ur->uart, req->param2);
break;
// **** 0xe2: uart set parity
case 0xe2:
ur = get_ring_by_number(req->param1);
if (!ur) {
break;
}
switch (req->param2) {
case 0:
// disable parity, 8-bit
ur->uart->CR1 &= ~(USART_CR1_PCE | USART_CR1_M);
break;
case 1:
// even parity, 9-bit
ur->uart->CR1 &= ~USART_CR1_PS;
ur->uart->CR1 |= USART_CR1_PCE | USART_CR1_M;
break;
case 2:
// odd parity, 9-bit
ur->uart->CR1 |= USART_CR1_PS;
ur->uart->CR1 |= USART_CR1_PCE | USART_CR1_M;
break;
default:
break;
}
break;
// **** 0xe4: uart set baud rate extended
case 0xe4:
ur = get_ring_by_number(req->param1);
if (!ur) {
break;
}
uart_set_baud(ur->uart, (int)req->param2*300);
break;
// **** 0xe5: set CAN loopback (for testing)
case 0xe5:
can_loopback = req->param1 > 0U;
@@ -333,16 +290,6 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
print("Clearing CAN CAN ring buffer failed: wrong bus number\n");
}
break;
// **** 0xf2: Clear UART ring buffer.
case 0xf2:
{
uart_ring * rb = get_ring_by_number(req->param1);
if (rb != NULL) {
print("Clearing UART queue.\n");
clear_uart_buff(rb);
}
break;
}
// **** 0xf3: Heartbeat. Resets heartbeat counter.
case 0xf3:
{
@@ -369,7 +316,6 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
// **** 0xf9: set CAN FD data bitrate
case 0xf9:
if ((req->param1 < PANDA_CAN_CNT) &&
current_board->has_canfd &&
is_speed_valid(req->param2, data_speeds, sizeof(data_speeds)/sizeof(data_speeds[0]))) {
bus_config[req->param1].can_data_speed = req->param2;
bus_config[req->param1].canfd_enabled = (req->param2 >= bus_config[req->param1].can_speed);
@@ -380,7 +326,7 @@ int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
break;
// **** 0xfc: set CAN FD non-ISO mode
case 0xfc:
if ((req->param1 < PANDA_CAN_CNT) && current_board->has_canfd) {
if (req->param1 < PANDA_CAN_CNT) {
bus_config[req->param1].canfd_non_iso = (req->param2 != 0U);
bool ret = can_init(CAN_NUM_FROM_BUS_NUM(req->param1));
UNUSED(ret);

View File

@@ -3,8 +3,6 @@
// ******************** Prototypes ********************
void print(const char *a);
void puth(unsigned int i);
void puth4(unsigned int i);
void hexdump(const void *a, int l);
typedef struct board board;
typedef struct harness_configuration harness_configuration;
void pwm_init(TIM_TypeDef *TIM, uint8_t channel);

View File

@@ -7,7 +7,7 @@ int power_save_status = POWER_SAVE_STATUS_DISABLED;
void enable_can_transceivers(bool enabled) {
// Leave main CAN always on for CAN-based ignition detection
uint8_t main_bus = (current_board->harness_config->has_harness && (harness.status == HARNESS_STATUS_FLIPPED)) ? 3U : 1U;
uint8_t main_bus = (harness.status == HARNESS_STATUS_FLIPPED) ? 3U : 1U;
for(uint8_t i=1U; i<=4U; i++){
current_board->enable_can_transceiver(i, (i == main_bus) || enabled);
}

View File

@@ -12,24 +12,12 @@
#include "drivers/clock_source.h"
#include "boards/dos.h"
// Unused functions on F4
void sound_tick(void) {}
void detect_board_type(void) {
// SPI lines floating: white (TODO: is this reliable? Not really, we have to enable ESP/GPS to be able to detect this on the UART)
set_gpio_output(GPIOC, 14, 1);
set_gpio_output(GPIOC, 5, 1);
if(!detect_with_pull(GPIOB, 1, PULL_UP) && !detect_with_pull(GPIOB, 7, PULL_UP)){
if (!detect_with_pull(GPIOB, 1, PULL_UP) && !detect_with_pull(GPIOB, 7, PULL_UP)) {
hw_type = HW_TYPE_DOS;
current_board = &board_dos;
} else if((detect_with_pull(GPIOA, 4, PULL_DOWN)) || (detect_with_pull(GPIOA, 5, PULL_DOWN)) || (detect_with_pull(GPIOA, 6, PULL_DOWN)) || (detect_with_pull(GPIOA, 7, PULL_DOWN))){
// white is deprecated
} else if(detect_with_pull(GPIOA, 13, PULL_DOWN)) { // Rev AB deprecated, so no pullup means black. In REV C, A13 is pulled up to 5V with a 10K
// grey is deprecated
} else if(!detect_with_pull(GPIOB, 15, PULL_UP)) {
// uno is deprecated
} else {
// black is deprecated
}
// Return A13 to the alt mode to fix SWD

View File

@@ -1,91 +1,12 @@
#if defined(ENABLE_SPI) || defined(BOOTSTUB)
void llspi_miso_dma(uint8_t *addr, int len) {
// disable DMA
DMA2_Stream3->CR &= ~DMA_SxCR_EN;
register_clear_bits(&(SPI1->CR2), SPI_CR2_TXDMAEN);
// setup source and length
register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU);
DMA2_Stream3->NDTR = len;
// enable DMA
register_set_bits(&(SPI1->CR2), SPI_CR2_TXDMAEN);
DMA2_Stream3->CR |= DMA_SxCR_EN;
UNUSED(addr);
UNUSED(len);
}
void llspi_mosi_dma(uint8_t *addr, int len) {
// disable DMA
register_clear_bits(&(SPI1->CR2), SPI_CR2_RXDMAEN);
DMA2_Stream2->CR &= ~DMA_SxCR_EN;
// drain the bus
volatile uint8_t dat = SPI1->DR;
(void)dat;
// setup destination and length
register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU);
DMA2_Stream2->NDTR = len;
// enable DMA
DMA2_Stream2->CR |= DMA_SxCR_EN;
register_set_bits(&(SPI1->CR2), SPI_CR2_RXDMAEN);
}
// SPI MOSI DMA FINISHED
static void DMA2_Stream2_IRQ_Handler(void) {
// Clear interrupt flag
ENTER_CRITICAL();
DMA2->LIFCR = DMA_LIFCR_CTCIF2;
spi_rx_done();
EXIT_CRITICAL();
UNUSED(addr);
UNUSED(len);
}
// SPI MISO DMA FINISHED
static void DMA2_Stream3_IRQ_Handler(void) {
// Clear interrupt flag
DMA2->LIFCR = DMA_LIFCR_CTCIF3;
// Wait until the transaction is actually finished and clear the DR
// Timeout to prevent hang when the master clock stops.
bool timed_out = false;
uint32_t start_time = microsecond_timer_get();
while (!(SPI1->SR & SPI_SR_TXE)) {
if (get_ts_elapsed(microsecond_timer_get(), start_time) > SPI_TIMEOUT_US) {
timed_out = true;
break;
}
}
volatile uint8_t dat = SPI1->DR;
(void)dat;
SPI1->DR = 0U;
if (timed_out) {
print("SPI: TX timeout\n");
}
spi_tx_done(timed_out);
}
// ***************************** SPI init *****************************
void llspi_init(void) {
REGISTER_INTERRUPT(DMA2_Stream2_IRQn, DMA2_Stream2_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA)
REGISTER_INTERRUPT(DMA2_Stream3_IRQn, DMA2_Stream3_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA)
// Setup MOSI DMA
register_set(&(DMA2_Stream2->CR), (DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_TCIE), 0x1E077EFEU);
register_set(&(DMA2_Stream2->PAR), (uint32_t)&(SPI1->DR), 0xFFFFFFFFU);
// Setup MISO DMA
register_set(&(DMA2_Stream3->CR), (DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE), 0x1E077EFEU);
register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI1->DR), 0xFFFFFFFFU);
// Enable SPI and the error interrupts
// TODO: verify clock phase and polarity
register_set(&(SPI1->CR1), SPI_CR1_SPE, 0xFFFFU);
register_set(&(SPI1->CR2), 0U, 0xF7U);
NVIC_EnableIRQ(DMA2_Stream2_IRQn);
NVIC_EnableIRQ(DMA2_Stream3_IRQn);
}
#endif

View File

@@ -29,7 +29,3 @@ void uart_tx_ring(uart_ring *q){
#define DIVMANT_(_PCLK_, _BAUD_) (DIV_((_PCLK_), (_BAUD_)) / 100U)
#define DIVFRAQ_(_PCLK_, _BAUD_) ((((DIV_((_PCLK_), (_BAUD_)) - (DIVMANT_((_PCLK_), (_BAUD_)) * 100U)) * 16U) + 50U) / 100U)
#define USART_BRR_(_PCLK_, _BAUD_) ((DIVMANT_((_PCLK_), (_BAUD_)) << 4) | (DIVFRAQ_((_PCLK_), (_BAUD_)) & 0x0FU))
void uart_set_baud(USART_TypeDef *u, unsigned int baud) {
u->BRR = USART_BRR_(APB1_FREQ*1000000U, baud);
}

View File

@@ -9,16 +9,8 @@ static void gpio_usb_init(void) {
GPIOA->OSPEEDR = GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12;
}
#ifdef ENABLE_SPI
void gpio_spi_init(void) {
// A4-A7: SPI
set_gpio_alternate(GPIOA, 4, GPIO_AF5_SPI1);
set_gpio_alternate(GPIOA, 5, GPIO_AF5_SPI1);
set_gpio_alternate(GPIOA, 6, GPIO_AF5_SPI1);
set_gpio_alternate(GPIOA, 7, GPIO_AF5_SPI1);
register_set_bits(&(GPIOA->OSPEEDR), GPIO_OSPEEDER_OSPEEDR4 | GPIO_OSPEEDER_OSPEEDR5 | GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7);
}
#endif
#ifdef BOOTSTUB
void gpio_usart2_init(void) {

View File

@@ -53,9 +53,6 @@
#include "stm32f4/board.h"
#include "stm32f4/clock.h"
#include "drivers/spi.h"
#include "stm32f4/llspi.h"
#if !defined(BOOTSTUB)
#include "drivers/uart.h"
#include "stm32f4/lluart.h"
@@ -69,6 +66,11 @@
#include "stm32f4/llusb.h"
// unused
void spi_init(void) {};
void sound_tick(void) {};
void can_tx_comms_resume_spi(void) {};
void early_gpio_float(void) {
RCC->AHB1ENR = RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;

View File

@@ -1,4 +1,3 @@
#if defined(ENABLE_SPI) || defined(BOOTSTUB)
// master -> panda DMA start
void llspi_mosi_dma(uint8_t *addr, int len) {
// disable DMA + SPI
@@ -106,4 +105,3 @@ void llspi_init(void) {
NVIC_EnableIRQ(DMA2_Stream3_IRQn);
NVIC_EnableIRQ(SPI4_IRQn);
}
#endif

View File

@@ -44,11 +44,6 @@ void uart_tx_ring(uart_ring *q){
EXIT_CRITICAL();
}
void uart_set_baud(USART_TypeDef *u, unsigned int baud) {
// UART7 is connected to APB1 at 60MHz
u->BRR = 60000000U / baud;
}
// This read after reading ISR clears all error interrupts. We don't want compiler warnings, nor optimizations
#define UART_READ_RDR(uart) volatile uint8_t t = (uart)->RDR; UNUSED(t);
@@ -90,11 +85,12 @@ static void uart_interrupt_handler(uart_ring *q) {
static void UART7_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_som_debug); }
void uart_init(uart_ring *q, int baud) {
void uart_init(uart_ring *q, unsigned int baud) {
if (q->uart == UART7) {
REGISTER_INTERRUPT(UART7_IRQn, UART7_IRQ_Handler, 150000U, FAULT_INTERRUPT_RATE_UART_7)
uart_set_baud(q->uart, baud);
// UART7 is connected to APB1 at 60MHz
q->uart->BRR = 60000000U / baud;
q->uart->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
// Enable interrupt on RX not empty

View File

@@ -9,7 +9,6 @@ static void gpio_usb_init(void) {
GPIOA->OSPEEDR = GPIO_OSPEEDR_OSPEED11 | GPIO_OSPEEDR_OSPEED12;
}
#ifdef ENABLE_SPI
void gpio_spi_init(void) {
set_gpio_alternate(GPIOE, 11, GPIO_AF5_SPI4);
set_gpio_alternate(GPIOE, 12, GPIO_AF5_SPI4);
@@ -17,7 +16,6 @@ void gpio_spi_init(void) {
set_gpio_alternate(GPIOE, 14, GPIO_AF5_SPI4);
register_set_bits(&(GPIOE->OSPEEDR), GPIO_OSPEEDR_OSPEED11 | GPIO_OSPEEDR_OSPEED12 | GPIO_OSPEEDR_OSPEED13 | GPIO_OSPEEDR_OSPEED14);
}
#endif
#ifdef BOOTSTUB
void gpio_usart2_init(void) {

View File

@@ -75,7 +75,7 @@ if __name__ == "__main__":
if args.bus:
bus = int(args.bus)
else:
bus = 1 if panda.has_obd() else 0
bus = 1
rx_addr = addr + int(args.rxoffset, base=16) if args.rxoffset else None
# Try all sub-addresses for addr. By default, this is None

View File

@@ -105,9 +105,6 @@ ensure_health_packet_version = partial(ensure_version, "health", "HEALTH_PACKET_
class Panda:
SERIAL_DEBUG = 0
SERIAL_ESP = 1
SERIAL_LIN1 = 2
SERIAL_LIN2 = 3
SERIAL_SOM_DEBUG = 4
USB_VIDS = (0xbbaa, 0x3801) # 0x3801 is comma's registered VID
@@ -115,15 +112,10 @@ class Panda:
REQUEST_IN = usb1.ENDPOINT_IN | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE
REQUEST_OUT = usb1.ENDPOINT_OUT | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE
# from https://github.com/commaai/openpilot/blob/103b4df18cbc38f4129555ab8b15824d1a672bdf/cereal/log.capnp#L648
HW_TYPE_UNKNOWN = b'\x00'
HW_TYPE_WHITE_PANDA = b'\x01'
HW_TYPE_GREY_PANDA = b'\x02'
HW_TYPE_BLACK_PANDA = b'\x03'
HW_TYPE_PEDAL = b'\x04'
HW_TYPE_UNO = b'\x05'
HW_TYPE_DOS = b'\x06'
HW_TYPE_RED_PANDA = b'\x07'
HW_TYPE_RED_PANDA_V2 = b'\x08'
HW_TYPE_TRES = b'\x09'
HW_TYPE_CUATRO = b'\x0a'
@@ -133,14 +125,12 @@ class Panda:
HEALTH_STRUCT = struct.Struct("<IIIIIIIIBBBBBHBBBHfBBHBHHB")
CAN_HEALTH_STRUCT = struct.Struct("<BIBBBBBBBBIIIIIIIHHBBBIIII")
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, HW_TYPE_RED_PANDA_V2, HW_TYPE_TRES, HW_TYPE_CUATRO]
F4_DEVICES = [HW_TYPE_DOS, ]
H7_DEVICES = [HW_TYPE_RED_PANDA, HW_TYPE_TRES, HW_TYPE_CUATRO]
INTERNAL_DEVICES = (HW_TYPE_UNO, HW_TYPE_DOS, HW_TYPE_TRES, HW_TYPE_CUATRO)
HAS_OBD = (HW_TYPE_BLACK_PANDA, HW_TYPE_UNO, HW_TYPE_DOS, HW_TYPE_RED_PANDA, HW_TYPE_RED_PANDA_V2, HW_TYPE_TRES, HW_TYPE_CUATRO)
INTERNAL_DEVICES = (HW_TYPE_DOS, HW_TYPE_TRES, HW_TYPE_CUATRO)
MAX_FAN_RPMs = {
HW_TYPE_UNO: 5100,
HW_TYPE_DOS: 6500,
HW_TYPE_TRES: 6600,
HW_TYPE_CUATRO: 12500,
@@ -669,9 +659,6 @@ class Panda:
raise ValueError(f"unknown HW type: {hw_type}")
def has_obd(self):
return self.get_type() in Panda.HAS_OBD
def is_internal(self):
return self.get_type() in Panda.INTERNAL_DEVICES
@@ -816,16 +803,6 @@ class Panda:
ret += self._handle.bulkWrite(2, struct.pack("B", port_number) + ln[i:i + 0x20])
return ret
def serial_clear(self, port_number):
"""Clears all messages (tx and rx) from the specified internal uart
ringbuffer as though it were drained.
Args:
port_number (int): port number of the uart to clear.
"""
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf2, port_number, 0, b'')
def send_heartbeat(self, engaged=True):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf3, engaged, 0, b'')

View File

@@ -5,7 +5,7 @@ Cppcheck checkers list from test_misra.sh:
TEST variant options:
--enable=all --disable=unusedFunction -DPANDA --addon=misra -DSTM32F4 -DSTM32F413xx /board/main.c
--enable=all --disable=unusedFunction --addon=misra -DSTM32F4 -DSTM32F413xx /board/main.c
Critical errors
@@ -460,7 +460,7 @@ Not available, Cppcheck Premium is not used
TEST variant options:
--enable=all --disable=unusedFunction -DPANDA --addon=misra -DSTM32H7 -DSTM32H725xx /board/main.c
--enable=all --disable=unusedFunction --addon=misra -DSTM32H7 -DSTM32H725xx /board/main.c
Critical errors

View File

@@ -64,7 +64,7 @@ cppcheck() {
fi
}
PANDA_OPTS="--enable=all --disable=unusedFunction -DPANDA --addon=misra"
PANDA_OPTS="--enable=all --disable=unusedFunction --addon=misra"
printf "\n${GREEN}** PANDA F4 CODE **${NC}\n"
cppcheck $PANDA_OPTS -DSTM32F4 -DSTM32F413xx $PANDA_DIR/board/main.c