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"
|
|
|
|
|
2017-07-13 02:25:10 +08:00
|
|
|
#include "libc.h"
|
2017-07-30 23:26:48 +08:00
|
|
|
#include "provision.h"
|
2017-07-21 14:45:48 +08:00
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
#include "main_declarations.h"
|
|
|
|
|
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"
|
|
|
|
|
|
|
|
#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-07-24 06:07:06 +08:00
|
|
|
// ********************* Serial debugging *********************
|
2017-07-21 04:41:21 +08:00
|
|
|
|
2019-10-23 06:27:55 +08:00
|
|
|
bool check_ignition(void) {
|
|
|
|
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
|
|
|
|
|
|
|
// jump to DFU flash
|
|
|
|
if (rcv == 'z') {
|
|
|
|
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
|
|
|
NVIC_SystemReset();
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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-05-22 23:30:32 +08:00
|
|
|
// ***************************** started logic *****************************
|
2019-07-24 06:07:06 +08:00
|
|
|
void started_interrupt_handler(uint8_t interrupt_line) {
|
|
|
|
volatile unsigned int pr = EXTI->PR & (1U << interrupt_line);
|
|
|
|
if ((pr & (1U << interrupt_line)) != 0U) {
|
2019-05-22 23:30:32 +08:00
|
|
|
#ifdef DEBUG
|
|
|
|
puts("got started interrupt\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// jenky debounce
|
|
|
|
delay(100000);
|
|
|
|
|
2019-08-29 03:57:42 +08:00
|
|
|
#ifdef EON
|
2019-10-03 02:48:40 +08:00
|
|
|
// set power savings mode here if on EON build
|
2019-10-23 06:27:55 +08:00
|
|
|
int power_save_state = check_ignition() ? POWER_SAVE_STATUS_DISABLED : POWER_SAVE_STATUS_ENABLED;
|
2019-08-29 03:57:42 +08:00
|
|
|
set_power_save_state(power_save_state);
|
2019-10-03 02:48:40 +08:00
|
|
|
// set CDP usb power mode everytime that the car starts to make sure EON is charging
|
2019-10-23 06:27:55 +08:00
|
|
|
if (check_ignition()) {
|
2019-10-03 02:48:40 +08:00
|
|
|
current_board->set_usb_power_mode(USB_POWER_CDP);
|
|
|
|
}
|
2019-08-29 03:57:42 +08:00
|
|
|
#endif
|
2019-05-22 23:30:32 +08:00
|
|
|
}
|
2019-07-24 06:07:06 +08:00
|
|
|
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);
|
2019-05-22 23:30:32 +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) {
|
|
|
|
int err = safety_set_mode(mode, param);
|
|
|
|
if (err == -1) {
|
|
|
|
puts("Error: safety set mode failed\n");
|
|
|
|
} else {
|
|
|
|
switch (mode) {
|
|
|
|
case SAFETY_NOOUTPUT:
|
|
|
|
set_intercept_relay(false);
|
|
|
|
if(hw_type == HW_TYPE_BLACK_PANDA){
|
|
|
|
current_board->set_can_mode(CAN_MODE_NORMAL);
|
|
|
|
}
|
2019-08-29 03:57:42 +08:00
|
|
|
can_silent = ALL_CAN_SILENT;
|
2019-07-24 06:07:06 +08:00
|
|
|
break;
|
|
|
|
case SAFETY_ELM327:
|
|
|
|
set_intercept_relay(false);
|
2019-08-29 03:57:42 +08:00
|
|
|
heartbeat_counter = 0U;
|
2019-07-24 06:07:06 +08:00
|
|
|
if(hw_type == HW_TYPE_BLACK_PANDA){
|
|
|
|
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
|
|
|
|
}
|
2019-08-29 03:57:42 +08:00
|
|
|
can_silent = ALL_CAN_LIVE;
|
2019-07-24 06:07:06 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
set_intercept_relay(true);
|
2019-08-29 03:57:42 +08:00
|
|
|
heartbeat_counter = 0U;
|
2019-07-24 06:07:06 +08:00
|
|
|
if(hw_type == HW_TYPE_BLACK_PANDA){
|
|
|
|
current_board->set_can_mode(CAN_MODE_NORMAL);
|
|
|
|
}
|
2019-08-29 03:57:42 +08:00
|
|
|
can_silent = ALL_CAN_LIVE;
|
2019-07-24 06:07:06 +08:00
|
|
|
break;
|
2019-09-28 08:18:02 +08:00
|
|
|
}
|
2019-07-24 06:07:06 +08:00
|
|
|
can_init_all();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-22 23:30:32 +08:00
|
|
|
// ***************************** USB port *****************************
|
|
|
|
|
2017-04-07 09:11:36 +08:00
|
|
|
int get_health_pkt(void *dat) {
|
|
|
|
struct __attribute__((packed)) {
|
2019-07-03 13:39:00 +08:00
|
|
|
uint32_t voltage_pkt;
|
|
|
|
uint32_t current_pkt;
|
2019-07-11 08:27:26 +08:00
|
|
|
uint32_t can_send_errs_pkt;
|
|
|
|
uint32_t can_fwd_errs_pkt;
|
|
|
|
uint32_t gmlan_send_errs_pkt;
|
2019-10-23 06:27:55 +08:00
|
|
|
uint8_t ignition_line_pkt;
|
|
|
|
uint8_t ignition_can_pkt;
|
2019-07-24 06:07:06 +08:00
|
|
|
uint8_t controls_allowed_pkt;
|
|
|
|
uint8_t gas_interceptor_detected_pkt;
|
|
|
|
uint8_t car_harness_status_pkt;
|
2019-10-03 02:48:40 +08:00
|
|
|
uint8_t usb_power_mode_pkt;
|
2017-04-07 09:11:36 +08:00
|
|
|
} *health = dat;
|
2017-07-21 14:36:06 +08:00
|
|
|
|
2019-10-05 05:51:26 +08:00
|
|
|
health->voltage_pkt = adc_get_voltage();
|
2017-08-29 04:15:47 +08:00
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
// No current sense on panda black
|
|
|
|
if(hw_type != HW_TYPE_BLACK_PANDA){
|
|
|
|
health->current_pkt = adc_get(ADCCHAN_CURRENT);
|
|
|
|
} else {
|
|
|
|
health->current_pkt = 0;
|
|
|
|
}
|
|
|
|
|
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-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-09-28 08:18:02 +08:00
|
|
|
|
2017-04-07 09:11:36 +08:00
|
|
|
return sizeof(*health);
|
|
|
|
}
|
|
|
|
|
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;
|
2017-07-21 14:36:06 +08:00
|
|
|
can_send(&to_push, bus_number);
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
int i;
|
2017-04-18 09:17:34 +08:00
|
|
|
switch (setup->b.bRequest) {
|
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;
|
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-07-24 06:07:06 +08:00
|
|
|
if(hw_type == HW_TYPE_BLACK_PANDA){
|
|
|
|
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.
|
|
|
|
// Allow NOOUTPUT and ELM security mode to be set over wifi.
|
2019-05-21 13:13:45 +08:00
|
|
|
if (hardwired || (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;
|
2017-07-19 12:05:09 +08:00
|
|
|
can_init(CAN_NUM_FROM_BUS_NUM(setup->b.wValue.w));
|
2017-07-18 10:43:30 +08:00
|
|
|
}
|
|
|
|
break;
|
2019-06-06 05:00:07 +08:00
|
|
|
// **** 0xdf: set long controls allowed
|
|
|
|
case 0xdf:
|
|
|
|
if (hardwired) {
|
2019-07-04 16:04:58 +08:00
|
|
|
long_controls_allowed = setup->b.wValue.w & 1U;
|
2019-06-06 05:00:07 +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;
|
2017-07-18 10:43:30 +08:00
|
|
|
// **** 0xf0: do k-line wValue pulse on uart2 for Acura
|
|
|
|
case 0xf0:
|
2019-07-04 16:04:58 +08:00
|
|
|
if (setup->b.wValue.w == 1U) {
|
2019-06-25 07:43:11 +08:00
|
|
|
GPIOC->ODR &= ~(1U << 10);
|
2017-04-07 09:11:36 +08:00
|
|
|
GPIOC->MODER &= ~GPIO_MODER_MODER10_1;
|
|
|
|
GPIOC->MODER |= GPIO_MODER_MODER10_0;
|
|
|
|
} else {
|
2019-06-25 07:43:11 +08:00
|
|
|
GPIOC->ODR &= ~(1U << 12);
|
2017-04-07 09:11:36 +08:00
|
|
|
GPIOC->MODER &= ~GPIO_MODER_MODER12_1;
|
|
|
|
GPIOC->MODER |= GPIO_MODER_MODER12_0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 80; i++) {
|
|
|
|
delay(8000);
|
2019-07-04 16:04:58 +08:00
|
|
|
if (setup->b.wValue.w == 1U) {
|
2019-06-25 07:43:11 +08:00
|
|
|
GPIOC->ODR |= (1U << 10);
|
|
|
|
GPIOC->ODR &= ~(1U << 10);
|
2017-04-07 09:11:36 +08:00
|
|
|
} else {
|
2019-06-25 07:43:11 +08:00
|
|
|
GPIOC->ODR |= (1U << 12);
|
|
|
|
GPIOC->ODR &= ~(1U << 12);
|
2017-04-07 09:11:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-04 16:04:58 +08:00
|
|
|
if (setup->b.wValue.w == 1U) {
|
2017-04-07 09:11:36 +08:00
|
|
|
GPIOC->MODER &= ~GPIO_MODER_MODER10_0;
|
|
|
|
GPIOC->MODER |= GPIO_MODER_MODER10_1;
|
|
|
|
} else {
|
|
|
|
GPIOC->MODER &= ~GPIO_MODER_MODER12_0;
|
|
|
|
GPIOC->MODER |= GPIO_MODER_MODER12_1;
|
|
|
|
}
|
|
|
|
|
|
|
|
delay(140 * 9000);
|
|
|
|
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-05-24 02:58:57 +08:00
|
|
|
uint64_t tcnt = 0;
|
2019-07-24 06:07:06 +08:00
|
|
|
|
|
|
|
// go into NOOUTPUT 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
|
|
|
|
|
|
|
// called once per second
|
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 TIM3_IRQHandler(void) {
|
2019-05-24 02:58:57 +08:00
|
|
|
if (TIM3->SR != 0) {
|
|
|
|
can_live = pending_can_live;
|
|
|
|
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->usb_power_mode_tick(tcnt);
|
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-07-04 16:04:58 +08:00
|
|
|
if ((tcnt & 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
|
|
|
|
|
|
|
|
// 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-07-24 06:07:06 +08:00
|
|
|
current_board->set_led(LED_BLUE, (tcnt & 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
|
2019-10-23 06:27:55 +08:00
|
|
|
if (heartbeat_counter >= (check_ignition() ? EON_HEARTBEAT_IGNITION_CNT_ON : EON_HEARTBEAT_IGNITION_CNT_OFF)) {
|
2019-07-24 06:07:06 +08:00
|
|
|
puts("EON hasn't sent a heartbeat for 0x"); puth(heartbeat_counter); puts(" seconds. Safety is set to NOOUTPUT mode.\n");
|
2019-10-05 04:30:00 +08:00
|
|
|
if(current_safety_mode != SAFETY_NOOUTPUT){
|
|
|
|
set_safety_mode(SAFETY_NOOUTPUT, 0U);
|
|
|
|
}
|
2019-07-24 06:07:06 +08:00
|
|
|
}
|
|
|
|
#endif
|
2019-05-24 02:58:57 +08:00
|
|
|
|
|
|
|
// on to the next one
|
2019-07-04 16:04:58 +08:00
|
|
|
tcnt += 1U;
|
2019-05-24 02:58:57 +08:00
|
|
|
}
|
|
|
|
TIM3->SR = 0;
|
|
|
|
}
|
|
|
|
|
2019-06-25 01:25:30 +08:00
|
|
|
int main(void) {
|
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-07-24 06:07:06 +08:00
|
|
|
// there is no LIN on panda black
|
|
|
|
if(hw_type != HW_TYPE_BLACK_PANDA){
|
|
|
|
// 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
|
|
|
|
|
2017-07-13 02:25:10 +08:00
|
|
|
// default to silent mode to prevent issues with Ford
|
2019-02-06 10:37:02 +08:00
|
|
|
// hardcode a specific safety mode if you want to force the panda to be in a specific mode
|
2019-07-09 11:08:20 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2017-09-05 14:51:42 +08:00
|
|
|
can_silent = ALL_CAN_SILENT;
|
2017-07-18 01:48:16 +08:00
|
|
|
can_init_all();
|
2017-05-31 00:46:21 +08:00
|
|
|
|
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-05-22 23:30:32 +08:00
|
|
|
#ifdef EON
|
|
|
|
// have to save power
|
2019-07-24 06:07:06 +08:00
|
|
|
if (hw_type == HW_TYPE_WHITE_PANDA) {
|
|
|
|
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
|
2019-05-23 05:48:08 +08:00
|
|
|
}
|
2019-05-24 02:58:57 +08:00
|
|
|
// only enter power save after the first cycle
|
2019-10-23 06:27:55 +08:00
|
|
|
/*if (check_ignition()) {
|
2019-06-27 09:24:21 +08:00
|
|
|
set_power_save_state(POWER_SAVE_STATUS_ENABLED);
|
2019-05-24 02:58:57 +08:00
|
|
|
}*/
|
2019-05-22 23:30:32 +08:00
|
|
|
#endif
|
|
|
|
|
2019-05-24 02:58:57 +08:00
|
|
|
// 48mhz / 65536 ~= 732 / 732 = 1
|
|
|
|
timer_init(TIM3, 732);
|
|
|
|
NVIC_EnableIRQ(TIM3_IRQn);
|
|
|
|
|
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) {
|
|
|
|
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++) {
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_led(LED_RED, 1);
|
2019-05-24 02:58:57 +08:00
|
|
|
if (fade < 512) { delay(fade); } else { delay(1024-fade); }
|
2019-07-24 06:07:06 +08:00
|
|
|
current_board->set_led(LED_RED, 0);
|
2019-05-24 02:58:57 +08:00
|
|
|
if (fade < 512) { delay(512-fade); } else { delay(fade-512); }
|
2017-08-22 23:27:00 +08:00
|
|
|
}
|
2019-05-22 00:47:43 +08:00
|
|
|
}
|
2017-08-23 00:44:08 +08:00
|
|
|
}
|
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;
|
|
|
|
}
|