2019-09-28 08:18:02 +08:00
|
|
|
//#define EON
|
2019-07-24 06:07:06 +08:00
|
|
|
//#define PANDA
|
2019-05-22 03:48:38 +08:00
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
// ********************* Includes *********************
|
2017-06-28 10:27:24 +08:00
|
|
|
#include "config.h"
|
2017-04-07 09:11:36 +08:00
|
|
|
#include "obj/gitversion.h"
|
|
|
|
|
2019-11-28 10:11:21 +08:00
|
|
|
#include "main_declarations.h"
|
2019-12-06 06:19:29 +08:00
|
|
|
#include "critical.h"
|
2019-11-28 10:11:21 +08:00
|
|
|
|
2017-07-13 02:25:10 +08:00
|
|
|
#include "libc.h"
|
2017-07-30 23:26:48 +08:00
|
|
|
#include "provision.h"
|
2019-11-28 10:11:21 +08:00
|
|
|
#include "faults.h"
|
2017-07-21 14:45:48 +08:00
|
|
|
|
2019-12-06 06:19:29 +08:00
|
|
|
#include "drivers/registers.h"
|
2019-11-28 10:11:21 +08:00
|
|
|
#include "drivers/interrupts.h"
|
2019-07-24 06:07:06 +08:00
|
|
|
|
2019-05-22 22:10:46 +08:00
|
|
|
#include "drivers/llcan.h"
|
2017-07-30 08:53:39 +08:00
|
|
|
#include "drivers/llgpio.h"
|
2019-07-24 06:07:06 +08:00
|
|
|
#include "drivers/adc.h"
|
2019-10-26 07:22:42 +08:00
|
|
|
#include "drivers/pwm.h"
|
2019-07-24 06:07:06 +08:00
|
|
|
|
|
|
|
#include "board.h"
|
2017-07-30 08:53:39 +08:00
|
|
|
|
2017-07-21 14:45:48 +08:00
|
|
|
#include "drivers/uart.h"
|
|
|
|
#include "drivers/usb.h"
|
2018-08-03 02:13:57 +08:00
|
|
|
#include "drivers/gmlan_alt.h"
|
2017-07-22 02:48:03 +08:00
|
|
|
#include "drivers/timer.h"
|
2019-05-21 23:11:38 +08:00
|
|
|
#include "drivers/clock.h"
|
2017-07-22 02:48:03 +08:00
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
#include "gpio.h"
|
|
|
|
|
2019-06-27 03:01:57 +08:00
|
|
|
#ifndef EON
|
|
|
|
#include "drivers/spi.h"
|
|
|
|
#endif
|
|
|
|
|
2019-04-02 13:45:00 +08:00
|
|
|
#include "power_saving.h"
|
2019-05-22 23:30:32 +08:00
|
|
|
#include "safety.h"
|
2019-07-24 06:07:06 +08:00
|
|
|
|
2019-05-22 23:30:32 +08:00
|
|
|
#include "drivers/can.h"
|
2017-07-30 08:53:39 +08:00
|
|
|
|
2019-12-10 02:54:48 +08:00
|
|
|
extern int _app_start[0xc000]; // Only first 3 sectors of size 0x4000 are used
|
|
|
|
|
2019-12-10 02:39:04 +08:00
|
|
|
struct __attribute__((packed)) health_t {
|
|
|
|
uint32_t uptime_pkt;
|
|
|
|
uint32_t voltage_pkt;
|
|
|
|
uint32_t current_pkt;
|
2019-12-20 10:16:31 +08:00
|
|
|
uint32_t can_rx_errs_pkt;
|
2019-12-10 02:39:04 +08:00
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
// ********************* Serial debugging *********************
|
2017-07-21 04:41:21 +08:00
|
|
|
|
2019-10-23 07:12:18 +08:00
|
|
|
bool check_started(void) {
|
2019-10-23 06:27:55 +08:00
|
|
|
return current_board->check_ignition() || ignition_can;
|
|
|
|
}
|
|
|
|
|
2017-07-21 04:41:21 +08:00
|
|
|
void debug_ring_callback(uart_ring *ring) {
|
|
|
|
char rcv;
|
|
|
|
while (getc(ring, &rcv)) {
|
2019-07-04 07:01:01 +08:00
|
|
|
(void)putc(ring, rcv); // misra-c2012-17.7: cast to void is ok: debug function
|
2017-07-21 04:41:21 +08:00
|
|
|
|
2019-12-11 00:14:30 +08:00
|
|
|
// 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
|
2017-07-21 04:41:21 +08:00
|
|
|
|
|
|
|
// normal reset
|
|
|
|
if (rcv == 'x') {
|
|
|
|
NVIC_SystemReset();
|
|
|
|
}
|
|
|
|
|
|
|
|
// enable CDP mode
|
|
|
|
if (rcv == 'C') {
|
|
|
|
puts("switching USB to CDP mode\n");
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_usb_power_mode(USB_POWER_CDP);
|
2017-07-21 04:41:21 +08:00
|
|
|
}
|
|
|
|
if (rcv == 'c') {
|
|
|
|
puts("switching USB to client mode\n");
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_usb_power_mode(USB_POWER_CLIENT);
|
2017-07-21 04:41:21 +08:00
|
|
|
}
|
|
|
|
if (rcv == 'D') {
|
|
|
|
puts("switching USB to DCP mode\n");
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_usb_power_mode(USB_POWER_DCP);
|
2017-07-21 04:41:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
// ****************************** safety mode ******************************
|
|
|
|
|
|
|
|
// this is the only way to leave silent mode
|
|
|
|
void set_safety_mode(uint16_t mode, int16_t param) {
|
2019-11-21 07:13:26 +08:00
|
|
|
uint16_t mode_copy = mode;
|
|
|
|
int err = set_safety_hooks(mode_copy, param);
|
2019-07-24 06:07:06 +08:00
|
|
|
if (err == -1) {
|
2019-11-21 05:36:29 +08:00
|
|
|
puts("Error: safety set mode failed. Falling back to SILENT\n");
|
2019-11-21 07:13:26 +08:00
|
|
|
mode_copy = SAFETY_SILENT;
|
|
|
|
err = set_safety_hooks(mode_copy, 0);
|
2019-11-21 05:36:29 +08:00
|
|
|
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
|
2019-09-28 08:18:02 +08:00
|
|
|
}
|
2019-11-21 05:36:29 +08:00
|
|
|
}
|
2019-07-24 06:07:06 +08:00
|
|
|
}
|
2019-11-21 07:13:26 +08:00
|
|
|
switch (mode_copy) {
|
2019-11-21 05:36:29 +08:00
|
|
|
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;
|
2019-11-21 06:04:07 +08:00
|
|
|
}
|
2019-11-21 05:36:29 +08:00
|
|
|
can_init_all();
|
2019-07-24 06:07:06 +08:00
|
|
|
}
|
|
|
|
|
2019-05-22 23:30:32 +08:00
|
|
|
// ***************************** USB port *****************************
|
|
|
|
|
2017-04-07 09:11:36 +08:00
|
|
|
int get_health_pkt(void *dat) {
|
2019-12-10 02:39:04 +08:00
|
|
|
COMPILE_TIME_ASSERT(sizeof(struct health_t) <= MAX_RESP_LEN);
|
|
|
|
struct health_t * health = (struct health_t*)dat;
|
2017-07-21 14:36:06 +08:00
|
|
|
|
2019-11-22 08:47:49 +08:00
|
|
|
health->uptime_pkt = uptime_cnt;
|
2019-10-05 05:51:26 +08:00
|
|
|
health->voltage_pkt = adc_get_voltage();
|
2019-10-26 07:22:42 +08:00
|
|
|
health->current_pkt = current_board->read_current();
|
2019-07-24 06:07:06 +08:00
|
|
|
|
2019-10-23 06:10:43 +08:00
|
|
|
//Use the GPIO pin to determine ignition or use a CAN based logic
|
2019-10-23 06:27:55 +08:00
|
|
|
health->ignition_line_pkt = (uint8_t)(current_board->check_ignition());
|
|
|
|
health->ignition_can_pkt = (uint8_t)(ignition_can);
|
2017-04-07 09:11:36 +08:00
|
|
|
|
2019-07-03 13:39:00 +08:00
|
|
|
health->controls_allowed_pkt = controls_allowed;
|
|
|
|
health->gas_interceptor_detected_pkt = gas_interceptor_detected;
|
2019-12-20 10:16:31 +08:00
|
|
|
health->can_rx_errs_pkt = can_rx_errs;
|
2019-07-11 08:27:26 +08:00
|
|
|
health->can_send_errs_pkt = can_send_errs;
|
|
|
|
health->can_fwd_errs_pkt = can_fwd_errs;
|
|
|
|
health->gmlan_send_errs_pkt = gmlan_send_errs;
|
2019-07-24 06:07:06 +08:00
|
|
|
health->car_harness_status_pkt = car_harness_status;
|
2019-10-03 02:48:40 +08:00
|
|
|
health->usb_power_mode_pkt = usb_power_mode;
|
2019-10-25 06:33:27 +08:00
|
|
|
health->safety_mode_pkt = (uint8_t)(current_safety_mode);
|
2019-11-22 04:53:00 +08:00
|
|
|
health->power_save_enabled_pkt = (uint8_t)(power_save_status == POWER_SAVE_STATUS_ENABLED);
|
2019-09-28 08:18:02 +08:00
|
|
|
|
2019-11-28 10:11:21 +08:00
|
|
|
health->fault_status_pkt = fault_status;
|
|
|
|
health->faults_pkt = faults;
|
2019-11-27 09:07:51 +08:00
|
|
|
|
2017-04-07 09:11:36 +08:00
|
|
|
return sizeof(*health);
|
|
|
|
}
|
|
|
|
|
2019-10-26 07:22:42 +08:00
|
|
|
int get_rtc_pkt(void *dat) {
|
|
|
|
timestamp_t t = rtc_get_time();
|
|
|
|
(void)memcpy(dat, &t, sizeof(t));
|
|
|
|
return sizeof(t);
|
|
|
|
}
|
|
|
|
|
2019-07-11 11:56:03 +08:00
|
|
|
int usb_cb_ep1_in(void *usbdata, int len, bool hardwired) {
|
2019-06-25 01:25:30 +08:00
|
|
|
UNUSED(hardwired);
|
2017-07-19 01:19:42 +08:00
|
|
|
CAN_FIFOMailBox_TypeDef *reply = (CAN_FIFOMailBox_TypeDef *)usbdata;
|
2017-04-07 09:11:36 +08:00
|
|
|
int ilen = 0;
|
2019-06-29 04:46:57 +08:00
|
|
|
while (ilen < MIN(len/0x10, 4) && can_pop(&can_rx_q, &reply[ilen])) {
|
|
|
|
ilen++;
|
|
|
|
}
|
2017-04-18 09:17:34 +08:00
|
|
|
return ilen*0x10;
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
|
|
|
|
2017-07-21 14:36:06 +08:00
|
|
|
// send on serial, first byte to select the ring
|
2019-07-11 11:56:03 +08:00
|
|
|
void usb_cb_ep2_out(void *usbdata, int len, bool hardwired) {
|
2019-06-25 01:25:30 +08:00
|
|
|
UNUSED(hardwired);
|
2019-07-11 11:56:03 +08:00
|
|
|
uint8_t *usbdata8 = (uint8_t *)usbdata;
|
|
|
|
uart_ring *ur = get_ring_by_number(usbdata8[0]);
|
2019-06-27 09:24:21 +08:00
|
|
|
if ((len != 0) && (ur != NULL)) {
|
2019-09-28 08:18:02 +08:00
|
|
|
if ((usbdata8[0] < 2U) || safety_tx_lin_hook(usbdata8[0] - 2U, &usbdata8[1], len - 1)) {
|
2019-06-29 04:46:57 +08:00
|
|
|
for (int i = 1; i < len; i++) {
|
2019-07-11 11:56:03 +08:00
|
|
|
while (!putc(ur, usbdata8[i])) {
|
2019-06-29 04:46:57 +08:00
|
|
|
// wait
|
|
|
|
}
|
|
|
|
}
|
2019-06-27 06:52:34 +08:00
|
|
|
}
|
2017-05-02 11:22:19 +08:00
|
|
|
}
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// send on CAN
|
2019-07-11 11:56:03 +08:00
|
|
|
void usb_cb_ep3_out(void *usbdata, int len, bool hardwired) {
|
2019-06-25 01:25:30 +08:00
|
|
|
UNUSED(hardwired);
|
2017-04-07 09:11:36 +08:00
|
|
|
int dpkt = 0;
|
2019-07-11 11:56:03 +08:00
|
|
|
uint32_t *d32 = (uint32_t *)usbdata;
|
|
|
|
for (dpkt = 0; dpkt < (len / 4); dpkt += 4) {
|
2017-04-07 09:11:36 +08:00
|
|
|
CAN_FIFOMailBox_TypeDef to_push;
|
2019-07-11 11:56:03 +08:00
|
|
|
to_push.RDHR = d32[dpkt + 3];
|
|
|
|
to_push.RDLR = d32[dpkt + 2];
|
|
|
|
to_push.RDTR = d32[dpkt + 1];
|
|
|
|
to_push.RIR = d32[dpkt];
|
2017-04-07 09:11:36 +08:00
|
|
|
|
2017-07-15 03:30:34 +08:00
|
|
|
uint8_t bus_number = (to_push.RDTR >> 4) & CAN_BUS_NUM_MASK;
|
2019-11-14 15:50:42 +08:00
|
|
|
can_send(&to_push, bus_number, false);
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-07 07:49:42 +08:00
|
|
|
void usb_cb_ep3_out_complete() {
|
|
|
|
if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_BULK_TRANSFER)) {
|
|
|
|
usb_outep3_resume_if_paused();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-13 02:25:10 +08:00
|
|
|
void usb_cb_enumeration_complete() {
|
2017-07-21 14:36:06 +08:00
|
|
|
puts("USB enumeration complete\n");
|
2017-08-22 23:27:00 +08:00
|
|
|
is_enumerated = 1;
|
2017-07-13 02:25:10 +08:00
|
|
|
}
|
|
|
|
|
2019-06-27 03:18:06 +08:00
|
|
|
int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) {
|
2019-07-04 16:04:58 +08:00
|
|
|
unsigned int resp_len = 0;
|
2017-04-07 09:11:36 +08:00
|
|
|
uart_ring *ur = NULL;
|
2020-06-19 02:17:00 +08:00
|
|
|
uint32_t ts;
|
|
|
|
uint32_t ts_timer;
|
2019-10-26 07:22:42 +08:00
|
|
|
timestamp_t t;
|
2020-06-19 02:17:00 +08:00
|
|
|
bool k_wakeup;
|
|
|
|
bool l_wakeup;
|
2017-04-18 09:17:34 +08:00
|
|
|
switch (setup->b.bRequest) {
|
2019-10-26 07:22:42 +08:00
|
|
|
// **** 0xa0: get rtc time
|
|
|
|
case 0xa0:
|
|
|
|
resp_len = get_rtc_pkt(resp);
|
|
|
|
break;
|
|
|
|
// **** 0xa1: set rtc year
|
|
|
|
case 0xa1:
|
|
|
|
t = rtc_get_time();
|
|
|
|
t.year = setup->b.wValue.w;
|
|
|
|
rtc_set_time(t);
|
|
|
|
break;
|
|
|
|
// **** 0xa2: set rtc month
|
|
|
|
case 0xa2:
|
|
|
|
t = rtc_get_time();
|
|
|
|
t.month = setup->b.wValue.w;
|
|
|
|
rtc_set_time(t);
|
|
|
|
break;
|
|
|
|
// **** 0xa3: set rtc day
|
|
|
|
case 0xa3:
|
|
|
|
t = rtc_get_time();
|
|
|
|
t.day = setup->b.wValue.w;
|
|
|
|
rtc_set_time(t);
|
|
|
|
break;
|
|
|
|
// **** 0xa4: set rtc weekday
|
|
|
|
case 0xa4:
|
|
|
|
t = rtc_get_time();
|
|
|
|
t.weekday = setup->b.wValue.w;
|
|
|
|
rtc_set_time(t);
|
|
|
|
break;
|
|
|
|
// **** 0xa5: set rtc hour
|
|
|
|
case 0xa5:
|
|
|
|
t = rtc_get_time();
|
|
|
|
t.hour = setup->b.wValue.w;
|
|
|
|
rtc_set_time(t);
|
|
|
|
break;
|
|
|
|
// **** 0xa6: set rtc minute
|
|
|
|
case 0xa6:
|
|
|
|
t = rtc_get_time();
|
|
|
|
t.minute = setup->b.wValue.w;
|
|
|
|
rtc_set_time(t);
|
|
|
|
break;
|
|
|
|
// **** 0xa7: set rtc second
|
|
|
|
case 0xa7:
|
|
|
|
t = rtc_get_time();
|
|
|
|
t.second = setup->b.wValue.w;
|
|
|
|
rtc_set_time(t);
|
|
|
|
break;
|
|
|
|
// **** 0xb0: set IR power
|
|
|
|
case 0xb0:
|
2020-01-31 11:23:19 +08:00
|
|
|
current_board->set_ir_power(setup->b.wValue.w);
|
2019-10-26 07:22:42 +08:00
|
|
|
break;
|
|
|
|
// **** 0xb1: set fan power
|
|
|
|
case 0xb1:
|
2020-01-24 08:54:34 +08:00
|
|
|
current_board->set_fan_power(setup->b.wValue.w);
|
2019-10-26 07:22:42 +08:00
|
|
|
break;
|
|
|
|
// **** 0xb2: get fan rpm
|
|
|
|
case 0xb2:
|
|
|
|
resp[0] = (fan_rpm & 0x00FFU);
|
|
|
|
resp[1] = ((fan_rpm & 0xFF00U) >> 8U);
|
|
|
|
resp_len = 2;
|
|
|
|
break;
|
2019-11-05 09:26:37 +08:00
|
|
|
// **** 0xb3: set phone power
|
|
|
|
case 0xb3:
|
|
|
|
current_board->set_phone_power(setup->b.wValue.w > 0U);
|
|
|
|
break;
|
2017-07-19 03:29:16 +08:00
|
|
|
// **** 0xc0: get CAN debug info
|
|
|
|
case 0xc0:
|
|
|
|
puts("can tx: "); puth(can_tx_cnt);
|
|
|
|
puts(" txd: "); puth(can_txd_cnt);
|
|
|
|
puts(" rx: "); puth(can_rx_cnt);
|
|
|
|
puts(" err: "); puth(can_err_cnt);
|
|
|
|
puts("\n");
|
|
|
|
break;
|
2019-07-24 06:07:06 +08:00
|
|
|
// **** 0xc1: get hardware type
|
2018-01-24 12:10:23 +08:00
|
|
|
case 0xc1:
|
2019-07-24 06:07:06 +08:00
|
|
|
resp[0] = hw_type;
|
2018-01-24 12:10:23 +08:00
|
|
|
resp_len = 1;
|
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xd0: fetch serial number
|
2017-04-29 07:56:40 +08:00
|
|
|
case 0xd0:
|
2019-05-22 00:47:43 +08:00
|
|
|
// addresses are OTP
|
2019-07-04 16:04:58 +08:00
|
|
|
if (setup->b.wValue.w == 1U) {
|
2019-07-11 11:56:03 +08:00
|
|
|
(void)memcpy(resp, (uint8_t *)0x1fff79c0, 0x10);
|
2019-05-22 00:47:43 +08:00
|
|
|
resp_len = 0x10;
|
|
|
|
} else {
|
|
|
|
get_provision_chunk(resp);
|
|
|
|
resp_len = PROVISION_CHUNK_LEN;
|
|
|
|
}
|
2017-04-29 07:56:40 +08:00
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xd1: enter bootloader mode
|
2017-04-07 09:11:36 +08:00
|
|
|
case 0xd1:
|
2017-07-23 05:18:00 +08:00
|
|
|
// this allows reflashing of the bootstub
|
|
|
|
// so it's blocked over wifi
|
2017-07-25 06:16:22 +08:00
|
|
|
switch (setup->b.wValue.w) {
|
|
|
|
case 0:
|
2019-09-05 07:05:50 +08:00
|
|
|
// only allow bootloader entry on debug builds
|
|
|
|
#ifdef ALLOW_DEBUG
|
|
|
|
if (hardwired) {
|
|
|
|
puts("-> entering bootloader\n");
|
|
|
|
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
|
|
|
NVIC_SystemReset();
|
|
|
|
}
|
|
|
|
#endif
|
2017-07-25 06:16:22 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2017-07-28 06:54:55 +08:00
|
|
|
puts("-> entering softloader\n");
|
2017-07-25 06:16:22 +08:00
|
|
|
enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC;
|
|
|
|
NVIC_SystemReset();
|
|
|
|
break;
|
2019-06-28 06:50:00 +08:00
|
|
|
default:
|
|
|
|
puts("Bootloader mode invalid\n");
|
|
|
|
break;
|
2017-04-29 00:45:58 +08:00
|
|
|
}
|
2017-04-07 09:11:36 +08:00
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xd2: get health packet
|
2017-04-07 09:11:36 +08:00
|
|
|
case 0xd2:
|
|
|
|
resp_len = get_health_pkt(resp);
|
|
|
|
break;
|
2019-12-10 02:54:48 +08:00
|
|
|
// **** 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;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xd6: get version
|
|
|
|
case 0xd6:
|
2019-06-25 08:50:01 +08:00
|
|
|
COMPILE_TIME_ASSERT(sizeof(gitversion) <= MAX_RESP_LEN);
|
2019-07-04 07:01:01 +08:00
|
|
|
(void)memcpy(resp, gitversion, sizeof(gitversion));
|
2019-07-04 16:04:58 +08:00
|
|
|
resp_len = sizeof(gitversion) - 1U;
|
2017-04-07 09:11:36 +08:00
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xd8: reset ST
|
|
|
|
case 0xd8:
|
2017-04-07 09:11:36 +08:00
|
|
|
NVIC_SystemReset();
|
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xd9: set ESP power
|
|
|
|
case 0xd9:
|
2019-07-04 16:04:58 +08:00
|
|
|
if (setup->b.wValue.w == 1U) {
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
|
2019-07-04 16:04:58 +08:00
|
|
|
} else if (setup->b.wValue.w == 2U) {
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_esp_gps_mode(ESP_GPS_BOOTMODE);
|
2017-04-27 03:38:33 +08:00
|
|
|
} else {
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
|
2017-04-27 03:38:33 +08:00
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xda: reset ESP, with optional boot mode
|
|
|
|
case 0xda:
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
|
2017-04-07 09:11:36 +08:00
|
|
|
delay(1000000);
|
2019-07-04 16:04:58 +08:00
|
|
|
if (setup->b.wValue.w == 1U) {
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_esp_gps_mode(ESP_GPS_BOOTMODE);
|
2017-07-23 05:18:00 +08:00
|
|
|
} else {
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
2017-07-23 05:18:00 +08:00
|
|
|
delay(1000000);
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
|
2017-04-07 09:11:36 +08:00
|
|
|
break;
|
2019-07-24 06:07:06 +08:00
|
|
|
// **** 0xdb: set GMLAN (white/grey) or OBD CAN (black) multiplexing mode
|
2017-07-18 01:48:16 +08:00
|
|
|
case 0xdb:
|
2019-10-26 07:22:42 +08:00
|
|
|
if(board_has_obd()){
|
2019-07-24 06:07:06 +08:00
|
|
|
if (setup->b.wValue.w == 1U) {
|
|
|
|
// Enable OBD CAN
|
|
|
|
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
|
2019-07-04 11:48:02 +08:00
|
|
|
} else {
|
2019-07-24 06:07:06 +08:00
|
|
|
// Disable OBD CAN
|
|
|
|
current_board->set_can_mode(CAN_MODE_NORMAL);
|
2019-09-28 08:18:02 +08:00
|
|
|
}
|
2019-05-22 00:47:43 +08:00
|
|
|
} else {
|
2019-07-24 06:07:06 +08:00
|
|
|
if (setup->b.wValue.w == 1U) {
|
|
|
|
// GMLAN ON
|
|
|
|
if (setup->b.wIndex.w == 1U) {
|
|
|
|
can_set_gmlan(1);
|
|
|
|
} else if (setup->b.wIndex.w == 2U) {
|
|
|
|
can_set_gmlan(2);
|
|
|
|
} else {
|
|
|
|
puts("Invalid bus num for GMLAN CAN set\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
can_set_gmlan(-1);
|
|
|
|
}
|
2019-05-22 00:47:43 +08:00
|
|
|
}
|
2017-04-07 09:11:36 +08:00
|
|
|
break;
|
2019-09-28 08:18:02 +08:00
|
|
|
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xdc: set safety mode
|
|
|
|
case 0xdc:
|
2019-07-24 06:07:06 +08:00
|
|
|
// Blocked over WiFi.
|
2019-11-21 03:56:26 +08:00
|
|
|
// 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)) {
|
2019-07-24 06:07:06 +08:00
|
|
|
set_safety_mode(setup->b.wValue.w, (uint16_t) setup->b.wIndex.w);
|
2017-07-18 01:48:16 +08:00
|
|
|
}
|
2017-05-02 14:40:49 +08:00
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xdd: enable can forwarding
|
|
|
|
case 0xdd:
|
|
|
|
// wValue = Can Bus Num to forward from
|
|
|
|
// wIndex = Can Bus Num to forward to
|
2019-05-21 13:13:45 +08:00
|
|
|
if ((setup->b.wValue.w < BUS_MAX) && (setup->b.wIndex.w < BUS_MAX) &&
|
|
|
|
(setup->b.wValue.w != setup->b.wIndex.w)) { // set forwarding
|
2017-07-22 02:30:07 +08:00
|
|
|
can_set_forwarding(setup->b.wValue.w, setup->b.wIndex.w & CAN_BUS_NUM_MASK);
|
2019-07-04 16:04:58 +08:00
|
|
|
} else if((setup->b.wValue.w < BUS_MAX) && (setup->b.wIndex.w == 0xFFU)){ //Clear Forwarding
|
2017-07-22 02:30:07 +08:00
|
|
|
can_set_forwarding(setup->b.wValue.w, -1);
|
2019-07-04 11:48:02 +08:00
|
|
|
} else {
|
|
|
|
puts("Invalid CAN bus forwarding\n");
|
2017-07-01 04:51:56 +08:00
|
|
|
}
|
2017-07-13 02:25:10 +08:00
|
|
|
break;
|
2017-07-18 10:43:30 +08:00
|
|
|
// **** 0xde: set can bitrate
|
|
|
|
case 0xde:
|
2017-07-19 12:05:09 +08:00
|
|
|
if (setup->b.wValue.w < BUS_MAX) {
|
2017-07-18 10:43:30 +08:00
|
|
|
can_speed[setup->b.wValue.w] = setup->b.wIndex.w;
|
2020-04-14 11:32:53 +08:00
|
|
|
bool ret = can_init(CAN_NUM_FROM_BUS_NUM(setup->b.wValue.w));
|
|
|
|
UNUSED(ret);
|
2017-07-18 10:43:30 +08:00
|
|
|
}
|
|
|
|
break;
|
2020-03-31 09:18:44 +08:00
|
|
|
// **** 0xdf: set unsafe mode
|
|
|
|
case 0xdf:
|
2020-04-01 07:30:01 +08:00
|
|
|
// you can only set this if you are in a non car safety mode
|
2020-04-02 01:17:51 +08:00
|
|
|
if ((current_safety_mode == SAFETY_SILENT) ||
|
|
|
|
(current_safety_mode == SAFETY_NOOUTPUT) ||
|
|
|
|
(current_safety_mode == SAFETY_ELM327)) {
|
2020-04-01 07:30:01 +08:00
|
|
|
unsafe_mode = setup->b.wValue.w;
|
|
|
|
}
|
2020-03-31 09:18:44 +08:00
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xe0: uart read
|
|
|
|
case 0xe0:
|
2017-04-18 09:17:34 +08:00
|
|
|
ur = get_ring_by_number(setup->b.wValue.w);
|
2019-06-29 04:46:57 +08:00
|
|
|
if (!ur) {
|
|
|
|
break;
|
|
|
|
}
|
2019-10-09 10:41:10 +08:00
|
|
|
|
|
|
|
// TODO: Remove this again and fix boardd code to hande the message bursts instead of single chars
|
|
|
|
if (ur == &uart_ring_esp_gps) {
|
|
|
|
dma_pointer_handler(ur, DMA2_Stream5->NDTR);
|
|
|
|
}
|
|
|
|
|
2017-04-18 09:17:34 +08:00
|
|
|
// read
|
2019-06-18 04:48:14 +08:00
|
|
|
while ((resp_len < MIN(setup->b.wLength.w, MAX_RESP_LEN)) &&
|
2017-07-22 02:48:03 +08:00
|
|
|
getc(ur, (char*)&resp[resp_len])) {
|
2017-04-18 09:17:34 +08:00
|
|
|
++resp_len;
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
2017-04-18 16:12:04 +08:00
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xe1: uart set baud rate
|
|
|
|
case 0xe1:
|
2017-04-18 09:17:34 +08:00
|
|
|
ur = get_ring_by_number(setup->b.wValue.w);
|
2019-06-29 04:46:57 +08:00
|
|
|
if (!ur) {
|
|
|
|
break;
|
|
|
|
}
|
2017-04-18 09:17:34 +08:00
|
|
|
uart_set_baud(ur->uart, setup->b.wIndex.w);
|
2017-04-07 09:11:36 +08:00
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xe2: uart set parity
|
|
|
|
case 0xe2:
|
2017-04-26 06:16:23 +08:00
|
|
|
ur = get_ring_by_number(setup->b.wValue.w);
|
2019-06-29 04:46:57 +08:00
|
|
|
if (!ur) {
|
|
|
|
break;
|
|
|
|
}
|
2017-04-26 06:16:23 +08:00
|
|
|
switch (setup->b.wIndex.w) {
|
|
|
|
case 0:
|
2017-04-27 09:39:26 +08:00
|
|
|
// disable parity, 8-bit
|
|
|
|
ur->uart->CR1 &= ~(USART_CR1_PCE | USART_CR1_M);
|
2017-04-26 06:16:23 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2017-04-27 09:39:26 +08:00
|
|
|
// even parity, 9-bit
|
2017-04-26 06:16:23 +08:00
|
|
|
ur->uart->CR1 &= ~USART_CR1_PS;
|
2017-04-27 09:39:26 +08:00
|
|
|
ur->uart->CR1 |= USART_CR1_PCE | USART_CR1_M;
|
2017-04-26 06:16:23 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
2017-04-27 09:39:26 +08:00
|
|
|
// odd parity, 9-bit
|
2017-04-26 06:16:23 +08:00
|
|
|
ur->uart->CR1 |= USART_CR1_PS;
|
2017-04-27 09:39:26 +08:00
|
|
|
ur->uart->CR1 |= USART_CR1_PCE | USART_CR1_M;
|
2017-04-26 06:16:23 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xe4: uart set baud rate extended
|
|
|
|
case 0xe4:
|
2017-05-30 14:03:11 +08:00
|
|
|
ur = get_ring_by_number(setup->b.wValue.w);
|
2019-06-29 04:46:57 +08:00
|
|
|
if (!ur) {
|
|
|
|
break;
|
|
|
|
}
|
2017-05-30 14:03:11 +08:00
|
|
|
uart_set_baud(ur->uart, (int)setup->b.wIndex.w*300);
|
|
|
|
break;
|
2017-07-18 01:48:16 +08:00
|
|
|
// **** 0xe5: set CAN loopback (for testing)
|
|
|
|
case 0xe5:
|
2019-07-04 16:04:58 +08:00
|
|
|
can_loopback = (setup->b.wValue.w > 0U);
|
2017-07-18 01:48:16 +08:00
|
|
|
can_init_all();
|
2017-07-15 11:25:13 +08:00
|
|
|
break;
|
2017-08-24 00:28:52 +08:00
|
|
|
// **** 0xe6: set USB power
|
|
|
|
case 0xe6:
|
2019-10-03 02:48:40 +08:00
|
|
|
current_board->set_usb_power_mode(setup->b.wValue.w);
|
2017-08-24 00:28:52 +08:00
|
|
|
break;
|
2019-11-22 04:53:00 +08:00
|
|
|
// **** 0xe7: set power save state
|
|
|
|
case 0xe7:
|
|
|
|
set_power_save_state(setup->b.wValue.w);
|
|
|
|
break;
|
2020-06-19 02:17:00 +08:00
|
|
|
// **** 0xf0: k-line/l-line wake-up pulse for KWP2000 fast initialization
|
2017-07-18 10:43:30 +08:00
|
|
|
case 0xf0:
|
2020-06-19 02:17:00 +08:00
|
|
|
k_wakeup = (setup->b.wValue.w == 0U) || (setup->b.wValue.w == 2U);
|
|
|
|
l_wakeup = (setup->b.wValue.w == 1U) || (setup->b.wValue.w == 2U);
|
|
|
|
|
|
|
|
ts = TIM2->CNT;
|
|
|
|
ts_timer = ts;
|
|
|
|
if (k_wakeup) {
|
|
|
|
set_gpio_output(GPIOC, 12, false);
|
|
|
|
}
|
|
|
|
if (l_wakeup) {
|
|
|
|
set_gpio_output(GPIOC, 10, false);
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
|
|
|
|
2020-06-19 02:17:00 +08:00
|
|
|
// hold low for 25 ms
|
|
|
|
while (get_ts_elapsed(TIM2->CNT, ts) < 25000U) {
|
|
|
|
// toggle pin every 5 ms to reset TXD dominant time-out timer
|
|
|
|
if (get_ts_elapsed(TIM2->CNT, ts_timer) >= 5000U) {
|
|
|
|
ts_timer = TIM2->CNT;
|
|
|
|
if (k_wakeup) {
|
|
|
|
register_set_bits(&(GPIOC->ODR), (1U << 12));
|
|
|
|
register_clear_bits(&(GPIOC->ODR), (1U << 12));
|
|
|
|
}
|
|
|
|
if (l_wakeup) {
|
|
|
|
register_set_bits(&(GPIOC->ODR), (1U << 10));
|
|
|
|
register_clear_bits(&(GPIOC->ODR), (1U << 10));
|
|
|
|
}
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-19 02:17:00 +08:00
|
|
|
if (k_wakeup) {
|
|
|
|
set_gpio_mode(GPIOC, 12, MODE_ALTERNATE);
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
2020-06-19 02:17:00 +08:00
|
|
|
if (l_wakeup) {
|
|
|
|
set_gpio_mode(GPIOC, 10, MODE_ALTERNATE);
|
|
|
|
}
|
|
|
|
// hold high until 49ms have passed
|
|
|
|
// (start communication needs to follow 49ms to 51ms after start of wakeup)
|
|
|
|
while (get_ts_elapsed(TIM2->CNT, ts) < 49000U) {}
|
2017-04-07 09:11:36 +08:00
|
|
|
break;
|
2017-08-17 17:03:08 +08:00
|
|
|
// **** 0xf1: Clear CAN ring buffer.
|
|
|
|
case 0xf1:
|
2019-07-04 16:04:58 +08:00
|
|
|
if (setup->b.wValue.w == 0xFFFFU) {
|
2017-08-17 17:03:08 +08:00
|
|
|
puts("Clearing CAN Rx queue\n");
|
|
|
|
can_clear(&can_rx_q);
|
|
|
|
} else if (setup->b.wValue.w < BUS_MAX) {
|
|
|
|
puts("Clearing CAN Tx queue\n");
|
|
|
|
can_clear(can_queues[setup->b.wValue.w]);
|
2019-07-04 11:48:02 +08:00
|
|
|
} else {
|
|
|
|
puts("Clearing CAN CAN ring buffer failed: wrong bus number\n");
|
2017-08-17 17:03:08 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
// **** 0xf2: Clear UART ring buffer.
|
|
|
|
case 0xf2:
|
|
|
|
{
|
|
|
|
uart_ring * rb = get_ring_by_number(setup->b.wValue.w);
|
2019-06-27 04:13:16 +08:00
|
|
|
if (rb != NULL) {
|
2017-08-17 17:03:08 +08:00
|
|
|
puts("Clearing UART queue.\n");
|
|
|
|
clear_uart_buff(rb);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2019-07-24 06:07:06 +08:00
|
|
|
// **** 0xf3: Heartbeat. Resets heartbeat counter.
|
|
|
|
case 0xf3:
|
|
|
|
{
|
|
|
|
heartbeat_counter = 0U;
|
|
|
|
break;
|
|
|
|
}
|
2017-04-07 09:11:36 +08:00
|
|
|
default:
|
|
|
|
puts("NO HANDLER ");
|
2017-04-18 09:17:34 +08:00
|
|
|
puth(setup->b.bRequest);
|
2017-04-07 09:11:36 +08:00
|
|
|
puts("\n");
|
2017-07-13 02:25:10 +08:00
|
|
|
break;
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
2017-04-18 09:17:34 +08:00
|
|
|
return resp_len;
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
|
|
|
|
2019-07-11 11:56:03 +08:00
|
|
|
#ifndef EON
|
2017-07-25 03:31:47 +08:00
|
|
|
int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) {
|
2017-04-18 22:34:56 +08:00
|
|
|
// data[0] = endpoint
|
|
|
|
// data[2] = length
|
|
|
|
// data[4:] = data
|
2019-06-25 01:25:30 +08:00
|
|
|
UNUSED(len);
|
2017-07-25 03:31:47 +08:00
|
|
|
int resp_len = 0;
|
2017-04-18 22:34:56 +08:00
|
|
|
switch (data[0]) {
|
|
|
|
case 0:
|
|
|
|
// control transfer
|
2017-07-25 03:31:47 +08:00
|
|
|
resp_len = usb_cb_control_msg((USB_Setup_TypeDef *)(data+4), data_out, 0);
|
2017-04-18 22:34:56 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// ep 1, read
|
2017-07-25 03:31:47 +08:00
|
|
|
resp_len = usb_cb_ep1_in(data_out, 0x40, 0);
|
2017-04-18 22:34:56 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
// ep 2, send serial
|
2017-05-02 13:46:12 +08:00
|
|
|
usb_cb_ep2_out(data+4, data[2], 0);
|
2017-04-18 22:34:56 +08:00
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
// ep 3, send CAN
|
2017-05-02 13:46:12 +08:00
|
|
|
usb_cb_ep3_out(data+4, data[2], 0);
|
2017-04-18 22:34:56 +08:00
|
|
|
break;
|
2019-06-28 06:50:00 +08:00
|
|
|
default:
|
|
|
|
puts("SPI data invalid");
|
|
|
|
break;
|
2017-04-18 22:34:56 +08:00
|
|
|
}
|
2017-07-25 03:31:47 +08:00
|
|
|
return resp_len;
|
2017-05-04 06:54:47 +08:00
|
|
|
}
|
2019-07-11 11:56:03 +08:00
|
|
|
#endif
|
2017-07-22 02:48:03 +08:00
|
|
|
|
2017-04-07 09:11:36 +08:00
|
|
|
// ***************************** main code *****************************
|
|
|
|
|
2019-07-09 06:13:52 +08:00
|
|
|
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
2019-06-25 01:25:30 +08:00
|
|
|
void __initialize_hardware_early(void) {
|
2017-04-07 09:11:36 +08:00
|
|
|
early();
|
|
|
|
}
|
|
|
|
|
2019-06-25 01:25:30 +08:00
|
|
|
void __attribute__ ((noinline)) enable_fpu(void) {
|
2018-04-12 10:52:42 +08:00
|
|
|
// enable the FPU
|
2019-07-04 16:04:58 +08:00
|
|
|
SCB->CPACR |= ((3UL << (10U * 2U)) | (3UL << (11U * 2U)));
|
2018-04-12 10:52:42 +08:00
|
|
|
}
|
|
|
|
|
2019-11-21 03:56:26 +08:00
|
|
|
// go into SILENT when the EON does not send a heartbeat for this amount of seconds.
|
2019-09-28 08:18:02 +08:00
|
|
|
#define EON_HEARTBEAT_IGNITION_CNT_ON 5U
|
|
|
|
#define EON_HEARTBEAT_IGNITION_CNT_OFF 2U
|
2019-05-24 02:58:57 +08:00
|
|
|
|
2019-12-21 17:25:54 +08:00
|
|
|
// called at 1Hz
|
2019-11-28 10:11:21 +08:00
|
|
|
void TIM1_BRK_TIM9_IRQ_Handler(void) {
|
2019-10-26 07:22:42 +08:00
|
|
|
if (TIM9->SR != 0) {
|
2019-05-24 02:58:57 +08:00
|
|
|
can_live = pending_can_live;
|
|
|
|
|
2019-11-22 08:47:49 +08:00
|
|
|
current_board->usb_power_mode_tick(uptime_cnt);
|
2019-05-24 02:58:57 +08:00
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
//puth(usart1_dma); puts(" "); puth(DMA2_Stream5->M0AR); puts(" "); puth(DMA2_Stream5->NDTR); puts("\n");
|
2019-05-24 02:58:57 +08:00
|
|
|
|
|
|
|
// reset this every 16th pass
|
2019-11-22 08:47:49 +08:00
|
|
|
if ((uptime_cnt & 0xFU) == 0U) {
|
2019-06-29 04:46:57 +08:00
|
|
|
pending_can_live = 0;
|
|
|
|
}
|
2019-05-24 02:58:57 +08:00
|
|
|
#ifdef DEBUG
|
2019-08-29 03:57:42 +08:00
|
|
|
puts("** blink ");
|
|
|
|
puth(can_rx_q.r_ptr); puts(" "); puth(can_rx_q.w_ptr); puts(" ");
|
|
|
|
puth(can_tx1_q.r_ptr); puts(" "); puth(can_tx1_q.w_ptr); puts(" ");
|
|
|
|
puth(can_tx2_q.r_ptr); puts(" "); puth(can_tx2_q.w_ptr); puts("\n");
|
2019-05-24 02:58:57 +08:00
|
|
|
#endif
|
|
|
|
|
2020-07-02 06:23:12 +08:00
|
|
|
// Tick drivers
|
2019-10-26 07:22:42 +08:00
|
|
|
fan_tick();
|
|
|
|
|
2019-05-24 02:58:57 +08:00
|
|
|
// set green LED to be controls allowed
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_led(LED_GREEN, controls_allowed);
|
2019-05-24 02:58:57 +08:00
|
|
|
|
|
|
|
// turn off the blue LED, turned on by CAN
|
|
|
|
// unless we are in power saving mode
|
2019-11-22 08:47:49 +08:00
|
|
|
current_board->set_led(LED_BLUE, (uptime_cnt & 1U) && (power_save_status == POWER_SAVE_STATUS_ENABLED));
|
2019-07-24 06:07:06 +08:00
|
|
|
|
|
|
|
// increase heartbeat counter and cap it at the uint32 limit
|
|
|
|
if (heartbeat_counter < __UINT32_MAX__) {
|
|
|
|
heartbeat_counter += 1U;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef EON
|
2019-11-22 04:53:00 +08:00
|
|
|
// 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
|
2019-10-23 07:12:18 +08:00
|
|
|
if (heartbeat_counter >= (check_started() ? EON_HEARTBEAT_IGNITION_CNT_ON : EON_HEARTBEAT_IGNITION_CNT_OFF)) {
|
2019-11-22 04:53:00 +08:00
|
|
|
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) {
|
2019-11-21 03:56:26 +08:00
|
|
|
set_safety_mode(SAFETY_SILENT, 0U);
|
2019-10-05 04:30:00 +08:00
|
|
|
}
|
2019-11-22 04:53:00 +08:00
|
|
|
if (power_save_status != POWER_SAVE_STATUS_ENABLED) {
|
|
|
|
set_power_save_state(POWER_SAVE_STATUS_ENABLED);
|
|
|
|
}
|
2020-01-31 11:23:19 +08:00
|
|
|
|
2020-06-12 09:14:41 +08:00
|
|
|
// Also disable IR when the heartbeat goes missing
|
2020-01-31 11:23:19 +08:00
|
|
|
current_board->set_ir_power(0U);
|
2020-06-12 09:14:41 +08:00
|
|
|
|
|
|
|
// If enumerated but no heartbeat (phone up, boardd not running), turn the fan on to cool the device
|
|
|
|
if(usb_enumerated()){
|
|
|
|
current_board->set_fan_power(50U);
|
|
|
|
} else {
|
|
|
|
current_board->set_fan_power(0U);
|
|
|
|
}
|
2019-11-22 04:53:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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);
|
2019-07-24 06:07:06 +08:00
|
|
|
}
|
|
|
|
#endif
|
2019-05-24 02:58:57 +08:00
|
|
|
|
2019-12-06 06:19:29 +08:00
|
|
|
// check registers
|
|
|
|
check_registers();
|
2019-12-10 02:39:04 +08:00
|
|
|
|
2019-12-04 08:44:55 +08:00
|
|
|
// set ignition_can to false after 2s of no CAN seen
|
|
|
|
if (ignition_can_cnt > 2U) {
|
|
|
|
ignition_can = false;
|
|
|
|
};
|
|
|
|
|
2019-05-24 02:58:57 +08:00
|
|
|
// on to the next one
|
2019-11-22 08:47:49 +08:00
|
|
|
uptime_cnt += 1U;
|
2019-11-27 13:19:54 +08:00
|
|
|
safety_mode_cnt += 1U;
|
2019-12-04 08:44:55 +08:00
|
|
|
ignition_can_cnt += 1U;
|
2019-12-21 17:25:54 +08:00
|
|
|
|
|
|
|
// synchronous safety check
|
|
|
|
safety_tick(current_hooks);
|
2019-05-24 02:58:57 +08:00
|
|
|
}
|
2019-10-26 07:22:42 +08:00
|
|
|
TIM9->SR = 0;
|
2019-05-24 02:58:57 +08:00
|
|
|
}
|
|
|
|
|
2020-06-03 05:21:41 +08:00
|
|
|
#define MAX_FADE 8192U
|
2019-06-25 01:25:30 +08:00
|
|
|
int main(void) {
|
2019-12-06 06:19:29 +08:00
|
|
|
// Init interrupt table
|
2019-11-28 10:11:21 +08:00
|
|
|
init_interrupts(true);
|
2019-12-06 06:19:29 +08:00
|
|
|
|
2019-11-28 10:11:21 +08:00
|
|
|
// 1s timer
|
|
|
|
REGISTER_INTERRUPT(TIM1_BRK_TIM9_IRQn, TIM1_BRK_TIM9_IRQ_Handler, 2U, FAULT_INTERRUPT_RATE_TIM1)
|
|
|
|
|
2017-07-21 14:42:19 +08:00
|
|
|
// shouldn't have interrupts here, but just in case
|
2019-08-29 03:53:51 +08:00
|
|
|
disable_interrupts();
|
2017-07-21 14:14:27 +08:00
|
|
|
|
2017-07-28 06:54:55 +08:00
|
|
|
// init early devices
|
2017-04-07 09:11:36 +08:00
|
|
|
clock_init();
|
2019-07-24 06:07:06 +08:00
|
|
|
peripherals_init();
|
|
|
|
detect_configuration();
|
|
|
|
detect_board_type();
|
|
|
|
adc_init();
|
2019-09-28 08:18:02 +08:00
|
|
|
|
2017-07-28 06:54:55 +08:00
|
|
|
// print hello
|
|
|
|
puts("\n\n\n************************ MAIN START ************************\n");
|
2017-04-18 04:57:34 +08:00
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
// check for non-supported board types
|
|
|
|
if(hw_type == HW_TYPE_UNKNOWN){
|
|
|
|
puts("Unsupported board type\n");
|
|
|
|
while (1) { /* hang */ }
|
2019-06-29 04:46:57 +08:00
|
|
|
}
|
2019-05-20 00:12:03 +08:00
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
puts("Config:\n");
|
|
|
|
puts(" Board type: "); puts(current_board->board_type); puts("\n");
|
|
|
|
puts(has_external_debug_serial ? " Real serial\n" : " USB serial\n");
|
|
|
|
puts(is_entering_bootmode ? " ESP wants bootmode\n" : " No bootmode\n");
|
|
|
|
|
|
|
|
// init board
|
|
|
|
current_board->init();
|
2017-04-07 09:11:36 +08:00
|
|
|
|
2018-04-12 10:52:42 +08:00
|
|
|
// panda has an FPU, let's use it!
|
|
|
|
enable_fpu();
|
|
|
|
|
2017-07-30 10:50:35 +08:00
|
|
|
// enable main uart if it's connected
|
|
|
|
if (has_external_debug_serial) {
|
|
|
|
// WEIRDNESS: without this gate around the UART, it would "crash", but only if the ESP is enabled
|
|
|
|
// assuming it's because the lines were left floating and spurious noise was on them
|
2019-10-05 04:28:56 +08:00
|
|
|
uart_init(&uart_ring_debug, 115200);
|
2017-07-30 10:50:35 +08:00
|
|
|
}
|
2017-04-07 09:11:36 +08:00
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
if (board_has_gps()) {
|
2019-10-05 04:28:56 +08:00
|
|
|
uart_init(&uart_ring_esp_gps, 9600);
|
2018-01-26 15:51:52 +08:00
|
|
|
} else {
|
|
|
|
// enable ESP uart
|
2019-10-05 04:28:56 +08:00
|
|
|
uart_init(&uart_ring_esp_gps, 115200);
|
2018-01-26 15:51:52 +08:00
|
|
|
}
|
2019-05-22 00:47:43 +08:00
|
|
|
|
2019-10-26 07:22:42 +08:00
|
|
|
if(board_has_lin()){
|
2019-07-24 06:07:06 +08:00
|
|
|
// enable LIN
|
2019-10-05 04:28:56 +08:00
|
|
|
uart_init(&uart_ring_lin1, 10400);
|
2019-07-24 06:07:06 +08:00
|
|
|
UART5->CR2 |= USART_CR2_LINEN;
|
2019-10-05 04:28:56 +08:00
|
|
|
uart_init(&uart_ring_lin2, 10400);
|
2019-07-24 06:07:06 +08:00
|
|
|
USART3->CR2 |= USART_CR2_LINEN;
|
|
|
|
}
|
2017-04-07 09:11:36 +08:00
|
|
|
|
2017-10-27 09:44:25 +08:00
|
|
|
// init microsecond system timer
|
|
|
|
// increments 1000000 times per second
|
|
|
|
// generate an update to set the prescaler
|
|
|
|
TIM2->PSC = 48-1;
|
|
|
|
TIM2->CR1 = TIM_CR1_CEN;
|
|
|
|
TIM2->EGR = TIM_EGR_UG;
|
|
|
|
// use TIM2->CNT to read
|
|
|
|
|
2019-11-21 03:56:26 +08:00
|
|
|
// init to SILENT and can silent
|
|
|
|
set_safety_mode(SAFETY_SILENT, 0);
|
2017-05-31 00:46:21 +08:00
|
|
|
|
2019-11-22 05:42:36 +08:00
|
|
|
// enable CAN TXs
|
|
|
|
current_board->enable_can_transcievers(true);
|
|
|
|
|
2019-06-27 03:01:57 +08:00
|
|
|
#ifndef EON
|
2017-04-07 09:11:36 +08:00
|
|
|
spi_init();
|
2019-06-27 03:01:57 +08:00
|
|
|
#endif
|
2019-05-22 00:47:43 +08:00
|
|
|
|
2019-10-26 07:22:42 +08:00
|
|
|
// 1hz
|
|
|
|
timer_init(TIM9, 1464);
|
|
|
|
NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
|
2019-05-24 02:58:57 +08:00
|
|
|
|
2019-04-02 13:45:00 +08:00
|
|
|
#ifdef DEBUG
|
|
|
|
puts("DEBUG ENABLED\n");
|
|
|
|
#endif
|
2019-07-24 06:07:06 +08:00
|
|
|
// enable USB (right before interrupts or enum can fail!)
|
|
|
|
usb_init();
|
2017-04-07 09:11:36 +08:00
|
|
|
|
|
|
|
puts("**** INTERRUPTS ON ****\n");
|
2019-06-15 04:28:15 +08:00
|
|
|
enable_interrupts();
|
2017-04-07 09:11:36 +08:00
|
|
|
|
|
|
|
// LED should keep on blinking all the time
|
2017-08-22 23:27:00 +08:00
|
|
|
uint64_t cnt = 0;
|
|
|
|
|
2017-04-07 09:11:36 +08:00
|
|
|
for (cnt=0;;cnt++) {
|
2019-05-24 02:58:57 +08:00
|
|
|
if (power_save_status == POWER_SAVE_STATUS_DISABLED) {
|
2019-11-28 10:11:21 +08:00
|
|
|
#ifdef DEBUG_FAULTS
|
|
|
|
if(fault_status == FAULT_STATUS_NONE){
|
|
|
|
#endif
|
2020-06-03 05:21:41 +08:00
|
|
|
uint32_t div_mode = ((usb_power_mode == USB_POWER_DCP) ? 4U : 1U);
|
2019-11-28 10:11:21 +08:00
|
|
|
|
|
|
|
// useful for debugging, fade breaks = panda is overloaded
|
2020-06-03 05:21:41 +08:00
|
|
|
for(uint32_t fade = 0U; fade < MAX_FADE; fade += div_mode){
|
|
|
|
current_board->set_led(LED_RED, true);
|
|
|
|
delay(fade >> 4);
|
|
|
|
current_board->set_led(LED_RED, false);
|
|
|
|
delay((MAX_FADE - fade) >> 4);
|
2019-05-22 00:47:43 +08:00
|
|
|
}
|
2020-06-03 05:21:41 +08:00
|
|
|
|
|
|
|
for(uint32_t fade = MAX_FADE; fade > 0U; fade -= div_mode){
|
|
|
|
current_board->set_led(LED_RED, true);
|
|
|
|
delay(fade >> 4);
|
|
|
|
current_board->set_led(LED_RED, false);
|
|
|
|
delay((MAX_FADE - fade) >> 4);
|
|
|
|
}
|
|
|
|
|
2019-11-28 10:11:21 +08:00
|
|
|
#ifdef DEBUG_FAULTS
|
|
|
|
} else {
|
|
|
|
current_board->set_led(LED_RED, 1);
|
|
|
|
delay(512000U);
|
|
|
|
current_board->set_led(LED_RED, 0);
|
|
|
|
delay(512000U);
|
|
|
|
}
|
|
|
|
#endif
|
2019-05-24 02:58:57 +08:00
|
|
|
} else {
|
|
|
|
__WFI();
|
2017-08-23 00:44:08 +08:00
|
|
|
}
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|