mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-08-20 23:53:44 +08:00
Squashed 'panda/' changes from 9881e6118..30c7ca8a5
30c7ca8a5 bump version to 1.5.3 9403dbebe Need to fix wifi test before re-enabling. 0812362b5 GPS UART fix until boardd is refactored (#294) ffbdb87a8 python2 -> 3 fixes to pedal flasher (#292) 78b75ef59 Added build type to release version strings 736c2cbf7 Fixed sending of bytes over PandaSerial 0894b28f1 Fixed USB power mode on black (#291) 4b3358c92 patch to be able to switch from EON to PC with a Panda that has EON b… (#290) a95c44a71 Made setting of NOOUTPUT on no heartbeat more efficient (#287) 948683688 UART instability fix with high interrupt load (#283) 9a9e9d47b Fix usb_power_mode missing initialization (#289) af0960ad3 DFU fix (#288) 70219d7bb match safety enum in cereal (#285) a338d3932 Fix build for jenkins test 78ef4a6eb Stop charge (#284) 5266a4028 Fix typo (#286) f4787ec5a Revert "turn on CDP when ignition switches on (#281)" d37daee97 Revert "NONE and CLIENT should be the same thing in white/grey pandas" e97b283e7 NONE and CLIENT should be the same thing in white/grey pandas 8c1df559f turn on CDP when ignition switches on (#281) 847a35d42 Fix bullet points fac027716 Misra update (#280) 5a04df6b1 Added description of regression tests to README c4aabae59 Fixed some python3 bugs in the test scripts and PandaSerial 9af0cb353 Bump version c4ac3d63b Disable GPS load switching on black pandas 078ee588c This is the correct table, actually 578b95ee3 Misra table of coverage added d383a2625 bump panda b98ca010d fix sdk build in python3 env (#279) 63d3dc7d3 Set python3 env before runnign get_sdk, so we know if it fails e951d79c0 legacy code we don't control can remain python2 11b715118 Merge pull request #276 from commaai/python3 9893a842a Merge pull request #277 from zorrobyte/patch-1 d3268690c Revert "revert back esptool to python2 and force to build esptools with python2" 875e76012 revert back esptool to python2 and force to build esptools with python2 9c40e6240 needed to install python3 ed2ac87cf Also moved safety tests to python3 6842b2d2c move esptool sdk installation before python3 env is set. Kind of a cheat b5a2cabcd this hopefully fixes build test 628050955 Fixes safety replay 2c220b623 this fixes language regr test fdbe789b8 use python 3 in Docker container ee1ae4f86 Better hash print 0de9ef73c Revert "Final 2to3 on the whole repo" c92fd3bc9 Final 2to3 on the whole repo 5f2bc4460 better b2a30fdbd make works! b74005d10 fix sign.py fe727706b read file as byte and no tab before sleep 32a344ef6 Update README.md 2dc34096a 2to3 applied ffa68ef71 undo unnecessary brackets for print dbc248027 Fix all the prints with 2to3, some need to be undo 5a7aeba0f xrange is gone 982c4c928 one more python3 env 1e2412a29 env python -> env python3 git-subtree-dir: panda git-subtree-split: 30c7ca8a53a3adb05d23d7cfe64fb716a656ef1a
This commit is contained in:
@@ -36,7 +36,7 @@ struct board {
|
||||
#define LED_GREEN 1U
|
||||
#define LED_BLUE 2U
|
||||
|
||||
// USB power modes
|
||||
// USB power modes (from cereal.log.health)
|
||||
#define USB_POWER_NONE 0U
|
||||
#define USB_POWER_CLIENT 1U
|
||||
#define USB_POWER_CDP 2U
|
||||
|
||||
+22
-11
@@ -38,7 +38,7 @@ void black_set_led(uint8_t color, bool enabled) {
|
||||
break;
|
||||
case LED_BLUE:
|
||||
set_gpio_output(GPIOC, 6, !enabled);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -53,11 +53,22 @@ void black_set_usb_load_switch(bool enabled) {
|
||||
}
|
||||
|
||||
void black_set_usb_power_mode(uint8_t mode) {
|
||||
usb_power_mode = mode;
|
||||
if (mode == USB_POWER_NONE) {
|
||||
black_set_usb_load_switch(false);
|
||||
} else {
|
||||
black_set_usb_load_switch(true);
|
||||
bool valid = false;
|
||||
switch (mode) {
|
||||
case USB_POWER_CLIENT:
|
||||
black_set_usb_load_switch(false);
|
||||
valid = true;
|
||||
break;
|
||||
case USB_POWER_CDP:
|
||||
black_set_usb_load_switch(true);
|
||||
valid = true;
|
||||
break;
|
||||
default:
|
||||
puts("Invalid USB power mode\n");
|
||||
break;
|
||||
}
|
||||
if (valid) {
|
||||
usb_power_mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,18 +78,15 @@ void black_set_esp_gps_mode(uint8_t mode) {
|
||||
// GPS OFF
|
||||
set_gpio_output(GPIOC, 14, 0);
|
||||
set_gpio_output(GPIOC, 5, 0);
|
||||
black_set_gps_load_switch(false);
|
||||
break;
|
||||
case ESP_GPS_ENABLED:
|
||||
// GPS ON
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 1);
|
||||
black_set_gps_load_switch(true);
|
||||
break;
|
||||
case ESP_GPS_BOOTMODE:
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 0);
|
||||
black_set_gps_load_switch(true);
|
||||
break;
|
||||
default:
|
||||
puts("Invalid ESP/GPS mode\n");
|
||||
@@ -106,7 +114,7 @@ void black_set_can_mode(uint8_t mode){
|
||||
// B12,B13: OBD mode
|
||||
set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2);
|
||||
set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
puts("Tried to set unsupported CAN mode: "); puth(mode); puts("\n");
|
||||
@@ -154,6 +162,9 @@ void black_init(void) {
|
||||
// Turn on USB load switch.
|
||||
black_set_usb_load_switch(true);
|
||||
|
||||
// Set right power mode
|
||||
black_set_usb_power_mode(USB_POWER_CDP);
|
||||
|
||||
// Initialize harness
|
||||
harness_init();
|
||||
|
||||
@@ -203,4 +214,4 @@ const board board_black = {
|
||||
.set_can_mode = black_set_can_mode,
|
||||
.usb_power_mode_tick = black_usb_power_mode_tick,
|
||||
.check_ignition = black_check_ignition
|
||||
};
|
||||
};
|
||||
|
||||
+30
-24
@@ -34,7 +34,7 @@ void white_set_led(uint8_t color, bool enabled) {
|
||||
break;
|
||||
case LED_BLUE:
|
||||
set_gpio_output(GPIOC, 6, !enabled);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -125,7 +125,7 @@ void white_set_can_mode(uint8_t mode){
|
||||
|
||||
// A8,A15: normal CAN3 mode
|
||||
set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3);
|
||||
set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3);
|
||||
set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3);
|
||||
break;
|
||||
case CAN_MODE_GMLAN_CAN3:
|
||||
// A8,A15: disable CAN3 mode
|
||||
@@ -143,7 +143,7 @@ void white_set_can_mode(uint8_t mode){
|
||||
// B5,B6: normal CAN2 mode
|
||||
set_gpio_alternate(GPIOB, 5, GPIO_AF9_CAN2);
|
||||
set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
puts("Tried to set unsupported CAN mode: "); puth(mode); puts("\n");
|
||||
break;
|
||||
@@ -152,7 +152,9 @@ void white_set_can_mode(uint8_t mode){
|
||||
|
||||
uint64_t marker = 0;
|
||||
void white_usb_power_mode_tick(uint64_t tcnt){
|
||||
#ifndef BOOTSTUB
|
||||
|
||||
// on EON or BOOTSTUB, no state machine
|
||||
#if !defined(BOOTSTUB) && !defined(EON)
|
||||
#define CURRENT_THRESHOLD 0xF00U
|
||||
#define CLICKS 5U // 5 seconds to switch modes
|
||||
|
||||
@@ -177,22 +179,19 @@ void white_usb_power_mode_tick(uint64_t tcnt){
|
||||
}
|
||||
break;
|
||||
case USB_POWER_CDP:
|
||||
// On the EON, if we get into CDP mode we stay here. No need to go to DCP.
|
||||
#ifndef EON
|
||||
// been CLICKS clicks since we switched to CDP
|
||||
if ((tcnt-marker) >= CLICKS) {
|
||||
// measure current draw, if positive and no enumeration, switch to DCP
|
||||
if (!is_enumerated && (current < CURRENT_THRESHOLD)) {
|
||||
puts("USBP: no enumeration with current draw, switching to DCP mode\n");
|
||||
white_set_usb_power_mode(USB_POWER_DCP);
|
||||
marker = tcnt;
|
||||
}
|
||||
}
|
||||
// keep resetting the timer if there's no current draw in CDP
|
||||
if (current >= CURRENT_THRESHOLD) {
|
||||
// been CLICKS clicks since we switched to CDP
|
||||
if ((tcnt-marker) >= CLICKS) {
|
||||
// measure current draw, if positive and no enumeration, switch to DCP
|
||||
if (!is_enumerated && (current < CURRENT_THRESHOLD)) {
|
||||
puts("USBP: no enumeration with current draw, switching to DCP mode\n");
|
||||
white_set_usb_power_mode(USB_POWER_DCP);
|
||||
marker = tcnt;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// keep resetting the timer if there's no current draw in CDP
|
||||
if (current >= CURRENT_THRESHOLD) {
|
||||
marker = tcnt;
|
||||
}
|
||||
break;
|
||||
case USB_POWER_DCP:
|
||||
// been at least CLICKS clicks since we switched to DCP
|
||||
@@ -213,9 +212,9 @@ void white_usb_power_mode_tick(uint64_t tcnt){
|
||||
puts("USB power mode invalid\n"); // set_usb_power_mode prevents assigning invalid values
|
||||
break;
|
||||
}
|
||||
#else
|
||||
#else
|
||||
UNUSED(tcnt);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool white_check_ignition(void){
|
||||
@@ -242,9 +241,6 @@ void white_init(void) {
|
||||
set_gpio_alternate(GPIOA, 6, GPIO_AF5_SPI1);
|
||||
set_gpio_alternate(GPIOA, 7, GPIO_AF5_SPI1);
|
||||
|
||||
// Set USB power mode
|
||||
white_set_usb_power_mode(USB_POWER_CLIENT);
|
||||
|
||||
// B12: GMLAN, ignition sense, pull up
|
||||
set_gpio_pullup(GPIOB, 12, PULL_UP);
|
||||
|
||||
@@ -292,6 +288,16 @@ void white_init(void) {
|
||||
EXTI->RTSR |= (1U << 1);
|
||||
EXTI->FTSR |= (1U << 1);
|
||||
NVIC_EnableIRQ(EXTI1_IRQn);
|
||||
|
||||
// Init usb power mode
|
||||
uint32_t voltage = adc_get_voltage();
|
||||
// Init in CDP mode only if panda is powered by 12V.
|
||||
// Otherwise a PC would not be able to flash a standalone panda with EON build
|
||||
if (voltage > 8000U) { // 8V threshold
|
||||
white_set_usb_power_mode(USB_POWER_CDP);
|
||||
} else {
|
||||
white_set_usb_power_mode(USB_POWER_CLIENT);
|
||||
}
|
||||
}
|
||||
|
||||
const harness_configuration white_harness_config = {
|
||||
@@ -310,4 +316,4 @@ const board board_white = {
|
||||
.set_can_mode = white_set_can_mode,
|
||||
.usb_power_mode_tick = white_usb_power_mode_tick,
|
||||
.check_ignition = white_check_ignition
|
||||
};
|
||||
};
|
||||
|
||||
+1
-2
@@ -32,6 +32,7 @@ const board *current_board;
|
||||
|
||||
#include "drivers/clock.h"
|
||||
#include "drivers/llgpio.h"
|
||||
#include "drivers/adc.h"
|
||||
|
||||
#include "board.h"
|
||||
|
||||
@@ -68,8 +69,6 @@ int main(void) {
|
||||
detect_configuration();
|
||||
detect_board_type();
|
||||
|
||||
current_board->set_usb_power_mode(USB_POWER_CLIENT);
|
||||
|
||||
if (enter_bootloader_mode == ENTER_SOFTLOADER_MAGIC) {
|
||||
enter_bootloader_mode = 0;
|
||||
soft_flasher_start();
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@
|
||||
#define PANDA_CONFIG_H
|
||||
|
||||
//#define DEBUG
|
||||
//#define DEBUG_UART
|
||||
//#define DEBUG_USB
|
||||
//#define DEBUG_SPI
|
||||
|
||||
@@ -22,7 +23,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#define NULL ((void*)0)
|
||||
#define COMPILE_TIME_ASSERT(pred) ((void)sizeof(char[1 - (2 * (!(pred)))]))
|
||||
#define COMPILE_TIME_ASSERT(pred) ((void)sizeof(char[1 - (2 * ((int)(!(pred))))]))
|
||||
|
||||
#define MIN(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
|
||||
@@ -36,3 +36,13 @@ uint32_t adc_get(unsigned int channel) {
|
||||
return ADC1->JDR1;
|
||||
}
|
||||
|
||||
uint32_t adc_get_voltage(void) {
|
||||
// REVC has a 10, 1 (1/11) voltage divider
|
||||
// Here is the calculation for the scale (s)
|
||||
// ADCV = VIN_S * (1/11) * (4095/3.3)
|
||||
// RETVAL = ADCV * s = VIN_S*1000
|
||||
// s = 1000/((4095/3.3)*(1/11)) = 8.8623046875
|
||||
|
||||
// Avoid needing floating point math, so output in mV
|
||||
return (adc_get(ADCCHAN_VOLTAGE) * 8862U) / 1000U;
|
||||
}
|
||||
|
||||
+4
-5
@@ -298,7 +298,7 @@ void process_can(uint8_t can_number) {
|
||||
to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000FU) | ((CAN_BUS_RET_FLAG | bus_number) << 4);
|
||||
to_push.RDLR = CAN->sTxMailBox[0].TDLR;
|
||||
to_push.RDHR = CAN->sTxMailBox[0].TDHR;
|
||||
can_send_errs += !can_push(&can_rx_q, &to_push);
|
||||
can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U;
|
||||
}
|
||||
|
||||
if ((CAN->TSR & CAN_TSR_TERR0) == CAN_TSR_TERR0) {
|
||||
@@ -367,7 +367,7 @@ void can_rx(uint8_t can_number) {
|
||||
safety_rx_hook(&to_push);
|
||||
|
||||
current_board->set_led(LED_BLUE, true);
|
||||
can_send_errs += !can_push(&can_rx_q, &to_push);
|
||||
can_send_errs += can_push(&can_rx_q, &to_push) ? 0U : 1U;
|
||||
|
||||
// next
|
||||
CAN->RF0R |= CAN_RF0R_RFOM0;
|
||||
@@ -393,10 +393,9 @@ void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) {
|
||||
// bus number isn't passed through
|
||||
to_push->RDTR &= 0xF;
|
||||
if ((bus_number == 3U) && (can_num_lookup[3] == 0xFFU)) {
|
||||
// TODO: why uint8 bro? only int8?
|
||||
gmlan_send_errs += !bitbang_gmlan(to_push);
|
||||
gmlan_send_errs += bitbang_gmlan(to_push) ? 0U : 1U;
|
||||
} else {
|
||||
can_fwd_errs += !can_push(can_queues[bus_number], to_push);
|
||||
can_fwd_errs += can_push(can_queues[bus_number], to_push) ? 0U : 1U;
|
||||
process_can(CAN_NUM_FROM_BUS_NUM(bus_number));
|
||||
}
|
||||
}
|
||||
|
||||
+255
-176
@@ -1,18 +1,43 @@
|
||||
// IRQs: USART1, USART2, USART3, UART5
|
||||
|
||||
#define FIFO_SIZE 0x400U
|
||||
// ***************************** Definitions *****************************
|
||||
#define FIFO_SIZE_INT 0x400U
|
||||
#define FIFO_SIZE_DMA 0x1000U
|
||||
|
||||
typedef struct uart_ring {
|
||||
volatile uint16_t w_ptr_tx;
|
||||
volatile uint16_t r_ptr_tx;
|
||||
uint8_t elems_tx[FIFO_SIZE];
|
||||
uint8_t *elems_tx;
|
||||
uint32_t tx_fifo_size;
|
||||
volatile uint16_t w_ptr_rx;
|
||||
volatile uint16_t r_ptr_rx;
|
||||
uint8_t elems_rx[FIFO_SIZE];
|
||||
uint8_t *elems_rx;
|
||||
uint32_t rx_fifo_size;
|
||||
USART_TypeDef *uart;
|
||||
void (*callback)(struct uart_ring*);
|
||||
bool dma_rx;
|
||||
} uart_ring;
|
||||
|
||||
void uart_init(USART_TypeDef *u, int baud);
|
||||
#define UART_BUFFER(x, size_rx, size_tx, uart_ptr, callback_ptr, rx_dma) \
|
||||
uint8_t elems_rx_##x[size_rx]; \
|
||||
uint8_t elems_tx_##x[size_tx]; \
|
||||
uart_ring uart_ring_##x = { \
|
||||
.w_ptr_tx = 0, \
|
||||
.r_ptr_tx = 0, \
|
||||
.elems_tx = ((uint8_t *)&elems_tx_##x), \
|
||||
.tx_fifo_size = size_tx, \
|
||||
.w_ptr_rx = 0, \
|
||||
.r_ptr_rx = 0, \
|
||||
.elems_rx = ((uint8_t *)&elems_rx_##x), \
|
||||
.rx_fifo_size = size_rx, \
|
||||
.uart = uart_ptr, \
|
||||
.callback = callback_ptr, \
|
||||
.dma_rx = rx_dma \
|
||||
};
|
||||
|
||||
|
||||
// ***************************** Function prototypes *****************************
|
||||
void uart_init(uart_ring *q, int baud);
|
||||
|
||||
bool getc(uart_ring *q, char *elem);
|
||||
bool putc(uart_ring *q, char elem);
|
||||
@@ -21,48 +46,35 @@ void puts(const char *a);
|
||||
void puth(unsigned int i);
|
||||
void hexdump(const void *a, int l);
|
||||
|
||||
void debug_ring_callback(uart_ring *ring);
|
||||
|
||||
// ***************************** serial port queues *****************************
|
||||
// ******************************** UART buffers ********************************
|
||||
|
||||
// esp = USART1
|
||||
uart_ring esp_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
|
||||
.w_ptr_rx = 0, .r_ptr_rx = 0,
|
||||
.uart = USART1,
|
||||
.callback = NULL};
|
||||
// esp_gps = USART1
|
||||
UART_BUFFER(esp_gps, FIFO_SIZE_DMA, FIFO_SIZE_INT, USART1, NULL, true)
|
||||
|
||||
// lin1, K-LINE = UART5
|
||||
// lin2, L-LINE = USART3
|
||||
uart_ring lin1_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
|
||||
.w_ptr_rx = 0, .r_ptr_rx = 0,
|
||||
.uart = UART5,
|
||||
.callback = NULL};
|
||||
uart_ring lin2_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
|
||||
.w_ptr_rx = 0, .r_ptr_rx = 0,
|
||||
.uart = USART3,
|
||||
.callback = NULL};
|
||||
UART_BUFFER(lin1, FIFO_SIZE_INT, FIFO_SIZE_INT, UART5, NULL, false)
|
||||
UART_BUFFER(lin2, FIFO_SIZE_INT, FIFO_SIZE_INT, USART3, NULL, false)
|
||||
|
||||
// debug = USART2
|
||||
void debug_ring_callback(uart_ring *ring);
|
||||
uart_ring debug_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
|
||||
.w_ptr_rx = 0, .r_ptr_rx = 0,
|
||||
.uart = USART2,
|
||||
.callback = debug_ring_callback};
|
||||
|
||||
UART_BUFFER(debug, FIFO_SIZE_INT, FIFO_SIZE_INT, USART2, debug_ring_callback, false)
|
||||
|
||||
uart_ring *get_ring_by_number(int a) {
|
||||
uart_ring *ring = NULL;
|
||||
switch(a) {
|
||||
case 0:
|
||||
ring = &debug_ring;
|
||||
ring = &uart_ring_debug;
|
||||
break;
|
||||
case 1:
|
||||
ring = &esp_ring;
|
||||
ring = &uart_ring_esp_gps;
|
||||
break;
|
||||
case 2:
|
||||
ring = &lin1_ring;
|
||||
ring = &uart_ring_lin1;
|
||||
break;
|
||||
case 3:
|
||||
ring = &lin2_ring;
|
||||
ring = &uart_ring_lin2;
|
||||
break;
|
||||
default:
|
||||
ring = NULL;
|
||||
@@ -71,52 +83,219 @@ uart_ring *get_ring_by_number(int a) {
|
||||
return ring;
|
||||
}
|
||||
|
||||
// ***************************** serial port *****************************
|
||||
// ***************************** Interrupt handlers *****************************
|
||||
|
||||
void uart_ring_process(uart_ring *q) {
|
||||
void uart_tx_ring(uart_ring *q){
|
||||
ENTER_CRITICAL();
|
||||
// TODO: check if external serial is connected
|
||||
int sr = q->uart->SR;
|
||||
|
||||
// Send out next byte of TX buffer
|
||||
if (q->w_ptr_tx != q->r_ptr_tx) {
|
||||
if ((sr & USART_SR_TXE) != 0) {
|
||||
q->uart->DR = q->elems_tx[q->r_ptr_tx];
|
||||
q->r_ptr_tx = (q->r_ptr_tx + 1U) % FIFO_SIZE;
|
||||
// Only send if transmit register is empty (aka last byte has been sent)
|
||||
if ((q->uart->SR & USART_SR_TXE) != 0) {
|
||||
q->uart->DR = q->elems_tx[q->r_ptr_tx]; // This clears TXE
|
||||
q->r_ptr_tx = (q->r_ptr_tx + 1U) % q->tx_fifo_size;
|
||||
}
|
||||
// there could be more to send
|
||||
q->uart->CR1 |= USART_CR1_TXEIE;
|
||||
} else {
|
||||
// nothing to send
|
||||
q->uart->CR1 &= ~USART_CR1_TXEIE;
|
||||
}
|
||||
|
||||
if ((sr & USART_SR_RXNE) || (sr & USART_SR_ORE)) {
|
||||
uint8_t c = q->uart->DR; // TODO: can drop packets
|
||||
if (q != &esp_ring) {
|
||||
uint16_t next_w_ptr = (q->w_ptr_rx + 1U) % FIFO_SIZE;
|
||||
if (next_w_ptr != q->r_ptr_rx) {
|
||||
q->elems_rx[q->w_ptr_rx] = c;
|
||||
q->w_ptr_rx = next_w_ptr;
|
||||
if (q->callback != NULL) {
|
||||
q->callback(q);
|
||||
}
|
||||
// Enable TXE interrupt if there is still data to be sent
|
||||
if(q->r_ptr_tx != q->w_ptr_tx){
|
||||
q->uart->CR1 |= USART_CR1_TXEIE;
|
||||
} else {
|
||||
q->uart->CR1 &= ~USART_CR1_TXEIE;
|
||||
}
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void uart_rx_ring(uart_ring *q){
|
||||
// Do not read out directly if DMA enabled
|
||||
if (q->dma_rx == false) {
|
||||
ENTER_CRITICAL();
|
||||
|
||||
// Read out RX buffer
|
||||
uint8_t c = q->uart->DR; // This read after reading SR clears a bunch of interrupts
|
||||
|
||||
uint16_t next_w_ptr = (q->w_ptr_rx + 1U) % q->rx_fifo_size;
|
||||
// Do not overwrite buffer data
|
||||
if (next_w_ptr != q->r_ptr_rx) {
|
||||
q->elems_rx[q->w_ptr_rx] = c;
|
||||
q->w_ptr_rx = next_w_ptr;
|
||||
if (q->callback != NULL) {
|
||||
q->callback(q);
|
||||
}
|
||||
}
|
||||
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
// This function should be called on:
|
||||
// * Half-transfer DMA interrupt
|
||||
// * Full-transfer DMA interrupt
|
||||
// * UART IDLE detection
|
||||
uint32_t prev_w_index = 0;
|
||||
void dma_pointer_handler(uart_ring *q, uint32_t dma_ndtr) {
|
||||
ENTER_CRITICAL();
|
||||
uint32_t w_index = (q->rx_fifo_size - dma_ndtr);
|
||||
|
||||
// Check for new data
|
||||
if (w_index != prev_w_index){
|
||||
// Check for overflow
|
||||
if (
|
||||
((prev_w_index < q->r_ptr_rx) && (q->r_ptr_rx <= w_index)) || // No rollover
|
||||
((w_index < prev_w_index) && ((q->r_ptr_rx <= w_index) || (prev_w_index < q->r_ptr_rx))) // Rollover
|
||||
){
|
||||
// We lost data. Set the new read pointer to the oldest byte still available
|
||||
q->r_ptr_rx = (w_index + 1U) % q->rx_fifo_size;
|
||||
}
|
||||
|
||||
// Set write pointer
|
||||
q->w_ptr_rx = w_index;
|
||||
}
|
||||
|
||||
if ((sr & USART_SR_ORE) != 0) {
|
||||
// set dropped packet flag?
|
||||
prev_w_index = w_index;
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
// This read after reading SR clears all error interrupts. We don't want compiler warnings, nor optimizations
|
||||
#define UART_READ_DR(uart) volatile uint8_t t = (uart)->DR; UNUSED(t);
|
||||
|
||||
void uart_interrupt_handler(uart_ring *q) {
|
||||
ENTER_CRITICAL();
|
||||
|
||||
// Read UART status. This is also the first step necessary in clearing most interrupts
|
||||
uint32_t status = q->uart->SR;
|
||||
|
||||
// If RXNE is set, perform a read. This clears RXNE, ORE, IDLE, NF and FE
|
||||
if((status & USART_SR_RXNE) != 0U){
|
||||
uart_rx_ring(q);
|
||||
}
|
||||
|
||||
// Detect errors and clear them
|
||||
uint32_t err = (status & USART_SR_ORE) | (status & USART_SR_NE) | (status & USART_SR_FE) | (status & USART_SR_PE);
|
||||
if(err != 0U){
|
||||
#ifdef DEBUG_UART
|
||||
puts("Encountered UART error: "); puth(err); puts("\n");
|
||||
#endif
|
||||
UART_READ_DR(q->uart)
|
||||
}
|
||||
// Send if necessary
|
||||
uart_tx_ring(q);
|
||||
|
||||
// Run DMA pointer handler if the line is idle
|
||||
if(q->dma_rx && (status & USART_SR_IDLE)){
|
||||
// Reset IDLE flag
|
||||
UART_READ_DR(q->uart)
|
||||
|
||||
if(q == &uart_ring_esp_gps){
|
||||
dma_pointer_handler(&uart_ring_esp_gps, DMA2_Stream5->NDTR);
|
||||
} else {
|
||||
#ifdef DEBUG_UART
|
||||
puts("No IDLE dma_pointer_handler implemented for this UART.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
// interrupt boilerplate
|
||||
void USART1_IRQHandler(void) { uart_interrupt_handler(&uart_ring_esp_gps); }
|
||||
void USART2_IRQHandler(void) { uart_interrupt_handler(&uart_ring_debug); }
|
||||
void USART3_IRQHandler(void) { uart_interrupt_handler(&uart_ring_lin2); }
|
||||
void UART5_IRQHandler(void) { uart_interrupt_handler(&uart_ring_lin1); }
|
||||
|
||||
void USART1_IRQHandler(void) { uart_ring_process(&esp_ring); }
|
||||
void USART2_IRQHandler(void) { uart_ring_process(&debug_ring); }
|
||||
void USART3_IRQHandler(void) { uart_ring_process(&lin2_ring); }
|
||||
void UART5_IRQHandler(void) { uart_ring_process(&lin1_ring); }
|
||||
void DMA2_Stream5_IRQHandler(void) {
|
||||
ENTER_CRITICAL();
|
||||
|
||||
// Handle errors
|
||||
if((DMA2->HISR & DMA_HISR_TEIF5) || (DMA2->HISR & DMA_HISR_DMEIF5) || (DMA2->HISR & DMA_HISR_FEIF5)){
|
||||
#ifdef DEBUG_UART
|
||||
puts("Encountered UART DMA error. Clearing and restarting DMA...\n");
|
||||
#endif
|
||||
|
||||
// Clear flags
|
||||
DMA2->HIFCR = DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5;
|
||||
|
||||
// Re-enable the DMA if necessary
|
||||
DMA2_Stream5->CR |= DMA_SxCR_EN;
|
||||
}
|
||||
|
||||
// Re-calculate write pointer and reset flags
|
||||
dma_pointer_handler(&uart_ring_esp_gps, DMA2_Stream5->NDTR);
|
||||
DMA2->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5;
|
||||
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
// ***************************** Hardware setup *****************************
|
||||
|
||||
void dma_rx_init(uart_ring *q) {
|
||||
// Initialization is UART-dependent
|
||||
if(q == &uart_ring_esp_gps){
|
||||
// DMA2, stream 5, channel 4
|
||||
|
||||
// Disable FIFO mode (enable direct)
|
||||
DMA2_Stream5->FCR &= ~DMA_SxFCR_DMDIS;
|
||||
|
||||
// Setup addresses
|
||||
DMA2_Stream5->PAR = (uint32_t)&(USART1->DR); // Source
|
||||
DMA2_Stream5->M0AR = (uint32_t)q->elems_rx; // Destination
|
||||
DMA2_Stream5->NDTR = q->rx_fifo_size; // Number of bytes to copy
|
||||
|
||||
// Circular, Increment memory, byte size, periph -> memory, enable
|
||||
// Transfer complete, half transfer, transfer error and direct mode error interrupt enable
|
||||
DMA2_Stream5->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_HTIE | DMA_SxCR_TCIE | DMA_SxCR_TEIE | DMA_SxCR_DMEIE | DMA_SxCR_EN;
|
||||
|
||||
// Enable DMA receiver in UART
|
||||
q->uart->CR3 |= USART_CR3_DMAR;
|
||||
|
||||
// Enable UART IDLE interrupt
|
||||
q->uart->CR1 |= USART_CR1_IDLEIE;
|
||||
|
||||
// Enable interrupt
|
||||
NVIC_EnableIRQ(DMA2_Stream5_IRQn);
|
||||
} else {
|
||||
puts("Tried to initialize RX DMA for an unsupported UART\n");
|
||||
}
|
||||
}
|
||||
|
||||
#define __DIV(_PCLK_, _BAUD_) (((_PCLK_) * 25U) / (4U * (_BAUD_)))
|
||||
#define __DIVMANT(_PCLK_, _BAUD_) (__DIV((_PCLK_), (_BAUD_)) / 100U)
|
||||
#define __DIVFRAQ(_PCLK_, _BAUD_) ((((__DIV((_PCLK_), (_BAUD_)) - (__DIVMANT((_PCLK_), (_BAUD_)) * 100U)) * 16U) + 50U) / 100U)
|
||||
#define __USART_BRR(_PCLK_, _BAUD_) ((__DIVMANT((_PCLK_), (_BAUD_)) << 4) | (__DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0FU))
|
||||
|
||||
void uart_set_baud(USART_TypeDef *u, unsigned int baud) {
|
||||
if (u == USART1) {
|
||||
// USART1 is on APB2
|
||||
u->BRR = __USART_BRR(48000000U, baud);
|
||||
} else {
|
||||
u->BRR = __USART_BRR(24000000U, baud);
|
||||
}
|
||||
}
|
||||
|
||||
void uart_init(uart_ring *q, int baud) {
|
||||
// Set baud and enable peripheral with TX and RX mode
|
||||
uart_set_baud(q->uart, baud);
|
||||
q->uart->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
|
||||
|
||||
// Enable UART interrupts
|
||||
if(q->uart == USART1){
|
||||
NVIC_EnableIRQ(USART1_IRQn);
|
||||
} else if (q->uart == USART2){
|
||||
NVIC_EnableIRQ(USART2_IRQn);
|
||||
} else if (q->uart == USART3){
|
||||
NVIC_EnableIRQ(USART3_IRQn);
|
||||
} else if (q->uart == UART5){
|
||||
NVIC_EnableIRQ(UART5_IRQn);
|
||||
} else {
|
||||
// UART not used. Skip enabling interrupts
|
||||
}
|
||||
|
||||
// Initialise RX DMA if used
|
||||
if(q->dma_rx){
|
||||
dma_rx_init(q);
|
||||
}
|
||||
}
|
||||
|
||||
// ************************* Low-level buffer functions *************************
|
||||
|
||||
bool getc(uart_ring *q, char *elem) {
|
||||
bool ret = false;
|
||||
@@ -124,7 +303,7 @@ bool getc(uart_ring *q, char *elem) {
|
||||
ENTER_CRITICAL();
|
||||
if (q->w_ptr_rx != q->r_ptr_rx) {
|
||||
if (elem != NULL) *elem = q->elems_rx[q->r_ptr_rx];
|
||||
q->r_ptr_rx = (q->r_ptr_rx + 1U) % FIFO_SIZE;
|
||||
q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size;
|
||||
ret = true;
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
@@ -137,7 +316,7 @@ bool injectc(uart_ring *q, char elem) {
|
||||
uint16_t next_w_ptr;
|
||||
|
||||
ENTER_CRITICAL();
|
||||
next_w_ptr = (q->w_ptr_rx + 1U) % FIFO_SIZE;
|
||||
next_w_ptr = (q->w_ptr_rx + 1U) % q->tx_fifo_size;
|
||||
if (next_w_ptr != q->r_ptr_rx) {
|
||||
q->elems_rx[q->w_ptr_rx] = elem;
|
||||
q->w_ptr_rx = next_w_ptr;
|
||||
@@ -153,7 +332,7 @@ bool putc(uart_ring *q, char elem) {
|
||||
uint16_t next_w_ptr;
|
||||
|
||||
ENTER_CRITICAL();
|
||||
next_w_ptr = (q->w_ptr_tx + 1U) % FIFO_SIZE;
|
||||
next_w_ptr = (q->w_ptr_tx + 1U) % q->tx_fifo_size;
|
||||
if (next_w_ptr != q->r_ptr_tx) {
|
||||
q->elems_tx[q->w_ptr_tx] = elem;
|
||||
q->w_ptr_tx = next_w_ptr;
|
||||
@@ -161,11 +340,13 @@ bool putc(uart_ring *q, char elem) {
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
|
||||
uart_ring_process(q);
|
||||
uart_tx_ring(q);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Seems dangerous to use (might lock CPU if called with interrupts disabled f.e.)
|
||||
// TODO: Remove? Not used anyways
|
||||
void uart_flush(uart_ring *q) {
|
||||
while (q->w_ptr_tx != q->r_ptr_tx) {
|
||||
__WFI();
|
||||
@@ -175,7 +356,7 @@ void uart_flush(uart_ring *q) {
|
||||
void uart_flush_sync(uart_ring *q) {
|
||||
// empty the TX buffer
|
||||
while (q->w_ptr_tx != q->r_ptr_tx) {
|
||||
uart_ring_process(q);
|
||||
uart_tx_ring(q);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,119 +374,15 @@ void clear_uart_buff(uart_ring *q) {
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
// ***************************** start UART code *****************************
|
||||
|
||||
#define __DIV(_PCLK_, _BAUD_) (((_PCLK_) * 25U) / (4U * (_BAUD_)))
|
||||
#define __DIVMANT(_PCLK_, _BAUD_) (__DIV((_PCLK_), (_BAUD_)) / 100U)
|
||||
#define __DIVFRAQ(_PCLK_, _BAUD_) ((((__DIV((_PCLK_), (_BAUD_)) - (__DIVMANT((_PCLK_), (_BAUD_)) * 100U)) * 16U) + 50U) / 100U)
|
||||
#define __USART_BRR(_PCLK_, _BAUD_) ((__DIVMANT((_PCLK_), (_BAUD_)) << 4) | (__DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0FU))
|
||||
|
||||
void uart_set_baud(USART_TypeDef *u, unsigned int baud) {
|
||||
if (u == USART1) {
|
||||
// USART1 is on APB2
|
||||
u->BRR = __USART_BRR(48000000U, baud);
|
||||
} else {
|
||||
u->BRR = __USART_BRR(24000000U, baud);
|
||||
}
|
||||
}
|
||||
|
||||
#define USART1_DMA_LEN 0x20
|
||||
char usart1_dma[USART1_DMA_LEN];
|
||||
|
||||
void uart_dma_drain(void) {
|
||||
uart_ring *q = &esp_ring;
|
||||
|
||||
ENTER_CRITICAL();
|
||||
|
||||
if ((DMA2->HISR & DMA_HISR_TCIF5) || (DMA2->HISR & DMA_HISR_HTIF5) || (DMA2_Stream5->NDTR != USART1_DMA_LEN)) {
|
||||
// disable DMA
|
||||
q->uart->CR3 &= ~USART_CR3_DMAR;
|
||||
DMA2_Stream5->CR &= ~DMA_SxCR_EN;
|
||||
while ((DMA2_Stream5->CR & DMA_SxCR_EN) != 0);
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < (USART1_DMA_LEN - DMA2_Stream5->NDTR); i++) {
|
||||
char c = usart1_dma[i];
|
||||
uint16_t next_w_ptr = (q->w_ptr_rx + 1U) % FIFO_SIZE;
|
||||
if (next_w_ptr != q->r_ptr_rx) {
|
||||
q->elems_rx[q->w_ptr_rx] = c;
|
||||
q->w_ptr_rx = next_w_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// reset DMA len
|
||||
DMA2_Stream5->NDTR = USART1_DMA_LEN;
|
||||
|
||||
// clear interrupts
|
||||
DMA2->HIFCR = DMA_HIFCR_CTCIF5 | DMA_HIFCR_CHTIF5;
|
||||
//DMA2->HIFCR = DMA_HIFCR_CTEIF5 | DMA_HIFCR_CDMEIF5 | DMA_HIFCR_CFEIF5;
|
||||
|
||||
// enable DMA
|
||||
DMA2_Stream5->CR |= DMA_SxCR_EN;
|
||||
q->uart->CR3 |= USART_CR3_DMAR;
|
||||
}
|
||||
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void DMA2_Stream5_IRQHandler(void) {
|
||||
//set_led(LED_BLUE, 1);
|
||||
uart_dma_drain();
|
||||
//set_led(LED_BLUE, 0);
|
||||
}
|
||||
|
||||
void uart_init(USART_TypeDef *u, int baud) {
|
||||
// enable uart and tx+rx mode
|
||||
u->CR1 = USART_CR1_UE;
|
||||
uart_set_baud(u, baud);
|
||||
|
||||
u->CR1 |= USART_CR1_TE | USART_CR1_RE;
|
||||
//u->CR2 = USART_CR2_STOP_0 | USART_CR2_STOP_1;
|
||||
//u->CR2 = USART_CR2_STOP_0;
|
||||
// ** UART is ready to work **
|
||||
|
||||
// enable interrupts
|
||||
if (u != USART1) {
|
||||
u->CR1 |= USART_CR1_RXNEIE;
|
||||
}
|
||||
|
||||
if (u == USART1) {
|
||||
// DMA2, stream 2, channel 3
|
||||
DMA2_Stream5->M0AR = (uint32_t)usart1_dma;
|
||||
DMA2_Stream5->NDTR = USART1_DMA_LEN;
|
||||
DMA2_Stream5->PAR = (uint32_t)&(USART1->DR);
|
||||
|
||||
// channel4, increment memory, periph -> memory, enable
|
||||
DMA2_Stream5->CR = DMA_SxCR_CHSEL_2 | DMA_SxCR_MINC | DMA_SxCR_HTIE | DMA_SxCR_TCIE | DMA_SxCR_EN;
|
||||
|
||||
// this one uses DMA receiver
|
||||
u->CR3 = USART_CR3_DMAR;
|
||||
|
||||
NVIC_EnableIRQ(DMA2_Stream5_IRQn);
|
||||
NVIC_EnableIRQ(USART1_IRQn);
|
||||
} else if (u == USART2) {
|
||||
NVIC_EnableIRQ(USART2_IRQn);
|
||||
} else if (u == USART3) {
|
||||
NVIC_EnableIRQ(USART3_IRQn);
|
||||
} else if (u == UART5) {
|
||||
NVIC_EnableIRQ(UART5_IRQn);
|
||||
} else {
|
||||
// USART type undefined, skip
|
||||
}
|
||||
}
|
||||
|
||||
// ************************ High-level debug functions **********************
|
||||
void putch(const char a) {
|
||||
if (has_external_debug_serial) {
|
||||
/*while ((debug_ring.uart->SR & USART_SR_TXE) == 0);
|
||||
debug_ring.uart->DR = a;*/
|
||||
|
||||
// assuming debugging is important if there's external serial connected
|
||||
while (!putc(&debug_ring, a));
|
||||
while (!putc(&uart_ring_debug, a));
|
||||
|
||||
//putc(&debug_ring, a);
|
||||
} else {
|
||||
// misra-c2012-17.7: serial debug function, ok to ignore output
|
||||
(void)injectc(&debug_ring, a);
|
||||
(void)injectc(&uart_ring_debug, a);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +404,7 @@ void putui(uint32_t i) {
|
||||
idx--;
|
||||
i_copy /= 10;
|
||||
} while (i_copy != 0U);
|
||||
puts(str + idx + 1U);
|
||||
puts(&str[idx + 1U]);
|
||||
}
|
||||
|
||||
void puth(unsigned int i) {
|
||||
@@ -345,10 +422,12 @@ void puth2(unsigned int i) {
|
||||
}
|
||||
|
||||
void hexdump(const void *a, int l) {
|
||||
for (int i=0; i < l; i++) {
|
||||
if ((i != 0) && ((i & 0xf) == 0)) puts("\n");
|
||||
puth2(((const unsigned char*)a)[i]);
|
||||
puts(" ");
|
||||
if (a != NULL) {
|
||||
for (int i=0; i < l; i++) {
|
||||
if ((i != 0) && ((i & 0xf) == 0)) puts("\n");
|
||||
puth2(((const unsigned char*)a)[i]);
|
||||
puts(" ");
|
||||
}
|
||||
}
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
+2
-2
@@ -439,7 +439,7 @@ void USB_WritePacket_EP0(uint8_t *src, uint16_t len) {
|
||||
USB_WritePacket(src, wplen, 0);
|
||||
|
||||
if (wplen < len) {
|
||||
ep0_txdata = src + wplen;
|
||||
ep0_txdata = &src[wplen];
|
||||
ep0_txlen = len - wplen;
|
||||
USBx_DEVICE->DIEPEMPMSK |= 1;
|
||||
} else {
|
||||
@@ -985,7 +985,7 @@ void usb_irqhandler(void) {
|
||||
if ((ep0_txlen != 0U) && ((USBx_INEP(0)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= 0x40U)) {
|
||||
uint16_t len = MIN(ep0_txlen, 0x40);
|
||||
USB_WritePacket(ep0_txdata, len, 0);
|
||||
ep0_txdata += len;
|
||||
ep0_txdata = &ep0_txdata[len];
|
||||
ep0_txlen -= len;
|
||||
if (ep0_txlen == 0U) {
|
||||
ep0_txdata = NULL;
|
||||
|
||||
+32
-43
@@ -1,4 +1,4 @@
|
||||
//#define EON
|
||||
//#define EON
|
||||
//#define PANDA
|
||||
|
||||
// ********************* Includes *********************
|
||||
@@ -78,10 +78,14 @@ void started_interrupt_handler(uint8_t interrupt_line) {
|
||||
// jenky debounce
|
||||
delay(100000);
|
||||
|
||||
// set power savings mode here if on EON build
|
||||
#ifdef EON
|
||||
// set power savings mode here if on EON build
|
||||
int power_save_state = current_board->check_ignition() ? 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 (current_board->check_ignition()) {
|
||||
current_board->set_usb_power_mode(USB_POWER_CDP);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
EXTI->PR = (1U << interrupt_line);
|
||||
@@ -134,7 +138,7 @@ void set_safety_mode(uint16_t mode, int16_t param) {
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (safety_ignition_hook() != -1) {
|
||||
// if the ignition hook depends on something other than the started GPIO
|
||||
// we have to disable power savings (fix for GM and Tesla)
|
||||
@@ -159,19 +163,10 @@ int get_health_pkt(void *dat) {
|
||||
uint8_t controls_allowed_pkt;
|
||||
uint8_t gas_interceptor_detected_pkt;
|
||||
uint8_t car_harness_status_pkt;
|
||||
uint8_t usb_power_mode_pkt;
|
||||
} *health = dat;
|
||||
|
||||
//Voltage will be measured in mv. 5000 = 5V
|
||||
uint32_t voltage = adc_get(ADCCHAN_VOLTAGE);
|
||||
|
||||
// REVC has a 10, 1 (1/11) voltage divider
|
||||
// Here is the calculation for the scale (s)
|
||||
// ADCV = VIN_S * (1/11) * (4095/3.3)
|
||||
// RETVAL = ADCV * s = VIN_S*1000
|
||||
// s = 1000/((4095/3.3)*(1/11)) = 8.8623046875
|
||||
|
||||
// Avoid needing floating point math
|
||||
health->voltage_pkt = (voltage * 8862U) / 1000U;
|
||||
health->voltage_pkt = adc_get_voltage();
|
||||
|
||||
// No current sense on panda black
|
||||
if(hw_type != HW_TYPE_BLACK_PANDA){
|
||||
@@ -195,7 +190,8 @@ int get_health_pkt(void *dat) {
|
||||
health->can_fwd_errs_pkt = can_fwd_errs;
|
||||
health->gmlan_send_errs_pkt = gmlan_send_errs;
|
||||
health->car_harness_status_pkt = car_harness_status;
|
||||
|
||||
health->usb_power_mode_pkt = usb_power_mode;
|
||||
|
||||
return sizeof(*health);
|
||||
}
|
||||
|
||||
@@ -215,7 +211,7 @@ void usb_cb_ep2_out(void *usbdata, int len, bool hardwired) {
|
||||
uint8_t *usbdata8 = (uint8_t *)usbdata;
|
||||
uart_ring *ur = get_ring_by_number(usbdata8[0]);
|
||||
if ((len != 0) && (ur != NULL)) {
|
||||
if ((usbdata8[0] < 2U) || safety_tx_lin_hook(usbdata8[0] - 2U, usbdata8 + 1, len - 1)) {
|
||||
if ((usbdata8[0] < 2U) || safety_tx_lin_hook(usbdata8[0] - 2U, &usbdata8[1], len - 1)) {
|
||||
for (int i = 1; i < len; i++) {
|
||||
while (!putc(ur, usbdata8[i])) {
|
||||
// wait
|
||||
@@ -346,7 +342,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
} else {
|
||||
// Disable OBD CAN
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (setup->b.wValue.w == 1U) {
|
||||
// GMLAN ON
|
||||
@@ -362,7 +358,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
// **** 0xdc: set safety mode
|
||||
case 0xdc:
|
||||
// Blocked over WiFi.
|
||||
@@ -403,9 +399,12 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
if (!ur) {
|
||||
break;
|
||||
}
|
||||
if (ur == &esp_ring) {
|
||||
uart_dma_drain();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// read
|
||||
while ((resp_len < MIN(setup->b.wLength.w, MAX_RESP_LEN)) &&
|
||||
getc(ur, (char*)&resp[resp_len])) {
|
||||
@@ -460,19 +459,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
break;
|
||||
// **** 0xe6: set USB power
|
||||
case 0xe6:
|
||||
if (setup->b.wValue.w == 0U) {
|
||||
puts("user setting NONE mode\n");
|
||||
current_board->set_usb_power_mode(USB_POWER_NONE);
|
||||
} else if (setup->b.wValue.w == 1U) {
|
||||
puts("user setting CDP mode\n");
|
||||
current_board->set_usb_power_mode(USB_POWER_CDP);
|
||||
} else if (setup->b.wValue.w == 2U) {
|
||||
puts("user setting DCP mode\n");
|
||||
current_board->set_usb_power_mode(USB_POWER_DCP);
|
||||
} else {
|
||||
puts("user setting CLIENT mode\n");
|
||||
current_board->set_usb_power_mode(USB_POWER_CLIENT);
|
||||
}
|
||||
current_board->set_usb_power_mode(setup->b.wValue.w);
|
||||
break;
|
||||
// **** 0xf0: do k-line wValue pulse on uart2 for Acura
|
||||
case 0xf0:
|
||||
@@ -591,8 +578,8 @@ void __attribute__ ((noinline)) enable_fpu(void) {
|
||||
uint64_t tcnt = 0;
|
||||
|
||||
// go into NOOUTPUT when the EON does not send a heartbeat for this amount of seconds.
|
||||
#define EON_HEARTBEAT_THRESHOLD_IGNITION_ON 5U
|
||||
#define EON_HEARTBEAT_THRESHOLD_IGNITION_OFF 2U
|
||||
#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
|
||||
@@ -629,9 +616,11 @@ void TIM3_IRQHandler(void) {
|
||||
|
||||
// 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
|
||||
if (heartbeat_counter >= (current_board->check_ignition() ? EON_HEARTBEAT_THRESHOLD_IGNITION_ON : EON_HEARTBEAT_THRESHOLD_IGNITION_OFF)) {
|
||||
if (heartbeat_counter >= (current_board->check_ignition() ? 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");
|
||||
set_safety_mode(SAFETY_NOOUTPUT, 0U);
|
||||
if(current_safety_mode != SAFETY_NOOUTPUT){
|
||||
set_safety_mode(SAFETY_NOOUTPUT, 0U);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -651,7 +640,7 @@ int main(void) {
|
||||
detect_configuration();
|
||||
detect_board_type();
|
||||
adc_init();
|
||||
|
||||
|
||||
// print hello
|
||||
puts("\n\n\n************************ MAIN START ************************\n");
|
||||
|
||||
@@ -676,22 +665,22 @@ int main(void) {
|
||||
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
|
||||
uart_init(USART2, 115200);
|
||||
uart_init(&uart_ring_debug, 115200);
|
||||
}
|
||||
|
||||
if (board_has_gps()) {
|
||||
uart_init(USART1, 9600);
|
||||
uart_init(&uart_ring_esp_gps, 9600);
|
||||
} else {
|
||||
// enable ESP uart
|
||||
uart_init(USART1, 115200);
|
||||
uart_init(&uart_ring_esp_gps, 115200);
|
||||
}
|
||||
|
||||
// there is no LIN on panda black
|
||||
if(hw_type != HW_TYPE_BLACK_PANDA){
|
||||
// enable LIN
|
||||
uart_init(UART5, 10400);
|
||||
uart_init(&uart_ring_lin1, 10400);
|
||||
UART5->CR2 |= USART_CR2_LINEN;
|
||||
uart_init(USART3, 10400);
|
||||
uart_init(&uart_ring_lin2, 10400);
|
||||
USART3->CR2 |= USART_CR2_LINEN;
|
||||
}
|
||||
|
||||
|
||||
@@ -84,9 +84,6 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
if (!ur) {
|
||||
break;
|
||||
}
|
||||
if (ur == &esp_ring) {
|
||||
uart_dma_drain();
|
||||
}
|
||||
// read
|
||||
while ((resp_len < MIN(setup->b.wLength.w, MAX_RESP_LEN)) &&
|
||||
getc(ur, (char*)&resp[resp_len])) {
|
||||
|
||||
+26
-23
@@ -16,6 +16,26 @@
|
||||
#include "safety/safety_mazda.h"
|
||||
#include "safety/safety_elm327.h"
|
||||
|
||||
// from cereal.car.CarParams.SafetyModel
|
||||
#define SAFETY_NOOUTPUT 0U
|
||||
#define SAFETY_HONDA 1U
|
||||
#define SAFETY_TOYOTA 2U
|
||||
#define SAFETY_ELM327 3U
|
||||
#define SAFETY_GM 4U
|
||||
#define SAFETY_HONDA_BOSCH 5U
|
||||
#define SAFETY_FORD 6U
|
||||
#define SAFETY_CADILLAC 7U
|
||||
#define SAFETY_HYUNDAI 8U
|
||||
#define SAFETY_CHRYSLER 9U
|
||||
#define SAFETY_TESLA 10U
|
||||
#define SAFETY_SUBARU 11U
|
||||
#define SAFETY_GM_PASSIVE 12U
|
||||
#define SAFETY_MAZDA 13U
|
||||
#define SAFETY_TOYOTA_IPAS 16U
|
||||
#define SAFETY_ALLOUTPUT 17U
|
||||
#define SAFETY_GM_ASCM 18U
|
||||
|
||||
uint16_t current_safety_mode = SAFETY_NOOUTPUT;
|
||||
const safety_hooks *current_hooks = &nooutput_hooks;
|
||||
|
||||
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push){
|
||||
@@ -45,42 +65,24 @@ typedef struct {
|
||||
const safety_hooks *hooks;
|
||||
} safety_hook_config;
|
||||
|
||||
#define SAFETY_NOOUTPUT 0U
|
||||
#define SAFETY_HONDA 1U
|
||||
#define SAFETY_TOYOTA 2U
|
||||
#define SAFETY_GM 3U
|
||||
#define SAFETY_HONDA_BOSCH 4U
|
||||
#define SAFETY_FORD 5U
|
||||
#define SAFETY_CADILLAC 6U
|
||||
#define SAFETY_HYUNDAI 7U
|
||||
#define SAFETY_TESLA 8U
|
||||
#define SAFETY_CHRYSLER 9U
|
||||
#define SAFETY_SUBARU 10U
|
||||
#define SAFETY_GM_PASSIVE 11U
|
||||
#define SAFETY_MAZDA 12U
|
||||
#define SAFETY_GM_ASCM 0x1334U
|
||||
#define SAFETY_TOYOTA_IPAS 0x1335U
|
||||
#define SAFETY_ALLOUTPUT 0x1337U
|
||||
#define SAFETY_ELM327 0xE327U
|
||||
|
||||
const safety_hook_config safety_hook_registry[] = {
|
||||
{SAFETY_NOOUTPUT, &nooutput_hooks},
|
||||
{SAFETY_HONDA, &honda_hooks},
|
||||
{SAFETY_HONDA_BOSCH, &honda_bosch_hooks},
|
||||
{SAFETY_TOYOTA, &toyota_hooks},
|
||||
{SAFETY_ELM327, &elm327_hooks},
|
||||
{SAFETY_GM, &gm_hooks},
|
||||
{SAFETY_HONDA_BOSCH, &honda_bosch_hooks},
|
||||
{SAFETY_FORD, &ford_hooks},
|
||||
{SAFETY_CADILLAC, &cadillac_hooks},
|
||||
{SAFETY_HYUNDAI, &hyundai_hooks},
|
||||
{SAFETY_CHRYSLER, &chrysler_hooks},
|
||||
{SAFETY_TESLA, &tesla_hooks},
|
||||
{SAFETY_SUBARU, &subaru_hooks},
|
||||
{SAFETY_GM_PASSIVE, &gm_passive_hooks},
|
||||
{SAFETY_MAZDA, &mazda_hooks},
|
||||
{SAFETY_TOYOTA_IPAS, &toyota_ipas_hooks},
|
||||
{SAFETY_GM_PASSIVE, &gm_passive_hooks},
|
||||
{SAFETY_GM_ASCM, &gm_ascm_hooks},
|
||||
{SAFETY_TESLA, &tesla_hooks},
|
||||
{SAFETY_ALLOUTPUT, &alloutput_hooks},
|
||||
{SAFETY_ELM327, &elm327_hooks},
|
||||
{SAFETY_GM_ASCM, &gm_ascm_hooks},
|
||||
};
|
||||
|
||||
int safety_set_mode(uint16_t mode, int16_t param) {
|
||||
@@ -89,6 +91,7 @@ int safety_set_mode(uint16_t mode, int16_t param) {
|
||||
for (int i = 0; i < hook_config_count; i++) {
|
||||
if (safety_hook_registry[i].id == mode) {
|
||||
current_hooks = safety_hook_registry[i].hooks;
|
||||
current_safety_mode = safety_hook_registry[i].id;
|
||||
set_status = 0; // set
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
// GAS/REGEN: safety check
|
||||
if (addr == 715) {
|
||||
int gas_regen = ((GET_BYTE(to_send, 2) & 0x7FU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3);
|
||||
// Disabled message is !engaed with gas
|
||||
// Disabled message is !engaged with gas
|
||||
// value that corresponds to max regen.
|
||||
if (!current_controls_allowed || !long_controls_allowed) {
|
||||
bool apply = GET_BYTE(to_send, 0) & 1U;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import print_function
|
||||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
import sys
|
||||
import time
|
||||
|
||||
Reference in New Issue
Block a user