mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-14 19:44:05 +08:00
Merge panda subtree
This commit is contained in:
+180
-134
@@ -5,10 +5,15 @@
|
||||
#include "config.h"
|
||||
#include "obj/gitversion.h"
|
||||
|
||||
#include "main_declarations.h"
|
||||
#include "critical.h"
|
||||
|
||||
#include "libc.h"
|
||||
#include "provision.h"
|
||||
#include "faults.h"
|
||||
|
||||
#include "main_declarations.h"
|
||||
#include "drivers/registers.h"
|
||||
#include "drivers/interrupts.h"
|
||||
|
||||
#include "drivers/llcan.h"
|
||||
#include "drivers/llgpio.h"
|
||||
@@ -34,6 +39,28 @@
|
||||
|
||||
#include "drivers/can.h"
|
||||
|
||||
extern int _app_start[0xc000]; // Only first 3 sectors of size 0x4000 are used
|
||||
|
||||
struct __attribute__((packed)) health_t {
|
||||
uint32_t uptime_pkt;
|
||||
uint32_t voltage_pkt;
|
||||
uint32_t current_pkt;
|
||||
uint32_t can_send_errs_pkt;
|
||||
uint32_t can_fwd_errs_pkt;
|
||||
uint32_t gmlan_send_errs_pkt;
|
||||
uint32_t faults_pkt;
|
||||
uint8_t ignition_line_pkt;
|
||||
uint8_t ignition_can_pkt;
|
||||
uint8_t controls_allowed_pkt;
|
||||
uint8_t gas_interceptor_detected_pkt;
|
||||
uint8_t car_harness_status_pkt;
|
||||
uint8_t usb_power_mode_pkt;
|
||||
uint8_t safety_mode_pkt;
|
||||
uint8_t fault_status_pkt;
|
||||
uint8_t power_save_enabled_pkt;
|
||||
};
|
||||
|
||||
|
||||
// ********************* Serial debugging *********************
|
||||
|
||||
bool check_started(void) {
|
||||
@@ -45,11 +72,14 @@ void debug_ring_callback(uart_ring *ring) {
|
||||
while (getc(ring, &rcv)) {
|
||||
(void)putc(ring, rcv); // misra-c2012-17.7: cast to void is ok: debug function
|
||||
|
||||
// jump to DFU flash
|
||||
if (rcv == 'z') {
|
||||
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
// 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') {
|
||||
@@ -72,100 +102,65 @@ void debug_ring_callback(uart_ring *ring) {
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************** started logic *****************************
|
||||
void started_interrupt_handler(uint8_t interrupt_line) {
|
||||
volatile unsigned int pr = EXTI->PR & (1U << interrupt_line);
|
||||
if ((pr & (1U << interrupt_line)) != 0U) {
|
||||
#ifdef DEBUG
|
||||
puts("got started interrupt\n");
|
||||
#endif
|
||||
|
||||
// jenky debounce
|
||||
delay(100000);
|
||||
|
||||
#ifdef EON
|
||||
// set power savings mode here if on EON build
|
||||
int power_save_state = check_started() ? POWER_SAVE_STATUS_DISABLED : POWER_SAVE_STATUS_ENABLED;
|
||||
set_power_save_state(power_save_state);
|
||||
// set CDP usb power mode everytime that the car starts to make sure EON is charging
|
||||
if (check_started()) {
|
||||
current_board->set_usb_power_mode(USB_POWER_CDP);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
EXTI->PR = (1U << interrupt_line);
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void EXTI0_IRQHandler(void) {
|
||||
started_interrupt_handler(0);
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void EXTI1_IRQHandler(void) {
|
||||
started_interrupt_handler(1);
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void EXTI3_IRQHandler(void) {
|
||||
started_interrupt_handler(3);
|
||||
}
|
||||
|
||||
// ****************************** safety mode ******************************
|
||||
|
||||
// this is the only way to leave silent mode
|
||||
void set_safety_mode(uint16_t mode, int16_t param) {
|
||||
int err = safety_set_mode(mode, param);
|
||||
uint16_t mode_copy = mode;
|
||||
int err = set_safety_hooks(mode_copy, param);
|
||||
if (err == -1) {
|
||||
puts("Error: safety set mode failed\n");
|
||||
} else {
|
||||
switch (mode) {
|
||||
case SAFETY_NOOUTPUT:
|
||||
set_intercept_relay(false);
|
||||
if(board_has_obd()){
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
can_silent = ALL_CAN_SILENT;
|
||||
break;
|
||||
case SAFETY_ELM327:
|
||||
set_intercept_relay(false);
|
||||
heartbeat_counter = 0U;
|
||||
if(board_has_obd()){
|
||||
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
default:
|
||||
set_intercept_relay(true);
|
||||
heartbeat_counter = 0U;
|
||||
if(board_has_obd()){
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
puts("Error: safety set mode failed. Falling back to SILENT\n");
|
||||
mode_copy = SAFETY_SILENT;
|
||||
err = set_safety_hooks(mode_copy, 0);
|
||||
if (err == -1) {
|
||||
puts("Error: Failed setting SILENT mode. Hanging\n");
|
||||
while (true) {
|
||||
// TERMINAL ERROR: we can't continue if SILENT safety mode isn't succesfully set
|
||||
}
|
||||
can_init_all();
|
||||
}
|
||||
}
|
||||
switch (mode_copy) {
|
||||
case SAFETY_SILENT:
|
||||
set_intercept_relay(false);
|
||||
if (board_has_obd()) {
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
can_silent = ALL_CAN_SILENT;
|
||||
break;
|
||||
case SAFETY_NOOUTPUT:
|
||||
set_intercept_relay(false);
|
||||
if (board_has_obd()) {
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
case SAFETY_ELM327:
|
||||
set_intercept_relay(false);
|
||||
heartbeat_counter = 0U;
|
||||
if (board_has_obd()) {
|
||||
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
default:
|
||||
set_intercept_relay(true);
|
||||
heartbeat_counter = 0U;
|
||||
if (board_has_obd()) {
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
}
|
||||
can_init_all();
|
||||
}
|
||||
|
||||
// ***************************** USB port *****************************
|
||||
|
||||
int get_health_pkt(void *dat) {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t voltage_pkt;
|
||||
uint32_t current_pkt;
|
||||
uint32_t can_send_errs_pkt;
|
||||
uint32_t can_fwd_errs_pkt;
|
||||
uint32_t gmlan_send_errs_pkt;
|
||||
uint8_t ignition_line_pkt;
|
||||
uint8_t ignition_can_pkt;
|
||||
uint8_t controls_allowed_pkt;
|
||||
uint8_t gas_interceptor_detected_pkt;
|
||||
uint8_t car_harness_status_pkt;
|
||||
uint8_t usb_power_mode_pkt;
|
||||
uint8_t safety_mode_pkt;
|
||||
} *health = dat;
|
||||
COMPILE_TIME_ASSERT(sizeof(struct health_t) <= MAX_RESP_LEN);
|
||||
struct health_t * health = (struct health_t*)dat;
|
||||
|
||||
health->uptime_pkt = uptime_cnt;
|
||||
health->voltage_pkt = adc_get_voltage();
|
||||
health->current_pkt = current_board->read_current();
|
||||
|
||||
@@ -181,6 +176,10 @@ int get_health_pkt(void *dat) {
|
||||
health->car_harness_status_pkt = car_harness_status;
|
||||
health->usb_power_mode_pkt = usb_power_mode;
|
||||
health->safety_mode_pkt = (uint8_t)(current_safety_mode);
|
||||
health->power_save_enabled_pkt = (uint8_t)(power_save_status == POWER_SAVE_STATUS_ENABLED);
|
||||
|
||||
health->fault_status_pkt = fault_status;
|
||||
health->faults_pkt = faults;
|
||||
|
||||
return sizeof(*health);
|
||||
}
|
||||
@@ -230,7 +229,7 @@ void usb_cb_ep3_out(void *usbdata, int len, bool hardwired) {
|
||||
to_push.RIR = d32[dpkt];
|
||||
|
||||
uint8_t bus_number = (to_push.RDTR >> 4) & CAN_BUS_NUM_MASK;
|
||||
can_send(&to_push, bus_number);
|
||||
can_send(&to_push, bus_number, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +312,10 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
resp[1] = ((fan_rpm & 0xFF00U) >> 8U);
|
||||
resp_len = 2;
|
||||
break;
|
||||
// **** 0xb3: set phone power
|
||||
case 0xb3:
|
||||
current_board->set_phone_power(setup->b.wValue.w > 0U);
|
||||
break;
|
||||
// **** 0xc0: get CAN debug info
|
||||
case 0xc0:
|
||||
puts("can tx: "); puth(can_tx_cnt);
|
||||
@@ -366,6 +369,24 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
case 0xd2:
|
||||
resp_len = get_health_pkt(resp);
|
||||
break;
|
||||
// **** 0xd3: get first 64 bytes of signature
|
||||
case 0xd3:
|
||||
{
|
||||
resp_len = 64;
|
||||
char * code = (char*)_app_start;
|
||||
int code_len = _app_start[0];
|
||||
(void)memcpy(resp, &code[code_len], resp_len);
|
||||
}
|
||||
break;
|
||||
// **** 0xd4: get second 64 bytes of signature
|
||||
case 0xd4:
|
||||
{
|
||||
resp_len = 64;
|
||||
char * code = (char*)_app_start;
|
||||
int code_len = _app_start[0];
|
||||
(void)memcpy(resp, &code[code_len + 64], resp_len);
|
||||
}
|
||||
break;
|
||||
// **** 0xd6: get version
|
||||
case 0xd6:
|
||||
COMPILE_TIME_ASSERT(sizeof(gitversion) <= MAX_RESP_LEN);
|
||||
@@ -427,8 +448,10 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
// **** 0xdc: set safety mode
|
||||
case 0xdc:
|
||||
// Blocked over WiFi.
|
||||
// Allow NOOUTPUT and ELM security mode to be set over wifi.
|
||||
if (hardwired || (setup->b.wValue.w == SAFETY_NOOUTPUT) || (setup->b.wValue.w == SAFETY_ELM327)) {
|
||||
// Allow SILENT, NOOUTPUT and ELM security mode to be set over wifi.
|
||||
if (hardwired || (setup->b.wValue.w == SAFETY_SILENT) ||
|
||||
(setup->b.wValue.w == SAFETY_NOOUTPUT) ||
|
||||
(setup->b.wValue.w == SAFETY_ELM327)) {
|
||||
set_safety_mode(setup->b.wValue.w, (uint16_t) setup->b.wIndex.w);
|
||||
}
|
||||
break;
|
||||
@@ -526,6 +549,10 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
case 0xe6:
|
||||
current_board->set_usb_power_mode(setup->b.wValue.w);
|
||||
break;
|
||||
// **** 0xe7: set power save state
|
||||
case 0xe7:
|
||||
set_power_save_state(setup->b.wValue.w);
|
||||
break;
|
||||
// **** 0xf0: do k-line wValue pulse on uart2 for Acura
|
||||
case 0xf0:
|
||||
if (setup->b.wValue.w == 1U) {
|
||||
@@ -640,24 +667,21 @@ void __attribute__ ((noinline)) enable_fpu(void) {
|
||||
SCB->CPACR |= ((3UL << (10U * 2U)) | (3UL << (11U * 2U)));
|
||||
}
|
||||
|
||||
uint64_t tcnt = 0;
|
||||
|
||||
// go into NOOUTPUT when the EON does not send a heartbeat for this amount of seconds.
|
||||
// go into SILENT when the EON does not send a heartbeat for this amount of seconds.
|
||||
#define EON_HEARTBEAT_IGNITION_CNT_ON 5U
|
||||
#define EON_HEARTBEAT_IGNITION_CNT_OFF 2U
|
||||
|
||||
// called once per second
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void TIM1_BRK_TIM9_IRQHandler(void) {
|
||||
void TIM1_BRK_TIM9_IRQ_Handler(void) {
|
||||
if (TIM9->SR != 0) {
|
||||
can_live = pending_can_live;
|
||||
|
||||
current_board->usb_power_mode_tick(tcnt);
|
||||
current_board->usb_power_mode_tick(uptime_cnt);
|
||||
|
||||
//puth(usart1_dma); puts(" "); puth(DMA2_Stream5->M0AR); puts(" "); puth(DMA2_Stream5->NDTR); puts("\n");
|
||||
|
||||
// reset this every 16th pass
|
||||
if ((tcnt & 0xFU) == 0U) {
|
||||
if ((uptime_cnt & 0xFU) == 0U) {
|
||||
pending_can_live = 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
@@ -676,30 +700,57 @@ void TIM1_BRK_TIM9_IRQHandler(void) {
|
||||
|
||||
// turn off the blue LED, turned on by CAN
|
||||
// unless we are in power saving mode
|
||||
current_board->set_led(LED_BLUE, (tcnt & 1U) && (power_save_status == POWER_SAVE_STATUS_ENABLED));
|
||||
current_board->set_led(LED_BLUE, (uptime_cnt & 1U) && (power_save_status == POWER_SAVE_STATUS_ENABLED));
|
||||
|
||||
// increase heartbeat counter and cap it at the uint32 limit
|
||||
if (heartbeat_counter < __UINT32_MAX__) {
|
||||
heartbeat_counter += 1U;
|
||||
}
|
||||
|
||||
// check heartbeat counter if we are running EON code. If the heartbeat has been gone for a while, go to NOOUTPUT safety mode.
|
||||
#ifdef EON
|
||||
// check heartbeat counter if we are running EON code.
|
||||
// if the heartbeat has been gone for a while, go to SILENT safety mode and enter power save
|
||||
if (heartbeat_counter >= (check_started() ? EON_HEARTBEAT_IGNITION_CNT_ON : EON_HEARTBEAT_IGNITION_CNT_OFF)) {
|
||||
puts("EON hasn't sent a heartbeat for 0x"); puth(heartbeat_counter); puts(" seconds. Safety is set to NOOUTPUT mode.\n");
|
||||
if(current_safety_mode != SAFETY_NOOUTPUT){
|
||||
set_safety_mode(SAFETY_NOOUTPUT, 0U);
|
||||
puts("EON hasn't sent a heartbeat for 0x");
|
||||
puth(heartbeat_counter);
|
||||
puts(" seconds. Safety is set to SILENT mode.\n");
|
||||
if (current_safety_mode != SAFETY_SILENT) {
|
||||
set_safety_mode(SAFETY_SILENT, 0U);
|
||||
}
|
||||
if (power_save_status != POWER_SAVE_STATUS_ENABLED) {
|
||||
set_power_save_state(POWER_SAVE_STATUS_ENABLED);
|
||||
}
|
||||
}
|
||||
|
||||
// enter CDP mode when car starts to ensure we are charging a turned off EON
|
||||
if (check_started() && (usb_power_mode != USB_POWER_CDP)) {
|
||||
current_board->set_usb_power_mode(USB_POWER_CDP);
|
||||
}
|
||||
#endif
|
||||
|
||||
// check registers
|
||||
check_registers();
|
||||
|
||||
// set ignition_can to false after 2s of no CAN seen
|
||||
if (ignition_can_cnt > 2U) {
|
||||
ignition_can = false;
|
||||
};
|
||||
|
||||
// on to the next one
|
||||
tcnt += 1U;
|
||||
uptime_cnt += 1U;
|
||||
safety_mode_cnt += 1U;
|
||||
ignition_can_cnt += 1U;
|
||||
}
|
||||
TIM9->SR = 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// Init interrupt table
|
||||
init_interrupts(true);
|
||||
|
||||
// 1s timer
|
||||
REGISTER_INTERRUPT(TIM1_BRK_TIM9_IRQn, TIM1_BRK_TIM9_IRQ_Handler, 2U, FAULT_INTERRUPT_RATE_TIM1)
|
||||
|
||||
// shouldn't have interrupts here, but just in case
|
||||
disable_interrupts();
|
||||
|
||||
@@ -760,32 +811,16 @@ int main(void) {
|
||||
TIM2->EGR = TIM_EGR_UG;
|
||||
// use TIM2->CNT to read
|
||||
|
||||
// default to silent mode to prevent issues with Ford
|
||||
// hardcode a specific safety mode if you want to force the panda to be in a specific mode
|
||||
int err = safety_set_mode(SAFETY_NOOUTPUT, 0);
|
||||
if (err == -1) {
|
||||
puts("Failed to set safety mode\n");
|
||||
while (true) {
|
||||
// if SAFETY_NOOUTPUT isn't succesfully set, we can't continue
|
||||
}
|
||||
}
|
||||
can_silent = ALL_CAN_SILENT;
|
||||
can_init_all();
|
||||
// init to SILENT and can silent
|
||||
set_safety_mode(SAFETY_SILENT, 0);
|
||||
|
||||
// enable CAN TXs
|
||||
current_board->enable_can_transcievers(true);
|
||||
|
||||
#ifndef EON
|
||||
spi_init();
|
||||
#endif
|
||||
|
||||
#ifdef EON
|
||||
// have to save power
|
||||
if (hw_type == HW_TYPE_WHITE_PANDA) {
|
||||
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
|
||||
}
|
||||
// only enter power save after the first cycle
|
||||
/*if (check_started()) {
|
||||
set_power_save_state(POWER_SAVE_STATUS_ENABLED);
|
||||
}*/
|
||||
#endif
|
||||
// 1hz
|
||||
timer_init(TIM9, 1464);
|
||||
NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
|
||||
@@ -804,19 +839,30 @@ int main(void) {
|
||||
|
||||
for (cnt=0;;cnt++) {
|
||||
if (power_save_status == POWER_SAVE_STATUS_DISABLED) {
|
||||
int div_mode = ((usb_power_mode == USB_POWER_DCP) ? 4 : 1);
|
||||
#ifdef DEBUG_FAULTS
|
||||
if(fault_status == FAULT_STATUS_NONE){
|
||||
#endif
|
||||
int div_mode = ((usb_power_mode == USB_POWER_DCP) ? 4 : 1);
|
||||
|
||||
// useful for debugging, fade breaks = panda is overloaded
|
||||
for (int div_mode_loop = 0; div_mode_loop < div_mode; div_mode_loop++) {
|
||||
for (int fade = 0; fade < 1024; fade += 8) {
|
||||
for (int i = 0; i < (128/div_mode); i++) {
|
||||
current_board->set_led(LED_RED, 1);
|
||||
if (fade < 512) { delay(fade); } else { delay(1024-fade); }
|
||||
current_board->set_led(LED_RED, 0);
|
||||
if (fade < 512) { delay(512-fade); } else { delay(fade-512); }
|
||||
// useful for debugging, fade breaks = panda is overloaded
|
||||
for (int div_mode_loop = 0; div_mode_loop < div_mode; div_mode_loop++) {
|
||||
for (int fade = 0; fade < 1024; fade += 8) {
|
||||
for (int i = 0; i < (128/div_mode); i++) {
|
||||
current_board->set_led(LED_RED, 1);
|
||||
if (fade < 512) { delay(fade); } else { delay(1024-fade); }
|
||||
current_board->set_led(LED_RED, 0);
|
||||
if (fade < 512) { delay(512-fade); } else { delay(fade-512); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_FAULTS
|
||||
} else {
|
||||
current_board->set_led(LED_RED, 1);
|
||||
delay(512000U);
|
||||
current_board->set_led(LED_RED, 0);
|
||||
delay(512000U);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
__WFI();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user