Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ def to_c_uint32(x):
return "{" + 'U,'.join(map(str, nums)) + "U}"


def build_project(project_name, project, main, extra_flags):
def build_project(project_name, project, main, extra_flags, extra_sources=None):
if extra_sources is None:
extra_sources = []
project_dir = Dir(f'./board/obj/{project_name}/')

flags = project["FLAGS"] + extra_flags + common_flags + [
Expand Down Expand Up @@ -115,7 +117,8 @@ def build_project(project_name, project, main, extra_flags):
# Build + sign main (aka app)
main_elf = env.Program(f"{project_dir}/main.elf", [
startup,
main
main,
*extra_sources,
], LINKFLAGS=[f"-Wl,--section-start,.isr_vector={project['APP_START_ADDRESS']}"] + flags)
main_bin = env.Objcopy(f"{project_dir}/main.bin", main_elf)
sign_py = File(f"./board/crypto/sign.py").srcnode().relpath
Expand Down Expand Up @@ -161,7 +164,10 @@ common_flags += [f"-DHEALTH_PACKET_VERSION=0x{hh:08X}U", f"-DCAN_PACKET_VERSION_
f"-DJUNGLE_HEALTH_PACKET_VERSION=0x{jh:08X}U"]

# panda fw
build_project("panda_h7", base_project_h7, "./board/main.c", [])
build_project("panda_h7", base_project_h7, "./board/main.c", [], [
"./board/drivers/bootkick.c",
"./board/drivers/simple_watchdog.c",
])

# panda jungle fw
flags = [
Expand Down
99 changes: 99 additions & 0 deletions board/drivers/bootkick.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include "stm32h7xx.h"

#include "board/drivers/bootkick.h"
#include "board/main_declarations.h"
#include "board/boards/board_declarations.h"

#define HARNESS_STATUS_NC 0U

typedef struct uart_ring {
volatile uint16_t w_ptr_tx;
volatile uint16_t r_ptr_tx;
uint8_t *elems_tx;
uint32_t tx_fifo_size;
volatile uint16_t w_ptr_rx;
volatile uint16_t r_ptr_rx;
uint8_t *elems_rx;
uint32_t rx_fifo_size;
USART_TypeDef *uart;
void (*callback)(struct uart_ring*);
bool overwrite;
} uart_ring;

struct harness_t {
uint8_t status;
uint16_t sbu1_voltage_mV;
uint16_t sbu2_voltage_mV;
bool relay_driven;
bool sbu_adc_lock;
};

extern struct harness_t harness;
extern uart_ring uart_ring_som_debug;

bool bootkick_reset_triggered = false;

void bootkick_tick(bool ignition, bool recent_heartbeat) {
static uint16_t bootkick_last_serial_ptr = 0;
static uint8_t waiting_to_boot_countdown = 0;
static uint8_t boot_reset_countdown = 0;
static uint8_t bootkick_harness_status_prev = HARNESS_STATUS_NC;
static bool bootkick_ign_prev = false;
static BootState boot_state = BOOT_BOOTKICK;
BootState boot_state_prev = boot_state;
const bool harness_inserted = (harness.status != bootkick_harness_status_prev) && (harness.status != HARNESS_STATUS_NC);

if ((ignition && !bootkick_ign_prev) || harness_inserted) {
// bootkick on rising edge of ignition or harness insertion
boot_state = BOOT_BOOTKICK;
} else if (recent_heartbeat) {
// disable bootkick once openpilot is up
boot_state = BOOT_STANDBY;
} else {

}

/*
Ensure SOM boots in case it goes into QDL mode. Reset behavior:
* shouldn't trigger on the first boot after power-on
* only try reset once per bootkick, i.e. don't keep trying until booted
* only try once per panda boot, since openpilot will reset panda on startup
* once BOOT_RESET is triggered, it stays until countdown is finished
*/
if (!bootkick_reset_triggered && (boot_state == BOOT_BOOTKICK) && (boot_state_prev == BOOT_STANDBY)) {
waiting_to_boot_countdown = 20U;
}
if (waiting_to_boot_countdown > 0U) {
bool serial_activity = uart_ring_som_debug.w_ptr_tx != bootkick_last_serial_ptr;
if (serial_activity || current_board->read_som_gpio() || (boot_state != BOOT_BOOTKICK)) {
waiting_to_boot_countdown = 0U;
} else {
// try a reset
if (waiting_to_boot_countdown == 1U) {
boot_reset_countdown = 5U;
}
}
}

// handle reset state
if (boot_reset_countdown > 0U) {
boot_state = BOOT_RESET;
bootkick_reset_triggered = true;
} else {
if (boot_state == BOOT_RESET) {
boot_state = BOOT_BOOTKICK;
}
}

// update state
bootkick_ign_prev = ignition;
bootkick_harness_status_prev = harness.status;
bootkick_last_serial_ptr = uart_ring_som_debug.w_ptr_tx;
if (waiting_to_boot_countdown > 0U) {
waiting_to_boot_countdown--;
}
if (boot_reset_countdown > 0U) {
boot_reset_countdown--;
}
current_board->set_bootkick(boot_state);
}
69 changes: 4 additions & 65 deletions board/drivers/bootkick.h
Original file line number Diff line number Diff line change
@@ -1,68 +1,7 @@
#include "board/drivers/drivers.h"
#pragma once

bool bootkick_reset_triggered = false;
#include <stdbool.h>

void bootkick_tick(bool ignition, bool recent_heartbeat) {
static uint16_t bootkick_last_serial_ptr = 0;
static uint8_t waiting_to_boot_countdown = 0;
static uint8_t boot_reset_countdown = 0;
static uint8_t bootkick_harness_status_prev = HARNESS_STATUS_NC;
static bool bootkick_ign_prev = false;
static BootState boot_state = BOOT_BOOTKICK;
BootState boot_state_prev = boot_state;
const bool harness_inserted = (harness.status != bootkick_harness_status_prev) && (harness.status != HARNESS_STATUS_NC);
extern bool bootkick_reset_triggered;

if ((ignition && !bootkick_ign_prev) || harness_inserted) {
// bootkick on rising edge of ignition or harness insertion
boot_state = BOOT_BOOTKICK;
} else if (recent_heartbeat) {
// disable bootkick once openpilot is up
boot_state = BOOT_STANDBY;
} else {

}

/*
Ensure SOM boots in case it goes into QDL mode. Reset behavior:
* shouldn't trigger on the first boot after power-on
* only try reset once per bootkick, i.e. don't keep trying until booted
* only try once per panda boot, since openpilot will reset panda on startup
* once BOOT_RESET is triggered, it stays until countdown is finished
*/
if (!bootkick_reset_triggered && (boot_state == BOOT_BOOTKICK) && (boot_state_prev == BOOT_STANDBY)) {
waiting_to_boot_countdown = 20U;
}
if (waiting_to_boot_countdown > 0U) {
bool serial_activity = uart_ring_som_debug.w_ptr_tx != bootkick_last_serial_ptr;
if (serial_activity || current_board->read_som_gpio() || (boot_state != BOOT_BOOTKICK)) {
waiting_to_boot_countdown = 0U;
} else {
// try a reset
if (waiting_to_boot_countdown == 1U) {
boot_reset_countdown = 5U;
}
}
}

// handle reset state
if (boot_reset_countdown > 0U) {
boot_state = BOOT_RESET;
bootkick_reset_triggered = true;
} else {
if (boot_state == BOOT_RESET) {
boot_state = BOOT_BOOTKICK;
}
}

// update state
bootkick_ign_prev = ignition;
bootkick_harness_status_prev = harness.status;
bootkick_last_serial_ptr = uart_ring_som_debug.w_ptr_tx;
if (waiting_to_boot_countdown > 0U) {
waiting_to_boot_countdown--;
}
if (boot_reset_countdown > 0U) {
boot_reset_countdown--;
}
current_board->set_bootkick(boot_state);
}
void bootkick_tick(bool ignition, bool recent_heartbeat);
6 changes: 0 additions & 6 deletions board/drivers/drivers.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,12 +211,6 @@ void init_registers(void);

// ******************** simple_watchdog ********************

typedef struct simple_watchdog_state_t {
uint32_t fault;
uint32_t last_ts;
uint32_t threshold;
} simple_watchdog_state_t;

void simple_watchdog_kick(void);
void simple_watchdog_init(uint32_t fault, uint32_t threshold);

Expand Down
2 changes: 2 additions & 0 deletions board/drivers/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ void set_gpio_alternate(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode)
void set_gpio_pullup(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode) {
ENTER_CRITICAL();
uint32_t tmp = GPIO->PUPDR;
// cppcheck-suppress misra-c2012-12.2; pin is a GPIO pin index
tmp &= ~(3U << (pin * 2U));
// cppcheck-suppress misra-c2012-12.2; pin is a GPIO pin index
tmp |= (mode << (pin * 2U));
register_set(&(GPIO->PUPDR), tmp, 0xFFFFFFFFU);
EXIT_CRITICAL();
Expand Down
37 changes: 37 additions & 0 deletions board/drivers/simple_watchdog.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "board/drivers/simple_watchdog.h"

#include <stdbool.h>

#include "stm32h7xx.h"

#include "board/main_declarations.h"
#include "board/sys/sys.h"

typedef struct simple_watchdog_state_t {
uint32_t fault;
uint32_t last_ts;
uint32_t threshold;
} simple_watchdog_state_t;

uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last);
uint32_t microsecond_timer_get(void);

static simple_watchdog_state_t wd_state;

void simple_watchdog_kick(void) {
uint32_t ts = microsecond_timer_get();

uint32_t et = get_ts_elapsed(ts, wd_state.last_ts);
if (et > wd_state.threshold) {
print("WD timeout 0x"); puth(et); print("\n");
fault_occurred(wd_state.fault);
}

wd_state.last_ts = ts;
}

void simple_watchdog_init(uint32_t fault, uint32_t threshold) {
wd_state.fault = fault;
wd_state.threshold = threshold;
wd_state.last_ts = microsecond_timer_get();
}
23 changes: 4 additions & 19 deletions board/drivers/simple_watchdog.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,6 @@
#include "board/drivers/drivers.h"
#pragma once

static simple_watchdog_state_t wd_state;
#include <stdint.h>

void simple_watchdog_kick(void) {
uint32_t ts = microsecond_timer_get();

uint32_t et = get_ts_elapsed(ts, wd_state.last_ts);
if (et > wd_state.threshold) {
print("WD timeout 0x"); puth(et); print("\n");
fault_occurred(wd_state.fault);
}

wd_state.last_ts = ts;
}

void simple_watchdog_init(uint32_t fault, uint32_t threshold) {
wd_state.fault = fault;
wd_state.threshold = threshold;
wd_state.last_ts = microsecond_timer_get();
}
void simple_watchdog_kick(void);
void simple_watchdog_init(uint32_t fault, uint32_t threshold);
2 changes: 0 additions & 2 deletions board/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
#include "board/drivers/led.h"
#include "board/drivers/pwm.h"
#include "board/drivers/usb.h"
#include "board/drivers/simple_watchdog.h"
#include "board/drivers/bootkick.h"

#include "board/early_init.h"
#include "board/provision.h"
Expand Down
Loading