mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-08-06 00:36:25 +08:00
Merge panda subtree
This commit is contained in:
+3
-1
@@ -19,7 +19,9 @@
|
||||
|
||||
void detect_board_type(void) {
|
||||
#ifdef PANDA
|
||||
// SPI lines floating: white (TODO: is this reliable?)
|
||||
// SPI lines floating: white (TODO: is this reliable? Not really, we have to enable ESP/GPS to be able to detect this on the UART)
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 1);
|
||||
if((detect_with_pull(GPIOA, 4, PULL_DOWN)) || (detect_with_pull(GPIOA, 5, PULL_DOWN)) || (detect_with_pull(GPIOA, 6, PULL_DOWN)) || (detect_with_pull(GPIOA, 7, PULL_DOWN))){
|
||||
hw_type = HW_TYPE_WHITE_PANDA;
|
||||
current_board = &board_white;
|
||||
|
||||
@@ -6,11 +6,12 @@ typedef void (*board_set_led)(uint8_t color, bool enabled);
|
||||
typedef void (*board_set_usb_power_mode)(uint8_t mode);
|
||||
typedef void (*board_set_esp_gps_mode)(uint8_t mode);
|
||||
typedef void (*board_set_can_mode)(uint8_t mode);
|
||||
typedef void (*board_usb_power_mode_tick)(uint64_t tcnt);
|
||||
typedef void (*board_usb_power_mode_tick)(uint32_t uptime);
|
||||
typedef bool (*board_check_ignition)(void);
|
||||
typedef uint32_t (*board_read_current)(void);
|
||||
typedef void (*board_set_ir_power)(uint8_t percentage);
|
||||
typedef void (*board_set_fan_power)(uint8_t percentage);
|
||||
typedef void (*board_set_phone_power)(bool enabled);
|
||||
|
||||
struct board {
|
||||
const char *board_type;
|
||||
@@ -27,6 +28,7 @@ struct board {
|
||||
board_read_current read_current;
|
||||
board_set_ir_power set_ir_power;
|
||||
board_set_fan_power set_fan_power;
|
||||
board_set_phone_power set_phone_power;
|
||||
};
|
||||
|
||||
// ******************* Definitions ********************
|
||||
|
||||
@@ -123,8 +123,8 @@ void black_set_can_mode(uint8_t mode){
|
||||
}
|
||||
}
|
||||
|
||||
void black_usb_power_mode_tick(uint64_t tcnt){
|
||||
UNUSED(tcnt);
|
||||
void black_usb_power_mode_tick(uint32_t uptime){
|
||||
UNUSED(uptime);
|
||||
// Not applicable
|
||||
}
|
||||
|
||||
@@ -146,6 +146,10 @@ void black_set_fan_power(uint8_t percentage){
|
||||
UNUSED(percentage);
|
||||
}
|
||||
|
||||
void black_set_phone_power(bool enabled){
|
||||
UNUSED(enabled);
|
||||
}
|
||||
|
||||
void black_init(void) {
|
||||
common_init_gpio();
|
||||
|
||||
@@ -158,6 +162,9 @@ void black_init(void) {
|
||||
set_gpio_mode(GPIOC, 0, MODE_ANALOG);
|
||||
set_gpio_mode(GPIOC, 3, MODE_ANALOG);
|
||||
|
||||
// Set default state of GPS
|
||||
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
|
||||
|
||||
// C10: OBD_SBU1_RELAY (harness relay driving output)
|
||||
// C11: OBD_SBU2_RELAY (harness relay driving output)
|
||||
set_gpio_mode(GPIOC, 10, MODE_OUTPUT);
|
||||
@@ -227,5 +234,6 @@ const board board_black = {
|
||||
.check_ignition = black_check_ignition,
|
||||
.read_current = black_read_current,
|
||||
.set_fan_power = black_set_fan_power,
|
||||
.set_ir_power = black_set_ir_power
|
||||
.set_ir_power = black_set_ir_power,
|
||||
.set_phone_power = black_set_phone_power
|
||||
};
|
||||
|
||||
@@ -61,7 +61,7 @@ void peripherals_init(void){
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // pedal and fan PWM
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // gmlan_alt and IR PWM
|
||||
//RCC->APB1ENR |= RCC_APB1ENR_TIM5EN;
|
||||
//RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM6EN; // interrupt timer
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN; // for RTC config
|
||||
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||
RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN;
|
||||
|
||||
@@ -3,10 +3,18 @@
|
||||
// ////////// //
|
||||
|
||||
// Most hardware functionality is similar to white panda
|
||||
|
||||
void grey_init(void) {
|
||||
white_grey_common_init();
|
||||
|
||||
// Set default state of GPS
|
||||
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
|
||||
}
|
||||
|
||||
const board board_grey = {
|
||||
.board_type = "Grey",
|
||||
.harness_config = &white_harness_config,
|
||||
.init = white_init,
|
||||
.init = grey_init,
|
||||
.enable_can_transciever = white_enable_can_transciever,
|
||||
.enable_can_transcievers = white_enable_can_transcievers,
|
||||
.set_led = white_set_led,
|
||||
@@ -17,5 +25,6 @@ const board board_grey = {
|
||||
.check_ignition = white_check_ignition,
|
||||
.read_current = white_read_current,
|
||||
.set_fan_power = white_set_fan_power,
|
||||
.set_ir_power = white_set_ir_power
|
||||
.set_ir_power = white_set_ir_power,
|
||||
.set_phone_power = white_set_phone_power
|
||||
};
|
||||
@@ -50,8 +50,8 @@ void pedal_set_can_mode(uint8_t mode){
|
||||
}
|
||||
}
|
||||
|
||||
void pedal_usb_power_mode_tick(uint64_t tcnt){
|
||||
UNUSED(tcnt);
|
||||
void pedal_usb_power_mode_tick(uint32_t uptime){
|
||||
UNUSED(uptime);
|
||||
// Not applicable
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@ void pedal_set_fan_power(uint8_t percentage){
|
||||
UNUSED(percentage);
|
||||
}
|
||||
|
||||
void pedal_set_phone_power(bool enabled){
|
||||
UNUSED(enabled);
|
||||
}
|
||||
|
||||
void pedal_init(void) {
|
||||
common_init_gpio();
|
||||
|
||||
@@ -108,5 +112,6 @@ const board board_pedal = {
|
||||
.check_ignition = pedal_check_ignition,
|
||||
.read_current = pedal_read_current,
|
||||
.set_fan_power = pedal_set_fan_power,
|
||||
.set_ir_power = pedal_set_ir_power
|
||||
.set_ir_power = pedal_set_ir_power,
|
||||
.set_phone_power = pedal_set_phone_power
|
||||
};
|
||||
+45
-11
@@ -1,6 +1,8 @@
|
||||
// ///////////// //
|
||||
// Uno + Harness //
|
||||
// ///////////// //
|
||||
#define BOOTKICK_TIME 3U
|
||||
uint8_t bootkick_timer = 0U;
|
||||
|
||||
void uno_enable_can_transciever(uint8_t transciever, bool enabled) {
|
||||
switch (transciever){
|
||||
@@ -48,9 +50,38 @@ void uno_set_gps_load_switch(bool enabled) {
|
||||
set_gpio_output(GPIOC, 12, enabled);
|
||||
}
|
||||
|
||||
void uno_set_bootkick(bool enabled){
|
||||
set_gpio_output(GPIOB, 14, !enabled);
|
||||
}
|
||||
|
||||
void uno_bootkick(void) {
|
||||
bootkick_timer = BOOTKICK_TIME;
|
||||
uno_set_bootkick(true);
|
||||
}
|
||||
|
||||
void uno_set_phone_power(bool enabled){
|
||||
set_gpio_output(GPIOB, 4, enabled);
|
||||
}
|
||||
|
||||
void uno_set_usb_power_mode(uint8_t mode) {
|
||||
UNUSED(mode);
|
||||
puts("Setting USB mode makes no sense on UNO\n");
|
||||
bool valid = false;
|
||||
switch (mode) {
|
||||
case USB_POWER_CLIENT:
|
||||
uno_set_phone_power(false);
|
||||
valid = true;
|
||||
break;
|
||||
case USB_POWER_CDP:
|
||||
uno_set_phone_power(true);
|
||||
uno_bootkick();
|
||||
valid = true;
|
||||
break;
|
||||
default:
|
||||
puts("Invalid USB power mode\n");
|
||||
break;
|
||||
}
|
||||
if (valid) {
|
||||
usb_power_mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
void uno_set_esp_gps_mode(uint8_t mode) {
|
||||
@@ -106,12 +137,11 @@ void uno_set_can_mode(uint8_t mode){
|
||||
}
|
||||
}
|
||||
|
||||
void uno_set_bootkick(bool enabled){
|
||||
set_gpio_output(GPIOB, 14, !enabled);
|
||||
}
|
||||
|
||||
void uno_usb_power_mode_tick(uint64_t tcnt){
|
||||
if(tcnt == 3U){
|
||||
void uno_usb_power_mode_tick(uint32_t uptime){
|
||||
UNUSED(uptime);
|
||||
if(bootkick_timer != 0U){
|
||||
bootkick_timer--;
|
||||
} else {
|
||||
uno_set_bootkick(false);
|
||||
}
|
||||
}
|
||||
@@ -152,6 +182,9 @@ void uno_init(void) {
|
||||
set_gpio_mode(GPIOC, 0, MODE_ANALOG);
|
||||
set_gpio_mode(GPIOC, 3, MODE_ANALOG);
|
||||
|
||||
// Set default state of GPS
|
||||
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
|
||||
|
||||
// C10: OBD_SBU1_RELAY (harness relay driving output)
|
||||
// C11: OBD_SBU2_RELAY (harness relay driving output)
|
||||
set_gpio_mode(GPIOC, 10, MODE_OUTPUT);
|
||||
@@ -168,7 +201,7 @@ void uno_init(void) {
|
||||
uno_set_gps_load_switch(true);
|
||||
|
||||
// Turn on phone regulator
|
||||
set_gpio_output(GPIOB, 4, 1);
|
||||
uno_set_phone_power(true);
|
||||
|
||||
// Initialize IR PWM and set to 0%
|
||||
set_gpio_alternate(GPIOB, 7, GPIO_AF2_TIM4);
|
||||
@@ -212,7 +245,7 @@ void uno_init(void) {
|
||||
}
|
||||
|
||||
// Bootkick phone
|
||||
uno_set_bootkick(true);
|
||||
uno_bootkick();
|
||||
}
|
||||
|
||||
const harness_configuration uno_harness_config = {
|
||||
@@ -243,5 +276,6 @@ const board board_uno = {
|
||||
.check_ignition = uno_check_ignition,
|
||||
.read_current = uno_read_current,
|
||||
.set_fan_power = uno_set_fan_power,
|
||||
.set_ir_power = uno_set_ir_power
|
||||
.set_ir_power = uno_set_ir_power,
|
||||
.set_phone_power = uno_set_phone_power
|
||||
};
|
||||
|
||||
+32
-21
@@ -78,11 +78,13 @@ void white_set_esp_gps_mode(uint8_t mode) {
|
||||
set_gpio_output(GPIOC, 14, 0);
|
||||
set_gpio_output(GPIOC, 5, 0);
|
||||
break;
|
||||
#ifndef EON
|
||||
case ESP_GPS_ENABLED:
|
||||
// ESP ON
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 1);
|
||||
break;
|
||||
#endif
|
||||
case ESP_GPS_BOOTMODE:
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 0);
|
||||
@@ -156,8 +158,8 @@ uint32_t white_read_current(void){
|
||||
return adc_get(ADCCHAN_CURRENT);
|
||||
}
|
||||
|
||||
uint64_t marker = 0;
|
||||
void white_usb_power_mode_tick(uint64_t tcnt){
|
||||
uint32_t marker = 0;
|
||||
void white_usb_power_mode_tick(uint32_t uptime){
|
||||
|
||||
// on EON or BOOTSTUB, no state machine
|
||||
#if !defined(BOOTSTUB) && !defined(EON)
|
||||
@@ -171,47 +173,47 @@ void white_usb_power_mode_tick(uint64_t tcnt){
|
||||
|
||||
switch (usb_power_mode) {
|
||||
case USB_POWER_CLIENT:
|
||||
if ((tcnt - marker) >= CLICKS) {
|
||||
if ((uptime - marker) >= CLICKS) {
|
||||
if (!is_enumerated) {
|
||||
puts("USBP: didn't enumerate, switching to CDP mode\n");
|
||||
// switch to CDP
|
||||
white_set_usb_power_mode(USB_POWER_CDP);
|
||||
marker = tcnt;
|
||||
marker = uptime;
|
||||
}
|
||||
}
|
||||
// keep resetting the timer if it's enumerated
|
||||
if (is_enumerated) {
|
||||
marker = tcnt;
|
||||
marker = uptime;
|
||||
}
|
||||
break;
|
||||
case USB_POWER_CDP:
|
||||
// been CLICKS clicks since we switched to CDP
|
||||
if ((tcnt-marker) >= CLICKS) {
|
||||
if ((uptime - 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;
|
||||
marker = uptime;
|
||||
}
|
||||
}
|
||||
// keep resetting the timer if there's no current draw in CDP
|
||||
if (current >= CURRENT_THRESHOLD) {
|
||||
marker = tcnt;
|
||||
marker = uptime;
|
||||
}
|
||||
break;
|
||||
case USB_POWER_DCP:
|
||||
// been at least CLICKS clicks since we switched to DCP
|
||||
if ((tcnt-marker) >= CLICKS) {
|
||||
if ((uptime - marker) >= CLICKS) {
|
||||
// if no current draw, switch back to CDP
|
||||
if (current >= CURRENT_THRESHOLD) {
|
||||
puts("USBP: no current draw, switching back to CDP mode\n");
|
||||
white_set_usb_power_mode(USB_POWER_CDP);
|
||||
marker = tcnt;
|
||||
marker = uptime;
|
||||
}
|
||||
}
|
||||
// keep resetting the timer if there's current draw in DCP
|
||||
if (current < CURRENT_THRESHOLD) {
|
||||
marker = tcnt;
|
||||
marker = uptime;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -219,7 +221,7 @@ void white_usb_power_mode_tick(uint64_t tcnt){
|
||||
break;
|
||||
}
|
||||
#else
|
||||
UNUSED(tcnt);
|
||||
UNUSED(uptime);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -236,7 +238,11 @@ bool white_check_ignition(void){
|
||||
return !get_gpio_input(GPIOA, 1);
|
||||
}
|
||||
|
||||
void white_init(void) {
|
||||
void white_set_phone_power(bool enabled){
|
||||
UNUSED(enabled);
|
||||
}
|
||||
|
||||
void white_grey_common_init(void) {
|
||||
common_init_gpio();
|
||||
|
||||
// C3: current sense
|
||||
@@ -296,13 +302,6 @@ void white_init(void) {
|
||||
// Set normal CAN mode
|
||||
white_set_can_mode(CAN_MODE_NORMAL);
|
||||
|
||||
// Setup ignition interrupts
|
||||
SYSCFG->EXTICR[1] = SYSCFG_EXTICR1_EXTI1_PA;
|
||||
EXTI->IMR |= (1U << 1);
|
||||
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.
|
||||
@@ -314,6 +313,17 @@ void white_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void white_init(void) {
|
||||
white_grey_common_init();
|
||||
|
||||
// Set default state of ESP
|
||||
#ifdef EON
|
||||
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
|
||||
#else
|
||||
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
|
||||
#endif
|
||||
}
|
||||
|
||||
const harness_configuration white_harness_config = {
|
||||
.has_harness = false
|
||||
};
|
||||
@@ -332,5 +342,6 @@ const board board_white = {
|
||||
.check_ignition = white_check_ignition,
|
||||
.read_current = white_read_current,
|
||||
.set_fan_power = white_set_fan_power,
|
||||
.set_ir_power = white_set_ir_power
|
||||
.set_ir_power = white_set_ir_power,
|
||||
.set_phone_power = white_set_phone_power
|
||||
};
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#define BOOTSTUB
|
||||
|
||||
#define VERS_TAG 0x53524556
|
||||
#define MIN_VERSION 2
|
||||
|
||||
#include "config.h"
|
||||
#include "obj/gitversion.h"
|
||||
|
||||
@@ -29,7 +32,11 @@ const board *current_board;
|
||||
// ********************* Includes *********************
|
||||
#include "libc.h"
|
||||
#include "provision.h"
|
||||
#include "critical.h"
|
||||
#include "faults.h"
|
||||
|
||||
#include "drivers/registers.h"
|
||||
#include "drivers/interrupts.h"
|
||||
#include "drivers/clock.h"
|
||||
#include "drivers/llgpio.h"
|
||||
#include "drivers/adc.h"
|
||||
@@ -65,6 +72,9 @@ extern void *_app_start[];
|
||||
// BOUNTY: $200 coupon on shop.comma.ai or $100 check.
|
||||
|
||||
int main(void) {
|
||||
// Init interrupt table
|
||||
init_interrupts(true);
|
||||
|
||||
disable_interrupts();
|
||||
clock_init();
|
||||
detect_configuration();
|
||||
@@ -83,6 +93,13 @@ int main(void) {
|
||||
uint8_t digest[SHA_DIGEST_SIZE];
|
||||
SHA_hash(&_app_start[1], len-4, digest);
|
||||
|
||||
// verify version, last bytes in the signed area
|
||||
uint32_t vers[2] = {0};
|
||||
memcpy(&vers, ((void*)&_app_start[0]) + len - sizeof(vers), sizeof(vers));
|
||||
if (vers[0] != VERS_TAG || vers[1] < MIN_VERSION) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// verify RSA signature
|
||||
if (RSA_verify(&release_rsa_key, ((void*)&_app_start[0]) + len, RSANUMBYTES, digest, SHA_DIGEST_SIZE)) {
|
||||
goto good;
|
||||
|
||||
@@ -33,7 +33,7 @@ POSTCOMPILE = @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $@
|
||||
|
||||
# this no longer pushes the bootstub
|
||||
flash: obj/$(PROJ_NAME).bin
|
||||
PYTHONPATH=../ python -c "from python import Panda; Panda().flash('obj/$(PROJ_NAME).bin')"
|
||||
PYTHONPATH=../ python3 -c "from python import Panda; Panda().flash('obj/$(PROJ_NAME).bin')"
|
||||
|
||||
ota: obj/$(PROJ_NAME).bin
|
||||
curl http://192.168.0.10/stupdate --upload-file $<
|
||||
@@ -42,7 +42,7 @@ bin: obj/$(PROJ_NAME).bin
|
||||
|
||||
# this flashes everything
|
||||
recover: obj/bootstub.$(PROJ_NAME).bin obj/$(PROJ_NAME).bin
|
||||
-PYTHONPATH=../ python -c "from python import Panda; Panda().reset(enter_bootloader=True)"
|
||||
-PYTHONPATH=../ python3 -c "from python import Panda; Panda().reset(enter_bootloader=True)"
|
||||
sleep 1.0
|
||||
$(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08004000 -D obj/$(PROJ_NAME).bin
|
||||
$(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.$(PROJ_NAME).bin
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
//#define DEBUG_UART
|
||||
//#define DEBUG_USB
|
||||
//#define DEBUG_SPI
|
||||
//#define DEBUG_FAULTS
|
||||
|
||||
#ifdef STM32F4
|
||||
#define PANDA
|
||||
@@ -37,5 +38,8 @@
|
||||
|
||||
#define MAX_RESP_LEN 0x40U
|
||||
|
||||
// Around (1Mbps / 8 bits/byte / 12 bytes per message)
|
||||
#define CAN_INTERRUPT_RATE 12000U
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// ********************* Critical section helpers *********************
|
||||
volatile bool interrupts_enabled = false;
|
||||
|
||||
void enable_interrupts(void) {
|
||||
interrupts_enabled = true;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void disable_interrupts(void) {
|
||||
interrupts_enabled = false;
|
||||
__disable_irq();
|
||||
}
|
||||
|
||||
uint8_t global_critical_depth = 0U;
|
||||
#define ENTER_CRITICAL() \
|
||||
__disable_irq(); \
|
||||
global_critical_depth += 1U;
|
||||
|
||||
#define EXIT_CRITICAL() \
|
||||
global_critical_depth -= 1U; \
|
||||
if ((global_critical_depth == 0U) && interrupts_enabled) { \
|
||||
__enable_irq(); \
|
||||
}
|
||||
@@ -9,26 +9,16 @@
|
||||
#define ADCCHAN_CURRENT 13
|
||||
|
||||
void adc_init(void) {
|
||||
// global setup
|
||||
ADC->CCR = ADC_CCR_TSVREFE | ADC_CCR_VBATE;
|
||||
//ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_EOCS | ADC_CR2_DDS;
|
||||
ADC1->CR2 = ADC_CR2_ADON;
|
||||
|
||||
// long
|
||||
//ADC1->SMPR1 = ADC_SMPR1_SMP10 | ADC_SMPR1_SMP11 | ADC_SMPR1_SMP12 | ADC_SMPR1_SMP13;
|
||||
ADC1->SMPR1 = ADC_SMPR1_SMP12 | ADC_SMPR1_SMP13;
|
||||
register_set(&(ADC->CCR), ADC_CCR_TSVREFE | ADC_CCR_VBATE, 0xC30000U);
|
||||
register_set(&(ADC1->CR2), ADC_CR2_ADON, 0xFF7F0F03U);
|
||||
register_set(&(ADC1->SMPR1), ADC_SMPR1_SMP12 | ADC_SMPR1_SMP13, 0x7FFFFFFU);
|
||||
}
|
||||
|
||||
uint32_t adc_get(unsigned int channel) {
|
||||
// includes length
|
||||
//ADC1->SQR1 = 0;
|
||||
|
||||
// select channel
|
||||
ADC1->JSQR = channel << 15;
|
||||
|
||||
//ADC1->CR1 = ADC_CR1_DISCNUM_0;
|
||||
//ADC1->CR1 = ADC_CR1_EOCIE;
|
||||
// Select channel
|
||||
register_set(&(ADC1->JSQR), (channel << 15U), 0x3FFFFFU);
|
||||
|
||||
// Start conversion
|
||||
ADC1->SR &= ~(ADC_SR_JEOC);
|
||||
ADC1->CR2 |= ADC_CR2_JSWSTART;
|
||||
while (!(ADC1->SR & ADC_SR_JEOC));
|
||||
|
||||
+38
-32
@@ -27,11 +27,12 @@ void can_set_forwarding(int from, int to);
|
||||
|
||||
void can_init(uint8_t can_number);
|
||||
void can_init_all(void);
|
||||
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number);
|
||||
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number, bool skip_tx_hook);
|
||||
bool can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem);
|
||||
|
||||
// Ignition detected from CAN meessages
|
||||
bool ignition_can = false;
|
||||
uint32_t ignition_can_cnt = 0U;
|
||||
|
||||
// end API
|
||||
|
||||
@@ -148,23 +149,10 @@ void can_set_speed(uint8_t can_number) {
|
||||
}
|
||||
}
|
||||
|
||||
void can_init(uint8_t can_number) {
|
||||
if (can_number != 0xffU) {
|
||||
CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
|
||||
can_set_speed(can_number);
|
||||
|
||||
llcan_init(CAN);
|
||||
|
||||
// in case there are queued up messages
|
||||
process_can(can_number);
|
||||
}
|
||||
}
|
||||
|
||||
void can_init_all(void) {
|
||||
for (uint8_t i=0U; i < CAN_MAX; i++) {
|
||||
can_init(i);
|
||||
}
|
||||
current_board->enable_can_transcievers(true);
|
||||
}
|
||||
|
||||
void can_flip_buses(uint8_t bus1, uint8_t bus2){
|
||||
@@ -336,11 +324,12 @@ void process_can(uint8_t can_number) {
|
||||
}
|
||||
|
||||
void ignition_can_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
int len = GET_LEN(to_push);
|
||||
|
||||
ignition_can_cnt = 0U; // reset counter
|
||||
|
||||
if (bus == 0) {
|
||||
// GM exception
|
||||
if ((addr == 0x1F1) && (len == 8)) {
|
||||
@@ -357,11 +346,6 @@ void ignition_can_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// this message isn't all zeros when ignition is on
|
||||
ignition_can = GET_BYTES_04(to_push) != 0;
|
||||
}
|
||||
// VW exception
|
||||
if ((addr == 0x3C0) && (len == 4)) {
|
||||
// VW Terminal 15 (ignition-on) state
|
||||
ignition_can = (GET_BYTE(to_push, 2) & 0x2) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +378,7 @@ void can_rx(uint8_t can_number) {
|
||||
to_send.RDTR = to_push.RDTR;
|
||||
to_send.RDLR = to_push.RDLR;
|
||||
to_send.RDHR = to_push.RDHR;
|
||||
can_send(&to_send, bus_fwd_num);
|
||||
can_send(&to_send, bus_fwd_num, true);
|
||||
}
|
||||
|
||||
safety_rx_hook(&to_push);
|
||||
@@ -408,20 +392,20 @@ void can_rx(uint8_t can_number) {
|
||||
}
|
||||
}
|
||||
|
||||
void CAN1_TX_IRQHandler(void) { process_can(0); }
|
||||
void CAN1_RX0_IRQHandler(void) { can_rx(0); }
|
||||
void CAN1_SCE_IRQHandler(void) { can_sce(CAN1); }
|
||||
void CAN1_TX_IRQ_Handler(void) { process_can(0); }
|
||||
void CAN1_RX0_IRQ_Handler(void) { can_rx(0); }
|
||||
void CAN1_SCE_IRQ_Handler(void) { can_sce(CAN1); }
|
||||
|
||||
void CAN2_TX_IRQHandler(void) { process_can(1); }
|
||||
void CAN2_RX0_IRQHandler(void) { can_rx(1); }
|
||||
void CAN2_SCE_IRQHandler(void) { can_sce(CAN2); }
|
||||
void CAN2_TX_IRQ_Handler(void) { process_can(1); }
|
||||
void CAN2_RX0_IRQ_Handler(void) { can_rx(1); }
|
||||
void CAN2_SCE_IRQ_Handler(void) { can_sce(CAN2); }
|
||||
|
||||
void CAN3_TX_IRQHandler(void) { process_can(2); }
|
||||
void CAN3_RX0_IRQHandler(void) { can_rx(2); }
|
||||
void CAN3_SCE_IRQHandler(void) { can_sce(CAN3); }
|
||||
void CAN3_TX_IRQ_Handler(void) { process_can(2); }
|
||||
void CAN3_RX0_IRQ_Handler(void) { can_rx(2); }
|
||||
void CAN3_SCE_IRQ_Handler(void) { can_sce(CAN3); }
|
||||
|
||||
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) {
|
||||
if (safety_tx_hook(to_push) != 0) {
|
||||
void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number, bool skip_tx_hook) {
|
||||
if (skip_tx_hook || safety_tx_hook(to_push) != 0) {
|
||||
if (bus_number < BUS_MAX) {
|
||||
// add CAN packet to send queue
|
||||
// bus number isn't passed through
|
||||
@@ -440,3 +424,25 @@ void can_set_forwarding(int from, int to) {
|
||||
can_forwarding[from] = to;
|
||||
}
|
||||
|
||||
void can_init(uint8_t can_number) {
|
||||
REGISTER_INTERRUPT(CAN1_TX_IRQn, CAN1_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_RX0_IRQn, CAN1_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_SCE_IRQn, CAN1_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN2_TX_IRQn, CAN2_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
|
||||
REGISTER_INTERRUPT(CAN2_RX0_IRQn, CAN2_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
|
||||
REGISTER_INTERRUPT(CAN2_SCE_IRQn, CAN2_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_2)
|
||||
REGISTER_INTERRUPT(CAN3_TX_IRQn, CAN3_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
|
||||
REGISTER_INTERRUPT(CAN3_RX0_IRQn, CAN3_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
|
||||
REGISTER_INTERRUPT(CAN3_SCE_IRQn, CAN3_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_3)
|
||||
|
||||
if (can_number != 0xffU) {
|
||||
CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number);
|
||||
can_set_speed(can_number);
|
||||
|
||||
llcan_init(CAN);
|
||||
|
||||
// in case there are queued up messages
|
||||
process_can(can_number);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-12
@@ -1,25 +1,24 @@
|
||||
void clock_init(void) {
|
||||
// enable external oscillator
|
||||
RCC->CR |= RCC_CR_HSEON;
|
||||
register_set_bits(&(RCC->CR), RCC_CR_HSEON);
|
||||
while ((RCC->CR & RCC_CR_HSERDY) == 0);
|
||||
|
||||
// divide things
|
||||
RCC->CFGR = RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4;
|
||||
register_set(&(RCC->CFGR), RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4, 0xFF7FFCF3U);
|
||||
|
||||
// 16mhz crystal
|
||||
RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 |
|
||||
RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE;
|
||||
register_set(&(RCC->PLLCFGR), RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE, 0x7F437FFFU);
|
||||
|
||||
// start PLL
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
register_set_bits(&(RCC->CR), RCC_CR_PLLON);
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0);
|
||||
|
||||
// Configure Flash prefetch, Instruction cache, Data cache and wait state
|
||||
// *** without this, it breaks ***
|
||||
FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;
|
||||
register_set(&(FLASH->ACR), FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS, 0x1F0FU);
|
||||
|
||||
// switch to PLL
|
||||
RCC->CFGR |= RCC_CFGR_SW_PLL;
|
||||
register_set_bits(&(RCC->CFGR), RCC_CFGR_SW_PLL);
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
|
||||
|
||||
// *** running on PLL ***
|
||||
@@ -27,14 +26,15 @@ void clock_init(void) {
|
||||
|
||||
void watchdog_init(void) {
|
||||
// setup watchdog
|
||||
IWDG->KR = 0x5555;
|
||||
IWDG->PR = 0; // divider /4
|
||||
IWDG->KR = 0x5555U;
|
||||
register_set(&(IWDG->PR), 0x0U, 0x7U); // divider/4
|
||||
|
||||
// 0 = 0.125 ms, let's have a 50ms watchdog
|
||||
IWDG->RLR = 400 - 1;
|
||||
IWDG->KR = 0xCCCC;
|
||||
register_set(&(IWDG->RLR), (400U-1U), 0xFFFU);
|
||||
IWDG->KR = 0xCCCCU;
|
||||
}
|
||||
|
||||
void watchdog_feed(void) {
|
||||
IWDG->KR = 0xAAAA;
|
||||
IWDG->KR = 0xAAAAU;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,22 +2,19 @@ void puth(unsigned int i);
|
||||
void puts(const char *a);
|
||||
|
||||
void dac_init(void) {
|
||||
// no buffers required since we have an opamp
|
||||
//DAC->CR = DAC_CR_EN1 | DAC_CR_BOFF1 | DAC_CR_EN2 | DAC_CR_BOFF2;
|
||||
DAC->DHR12R1 = 0;
|
||||
DAC->DHR12R2 = 0;
|
||||
DAC->CR = DAC_CR_EN1 | DAC_CR_EN2;
|
||||
// No buffers required since we have an opamp
|
||||
register_set(&(DAC->DHR12R1), 0U, 0xFFFU);
|
||||
register_set(&(DAC->DHR12R2), 0U, 0xFFFU);
|
||||
register_set(&(DAC->CR), DAC_CR_EN1 | DAC_CR_EN2, 0x3FFF3FFFU);
|
||||
}
|
||||
|
||||
void dac_set(int channel, uint32_t value) {
|
||||
if (channel == 0) {
|
||||
DAC->DHR12R1 = value;
|
||||
register_set(&(DAC->DHR12R1), value, 0xFFFU);
|
||||
} else if (channel == 1) {
|
||||
DAC->DHR12R2 = value;
|
||||
register_set(&(DAC->DHR12R2), value, 0xFFFU);
|
||||
} else {
|
||||
puts("Failed to set DAC: invalid channel value: ");
|
||||
puth(value);
|
||||
puts("\n");
|
||||
puts("Failed to set DAC: invalid channel value: 0x"); puth(value); puts("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-13
@@ -1,15 +1,3 @@
|
||||
void fan_init(void){
|
||||
// Init PWM speed control
|
||||
pwm_init(TIM3, 3);
|
||||
|
||||
// Init TACH interrupt
|
||||
SYSCFG->EXTICR[0] = SYSCFG_EXTICR1_EXTI2_PD;
|
||||
EXTI->IMR |= (1U << 2);
|
||||
EXTI->RTSR |= (1U << 2);
|
||||
EXTI->FTSR |= (1U << 2);
|
||||
NVIC_EnableIRQ(EXTI2_IRQn);
|
||||
}
|
||||
|
||||
void fan_set_power(uint8_t percentage){
|
||||
pwm_set(TIM3, 3, percentage);
|
||||
}
|
||||
@@ -27,10 +15,25 @@ void fan_tick(void){
|
||||
}
|
||||
|
||||
// TACH interrupt handler
|
||||
void EXTI2_IRQHandler(void) {
|
||||
void EXTI2_IRQ_Handler(void) {
|
||||
volatile unsigned int pr = EXTI->PR & (1U << 2);
|
||||
if ((pr & (1U << 2)) != 0U) {
|
||||
fan_tach_counter++;
|
||||
}
|
||||
EXTI->PR = (1U << 2);
|
||||
}
|
||||
|
||||
void fan_init(void){
|
||||
// 5000RPM * 4 tach edges / 60 seconds
|
||||
REGISTER_INTERRUPT(EXTI2_IRQn, EXTI2_IRQ_Handler, 700U, FAULT_INTERRUPT_RATE_TACH)
|
||||
|
||||
// Init PWM speed control
|
||||
pwm_init(TIM3, 3);
|
||||
|
||||
// Init TACH interrupt
|
||||
register_set(&(SYSCFG->EXTICR[0]), SYSCFG_EXTICR1_EXTI2_PD, 0xF00U);
|
||||
register_set_bits(&(EXTI->IMR), (1U << 2));
|
||||
register_set_bits(&(EXTI->RTSR), (1U << 2));
|
||||
register_set_bits(&(EXTI->FTSR), (1U << 2));
|
||||
NVIC_EnableIRQ(EXTI2_IRQn);
|
||||
}
|
||||
@@ -124,15 +124,15 @@ int get_bit_message(char *out, CAN_FIFOMailBox_TypeDef *to_bang) {
|
||||
|
||||
void setup_timer4(void) {
|
||||
// setup
|
||||
TIM4->PSC = 48-1; // tick on 1 us
|
||||
TIM4->CR1 = TIM_CR1_CEN; // enable
|
||||
TIM4->ARR = 30-1; // 33.3 kbps
|
||||
register_set(&(TIM4->PSC), (48-1), 0xFFFFU); // Tick on 1 us
|
||||
register_set(&(TIM4->CR1), TIM_CR1_CEN, 0x3FU); // Enable
|
||||
register_set(&(TIM4->ARR), (30-1), 0xFFFFU); // 33.3 kbps
|
||||
|
||||
// in case it's disabled
|
||||
NVIC_EnableIRQ(TIM4_IRQn);
|
||||
|
||||
// run the interrupt
|
||||
TIM4->DIER = TIM_DIER_UIE; // update interrupt
|
||||
register_set(&(TIM4->DIER), TIM_DIER_UIE, 0x5F5FU); // Update interrupt
|
||||
TIM4->SR = 0;
|
||||
}
|
||||
|
||||
@@ -171,9 +171,9 @@ void reset_gmlan_switch_timeout(void) {
|
||||
|
||||
void set_bitbanged_gmlan(int val) {
|
||||
if (val != 0) {
|
||||
GPIOB->ODR |= (1U << 13);
|
||||
register_set_bits(&(GPIOB->ODR), (1U << 13));
|
||||
} else {
|
||||
GPIOB->ODR &= ~(1U << 13);
|
||||
register_clear_bits(&(GPIOB->ODR), (1U << 13));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ int gmlan_fail_count = 0;
|
||||
#define REQUIRED_SILENT_TIME 10
|
||||
#define MAX_FAIL_COUNT 10
|
||||
|
||||
void TIM4_IRQHandler(void) {
|
||||
void TIM4_IRQ_Handler(void) {
|
||||
if (gmlan_alt_mode == BITBANG) {
|
||||
if ((TIM4->SR & TIM_SR_UIF) && (gmlan_sendmax != -1)) {
|
||||
int read = get_gpio_input(GPIOB, 12);
|
||||
@@ -231,8 +231,8 @@ void TIM4_IRQHandler(void) {
|
||||
if ((gmlan_sending == gmlan_sendmax) || (gmlan_fail_count == MAX_FAIL_COUNT)) {
|
||||
set_bitbanged_gmlan(1); // recessive
|
||||
set_gpio_mode(GPIOB, 13, MODE_INPUT);
|
||||
TIM4->DIER = 0; // no update interrupt
|
||||
TIM4->CR1 = 0; // disable timer
|
||||
register_clear_bits(&(TIM4->DIER), TIM_DIER_UIE); // No update interrupt
|
||||
register_set(&(TIM4->CR1), 0U, 0x3FU); // Disable timer
|
||||
gmlan_sendmax = -1; // exit
|
||||
}
|
||||
}
|
||||
@@ -279,6 +279,8 @@ bool bitbang_gmlan(CAN_FIFOMailBox_TypeDef *to_bang) {
|
||||
set_bitbanged_gmlan(1); // recessive
|
||||
set_gpio_mode(GPIOB, 13, MODE_OUTPUT);
|
||||
|
||||
// 33kbps
|
||||
REGISTER_INTERRUPT(TIM4_IRQn, TIM4_IRQ_Handler, 40000U, FAULT_INTERRUPT_RATE_GMLAN)
|
||||
setup_timer4();
|
||||
}
|
||||
return gmlan_send_ok;
|
||||
|
||||
@@ -8,7 +8,7 @@ uint8_t car_harness_status = 0U;
|
||||
|
||||
struct harness_configuration {
|
||||
const bool has_harness;
|
||||
GPIO_TypeDef *GPIO_SBU1;
|
||||
GPIO_TypeDef *GPIO_SBU1;
|
||||
GPIO_TypeDef *GPIO_SBU2;
|
||||
GPIO_TypeDef *GPIO_relay_normal;
|
||||
GPIO_TypeDef *GPIO_relay_flipped;
|
||||
@@ -52,28 +52,6 @@ bool harness_check_ignition(void) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO: refactor to use harness config
|
||||
void harness_setup_ignition_interrupts(void){
|
||||
if(car_harness_status == HARNESS_STATUS_NORMAL){
|
||||
SYSCFG->EXTICR[0] = SYSCFG_EXTICR1_EXTI3_PC;
|
||||
EXTI->IMR |= (1U << 3);
|
||||
EXTI->RTSR |= (1U << 3);
|
||||
EXTI->FTSR |= (1U << 3);
|
||||
puts("setup interrupts: normal\n");
|
||||
} else if(car_harness_status == HARNESS_STATUS_FLIPPED) {
|
||||
SYSCFG->EXTICR[0] = SYSCFG_EXTICR1_EXTI0_PC;
|
||||
EXTI->IMR |= (1U << 0);
|
||||
EXTI->RTSR |= (1U << 0);
|
||||
EXTI->FTSR |= (1U << 0);
|
||||
NVIC_EnableIRQ(EXTI1_IRQn);
|
||||
puts("setup interrupts: flipped\n");
|
||||
} else {
|
||||
puts("tried to setup ignition interrupts without harness connected\n");
|
||||
}
|
||||
NVIC_EnableIRQ(EXTI0_IRQn);
|
||||
NVIC_EnableIRQ(EXTI3_IRQn);
|
||||
}
|
||||
|
||||
uint8_t harness_detect_orientation(void) {
|
||||
uint8_t ret = HARNESS_STATUS_NC;
|
||||
|
||||
@@ -117,14 +95,11 @@ void harness_init(void) {
|
||||
set_gpio_mode(current_board->harness_config->GPIO_SBU2, current_board->harness_config->pin_SBU2, MODE_INPUT);
|
||||
} else {
|
||||
set_gpio_mode(current_board->harness_config->GPIO_SBU1, current_board->harness_config->pin_SBU1, MODE_INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
// keep busses connected by default
|
||||
set_intercept_relay(false);
|
||||
|
||||
// setup ignition interrupts
|
||||
harness_setup_ignition_interrupts();
|
||||
} else {
|
||||
puts("failed to detect car harness!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
typedef struct interrupt {
|
||||
IRQn_Type irq_type;
|
||||
void (*handler)(void);
|
||||
uint32_t call_counter;
|
||||
uint32_t max_call_rate; // Call rate is defined as the amount of calls each second
|
||||
uint32_t call_rate_fault;
|
||||
} interrupt;
|
||||
|
||||
void unused_interrupt_handler(void) {
|
||||
// Something is wrong if this handler is called!
|
||||
puts("Unused interrupt handler called!\n");
|
||||
fault_occurred(FAULT_UNUSED_INTERRUPT_HANDLED);
|
||||
}
|
||||
|
||||
#define NUM_INTERRUPTS 102U // There are 102 external interrupt sources (see stm32f413.h)
|
||||
interrupt interrupts[NUM_INTERRUPTS];
|
||||
|
||||
#define REGISTER_INTERRUPT(irq_num, func_ptr, call_rate, rate_fault) \
|
||||
interrupts[irq_num].irq_type = irq_num; \
|
||||
interrupts[irq_num].handler = func_ptr; \
|
||||
interrupts[irq_num].call_counter = 0U; \
|
||||
interrupts[irq_num].max_call_rate = call_rate; \
|
||||
interrupts[irq_num].call_rate_fault = rate_fault;
|
||||
|
||||
bool check_interrupt_rate = false;
|
||||
|
||||
void handle_interrupt(IRQn_Type irq_type){
|
||||
interrupts[irq_type].call_counter++;
|
||||
interrupts[irq_type].handler();
|
||||
|
||||
// Check that the interrupts don't fire too often
|
||||
if(check_interrupt_rate && (interrupts[irq_type].call_counter > interrupts[irq_type].max_call_rate)){
|
||||
puts("Interrupt 0x"); puth(irq_type); puts(" fired too often (0x"); puth(interrupts[irq_type].call_counter); puts("/s)!\n");
|
||||
fault_occurred(interrupts[irq_type].call_rate_fault);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset interrupt counter every second
|
||||
void TIM6_DAC_IRQ_Handler(void) {
|
||||
if (TIM6->SR != 0) {
|
||||
for(uint16_t i=0U; i<NUM_INTERRUPTS; i++){
|
||||
interrupts[i].call_counter = 0U;
|
||||
}
|
||||
}
|
||||
TIM6->SR = 0;
|
||||
}
|
||||
|
||||
void init_interrupts(bool check_rate_limit){
|
||||
check_interrupt_rate = check_rate_limit;
|
||||
|
||||
for(uint16_t i=0U; i<NUM_INTERRUPTS; i++){
|
||||
interrupts[i].handler = unused_interrupt_handler;
|
||||
}
|
||||
|
||||
// Init timer 10 for a 1s interval
|
||||
register_set_bits(&(RCC->APB1ENR), RCC_APB1ENR_TIM6EN); // Enable interrupt timer peripheral
|
||||
REGISTER_INTERRUPT(TIM6_DAC_IRQn, TIM6_DAC_IRQ_Handler, 1, FAULT_INTERRUPT_RATE_INTERRUPTS)
|
||||
register_set(&(TIM6->PSC), (732-1), 0xFFFFU);
|
||||
register_set(&(TIM6->DIER), TIM_DIER_UIE, 0x5F5FU);
|
||||
register_set(&(TIM6->CR1), TIM_CR1_CEN, 0x3FU);
|
||||
TIM6->SR = 0;
|
||||
NVIC_EnableIRQ(TIM6_DAC_IRQn);
|
||||
}
|
||||
|
||||
// ********************* Bare interrupt handlers *********************
|
||||
// Only implemented the STM32F413 interrupts for now, the STM32F203 specific ones do not fall into the scope of SIL2
|
||||
|
||||
void WWDG_IRQHandler(void) {handle_interrupt(WWDG_IRQn);}
|
||||
void PVD_IRQHandler(void) {handle_interrupt(PVD_IRQn);}
|
||||
void TAMP_STAMP_IRQHandler(void) {handle_interrupt(TAMP_STAMP_IRQn);}
|
||||
void RTC_WKUP_IRQHandler(void) {handle_interrupt(RTC_WKUP_IRQn);}
|
||||
void FLASH_IRQHandler(void) {handle_interrupt(FLASH_IRQn);}
|
||||
void RCC_IRQHandler(void) {handle_interrupt(RCC_IRQn);}
|
||||
void EXTI0_IRQHandler(void) {handle_interrupt(EXTI0_IRQn);}
|
||||
void EXTI1_IRQHandler(void) {handle_interrupt(EXTI1_IRQn);}
|
||||
void EXTI2_IRQHandler(void) {handle_interrupt(EXTI2_IRQn);}
|
||||
void EXTI3_IRQHandler(void) {handle_interrupt(EXTI3_IRQn);}
|
||||
void EXTI4_IRQHandler(void) {handle_interrupt(EXTI4_IRQn);}
|
||||
void DMA1_Stream0_IRQHandler(void) {handle_interrupt(DMA1_Stream0_IRQn);}
|
||||
void DMA1_Stream1_IRQHandler(void) {handle_interrupt(DMA1_Stream1_IRQn);}
|
||||
void DMA1_Stream2_IRQHandler(void) {handle_interrupt(DMA1_Stream2_IRQn);}
|
||||
void DMA1_Stream3_IRQHandler(void) {handle_interrupt(DMA1_Stream3_IRQn);}
|
||||
void DMA1_Stream4_IRQHandler(void) {handle_interrupt(DMA1_Stream4_IRQn);}
|
||||
void DMA1_Stream5_IRQHandler(void) {handle_interrupt(DMA1_Stream5_IRQn);}
|
||||
void DMA1_Stream6_IRQHandler(void) {handle_interrupt(DMA1_Stream6_IRQn);}
|
||||
void ADC_IRQHandler(void) {handle_interrupt(ADC_IRQn);}
|
||||
void CAN1_TX_IRQHandler(void) {handle_interrupt(CAN1_TX_IRQn);}
|
||||
void CAN1_RX0_IRQHandler(void) {handle_interrupt(CAN1_RX0_IRQn);}
|
||||
void CAN1_RX1_IRQHandler(void) {handle_interrupt(CAN1_RX1_IRQn);}
|
||||
void CAN1_SCE_IRQHandler(void) {handle_interrupt(CAN1_SCE_IRQn);}
|
||||
void EXTI9_5_IRQHandler(void) {handle_interrupt(EXTI9_5_IRQn);}
|
||||
void TIM1_BRK_TIM9_IRQHandler(void) {handle_interrupt(TIM1_BRK_TIM9_IRQn);}
|
||||
void TIM1_UP_TIM10_IRQHandler(void) {handle_interrupt(TIM1_UP_TIM10_IRQn);}
|
||||
void TIM1_TRG_COM_TIM11_IRQHandler(void) {handle_interrupt(TIM1_TRG_COM_TIM11_IRQn);}
|
||||
void TIM1_CC_IRQHandler(void) {handle_interrupt(TIM1_CC_IRQn);}
|
||||
void TIM2_IRQHandler(void) {handle_interrupt(TIM2_IRQn);}
|
||||
void TIM3_IRQHandler(void) {handle_interrupt(TIM3_IRQn);}
|
||||
void TIM4_IRQHandler(void) {handle_interrupt(TIM4_IRQn);}
|
||||
void I2C1_EV_IRQHandler(void) {handle_interrupt(I2C1_EV_IRQn);}
|
||||
void I2C1_ER_IRQHandler(void) {handle_interrupt(I2C1_ER_IRQn);}
|
||||
void I2C2_EV_IRQHandler(void) {handle_interrupt(I2C2_EV_IRQn);}
|
||||
void I2C2_ER_IRQHandler(void) {handle_interrupt(I2C2_ER_IRQn);}
|
||||
void SPI1_IRQHandler(void) {handle_interrupt(SPI1_IRQn);}
|
||||
void SPI2_IRQHandler(void) {handle_interrupt(SPI2_IRQn);}
|
||||
void USART1_IRQHandler(void) {handle_interrupt(USART1_IRQn);}
|
||||
void USART2_IRQHandler(void) {handle_interrupt(USART2_IRQn);}
|
||||
void USART3_IRQHandler(void) {handle_interrupt(USART3_IRQn);}
|
||||
void EXTI15_10_IRQHandler(void) {handle_interrupt(EXTI15_10_IRQn);}
|
||||
void RTC_Alarm_IRQHandler(void) {handle_interrupt(RTC_Alarm_IRQn);}
|
||||
void OTG_FS_WKUP_IRQHandler(void) {handle_interrupt(OTG_FS_WKUP_IRQn);}
|
||||
void TIM8_BRK_TIM12_IRQHandler(void) {handle_interrupt(TIM8_BRK_TIM12_IRQn);}
|
||||
void TIM8_UP_TIM13_IRQHandler(void) {handle_interrupt(TIM8_UP_TIM13_IRQn);}
|
||||
void TIM8_TRG_COM_TIM14_IRQHandler(void) {handle_interrupt(TIM8_TRG_COM_TIM14_IRQn);}
|
||||
void TIM8_CC_IRQHandler(void) {handle_interrupt(TIM8_CC_IRQn);}
|
||||
void DMA1_Stream7_IRQHandler(void) {handle_interrupt(DMA1_Stream7_IRQn);}
|
||||
void FSMC_IRQHandler(void) {handle_interrupt(FSMC_IRQn);}
|
||||
void SDIO_IRQHandler(void) {handle_interrupt(SDIO_IRQn);}
|
||||
void TIM5_IRQHandler(void) {handle_interrupt(TIM5_IRQn);}
|
||||
void SPI3_IRQHandler(void) {handle_interrupt(SPI3_IRQn);}
|
||||
void UART4_IRQHandler(void) {handle_interrupt(UART4_IRQn);}
|
||||
void UART5_IRQHandler(void) {handle_interrupt(UART5_IRQn);}
|
||||
void TIM6_DAC_IRQHandler(void) {handle_interrupt(TIM6_DAC_IRQn);}
|
||||
void TIM7_IRQHandler(void) {handle_interrupt(TIM7_IRQn);}
|
||||
void DMA2_Stream0_IRQHandler(void) {handle_interrupt(DMA2_Stream0_IRQn);}
|
||||
void DMA2_Stream1_IRQHandler(void) {handle_interrupt(DMA2_Stream1_IRQn);}
|
||||
void DMA2_Stream2_IRQHandler(void) {handle_interrupt(DMA2_Stream2_IRQn);}
|
||||
void DMA2_Stream3_IRQHandler(void) {handle_interrupt(DMA2_Stream3_IRQn);}
|
||||
void DMA2_Stream4_IRQHandler(void) {handle_interrupt(DMA2_Stream4_IRQn);}
|
||||
void CAN2_TX_IRQHandler(void) {handle_interrupt(CAN2_TX_IRQn);}
|
||||
void CAN2_RX0_IRQHandler(void) {handle_interrupt(CAN2_RX0_IRQn);}
|
||||
void CAN2_RX1_IRQHandler(void) {handle_interrupt(CAN2_RX1_IRQn);}
|
||||
void CAN2_SCE_IRQHandler(void) {handle_interrupt(CAN2_SCE_IRQn);}
|
||||
void OTG_FS_IRQHandler(void) {handle_interrupt(OTG_FS_IRQn);}
|
||||
void DMA2_Stream5_IRQHandler(void) {handle_interrupt(DMA2_Stream5_IRQn);}
|
||||
void DMA2_Stream6_IRQHandler(void) {handle_interrupt(DMA2_Stream6_IRQn);}
|
||||
void DMA2_Stream7_IRQHandler(void) {handle_interrupt(DMA2_Stream7_IRQn);}
|
||||
void USART6_IRQHandler(void) {handle_interrupt(USART6_IRQn);}
|
||||
void I2C3_EV_IRQHandler(void) {handle_interrupt(I2C3_EV_IRQn);}
|
||||
void I2C3_ER_IRQHandler(void) {handle_interrupt(I2C3_ER_IRQn);}
|
||||
#ifdef STM32F4
|
||||
void DFSDM1_FLT0_IRQHandler(void) {handle_interrupt(DFSDM1_FLT0_IRQn);}
|
||||
void DFSDM1_FLT1_IRQHandler(void) {handle_interrupt(DFSDM1_FLT1_IRQn);}
|
||||
void CAN3_TX_IRQHandler(void) {handle_interrupt(CAN3_TX_IRQn);}
|
||||
void CAN3_RX0_IRQHandler(void) {handle_interrupt(CAN3_RX0_IRQn);}
|
||||
void CAN3_RX1_IRQHandler(void) {handle_interrupt(CAN3_RX1_IRQn);}
|
||||
void CAN3_SCE_IRQHandler(void) {handle_interrupt(CAN3_SCE_IRQn);}
|
||||
void RNG_IRQHandler(void) {handle_interrupt(RNG_IRQn);}
|
||||
void FPU_IRQHandler(void) {handle_interrupt(FPU_IRQn);}
|
||||
void UART7_IRQHandler(void) {handle_interrupt(UART7_IRQn);}
|
||||
void UART8_IRQHandler(void) {handle_interrupt(UART8_IRQn);}
|
||||
void SPI4_IRQHandler(void) {handle_interrupt(SPI4_IRQn);}
|
||||
void SPI5_IRQHandler(void) {handle_interrupt(SPI5_IRQn);}
|
||||
void SAI1_IRQHandler(void) {handle_interrupt(SAI1_IRQn);}
|
||||
void UART9_IRQHandler(void) {handle_interrupt(UART9_IRQn);}
|
||||
void UART10_IRQHandler(void) {handle_interrupt(UART10_IRQn);}
|
||||
void QUADSPI_IRQHandler(void) {handle_interrupt(QUADSPI_IRQn);}
|
||||
void FMPI2C1_EV_IRQHandler(void) {handle_interrupt(FMPI2C1_EV_IRQn);}
|
||||
void FMPI2C1_ER_IRQHandler(void) {handle_interrupt(FMPI2C1_ER_IRQn);}
|
||||
void LPTIM1_IRQHandler(void) {handle_interrupt(LPTIM1_IRQn);}
|
||||
void DFSDM2_FLT0_IRQHandler(void) {handle_interrupt(DFSDM2_FLT0_IRQn);}
|
||||
void DFSDM2_FLT1_IRQHandler(void) {handle_interrupt(DFSDM2_FLT1_IRQn);}
|
||||
void DFSDM2_FLT2_IRQHandler(void) {handle_interrupt(DFSDM2_FLT2_IRQn);}
|
||||
void DFSDM2_FLT3_IRQHandler(void) {handle_interrupt(DFSDM2_FLT3_IRQn);}
|
||||
#endif
|
||||
+20
-16
@@ -19,25 +19,24 @@ void puts(const char *a);
|
||||
|
||||
bool llcan_set_speed(CAN_TypeDef *CAN_obj, uint32_t speed, bool loopback, bool silent) {
|
||||
// initialization mode
|
||||
CAN_obj->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ;
|
||||
register_set(&(CAN_obj->MCR), CAN_MCR_TTCM | CAN_MCR_INRQ, 0x180FFU);
|
||||
while((CAN_obj->MSR & CAN_MSR_INAK) != CAN_MSR_INAK);
|
||||
|
||||
// set time quanta from defines
|
||||
CAN_obj->BTR = (CAN_BTR_TS1_0 * (CAN_SEQ1-1)) |
|
||||
register_set(&(CAN_obj->BTR), ((CAN_BTR_TS1_0 * (CAN_SEQ1-1)) |
|
||||
(CAN_BTR_TS2_0 * (CAN_SEQ2-1)) |
|
||||
(can_speed_to_prescaler(speed) - 1U);
|
||||
(can_speed_to_prescaler(speed) - 1U)), 0xC37F03FFU);
|
||||
|
||||
// silent loopback mode for debugging
|
||||
if (loopback) {
|
||||
CAN_obj->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM;
|
||||
register_set_bits(&(CAN_obj->BTR), CAN_BTR_SILM | CAN_BTR_LBKM);
|
||||
}
|
||||
if (silent) {
|
||||
CAN_obj->BTR |= CAN_BTR_SILM;
|
||||
register_set_bits(&(CAN_obj->BTR), CAN_BTR_SILM);
|
||||
}
|
||||
|
||||
// reset
|
||||
// cppcheck-suppress redundantAssignment ; it's a register
|
||||
CAN_obj->MCR = CAN_MCR_TTCM | CAN_MCR_ABOM;
|
||||
register_set(&(CAN_obj->MCR), CAN_MCR_TTCM | CAN_MCR_ABOM, 0x180FFU);
|
||||
|
||||
#define CAN_TIMEOUT 1000000
|
||||
int tmp = 0;
|
||||
@@ -51,20 +50,25 @@ bool llcan_set_speed(CAN_TypeDef *CAN_obj, uint32_t speed, bool loopback, bool s
|
||||
}
|
||||
|
||||
void llcan_init(CAN_TypeDef *CAN_obj) {
|
||||
// accept all filter
|
||||
CAN_obj->FMR |= CAN_FMR_FINIT;
|
||||
// Enter init mode
|
||||
register_set_bits(&(CAN_obj->FMR), CAN_FMR_FINIT);
|
||||
|
||||
// Wait for INAK bit to be set
|
||||
while(((CAN_obj->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)) {}
|
||||
|
||||
// no mask
|
||||
CAN_obj->sFilterRegister[0].FR1 = 0;
|
||||
CAN_obj->sFilterRegister[0].FR2 = 0;
|
||||
CAN_obj->sFilterRegister[14].FR1 = 0;
|
||||
CAN_obj->sFilterRegister[14].FR2 = 0;
|
||||
// For some weird reason some of these registers do not want to set properly on CAN2 and CAN3. Probably something to do with the single/dual mode and their different filters.
|
||||
CAN_obj->sFilterRegister[0].FR1 = 0U;
|
||||
CAN_obj->sFilterRegister[0].FR2 = 0U;
|
||||
CAN_obj->sFilterRegister[14].FR1 = 0U;
|
||||
CAN_obj->sFilterRegister[14].FR2 = 0U;
|
||||
CAN_obj->FA1R |= 1U | (1U << 14);
|
||||
|
||||
CAN_obj->FMR &= ~(CAN_FMR_FINIT);
|
||||
// Exit init mode, do not wait
|
||||
register_clear_bits(&(CAN_obj->FMR), CAN_FMR_FINIT);
|
||||
|
||||
// enable certain CAN interrupts
|
||||
CAN_obj->IER |= CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_WKUIE;
|
||||
register_set_bits(&(CAN_obj->IER), CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_WKUIE);
|
||||
|
||||
if (CAN_obj == CAN1) {
|
||||
NVIC_EnableIRQ(CAN1_TX_IRQn);
|
||||
@@ -87,7 +91,7 @@ void llcan_init(CAN_TypeDef *CAN_obj) {
|
||||
|
||||
void llcan_clear_send(CAN_TypeDef *CAN_obj) {
|
||||
CAN_obj->TSR |= CAN_TSR_ABRQ0;
|
||||
CAN_obj->MSR &= ~(CAN_MSR_ERRI);
|
||||
register_clear_bits(&(CAN_obj->MSR), CAN_MSR_ERRI);
|
||||
// cppcheck-suppress selfAssignment ; needed to clear the register
|
||||
CAN_obj->MSR = CAN_obj->MSR;
|
||||
}
|
||||
|
||||
@@ -15,16 +15,16 @@ void set_gpio_mode(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode) {
|
||||
uint32_t tmp = GPIO->MODER;
|
||||
tmp &= ~(3U << (pin * 2U));
|
||||
tmp |= (mode << (pin * 2U));
|
||||
GPIO->MODER = tmp;
|
||||
register_set(&(GPIO->MODER), tmp, 0xFFFFFFFFU);
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void set_gpio_output(GPIO_TypeDef *GPIO, unsigned int pin, bool enabled) {
|
||||
ENTER_CRITICAL();
|
||||
if (enabled) {
|
||||
GPIO->ODR |= (1U << pin);
|
||||
register_set_bits(&(GPIO->ODR), (1U << pin));
|
||||
} else {
|
||||
GPIO->ODR &= ~(1U << pin);
|
||||
register_clear_bits(&(GPIO->ODR), (1U << pin));
|
||||
}
|
||||
set_gpio_mode(GPIO, pin, MODE_OUTPUT);
|
||||
EXIT_CRITICAL();
|
||||
@@ -33,9 +33,9 @@ void set_gpio_output(GPIO_TypeDef *GPIO, unsigned int pin, bool enabled) {
|
||||
void set_gpio_output_type(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int output_type){
|
||||
ENTER_CRITICAL();
|
||||
if(output_type == OUTPUT_TYPE_OPEN_DRAIN) {
|
||||
GPIO->OTYPER |= (1U << pin);
|
||||
register_set_bits(&(GPIO->OTYPER), (1U << pin));
|
||||
} else {
|
||||
GPIO->OTYPER &= ~(1U << pin);
|
||||
register_clear_bits(&(GPIO->OTYPER), (1U << pin));
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
@@ -45,7 +45,7 @@ void set_gpio_alternate(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode)
|
||||
uint32_t tmp = GPIO->AFR[pin >> 3U];
|
||||
tmp &= ~(0xFU << ((pin & 7U) * 4U));
|
||||
tmp |= mode << ((pin & 7U) * 4U);
|
||||
GPIO->AFR[pin >> 3] = tmp;
|
||||
register_set(&(GPIO->AFR[pin >> 3]), tmp, 0xFFFFFFFFU);
|
||||
set_gpio_mode(GPIO, pin, MODE_ALTERNATE);
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
@@ -55,7 +55,7 @@ void set_gpio_pullup(GPIO_TypeDef *GPIO, unsigned int pin, unsigned int mode) {
|
||||
uint32_t tmp = GPIO->PUPDR;
|
||||
tmp &= ~(3U << (pin * 2U));
|
||||
tmp |= (mode << (pin * 2U));
|
||||
GPIO->PUPDR = tmp;
|
||||
register_set(&(GPIO->PUPDR), tmp, 0xFFFFFFFFU);
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
|
||||
+16
-15
@@ -1,53 +1,54 @@
|
||||
#define PWM_COUNTER_OVERFLOW 2000U // To get ~50kHz
|
||||
|
||||
// TODO: Implement for 32-bit timers
|
||||
|
||||
void pwm_init(TIM_TypeDef *TIM, uint8_t channel){
|
||||
// Enable timer and auto-reload
|
||||
TIM->CR1 = TIM_CR1_CEN | TIM_CR1_ARPE;
|
||||
register_set(&(TIM->CR1), TIM_CR1_CEN | TIM_CR1_ARPE, 0x3FU);
|
||||
|
||||
// Set channel as PWM mode 1 and enable output
|
||||
switch(channel){
|
||||
case 1U:
|
||||
TIM->CCMR1 |= (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE);
|
||||
TIM->CCER |= TIM_CCER_CC1E;
|
||||
register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE));
|
||||
register_set_bits(&(TIM->CCER), TIM_CCER_CC1E);
|
||||
break;
|
||||
case 2U:
|
||||
TIM->CCMR1 |= (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE);
|
||||
TIM->CCER |= TIM_CCER_CC2E;
|
||||
register_set_bits(&(TIM->CCMR1), (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE));
|
||||
register_set_bits(&(TIM->CCER), TIM_CCER_CC2E);
|
||||
break;
|
||||
case 3U:
|
||||
TIM->CCMR2 |= (TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE);
|
||||
TIM->CCER |= TIM_CCER_CC3E;
|
||||
register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3PE));
|
||||
register_set_bits(&(TIM->CCER), TIM_CCER_CC3E);
|
||||
break;
|
||||
case 4U:
|
||||
TIM->CCMR2 |= (TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4PE);
|
||||
TIM->CCER |= TIM_CCER_CC4E;
|
||||
register_set_bits(&(TIM->CCMR2), (TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4PE));
|
||||
register_set_bits(&(TIM->CCER), TIM_CCER_CC4E);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Set max counter value
|
||||
TIM->ARR = PWM_COUNTER_OVERFLOW;
|
||||
register_set(&(TIM->ARR), PWM_COUNTER_OVERFLOW, 0xFFFFU);
|
||||
|
||||
// Update registers and clear counter
|
||||
TIM->EGR |= TIM_EGR_UG;
|
||||
}
|
||||
|
||||
// TODO: Implement for 32-bit timers
|
||||
void pwm_set(TIM_TypeDef *TIM, uint8_t channel, uint8_t percentage){
|
||||
uint16_t comp_value = (((uint16_t) percentage * PWM_COUNTER_OVERFLOW) / 100U);
|
||||
switch(channel){
|
||||
case 1U:
|
||||
TIM->CCR1 = comp_value;
|
||||
register_set(&(TIM->CCR1), comp_value, 0xFFFFU);
|
||||
break;
|
||||
case 2U:
|
||||
TIM->CCR2 = comp_value;
|
||||
register_set(&(TIM->CCR2), comp_value, 0xFFFFU);
|
||||
break;
|
||||
case 3U:
|
||||
TIM->CCR3 = comp_value;
|
||||
register_set(&(TIM->CCR3), comp_value, 0xFFFFU);
|
||||
break;
|
||||
case 4U:
|
||||
TIM->CCR4 = comp_value;
|
||||
register_set(&(TIM->CCR4), comp_value, 0xFFFFU);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
|
||||
typedef struct reg {
|
||||
volatile uint32_t *address;
|
||||
uint32_t value;
|
||||
uint32_t check_mask;
|
||||
} reg;
|
||||
|
||||
// 10 bit hash with 23 as a prime
|
||||
#define REGISTER_MAP_SIZE 0x3FFU
|
||||
#define HASHING_PRIME 23U
|
||||
#define CHECK_COLLISION(hash, addr) (((uint32_t) register_map[hash].address != 0U) && (register_map[hash].address != addr))
|
||||
|
||||
reg register_map[REGISTER_MAP_SIZE];
|
||||
|
||||
// Hash spread in first and second iterations seems to be reasonable.
|
||||
// See: tests/development/register_hashmap_spread.py
|
||||
// Also, check the collision warnings in the debug output, and minimize those.
|
||||
uint16_t hash_addr(uint32_t input){
|
||||
return (((input >> 16U) ^ ((((input + 1U) & 0xFFFFU) * HASHING_PRIME) & 0xFFFFU)) & REGISTER_MAP_SIZE);
|
||||
}
|
||||
|
||||
// Do not put bits in the check mask that get changed by the hardware
|
||||
void register_set(volatile uint32_t *addr, uint32_t val, uint32_t mask){
|
||||
ENTER_CRITICAL()
|
||||
// Set bits in register that are also in the mask
|
||||
(*addr) = ((*addr) & (~mask)) | (val & mask);
|
||||
|
||||
// Add these values to the map
|
||||
uint16_t hash = hash_addr((uint32_t) addr);
|
||||
uint16_t tries = REGISTER_MAP_SIZE;
|
||||
while(CHECK_COLLISION(hash, addr) && (tries > 0U)) { hash = hash_addr((uint32_t) hash); tries--;}
|
||||
if (tries != 0U){
|
||||
register_map[hash].address = addr;
|
||||
register_map[hash].value = (register_map[hash].value & (~mask)) | (val & mask);
|
||||
register_map[hash].check_mask |= mask;
|
||||
} else {
|
||||
#ifdef DEBUG_FAULTS
|
||||
puts("Hash collision: address 0x"); puth((uint32_t) addr); puts("!\n");
|
||||
#endif
|
||||
}
|
||||
EXIT_CRITICAL()
|
||||
}
|
||||
|
||||
// Set individual bits. Also add them to the check_mask.
|
||||
// Do not use this to change bits that get reset by the hardware
|
||||
void register_set_bits(volatile uint32_t *addr, uint32_t val) {
|
||||
return register_set(addr, val, val);
|
||||
}
|
||||
|
||||
// Clear individual bits. Also add them to the check_mask.
|
||||
// Do not use this to clear bits that get set by the hardware
|
||||
void register_clear_bits(volatile uint32_t *addr, uint32_t val) {
|
||||
return register_set(addr, (~val), val);
|
||||
}
|
||||
|
||||
// To be called periodically
|
||||
void check_registers(void){
|
||||
for(uint16_t i=0U; i<REGISTER_MAP_SIZE; i++){
|
||||
if((uint32_t) register_map[i].address != 0U){
|
||||
ENTER_CRITICAL()
|
||||
if((*(register_map[i].address) & register_map[i].check_mask) != (register_map[i].value & register_map[i].check_mask)){
|
||||
#ifdef DEBUG_FAULTS
|
||||
puts("Register at address 0x"); puth((uint32_t) register_map[i].address); puts(" is divergent!");
|
||||
puts(" Map: 0x"); puth(register_map[i].value);
|
||||
puts(" Register: 0x"); puth(*(register_map[i].address));
|
||||
puts(" Mask: 0x"); puth(register_map[i].check_mask);
|
||||
puts("\n");
|
||||
#endif
|
||||
fault_occurred(FAULT_REGISTER_DIVERGENT);
|
||||
}
|
||||
EXIT_CRITICAL()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_registers(void) {
|
||||
for(uint16_t i=0U; i<REGISTER_MAP_SIZE; i++){
|
||||
register_map[i].address = (volatile uint32_t *) 0U;
|
||||
register_map[i].check_mask = 0U;
|
||||
}
|
||||
}
|
||||
+10
-10
@@ -27,19 +27,19 @@ void rtc_init(void){
|
||||
if((RCC->BDCR & RCC_BDCR_MASK) != RCC_BDCR_OPTIONS){
|
||||
puts("Initializing RTC\n");
|
||||
// Reset backup domain
|
||||
RCC->BDCR |= RCC_BDCR_BDRST;
|
||||
register_set_bits(&(RCC->BDCR), RCC_BDCR_BDRST);
|
||||
|
||||
// Disable write protection
|
||||
PWR->CR |= PWR_CR_DBP;
|
||||
register_set_bits(&(PWR->CR), PWR_CR_DBP);
|
||||
|
||||
// Clear backup domain reset
|
||||
RCC->BDCR &= ~(RCC_BDCR_BDRST);
|
||||
register_clear_bits(&(RCC->BDCR), RCC_BDCR_BDRST);
|
||||
|
||||
// Set RTC options
|
||||
RCC->BDCR = RCC_BDCR_OPTIONS | (RCC->BDCR & (~RCC_BDCR_MASK));
|
||||
register_set(&(RCC->BDCR), RCC_BDCR_OPTIONS, RCC_BDCR_MASK);
|
||||
|
||||
// Enable write protection
|
||||
PWR->CR &= ~(PWR_CR_DBP);
|
||||
register_clear_bits(&(PWR->CR), PWR_CR_DBP);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,12 +49,12 @@ void rtc_set_time(timestamp_t time){
|
||||
puts("Setting RTC time\n");
|
||||
|
||||
// Disable write protection
|
||||
PWR->CR |= PWR_CR_DBP;
|
||||
register_set_bits(&(PWR->CR), PWR_CR_DBP);
|
||||
RTC->WPR = 0xCA;
|
||||
RTC->WPR = 0x53;
|
||||
|
||||
// Enable initialization mode
|
||||
RTC->ISR |= RTC_ISR_INIT;
|
||||
register_set_bits(&(RTC->ISR), RTC_ISR_INIT);
|
||||
while((RTC->ISR & RTC_ISR_INITF) == 0){}
|
||||
|
||||
// Set time
|
||||
@@ -62,17 +62,17 @@ void rtc_set_time(timestamp_t time){
|
||||
RTC->DR = (to_bcd(time.year - YEAR_OFFSET) << RTC_DR_YU_Pos) | (time.weekday << RTC_DR_WDU_Pos) | (to_bcd(time.month) << RTC_DR_MU_Pos) | (to_bcd(time.day) << RTC_DR_DU_Pos);
|
||||
|
||||
// Set options
|
||||
RTC->CR = 0U;
|
||||
register_set(&(RTC->CR), 0U, 0xFCFFFFU);
|
||||
|
||||
// Disable initalization mode
|
||||
RTC->ISR &= ~(RTC_ISR_INIT);
|
||||
register_clear_bits(&(RTC->ISR), RTC_ISR_INIT);
|
||||
|
||||
// Wait for synchronization
|
||||
while((RTC->ISR & RTC_ISR_RSF) == 0){}
|
||||
|
||||
// Re-enable write protection
|
||||
RTC->WPR = 0x00;
|
||||
PWR->CR &= ~(PWR_CR_DBP);
|
||||
register_clear_bits(&(PWR->CR), PWR_CR_DBP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+45
-41
@@ -10,45 +10,22 @@ uint8_t spi_buf[SPI_BUF_SIZE];
|
||||
int spi_buf_count = 0;
|
||||
int spi_total_count = 0;
|
||||
|
||||
void spi_init(void) {
|
||||
//puts("SPI init\n");
|
||||
SPI1->CR1 = SPI_CR1_SPE;
|
||||
|
||||
// enable SPI interrupts
|
||||
//SPI1->CR2 = SPI_CR2_RXNEIE | SPI_CR2_ERRIE | SPI_CR2_TXEIE;
|
||||
SPI1->CR2 = SPI_CR2_RXNEIE;
|
||||
|
||||
NVIC_EnableIRQ(DMA2_Stream2_IRQn);
|
||||
NVIC_EnableIRQ(DMA2_Stream3_IRQn);
|
||||
//NVIC_EnableIRQ(SPI1_IRQn);
|
||||
|
||||
// reset handshake back to pull up
|
||||
set_gpio_mode(GPIOB, 0, MODE_INPUT);
|
||||
set_gpio_pullup(GPIOB, 0, PULL_UP);
|
||||
|
||||
// setup interrupt on falling edge of SPI enable (on PA4)
|
||||
SYSCFG->EXTICR[2] = SYSCFG_EXTICR2_EXTI4_PA;
|
||||
EXTI->IMR |= (1U << 4);
|
||||
EXTI->FTSR |= (1U << 4);
|
||||
NVIC_EnableIRQ(EXTI4_IRQn);
|
||||
}
|
||||
|
||||
void spi_tx_dma(void *addr, int len) {
|
||||
// disable DMA
|
||||
SPI1->CR2 &= ~SPI_CR2_TXDMAEN;
|
||||
DMA2_Stream3->CR &= ~DMA_SxCR_EN;
|
||||
register_clear_bits(&(SPI1->CR2), SPI_CR2_TXDMAEN);
|
||||
register_clear_bits(&(DMA2_Stream3->CR), DMA_SxCR_EN);
|
||||
|
||||
// DMA2, stream 3, channel 3
|
||||
DMA2_Stream3->M0AR = (uint32_t)addr;
|
||||
register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU);
|
||||
DMA2_Stream3->NDTR = len;
|
||||
DMA2_Stream3->PAR = (uint32_t)&(SPI1->DR);
|
||||
register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI1->DR), 0xFFFFFFFFU);
|
||||
|
||||
// channel3, increment memory, memory -> periph, enable
|
||||
DMA2_Stream3->CR = DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_EN;
|
||||
register_set(&(DMA2_Stream3->CR), (DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_EN), 0x1E077EFEU);
|
||||
delay(0);
|
||||
DMA2_Stream3->CR |= DMA_SxCR_TCIE;
|
||||
register_set_bits(&(DMA2_Stream3->CR), DMA_SxCR_TCIE);
|
||||
|
||||
SPI1->CR2 |= SPI_CR2_TXDMAEN;
|
||||
register_set_bits(&(SPI1->CR2), SPI_CR2_TXDMAEN);
|
||||
|
||||
// signal data is ready by driving low
|
||||
// esp must be configured as input by this point
|
||||
@@ -57,33 +34,32 @@ void spi_tx_dma(void *addr, int len) {
|
||||
|
||||
void spi_rx_dma(void *addr, int len) {
|
||||
// disable DMA
|
||||
SPI1->CR2 &= ~SPI_CR2_RXDMAEN;
|
||||
DMA2_Stream2->CR &= ~DMA_SxCR_EN;
|
||||
register_clear_bits(&(SPI1->CR2), SPI_CR2_RXDMAEN);
|
||||
register_clear_bits(&(DMA2_Stream2->CR), DMA_SxCR_EN);
|
||||
|
||||
// drain the bus
|
||||
volatile uint8_t dat = SPI1->DR;
|
||||
(void)dat;
|
||||
|
||||
// DMA2, stream 2, channel 3
|
||||
DMA2_Stream2->M0AR = (uint32_t)addr;
|
||||
register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU);
|
||||
DMA2_Stream2->NDTR = len;
|
||||
DMA2_Stream2->PAR = (uint32_t)&(SPI1->DR);
|
||||
register_set(&(DMA2_Stream2->PAR), (uint32_t)&(SPI1->DR), 0xFFFFFFFFU);
|
||||
|
||||
// channel3, increment memory, periph -> memory, enable
|
||||
DMA2_Stream2->CR = DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_EN;
|
||||
register_set(&(DMA2_Stream2->CR), (DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_EN), 0x1E077EFEU);
|
||||
delay(0);
|
||||
DMA2_Stream2->CR |= DMA_SxCR_TCIE;
|
||||
register_set_bits(&(DMA2_Stream2->CR), DMA_SxCR_TCIE);
|
||||
|
||||
SPI1->CR2 |= SPI_CR2_RXDMAEN;
|
||||
register_set_bits(&(SPI1->CR2), SPI_CR2_RXDMAEN);
|
||||
}
|
||||
|
||||
// ***************************** SPI IRQs *****************************
|
||||
|
||||
// can't go on the stack cause it's DMAed
|
||||
uint8_t spi_tx_buf[0x44];
|
||||
|
||||
// SPI RX
|
||||
void DMA2_Stream2_IRQHandler(void) {
|
||||
void DMA2_Stream2_IRQ_Handler(void) {
|
||||
int *resp_len = (int*)spi_tx_buf;
|
||||
(void)memset(spi_tx_buf, 0xaa, 0x44);
|
||||
*resp_len = spi_cb_rx(spi_buf, 0x14, spi_tx_buf+4);
|
||||
@@ -99,7 +75,7 @@ void DMA2_Stream2_IRQHandler(void) {
|
||||
}
|
||||
|
||||
// SPI TX
|
||||
void DMA2_Stream3_IRQHandler(void) {
|
||||
void DMA2_Stream3_IRQ_Handler(void) {
|
||||
#ifdef DEBUG_SPI
|
||||
puts("SPI handshake\n");
|
||||
#endif
|
||||
@@ -112,7 +88,7 @@ void DMA2_Stream3_IRQHandler(void) {
|
||||
DMA2->LIFCR = DMA_LIFCR_CTCIF3;
|
||||
}
|
||||
|
||||
void EXTI4_IRQHandler(void) {
|
||||
void EXTI4_IRQ_Handler(void) {
|
||||
volatile unsigned int pr = EXTI->PR & (1U << 4);
|
||||
#ifdef DEBUG_SPI
|
||||
puts("exti4\n");
|
||||
@@ -125,3 +101,31 @@ void EXTI4_IRQHandler(void) {
|
||||
EXTI->PR = pr;
|
||||
}
|
||||
|
||||
// ***************************** SPI init *****************************
|
||||
void spi_init(void) {
|
||||
// Max SPI clock the ESP can produce is 80MHz. At buffer size of 256 bytes, that's a max of about 40k buffers per second
|
||||
REGISTER_INTERRUPT(DMA2_Stream2_IRQn, DMA2_Stream2_IRQ_Handler, 50000U, FAULT_INTERRUPT_RATE_SPI_DMA)
|
||||
REGISTER_INTERRUPT(DMA2_Stream3_IRQn, DMA2_Stream3_IRQ_Handler, 50000U, FAULT_INTERRUPT_RATE_SPI_DMA)
|
||||
REGISTER_INTERRUPT(EXTI4_IRQn, EXTI4_IRQ_Handler, 50000U, FAULT_INTERRUPT_RATE_SPI_CS) // TODO: Figure out if this is a reasonable limit
|
||||
|
||||
//puts("SPI init\n");
|
||||
register_set(&(SPI1->CR1), SPI_CR1_SPE, 0xFFFFU);
|
||||
|
||||
// enable SPI interrupts
|
||||
//SPI1->CR2 = SPI_CR2_RXNEIE | SPI_CR2_ERRIE | SPI_CR2_TXEIE;
|
||||
register_set(&(SPI1->CR2), SPI_CR2_RXNEIE, 0xF7U);
|
||||
|
||||
NVIC_EnableIRQ(DMA2_Stream2_IRQn);
|
||||
NVIC_EnableIRQ(DMA2_Stream3_IRQn);
|
||||
//NVIC_EnableIRQ(SPI1_IRQn);
|
||||
|
||||
// reset handshake back to pull up
|
||||
set_gpio_mode(GPIOB, 0, MODE_INPUT);
|
||||
set_gpio_pullup(GPIOB, 0, PULL_UP);
|
||||
|
||||
// setup interrupt on falling edge of SPI enable (on PA4)
|
||||
register_set(&(SYSCFG->EXTICR[2]), SYSCFG_EXTICR2_EXTI4_PA, 0xFFFFU);
|
||||
register_set_bits(&(EXTI->IMR), (1U << 4));
|
||||
register_set_bits(&(EXTI->FTSR), (1U << 4));
|
||||
NVIC_EnableIRQ(EXTI4_IRQn);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
void timer_init(TIM_TypeDef *TIM, int psc) {
|
||||
TIM->PSC = psc-1;
|
||||
TIM->DIER = TIM_DIER_UIE;
|
||||
TIM->CR1 = TIM_CR1_CEN;
|
||||
register_set(&(TIM->PSC), (psc-1), 0xFFFFU);
|
||||
register_set(&(TIM->DIER), TIM_DIER_UIE, 0x5F5FU);
|
||||
register_set(&(TIM->CR1), TIM_CR1_CEN, 0x3FU);
|
||||
TIM->SR = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -197,12 +197,12 @@ void uart_interrupt_handler(uart_ring *q) {
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
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_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_esp_gps); }
|
||||
void USART2_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_debug); }
|
||||
void USART3_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_lin2); }
|
||||
void UART5_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_lin1); }
|
||||
|
||||
void DMA2_Stream5_IRQHandler(void) {
|
||||
void DMA2_Stream5_IRQ_Handler(void) {
|
||||
ENTER_CRITICAL();
|
||||
|
||||
// Handle errors
|
||||
@@ -272,6 +272,13 @@ void uart_set_baud(USART_TypeDef *u, unsigned int baud) {
|
||||
}
|
||||
|
||||
void uart_init(uart_ring *q, int baud) {
|
||||
// Register interrupts (max data rate: 115200 baud)
|
||||
REGISTER_INTERRUPT(USART1_IRQn, USART1_IRQ_Handler, 150000U, FAULT_INTERRUPT_RATE_UART_1)
|
||||
REGISTER_INTERRUPT(USART2_IRQn, USART2_IRQ_Handler, 150000U, FAULT_INTERRUPT_RATE_UART_2)
|
||||
REGISTER_INTERRUPT(USART3_IRQn, USART3_IRQ_Handler, 150000U, FAULT_INTERRUPT_RATE_UART_3)
|
||||
REGISTER_INTERRUPT(UART5_IRQn, UART5_IRQ_Handler, 150000U, FAULT_INTERRUPT_RATE_UART_5)
|
||||
REGISTER_INTERRUPT(DMA2_Stream5_IRQn, DMA2_Stream5_IRQ_Handler, 100U, FAULT_INTERRUPT_RATE_UART_DMA) // Called twice per buffer
|
||||
|
||||
// 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;
|
||||
|
||||
+77
-79
@@ -281,15 +281,8 @@ uint8_t binary_object_store_desc[] = {
|
||||
// BOS header
|
||||
BINARY_OBJECT_STORE_DESCRIPTOR_LENGTH, // bLength, this is only the length of the header
|
||||
BINARY_OBJECT_STORE_DESCRIPTOR, // bDescriptorType
|
||||
0x40, 0x00, // wTotalLength (LSB, MSB)
|
||||
0x03, // bNumDeviceCaps (USB 2.0 + WebUSB + WinUSB)
|
||||
|
||||
// -------------------------------------------------
|
||||
// USB 2.0 extension descriptor
|
||||
0x07, // bLength, Descriptor size
|
||||
0x10, // bDescriptorType, Device Capability Descriptor Type
|
||||
0x02, // bDevCapabilityType, USB 2.0 extension capability type
|
||||
0x00, 0x00, 0x00, 0x00, // bmAttributes, LIBUSB_BM_LPM_SUPPORT = 2 and its the only option
|
||||
0x39, 0x00, // wTotalLength (LSB, MSB)
|
||||
0x02, // bNumDeviceCaps (WebUSB + WinUSB)
|
||||
|
||||
// -------------------------------------------------
|
||||
// WebUSB descriptor
|
||||
@@ -667,76 +660,7 @@ void usb_setup(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void usb_init(void) {
|
||||
// full speed PHY, do reset and remove power down
|
||||
/*puth(USBx->GRSTCTL);
|
||||
puts(" resetting PHY\n");*/
|
||||
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0);
|
||||
//puts("AHB idle\n");
|
||||
|
||||
// reset PHY here
|
||||
USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
|
||||
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
|
||||
//puts("reset done\n");
|
||||
|
||||
// internal PHY, force device mode
|
||||
USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_FDMOD;
|
||||
|
||||
// slowest timings
|
||||
USBx->GUSBCFG |= ((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
|
||||
|
||||
// power up the PHY
|
||||
#ifdef STM32F4
|
||||
USBx->GCCFG = USB_OTG_GCCFG_PWRDWN;
|
||||
|
||||
//USBx->GCCFG |= USB_OTG_GCCFG_VBDEN | USB_OTG_GCCFG_SDEN |USB_OTG_GCCFG_PDEN | USB_OTG_GCCFG_DCDEN;
|
||||
|
||||
/* B-peripheral session valid override enable*/
|
||||
USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
|
||||
USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
|
||||
#else
|
||||
USBx->GCCFG = USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS;
|
||||
#endif
|
||||
|
||||
// be a device, slowest timings
|
||||
//USBx->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL;
|
||||
//USBx->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
|
||||
//USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL;
|
||||
|
||||
// **** for debugging, doesn't seem to work ****
|
||||
//USBx->GUSBCFG |= USB_OTG_GUSBCFG_CTXPKT;
|
||||
|
||||
// reset PHY clock
|
||||
USBx_PCGCCTL = 0;
|
||||
|
||||
// enable the fancy OTG things
|
||||
// DCFG_FRAME_INTERVAL_80 is 0
|
||||
//USBx->GUSBCFG |= USB_OTG_GUSBCFG_HNPCAP | USB_OTG_GUSBCFG_SRPCAP;
|
||||
USBx_DEVICE->DCFG |= USB_OTG_SPEED_FULL | USB_OTG_DCFG_NZLSOHSK;
|
||||
|
||||
//USBx_DEVICE->DCFG = USB_OTG_DCFG_NZLSOHSK | USB_OTG_DCFG_DSPD;
|
||||
//USBx_DEVICE->DCFG = USB_OTG_DCFG_DSPD;
|
||||
|
||||
// clear pending interrupts
|
||||
USBx->GINTSTS = 0xBFFFFFFFU;
|
||||
|
||||
// setup USB interrupts
|
||||
// all interrupts except TXFIFO EMPTY
|
||||
//USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
|
||||
//USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM);
|
||||
USBx->GINTMSK = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_OTGINT |
|
||||
USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_GONAKEFFM | USB_OTG_GINTMSK_GINAKEFFM |
|
||||
USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_USBSUSPM |
|
||||
USB_OTG_GINTMSK_CIDSCHGM | USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_MMISM;
|
||||
|
||||
USBx->GAHBCFG = USB_OTG_GAHBCFG_GINT;
|
||||
|
||||
// DCTL startup value is 2 on new chip, 0 on old chip
|
||||
USBx_DEVICE->DCTL = 0;
|
||||
|
||||
// enable the IRQ
|
||||
NVIC_EnableIRQ(OTG_FS_IRQn);
|
||||
}
|
||||
|
||||
// ***************************** USB port *****************************
|
||||
|
||||
@@ -1008,7 +932,7 @@ void usb_irqhandler(void) {
|
||||
//USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
|
||||
}
|
||||
|
||||
void OTG_FS_IRQHandler(void) {
|
||||
void OTG_FS_IRQ_Handler(void) {
|
||||
NVIC_DisableIRQ(OTG_FS_IRQn);
|
||||
//__disable_irq();
|
||||
usb_irqhandler();
|
||||
@@ -1016,3 +940,77 @@ void OTG_FS_IRQHandler(void) {
|
||||
NVIC_EnableIRQ(OTG_FS_IRQn);
|
||||
}
|
||||
|
||||
// ***************************** USB init *****************************
|
||||
|
||||
void usb_init(void) {
|
||||
REGISTER_INTERRUPT(OTG_FS_IRQn, OTG_FS_IRQ_Handler, 1500000U, FAULT_INTERRUPT_RATE_USB) //TODO: Find out a better rate limit for USB. Now it's the 1.5MB/s rate
|
||||
|
||||
// full speed PHY, do reset and remove power down
|
||||
/*puth(USBx->GRSTCTL);
|
||||
puts(" resetting PHY\n");*/
|
||||
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0);
|
||||
//puts("AHB idle\n");
|
||||
|
||||
// reset PHY here
|
||||
USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
|
||||
while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
|
||||
//puts("reset done\n");
|
||||
|
||||
// internal PHY, force device mode
|
||||
USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_FDMOD;
|
||||
|
||||
// slowest timings
|
||||
USBx->GUSBCFG |= ((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
|
||||
|
||||
// power up the PHY
|
||||
#ifdef STM32F4
|
||||
USBx->GCCFG = USB_OTG_GCCFG_PWRDWN;
|
||||
|
||||
//USBx->GCCFG |= USB_OTG_GCCFG_VBDEN | USB_OTG_GCCFG_SDEN |USB_OTG_GCCFG_PDEN | USB_OTG_GCCFG_DCDEN;
|
||||
|
||||
/* B-peripheral session valid override enable*/
|
||||
USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL;
|
||||
USBx->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN;
|
||||
#else
|
||||
USBx->GCCFG = USB_OTG_GCCFG_PWRDWN | USB_OTG_GCCFG_NOVBUSSENS;
|
||||
#endif
|
||||
|
||||
// be a device, slowest timings
|
||||
//USBx->GUSBCFG = USB_OTG_GUSBCFG_FDMOD | USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL;
|
||||
//USBx->GUSBCFG |= (uint32_t)((USBD_FS_TRDT_VALUE << 10) & USB_OTG_GUSBCFG_TRDT);
|
||||
//USBx->GUSBCFG = USB_OTG_GUSBCFG_PHYSEL | USB_OTG_GUSBCFG_TRDT | USB_OTG_GUSBCFG_TOCAL;
|
||||
|
||||
// **** for debugging, doesn't seem to work ****
|
||||
//USBx->GUSBCFG |= USB_OTG_GUSBCFG_CTXPKT;
|
||||
|
||||
// reset PHY clock
|
||||
USBx_PCGCCTL = 0;
|
||||
|
||||
// enable the fancy OTG things
|
||||
// DCFG_FRAME_INTERVAL_80 is 0
|
||||
//USBx->GUSBCFG |= USB_OTG_GUSBCFG_HNPCAP | USB_OTG_GUSBCFG_SRPCAP;
|
||||
USBx_DEVICE->DCFG |= USB_OTG_SPEED_FULL | USB_OTG_DCFG_NZLSOHSK;
|
||||
|
||||
//USBx_DEVICE->DCFG = USB_OTG_DCFG_NZLSOHSK | USB_OTG_DCFG_DSPD;
|
||||
//USBx_DEVICE->DCFG = USB_OTG_DCFG_DSPD;
|
||||
|
||||
// clear pending interrupts
|
||||
USBx->GINTSTS = 0xBFFFFFFFU;
|
||||
|
||||
// setup USB interrupts
|
||||
// all interrupts except TXFIFO EMPTY
|
||||
//USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM | USB_OTG_GINTSTS_SOF | USB_OTG_GINTSTS_EOPF);
|
||||
//USBx->GINTMSK = 0xFFFFFFFF & ~(USB_OTG_GINTMSK_NPTXFEM | USB_OTG_GINTMSK_PTXFEM);
|
||||
USBx->GINTMSK = USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_OTGINT |
|
||||
USB_OTG_GINTMSK_RXFLVLM | USB_OTG_GINTMSK_GONAKEFFM | USB_OTG_GINTMSK_GINAKEFFM |
|
||||
USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IEPINT | USB_OTG_GINTMSK_USBSUSPM |
|
||||
USB_OTG_GINTMSK_CIDSCHGM | USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_MMISM;
|
||||
|
||||
USBx->GAHBCFG = USB_OTG_GAHBCFG_GINT;
|
||||
|
||||
// DCTL startup value is 2 on new chip, 0 on old chip
|
||||
USBx_DEVICE->DCTL = 0;
|
||||
|
||||
// enable the IRQ
|
||||
NVIC_EnableIRQ(OTG_FS_IRQn);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#define FAULT_STATUS_NONE 0U
|
||||
#define FAULT_STATUS_TEMPORARY 1U
|
||||
#define FAULT_STATUS_PERMANENT 2U
|
||||
|
||||
// Fault types
|
||||
#define FAULT_RELAY_MALFUNCTION (1U << 0)
|
||||
#define FAULT_UNUSED_INTERRUPT_HANDLED (1U << 1)
|
||||
#define FAULT_INTERRUPT_RATE_CAN_1 (1U << 2)
|
||||
#define FAULT_INTERRUPT_RATE_CAN_2 (1U << 3)
|
||||
#define FAULT_INTERRUPT_RATE_CAN_3 (1U << 4)
|
||||
#define FAULT_INTERRUPT_RATE_TACH (1U << 5)
|
||||
#define FAULT_INTERRUPT_RATE_GMLAN (1U << 6)
|
||||
#define FAULT_INTERRUPT_RATE_INTERRUPTS (1U << 7)
|
||||
#define FAULT_INTERRUPT_RATE_SPI_DMA (1U << 8)
|
||||
#define FAULT_INTERRUPT_RATE_SPI_CS (1U << 9)
|
||||
#define FAULT_INTERRUPT_RATE_UART_1 (1U << 10)
|
||||
#define FAULT_INTERRUPT_RATE_UART_2 (1U << 11)
|
||||
#define FAULT_INTERRUPT_RATE_UART_3 (1U << 12)
|
||||
#define FAULT_INTERRUPT_RATE_UART_5 (1U << 13)
|
||||
#define FAULT_INTERRUPT_RATE_UART_DMA (1U << 14)
|
||||
#define FAULT_INTERRUPT_RATE_USB (1U << 15)
|
||||
#define FAULT_INTERRUPT_RATE_TIM1 (1U << 16)
|
||||
#define FAULT_INTERRUPT_RATE_TIM3 (1U << 17)
|
||||
#define FAULT_REGISTER_DIVERGENT (1U << 18)
|
||||
|
||||
// Permanent faults
|
||||
#define PERMANENT_FAULTS 0U
|
||||
|
||||
uint8_t fault_status = FAULT_STATUS_NONE;
|
||||
uint32_t faults = 0U;
|
||||
|
||||
void fault_occurred(uint32_t fault) {
|
||||
faults |= fault;
|
||||
if((PERMANENT_FAULTS & fault) != 0U){
|
||||
puts("Permanent fault occurred: 0x"); puth(fault); puts("\n");
|
||||
fault_status = FAULT_STATUS_PERMANENT;
|
||||
} else {
|
||||
puts("Temporary fault occurred: 0x"); puth(fault); puts("\n");
|
||||
fault_status = FAULT_STATUS_TEMPORARY;
|
||||
}
|
||||
}
|
||||
|
||||
void fault_recovered(uint32_t fault) {
|
||||
if((PERMANENT_FAULTS & fault) == 0U){
|
||||
faults &= ~fault;
|
||||
} else {
|
||||
puts("Cannot recover from a permanent fault!\n");
|
||||
}
|
||||
}
|
||||
+3
-7
@@ -23,6 +23,9 @@ void early(void) {
|
||||
// Reset global critical depth
|
||||
global_critical_depth = 0;
|
||||
|
||||
// Init register and interrupt tables
|
||||
init_registers();
|
||||
|
||||
// neccesary for DFU flashing on a non-power cycled white panda
|
||||
enable_interrupts();
|
||||
|
||||
@@ -59,13 +62,6 @@ void early(void) {
|
||||
detect_configuration();
|
||||
detect_board_type();
|
||||
|
||||
#ifdef PANDA
|
||||
// enable the ESP, disable ESP boot mode
|
||||
// dont disable on grey panda
|
||||
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
|
||||
#endif
|
||||
|
||||
|
||||
if (enter_bootloader_mode == ENTER_BOOTLOADER_MAGIC) {
|
||||
#ifdef PANDA
|
||||
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
|
||||
|
||||
@@ -141,6 +141,7 @@ typedef enum
|
||||
TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */
|
||||
TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare global interrupt */
|
||||
DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */
|
||||
FSMC_IRQn = 48, /*!< FSMC global Interrupt */
|
||||
SDIO_IRQn = 49, /*!< SDIO global Interrupt */
|
||||
TIM5_IRQn = 50, /*!< TIM5 global Interrupt */
|
||||
SPI3_IRQn = 51, /*!< SPI3 global Interrupt */
|
||||
|
||||
@@ -40,28 +40,3 @@ int memcmp(const void * ptr1, const void * ptr2, unsigned int num) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ********************* IRQ helpers *********************
|
||||
|
||||
volatile bool interrupts_enabled = false;
|
||||
|
||||
void enable_interrupts(void) {
|
||||
interrupts_enabled = true;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
void disable_interrupts(void) {
|
||||
interrupts_enabled = false;
|
||||
__disable_irq();
|
||||
}
|
||||
|
||||
uint8_t global_critical_depth = 0U;
|
||||
#define ENTER_CRITICAL() \
|
||||
__disable_irq(); \
|
||||
global_critical_depth += 1U;
|
||||
|
||||
#define EXIT_CRITICAL() \
|
||||
global_critical_depth -= 1U; \
|
||||
if ((global_critical_depth == 0U) && interrupts_enabled) { \
|
||||
__enable_irq(); \
|
||||
}
|
||||
|
||||
|
||||
+180
-134
@@ -5,10 +5,15 @@
|
||||
#include "config.h"
|
||||
#include "obj/gitversion.h"
|
||||
|
||||
#include "main_declarations.h"
|
||||
#include "critical.h"
|
||||
|
||||
#include "libc.h"
|
||||
#include "provision.h"
|
||||
#include "faults.h"
|
||||
|
||||
#include "main_declarations.h"
|
||||
#include "drivers/registers.h"
|
||||
#include "drivers/interrupts.h"
|
||||
|
||||
#include "drivers/llcan.h"
|
||||
#include "drivers/llgpio.h"
|
||||
@@ -34,6 +39,28 @@
|
||||
|
||||
#include "drivers/can.h"
|
||||
|
||||
extern int _app_start[0xc000]; // Only first 3 sectors of size 0x4000 are used
|
||||
|
||||
struct __attribute__((packed)) health_t {
|
||||
uint32_t uptime_pkt;
|
||||
uint32_t voltage_pkt;
|
||||
uint32_t current_pkt;
|
||||
uint32_t can_send_errs_pkt;
|
||||
uint32_t can_fwd_errs_pkt;
|
||||
uint32_t gmlan_send_errs_pkt;
|
||||
uint32_t faults_pkt;
|
||||
uint8_t ignition_line_pkt;
|
||||
uint8_t ignition_can_pkt;
|
||||
uint8_t controls_allowed_pkt;
|
||||
uint8_t gas_interceptor_detected_pkt;
|
||||
uint8_t car_harness_status_pkt;
|
||||
uint8_t usb_power_mode_pkt;
|
||||
uint8_t safety_mode_pkt;
|
||||
uint8_t fault_status_pkt;
|
||||
uint8_t power_save_enabled_pkt;
|
||||
};
|
||||
|
||||
|
||||
// ********************* Serial debugging *********************
|
||||
|
||||
bool check_started(void) {
|
||||
@@ -45,11 +72,14 @@ void debug_ring_callback(uart_ring *ring) {
|
||||
while (getc(ring, &rcv)) {
|
||||
(void)putc(ring, rcv); // misra-c2012-17.7: cast to void is ok: debug function
|
||||
|
||||
// jump to DFU flash
|
||||
if (rcv == 'z') {
|
||||
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
// only allow bootloader entry on debug builds
|
||||
#ifdef ALLOW_DEBUG
|
||||
// jump to DFU flash
|
||||
if (rcv == 'z') {
|
||||
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
#endif
|
||||
|
||||
// normal reset
|
||||
if (rcv == 'x') {
|
||||
@@ -72,100 +102,65 @@ void debug_ring_callback(uart_ring *ring) {
|
||||
}
|
||||
}
|
||||
|
||||
// ***************************** started logic *****************************
|
||||
void started_interrupt_handler(uint8_t interrupt_line) {
|
||||
volatile unsigned int pr = EXTI->PR & (1U << interrupt_line);
|
||||
if ((pr & (1U << interrupt_line)) != 0U) {
|
||||
#ifdef DEBUG
|
||||
puts("got started interrupt\n");
|
||||
#endif
|
||||
|
||||
// jenky debounce
|
||||
delay(100000);
|
||||
|
||||
#ifdef EON
|
||||
// set power savings mode here if on EON build
|
||||
int power_save_state = check_started() ? POWER_SAVE_STATUS_DISABLED : POWER_SAVE_STATUS_ENABLED;
|
||||
set_power_save_state(power_save_state);
|
||||
// set CDP usb power mode everytime that the car starts to make sure EON is charging
|
||||
if (check_started()) {
|
||||
current_board->set_usb_power_mode(USB_POWER_CDP);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
EXTI->PR = (1U << interrupt_line);
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void EXTI0_IRQHandler(void) {
|
||||
started_interrupt_handler(0);
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void EXTI1_IRQHandler(void) {
|
||||
started_interrupt_handler(1);
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void EXTI3_IRQHandler(void) {
|
||||
started_interrupt_handler(3);
|
||||
}
|
||||
|
||||
// ****************************** safety mode ******************************
|
||||
|
||||
// this is the only way to leave silent mode
|
||||
void set_safety_mode(uint16_t mode, int16_t param) {
|
||||
int err = safety_set_mode(mode, param);
|
||||
uint16_t mode_copy = mode;
|
||||
int err = set_safety_hooks(mode_copy, param);
|
||||
if (err == -1) {
|
||||
puts("Error: safety set mode failed\n");
|
||||
} else {
|
||||
switch (mode) {
|
||||
case SAFETY_NOOUTPUT:
|
||||
set_intercept_relay(false);
|
||||
if(board_has_obd()){
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
can_silent = ALL_CAN_SILENT;
|
||||
break;
|
||||
case SAFETY_ELM327:
|
||||
set_intercept_relay(false);
|
||||
heartbeat_counter = 0U;
|
||||
if(board_has_obd()){
|
||||
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
default:
|
||||
set_intercept_relay(true);
|
||||
heartbeat_counter = 0U;
|
||||
if(board_has_obd()){
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
puts("Error: safety set mode failed. Falling back to SILENT\n");
|
||||
mode_copy = SAFETY_SILENT;
|
||||
err = set_safety_hooks(mode_copy, 0);
|
||||
if (err == -1) {
|
||||
puts("Error: Failed setting SILENT mode. Hanging\n");
|
||||
while (true) {
|
||||
// TERMINAL ERROR: we can't continue if SILENT safety mode isn't succesfully set
|
||||
}
|
||||
can_init_all();
|
||||
}
|
||||
}
|
||||
switch (mode_copy) {
|
||||
case SAFETY_SILENT:
|
||||
set_intercept_relay(false);
|
||||
if (board_has_obd()) {
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
can_silent = ALL_CAN_SILENT;
|
||||
break;
|
||||
case SAFETY_NOOUTPUT:
|
||||
set_intercept_relay(false);
|
||||
if (board_has_obd()) {
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
case SAFETY_ELM327:
|
||||
set_intercept_relay(false);
|
||||
heartbeat_counter = 0U;
|
||||
if (board_has_obd()) {
|
||||
current_board->set_can_mode(CAN_MODE_OBD_CAN2);
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
default:
|
||||
set_intercept_relay(true);
|
||||
heartbeat_counter = 0U;
|
||||
if (board_has_obd()) {
|
||||
current_board->set_can_mode(CAN_MODE_NORMAL);
|
||||
}
|
||||
can_silent = ALL_CAN_LIVE;
|
||||
break;
|
||||
}
|
||||
can_init_all();
|
||||
}
|
||||
|
||||
// ***************************** USB port *****************************
|
||||
|
||||
int get_health_pkt(void *dat) {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t voltage_pkt;
|
||||
uint32_t current_pkt;
|
||||
uint32_t can_send_errs_pkt;
|
||||
uint32_t can_fwd_errs_pkt;
|
||||
uint32_t gmlan_send_errs_pkt;
|
||||
uint8_t ignition_line_pkt;
|
||||
uint8_t ignition_can_pkt;
|
||||
uint8_t controls_allowed_pkt;
|
||||
uint8_t gas_interceptor_detected_pkt;
|
||||
uint8_t car_harness_status_pkt;
|
||||
uint8_t usb_power_mode_pkt;
|
||||
uint8_t safety_mode_pkt;
|
||||
} *health = dat;
|
||||
COMPILE_TIME_ASSERT(sizeof(struct health_t) <= MAX_RESP_LEN);
|
||||
struct health_t * health = (struct health_t*)dat;
|
||||
|
||||
health->uptime_pkt = uptime_cnt;
|
||||
health->voltage_pkt = adc_get_voltage();
|
||||
health->current_pkt = current_board->read_current();
|
||||
|
||||
@@ -181,6 +176,10 @@ int get_health_pkt(void *dat) {
|
||||
health->car_harness_status_pkt = car_harness_status;
|
||||
health->usb_power_mode_pkt = usb_power_mode;
|
||||
health->safety_mode_pkt = (uint8_t)(current_safety_mode);
|
||||
health->power_save_enabled_pkt = (uint8_t)(power_save_status == POWER_SAVE_STATUS_ENABLED);
|
||||
|
||||
health->fault_status_pkt = fault_status;
|
||||
health->faults_pkt = faults;
|
||||
|
||||
return sizeof(*health);
|
||||
}
|
||||
@@ -230,7 +229,7 @@ void usb_cb_ep3_out(void *usbdata, int len, bool hardwired) {
|
||||
to_push.RIR = d32[dpkt];
|
||||
|
||||
uint8_t bus_number = (to_push.RDTR >> 4) & CAN_BUS_NUM_MASK;
|
||||
can_send(&to_push, bus_number);
|
||||
can_send(&to_push, bus_number, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +312,10 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
resp[1] = ((fan_rpm & 0xFF00U) >> 8U);
|
||||
resp_len = 2;
|
||||
break;
|
||||
// **** 0xb3: set phone power
|
||||
case 0xb3:
|
||||
current_board->set_phone_power(setup->b.wValue.w > 0U);
|
||||
break;
|
||||
// **** 0xc0: get CAN debug info
|
||||
case 0xc0:
|
||||
puts("can tx: "); puth(can_tx_cnt);
|
||||
@@ -366,6 +369,24 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
case 0xd2:
|
||||
resp_len = get_health_pkt(resp);
|
||||
break;
|
||||
// **** 0xd3: get first 64 bytes of signature
|
||||
case 0xd3:
|
||||
{
|
||||
resp_len = 64;
|
||||
char * code = (char*)_app_start;
|
||||
int code_len = _app_start[0];
|
||||
(void)memcpy(resp, &code[code_len], resp_len);
|
||||
}
|
||||
break;
|
||||
// **** 0xd4: get second 64 bytes of signature
|
||||
case 0xd4:
|
||||
{
|
||||
resp_len = 64;
|
||||
char * code = (char*)_app_start;
|
||||
int code_len = _app_start[0];
|
||||
(void)memcpy(resp, &code[code_len + 64], resp_len);
|
||||
}
|
||||
break;
|
||||
// **** 0xd6: get version
|
||||
case 0xd6:
|
||||
COMPILE_TIME_ASSERT(sizeof(gitversion) <= MAX_RESP_LEN);
|
||||
@@ -427,8 +448,10 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
// **** 0xdc: set safety mode
|
||||
case 0xdc:
|
||||
// Blocked over WiFi.
|
||||
// Allow NOOUTPUT and ELM security mode to be set over wifi.
|
||||
if (hardwired || (setup->b.wValue.w == SAFETY_NOOUTPUT) || (setup->b.wValue.w == SAFETY_ELM327)) {
|
||||
// Allow SILENT, NOOUTPUT and ELM security mode to be set over wifi.
|
||||
if (hardwired || (setup->b.wValue.w == SAFETY_SILENT) ||
|
||||
(setup->b.wValue.w == SAFETY_NOOUTPUT) ||
|
||||
(setup->b.wValue.w == SAFETY_ELM327)) {
|
||||
set_safety_mode(setup->b.wValue.w, (uint16_t) setup->b.wIndex.w);
|
||||
}
|
||||
break;
|
||||
@@ -526,6 +549,10 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
case 0xe6:
|
||||
current_board->set_usb_power_mode(setup->b.wValue.w);
|
||||
break;
|
||||
// **** 0xe7: set power save state
|
||||
case 0xe7:
|
||||
set_power_save_state(setup->b.wValue.w);
|
||||
break;
|
||||
// **** 0xf0: do k-line wValue pulse on uart2 for Acura
|
||||
case 0xf0:
|
||||
if (setup->b.wValue.w == 1U) {
|
||||
@@ -640,24 +667,21 @@ void __attribute__ ((noinline)) enable_fpu(void) {
|
||||
SCB->CPACR |= ((3UL << (10U * 2U)) | (3UL << (11U * 2U)));
|
||||
}
|
||||
|
||||
uint64_t tcnt = 0;
|
||||
|
||||
// go into NOOUTPUT when the EON does not send a heartbeat for this amount of seconds.
|
||||
// go into SILENT when the EON does not send a heartbeat for this amount of seconds.
|
||||
#define EON_HEARTBEAT_IGNITION_CNT_ON 5U
|
||||
#define EON_HEARTBEAT_IGNITION_CNT_OFF 2U
|
||||
|
||||
// called once per second
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void TIM1_BRK_TIM9_IRQHandler(void) {
|
||||
void TIM1_BRK_TIM9_IRQ_Handler(void) {
|
||||
if (TIM9->SR != 0) {
|
||||
can_live = pending_can_live;
|
||||
|
||||
current_board->usb_power_mode_tick(tcnt);
|
||||
current_board->usb_power_mode_tick(uptime_cnt);
|
||||
|
||||
//puth(usart1_dma); puts(" "); puth(DMA2_Stream5->M0AR); puts(" "); puth(DMA2_Stream5->NDTR); puts("\n");
|
||||
|
||||
// reset this every 16th pass
|
||||
if ((tcnt & 0xFU) == 0U) {
|
||||
if ((uptime_cnt & 0xFU) == 0U) {
|
||||
pending_can_live = 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
@@ -676,30 +700,57 @@ void TIM1_BRK_TIM9_IRQHandler(void) {
|
||||
|
||||
// turn off the blue LED, turned on by CAN
|
||||
// unless we are in power saving mode
|
||||
current_board->set_led(LED_BLUE, (tcnt & 1U) && (power_save_status == POWER_SAVE_STATUS_ENABLED));
|
||||
current_board->set_led(LED_BLUE, (uptime_cnt & 1U) && (power_save_status == POWER_SAVE_STATUS_ENABLED));
|
||||
|
||||
// increase heartbeat counter and cap it at the uint32 limit
|
||||
if (heartbeat_counter < __UINT32_MAX__) {
|
||||
heartbeat_counter += 1U;
|
||||
}
|
||||
|
||||
// check heartbeat counter if we are running EON code. If the heartbeat has been gone for a while, go to NOOUTPUT safety mode.
|
||||
#ifdef EON
|
||||
// check heartbeat counter if we are running EON code.
|
||||
// if the heartbeat has been gone for a while, go to SILENT safety mode and enter power save
|
||||
if (heartbeat_counter >= (check_started() ? EON_HEARTBEAT_IGNITION_CNT_ON : EON_HEARTBEAT_IGNITION_CNT_OFF)) {
|
||||
puts("EON hasn't sent a heartbeat for 0x"); puth(heartbeat_counter); puts(" seconds. Safety is set to NOOUTPUT mode.\n");
|
||||
if(current_safety_mode != SAFETY_NOOUTPUT){
|
||||
set_safety_mode(SAFETY_NOOUTPUT, 0U);
|
||||
puts("EON hasn't sent a heartbeat for 0x");
|
||||
puth(heartbeat_counter);
|
||||
puts(" seconds. Safety is set to SILENT mode.\n");
|
||||
if (current_safety_mode != SAFETY_SILENT) {
|
||||
set_safety_mode(SAFETY_SILENT, 0U);
|
||||
}
|
||||
if (power_save_status != POWER_SAVE_STATUS_ENABLED) {
|
||||
set_power_save_state(POWER_SAVE_STATUS_ENABLED);
|
||||
}
|
||||
}
|
||||
|
||||
// enter CDP mode when car starts to ensure we are charging a turned off EON
|
||||
if (check_started() && (usb_power_mode != USB_POWER_CDP)) {
|
||||
current_board->set_usb_power_mode(USB_POWER_CDP);
|
||||
}
|
||||
#endif
|
||||
|
||||
// check registers
|
||||
check_registers();
|
||||
|
||||
// set ignition_can to false after 2s of no CAN seen
|
||||
if (ignition_can_cnt > 2U) {
|
||||
ignition_can = false;
|
||||
};
|
||||
|
||||
// on to the next one
|
||||
tcnt += 1U;
|
||||
uptime_cnt += 1U;
|
||||
safety_mode_cnt += 1U;
|
||||
ignition_can_cnt += 1U;
|
||||
}
|
||||
TIM9->SR = 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// Init interrupt table
|
||||
init_interrupts(true);
|
||||
|
||||
// 1s timer
|
||||
REGISTER_INTERRUPT(TIM1_BRK_TIM9_IRQn, TIM1_BRK_TIM9_IRQ_Handler, 2U, FAULT_INTERRUPT_RATE_TIM1)
|
||||
|
||||
// shouldn't have interrupts here, but just in case
|
||||
disable_interrupts();
|
||||
|
||||
@@ -760,32 +811,16 @@ int main(void) {
|
||||
TIM2->EGR = TIM_EGR_UG;
|
||||
// use TIM2->CNT to read
|
||||
|
||||
// default to silent mode to prevent issues with Ford
|
||||
// hardcode a specific safety mode if you want to force the panda to be in a specific mode
|
||||
int err = safety_set_mode(SAFETY_NOOUTPUT, 0);
|
||||
if (err == -1) {
|
||||
puts("Failed to set safety mode\n");
|
||||
while (true) {
|
||||
// if SAFETY_NOOUTPUT isn't succesfully set, we can't continue
|
||||
}
|
||||
}
|
||||
can_silent = ALL_CAN_SILENT;
|
||||
can_init_all();
|
||||
// init to SILENT and can silent
|
||||
set_safety_mode(SAFETY_SILENT, 0);
|
||||
|
||||
// enable CAN TXs
|
||||
current_board->enable_can_transcievers(true);
|
||||
|
||||
#ifndef EON
|
||||
spi_init();
|
||||
#endif
|
||||
|
||||
#ifdef EON
|
||||
// have to save power
|
||||
if (hw_type == HW_TYPE_WHITE_PANDA) {
|
||||
current_board->set_esp_gps_mode(ESP_GPS_DISABLED);
|
||||
}
|
||||
// only enter power save after the first cycle
|
||||
/*if (check_started()) {
|
||||
set_power_save_state(POWER_SAVE_STATUS_ENABLED);
|
||||
}*/
|
||||
#endif
|
||||
// 1hz
|
||||
timer_init(TIM9, 1464);
|
||||
NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
|
||||
@@ -804,19 +839,30 @@ int main(void) {
|
||||
|
||||
for (cnt=0;;cnt++) {
|
||||
if (power_save_status == POWER_SAVE_STATUS_DISABLED) {
|
||||
int div_mode = ((usb_power_mode == USB_POWER_DCP) ? 4 : 1);
|
||||
#ifdef DEBUG_FAULTS
|
||||
if(fault_status == FAULT_STATUS_NONE){
|
||||
#endif
|
||||
int div_mode = ((usb_power_mode == USB_POWER_DCP) ? 4 : 1);
|
||||
|
||||
// useful for debugging, fade breaks = panda is overloaded
|
||||
for (int div_mode_loop = 0; div_mode_loop < div_mode; div_mode_loop++) {
|
||||
for (int fade = 0; fade < 1024; fade += 8) {
|
||||
for (int i = 0; i < (128/div_mode); i++) {
|
||||
current_board->set_led(LED_RED, 1);
|
||||
if (fade < 512) { delay(fade); } else { delay(1024-fade); }
|
||||
current_board->set_led(LED_RED, 0);
|
||||
if (fade < 512) { delay(512-fade); } else { delay(fade-512); }
|
||||
// useful for debugging, fade breaks = panda is overloaded
|
||||
for (int div_mode_loop = 0; div_mode_loop < div_mode; div_mode_loop++) {
|
||||
for (int fade = 0; fade < 1024; fade += 8) {
|
||||
for (int i = 0; i < (128/div_mode); i++) {
|
||||
current_board->set_led(LED_RED, 1);
|
||||
if (fade < 512) { delay(fade); } else { delay(1024-fade); }
|
||||
current_board->set_led(LED_RED, 0);
|
||||
if (fade < 512) { delay(512-fade); } else { delay(fade-512); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_FAULTS
|
||||
} else {
|
||||
current_board->set_led(LED_RED, 1);
|
||||
delay(512000U);
|
||||
current_board->set_led(LED_RED, 0);
|
||||
delay(512000U);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
__WFI();
|
||||
}
|
||||
|
||||
@@ -11,4 +11,5 @@ void can_set_obd(uint8_t harness_orientation, bool obd);
|
||||
uint8_t hw_type = 0;
|
||||
const board *current_board;
|
||||
bool is_enumerated = 0;
|
||||
uint32_t heartbeat_counter = 0;
|
||||
uint32_t heartbeat_counter = 0;
|
||||
uint32_t uptime_cnt = 0;
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
#include "libc.h"
|
||||
|
||||
#include "main_declarations.h"
|
||||
#include "critical.h"
|
||||
#include "faults.h"
|
||||
|
||||
#include "drivers/registers.h"
|
||||
#include "drivers/interrupts.h"
|
||||
#include "drivers/llcan.h"
|
||||
#include "drivers/llgpio.h"
|
||||
#include "drivers/adc.h"
|
||||
@@ -129,8 +133,7 @@ uint8_t pedal_checksum(uint8_t *dat, int len) {
|
||||
#define CAN_GAS_SIZE 6
|
||||
#define COUNTER_CYCLE 0xFU
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void CAN1_TX_IRQHandler(void) {
|
||||
void CAN1_TX_IRQ_Handler(void) {
|
||||
// clear interrupt
|
||||
CAN->TSR |= CAN_TSR_RQCP0;
|
||||
}
|
||||
@@ -152,8 +155,7 @@ uint32_t current_index = 0;
|
||||
#define FAULT_INVALID 6U
|
||||
uint8_t state = FAULT_STARTUP;
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void CAN1_RX0_IRQHandler(void) {
|
||||
void CAN1_RX0_IRQ_Handler(void) {
|
||||
while ((CAN->RF0R & CAN_RF0R_FMP0) != 0) {
|
||||
#ifdef DEBUG
|
||||
puts("CAN RX\n");
|
||||
@@ -216,8 +218,7 @@ void CAN1_RX0_IRQHandler(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void CAN1_SCE_IRQHandler(void) {
|
||||
void CAN1_SCE_IRQ_Handler(void) {
|
||||
state = FAULT_SCE;
|
||||
llcan_clear_send(CAN);
|
||||
}
|
||||
@@ -228,8 +229,7 @@ unsigned int pkt_idx = 0;
|
||||
|
||||
int led_value = 0;
|
||||
|
||||
// cppcheck-suppress unusedFunction ; used in headers not included in cppcheck
|
||||
void TIM3_IRQHandler(void) {
|
||||
void TIM3_IRQ_Handler(void) {
|
||||
#ifdef DEBUG
|
||||
puth(TIM3->CNT);
|
||||
puts(" ");
|
||||
@@ -296,6 +296,16 @@ void pedal(void) {
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// Init interrupt table
|
||||
init_interrupts(true);
|
||||
|
||||
REGISTER_INTERRUPT(CAN1_TX_IRQn, CAN1_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_RX0_IRQn, CAN1_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_SCE_IRQn, CAN1_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
|
||||
// Should run at around 732Hz (see init below)
|
||||
REGISTER_INTERRUPT(TIM3_IRQn, TIM3_IRQ_Handler, 1000U, FAULT_INTERRUPT_RATE_TIM3)
|
||||
|
||||
disable_interrupts();
|
||||
|
||||
// init devices
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// WARNING: To stay in compliance with the SIL2 rules laid out in STM UM1840, we should never implement any of the available hardware low power modes.
|
||||
// See rule: CoU_3
|
||||
|
||||
#define POWER_SAVE_STATUS_DISABLED 0
|
||||
#define POWER_SAVE_STATUS_ENABLED 1
|
||||
|
||||
|
||||
+26
-10
@@ -18,7 +18,7 @@
|
||||
#include "safety/safety_elm327.h"
|
||||
|
||||
// from cereal.car.CarParams.SafetyModel
|
||||
#define SAFETY_NOOUTPUT 0U
|
||||
#define SAFETY_SILENT 0U
|
||||
#define SAFETY_HONDA 1U
|
||||
#define SAFETY_TOYOTA 2U
|
||||
#define SAFETY_ELM327 3U
|
||||
@@ -35,8 +35,9 @@
|
||||
#define SAFETY_TOYOTA_IPAS 16U
|
||||
#define SAFETY_ALLOUTPUT 17U
|
||||
#define SAFETY_GM_ASCM 18U
|
||||
#define SAFETY_NOOUTPUT 19U
|
||||
|
||||
uint16_t current_safety_mode = SAFETY_NOOUTPUT;
|
||||
uint16_t current_safety_mode = SAFETY_SILENT;
|
||||
const safety_hooks *current_hooks = &nooutput_hooks;
|
||||
|
||||
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push){
|
||||
@@ -55,39 +56,54 @@ int safety_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
return current_hooks->fwd(bus_num, to_fwd);
|
||||
}
|
||||
|
||||
bool addr_allowed(int addr, int bus, const AddrBus addr_list[], int len) {
|
||||
bool allowed = false;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((addr == addr_list[i].addr) && (bus == addr_list[i].bus)) {
|
||||
allowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint16_t id;
|
||||
const safety_hooks *hooks;
|
||||
} safety_hook_config;
|
||||
|
||||
const safety_hook_config safety_hook_registry[] = {
|
||||
{SAFETY_NOOUTPUT, &nooutput_hooks},
|
||||
{SAFETY_SILENT, &nooutput_hooks},
|
||||
{SAFETY_HONDA, &honda_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_MAZDA, &mazda_hooks},
|
||||
{SAFETY_VOLKSWAGEN, &volkswagen_hooks},
|
||||
{SAFETY_NOOUTPUT, &nooutput_hooks},
|
||||
#ifdef ALLOW_DEBUG
|
||||
{SAFETY_CADILLAC, &cadillac_hooks},
|
||||
{SAFETY_TOYOTA_IPAS, &toyota_ipas_hooks},
|
||||
{SAFETY_TESLA, &tesla_hooks},
|
||||
{SAFETY_ALLOUTPUT, &alloutput_hooks},
|
||||
{SAFETY_GM_ASCM, &gm_ascm_hooks},
|
||||
{SAFETY_FORD, &ford_hooks},
|
||||
#endif
|
||||
};
|
||||
|
||||
int safety_set_mode(uint16_t mode, int16_t param) {
|
||||
int set_status = -1; // not set
|
||||
int set_safety_hooks(uint16_t mode, int16_t param) {
|
||||
safety_mode_cnt = 0U; // reset safety mode timer
|
||||
int set_status = -1; // not set
|
||||
int hook_config_count = sizeof(safety_hook_registry) / sizeof(safety_hook_config);
|
||||
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
|
||||
set_status = 0; // set
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -205,7 +221,7 @@ float interpolate(struct lookup_t xy, float x) {
|
||||
float y0 = xy.y[i];
|
||||
float dx = xy.x[i+1] - x0;
|
||||
float dy = xy.y[i+1] - y0;
|
||||
// dx should not be zero as xy.x is supposed ot be monotonic
|
||||
// dx should not be zero as xy.x is supposed to be monotonic
|
||||
if (dx <= 0.) {
|
||||
dx = 0.0001;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#define CADILLAC_TORQUE_MSG_N 4 // 4 torque messages: 0x151, 0x152, 0x153, 0x154
|
||||
|
||||
const AddrBus CADILLAC_TX_MSGS[] = {{0x151, 2}, {0x152, 0}, {0x153, 2}, {0x154, 0}};
|
||||
const int CADILLAC_MAX_STEER = 150; // 1s
|
||||
// real time torque limit to prevent controls spamming
|
||||
// the real time limit is 1500/sec
|
||||
@@ -55,6 +56,11 @@ static void cadillac_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int tx = 1;
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (!addr_allowed(addr, bus, CADILLAC_TX_MSGS, sizeof(CADILLAC_TX_MSGS) / sizeof(CADILLAC_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// steer cmd checks
|
||||
if ((addr == 0x151) || (addr == 0x152) || (addr == 0x153) || (addr == 0x154)) {
|
||||
@@ -109,13 +115,8 @@ static int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
return tx;
|
||||
}
|
||||
|
||||
static void cadillac_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = 0;
|
||||
}
|
||||
|
||||
const safety_hooks cadillac_hooks = {
|
||||
.init = cadillac_init,
|
||||
.init = nooutput_init,
|
||||
.rx = cadillac_rx_hook,
|
||||
.tx = cadillac_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
|
||||
@@ -4,8 +4,8 @@ const uint32_t CHRYSLER_RT_INTERVAL = 250000; // 250ms between real time checks
|
||||
const int CHRYSLER_MAX_RATE_UP = 3;
|
||||
const int CHRYSLER_MAX_RATE_DOWN = 3;
|
||||
const int CHRYSLER_MAX_TORQUE_ERROR = 80; // max torque cmd in excess of torque motor
|
||||
const AddrBus CHRYSLER_TX_MSGS[] = {{571, 0}, {658, 0}, {678, 0}};
|
||||
|
||||
bool chrysler_camera_detected = 0; // is giraffe switch 2 high?
|
||||
int chrysler_rt_torque_last = 0;
|
||||
int chrysler_desired_torque_last = 0;
|
||||
int chrysler_cruise_engaged_last = 0;
|
||||
@@ -36,23 +36,25 @@ static void chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
chrysler_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
|
||||
// check if stock camera ECU is still online
|
||||
if ((bus == 0) && (addr == 0x292)) {
|
||||
chrysler_camera_detected = 1;
|
||||
controls_allowed = 0;
|
||||
// check if stock camera ECU is on bus 0
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == 0x292)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
int tx = 1;
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
// If camera is on bus 0, then nothing can be sent
|
||||
if (chrysler_camera_detected) {
|
||||
if (!addr_allowed(addr, bus, CHRYSLER_TX_MSGS, sizeof(CHRYSLER_TX_MSGS) / sizeof(CHRYSLER_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
int addr = GET_ADDR(to_send);
|
||||
if (relay_malfunction) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// LKA STEER
|
||||
if (addr == 0x292) {
|
||||
@@ -100,39 +102,37 @@ static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
}
|
||||
}
|
||||
|
||||
// FORCE CANCEL: safety check only relevant when spamming the cancel button.
|
||||
// ensuring that only the cancel button press is sent when controls are off.
|
||||
// This avoids unintended engagements while still allowing resume spam
|
||||
// TODO: fix bug preventing the button msg to be fwd'd on bus 2
|
||||
// FORCE CANCEL: only the cancel button press is allowed
|
||||
if (addr == 571) {
|
||||
if (GET_BYTE(to_send, 0) != 1) {
|
||||
tx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 1 allows the message through
|
||||
return tx;
|
||||
}
|
||||
|
||||
static void chrysler_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = 0;
|
||||
chrysler_camera_detected = 0;
|
||||
}
|
||||
|
||||
static int chrysler_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
|
||||
int bus_fwd = -1;
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
// forward CAN 0 -> 2 so stock LKAS camera sees messages
|
||||
if ((bus_num == 0) && !chrysler_camera_detected) {
|
||||
bus_fwd = 2;
|
||||
}
|
||||
// forward all messages from camera except LKAS_COMMAND and LKAS_HUD
|
||||
if ((bus_num == 2) && !chrysler_camera_detected && (addr != 658) && (addr != 678)) {
|
||||
bus_fwd = 0;
|
||||
|
||||
if (!relay_malfunction) {
|
||||
// forward CAN 0 -> 2 so stock LKAS camera sees messages
|
||||
if (bus_num == 0) {
|
||||
bus_fwd = 2;
|
||||
}
|
||||
// forward all messages from camera except LKAS_COMMAND and LKAS_HUD
|
||||
if ((bus_num == 2) && (addr != 658) && (addr != 678)) {
|
||||
bus_fwd = 0;
|
||||
}
|
||||
}
|
||||
return bus_fwd;
|
||||
}
|
||||
|
||||
|
||||
const safety_hooks chrysler_hooks = {
|
||||
.init = chrysler_init,
|
||||
.init = nooutput_init,
|
||||
.rx = chrysler_rx_hook,
|
||||
.tx = chrysler_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
|
||||
@@ -6,7 +6,8 @@ void default_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
static void nooutput_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = 0;
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
}
|
||||
|
||||
static int nooutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -39,7 +40,8 @@ const safety_hooks nooutput_hooks = {
|
||||
|
||||
static void alloutput_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = 1;
|
||||
controls_allowed = true;
|
||||
relay_malfunction = false;
|
||||
}
|
||||
|
||||
static int alloutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
@@ -12,7 +12,7 @@ static int elm327_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
//Check valid 29 bit send addresses for ISO 15765-4
|
||||
//Check valid 11 bit send addresses for ISO 15765-4
|
||||
if ((addr != 0x18DB33F1) && ((addr & 0x1FFF00FF) != 0x18DA00F1) &&
|
||||
((addr != 0x7DF) && ((addr & 0x7F8) != 0x7E0))) {
|
||||
((addr != 0x7DF) && ((addr & 0x1FFFFFF8) != 0x7E0))) {
|
||||
tx = 0;
|
||||
}
|
||||
return tx;
|
||||
|
||||
@@ -14,6 +14,7 @@ bool ford_moving = false;
|
||||
static void ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
int addr = GET_ADDR(to_push);
|
||||
int bus = GET_BUS(to_push);
|
||||
|
||||
if (addr == 0x217) {
|
||||
// wheel speeds are 14 bits every 16
|
||||
@@ -53,6 +54,10 @@ static void ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
}
|
||||
ford_gas_prev = gas;
|
||||
}
|
||||
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == 0x3CA)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
}
|
||||
|
||||
// all commands: just steering
|
||||
@@ -64,11 +69,16 @@ static void ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int ford_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
int tx = 1;
|
||||
int addr = GET_ADDR(to_send);
|
||||
|
||||
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
|
||||
// and the the latching controls_allowed flag is True
|
||||
int pedal_pressed = ford_gas_prev || (ford_brake_prev && ford_moving);
|
||||
bool current_controls_allowed = controls_allowed && !(pedal_pressed);
|
||||
int addr = GET_ADDR(to_send);
|
||||
|
||||
if (relay_malfunction) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// STEER: safety check
|
||||
if (addr == 0x3CA) {
|
||||
@@ -92,6 +102,8 @@ static int ford_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
return tx;
|
||||
}
|
||||
|
||||
// TODO: keep camera on bus 2 and make a fwd_hook
|
||||
|
||||
const safety_hooks ford_hooks = {
|
||||
.init = nooutput_init,
|
||||
.rx = ford_rx_hook,
|
||||
|
||||
@@ -18,19 +18,21 @@ const int GM_DRIVER_TORQUE_FACTOR = 4;
|
||||
const int GM_MAX_GAS = 3072;
|
||||
const int GM_MAX_REGEN = 1404;
|
||||
const int GM_MAX_BRAKE = 350;
|
||||
const AddrBus GM_TX_MSGS[] = {{384, 0}, {1033, 0}, {1034, 0}, {715, 0}, {880, 0}, // pt bus
|
||||
{161, 1}, {774, 1}, {776, 1}, {784, 1}, // obs bus
|
||||
{789, 2}, // ch bus
|
||||
{0x104c006c, 3}, {0x10400060, 3}}; // gmlan
|
||||
|
||||
int gm_brake_prev = 0;
|
||||
int gm_gas_prev = 0;
|
||||
bool gm_moving = false;
|
||||
// silence everything if stock car control ECUs are still online
|
||||
bool gm_ascm_detected = 0;
|
||||
int gm_rt_torque_last = 0;
|
||||
int gm_desired_torque_last = 0;
|
||||
uint32_t gm_ts_last = 0;
|
||||
struct sample_t gm_torque_driver; // last few driver torques measured
|
||||
|
||||
static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus_number = GET_BUS(to_push);
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
if (addr == 388) {
|
||||
@@ -46,15 +48,6 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
gm_moving = GET_BYTE(to_push, 0) | GET_BYTE(to_push, 1);
|
||||
}
|
||||
|
||||
// Check if ASCM or LKA camera are online
|
||||
// on powertrain bus.
|
||||
// 384 = ASCMLKASteeringCmd
|
||||
// 715 = ASCMGasRegenCmd
|
||||
if ((bus_number == 0) && ((addr == 384) || (addr == 715))) {
|
||||
gm_ascm_detected = 1;
|
||||
controls_allowed = 0;
|
||||
}
|
||||
|
||||
// ACC steering wheel buttons
|
||||
if (addr == 481) {
|
||||
int button = (GET_BYTE(to_push, 5) & 0x70) >> 4;
|
||||
@@ -102,6 +95,14 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if ASCM or LKA camera are online
|
||||
// on powertrain bus.
|
||||
// 384 = ASCMLKASteeringCmd
|
||||
// 715 = ASCMGasRegenCmd
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && ((addr == 384) || (addr == 715))) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
}
|
||||
|
||||
// all commands: gas/regen, friction brake and steering
|
||||
@@ -113,9 +114,14 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
int tx = 1;
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
// There can be only one! (ASCM)
|
||||
if (gm_ascm_detected) {
|
||||
if (!addr_allowed(addr, bus, GM_TX_MSGS, sizeof(GM_TX_MSGS)/sizeof(GM_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
if (relay_malfunction) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
@@ -124,8 +130,6 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int pedal_pressed = gm_gas_prev || (gm_brake_prev && gm_moving);
|
||||
bool current_controls_allowed = controls_allowed && !pedal_pressed;
|
||||
|
||||
int addr = GET_ADDR(to_send);
|
||||
|
||||
// BRAKE: safety check
|
||||
if (addr == 789) {
|
||||
int brake = ((GET_BYTE(to_send, 0) & 0xFU) << 8) + GET_BYTE(to_send, 1);
|
||||
@@ -188,11 +192,6 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
}
|
||||
}
|
||||
|
||||
// PARK ASSIST STEER: unlimited torque, no thanks
|
||||
if (addr == 823) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// GAS/REGEN: safety check
|
||||
if (addr == 715) {
|
||||
int gas_regen = ((GET_BYTE(to_send, 2) & 0x7FU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3);
|
||||
@@ -213,14 +212,9 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
return tx;
|
||||
}
|
||||
|
||||
static void gm_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = 0;
|
||||
}
|
||||
|
||||
|
||||
const safety_hooks gm_hooks = {
|
||||
.init = gm_init,
|
||||
.init = nooutput_init,
|
||||
.rx = gm_rx_hook,
|
||||
.tx = gm_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
// accel rising edge
|
||||
// brake rising edge
|
||||
// brake > 0mph
|
||||
|
||||
const AddrBus HONDA_N_TX_MSGS[] = {{0xE4, 0}, {0x194, 0}, {0x1FA, 0}, {0x200, 0}, {0x30C, 0}, {0x33D, 0}, {0x39F, 0}};
|
||||
const AddrBus HONDA_BH_TX_MSGS[] = {{0xE4, 0}, {0x296, 1}, {0x33D, 0}}; // Bosch Harness
|
||||
const AddrBus HONDA_BG_TX_MSGS[] = {{0xE4, 2}, {0x296, 0}, {0x33D, 2}}; // Bosch Giraffe
|
||||
const int HONDA_GAS_INTERCEPTOR_THRESHOLD = 328; // ratio between offset and gain from dbc file
|
||||
int honda_brake = 0;
|
||||
int honda_gas_prev = 0;
|
||||
@@ -95,7 +97,17 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
} else if (honda_stock_brake >= honda_brake) {
|
||||
honda_fwd_brake = true;
|
||||
} else {
|
||||
// Leave honda forward brake as is
|
||||
// Leave Honda forward brake as is
|
||||
}
|
||||
}
|
||||
|
||||
// if steering controls messages are received on the destination bus, it's an indication
|
||||
// that the relay might be malfunctioning
|
||||
int bus_rdr_car = (board_has_relay()) ? 0 : 2; // radar bus, car side
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && ((addr == 0xE4) || (addr == 0x194))) {
|
||||
if ((honda_bosch_hardware && (bus == bus_rdr_car)) ||
|
||||
(!honda_bosch_hardware && (bus == 0))) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,6 +124,22 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (honda_bosch_hardware) {
|
||||
if (board_has_relay() && !addr_allowed(addr, bus, HONDA_BH_TX_MSGS, sizeof(HONDA_BH_TX_MSGS)/sizeof(HONDA_BH_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
if (!board_has_relay() && !addr_allowed(addr, bus, HONDA_BG_TX_MSGS, sizeof(HONDA_BG_TX_MSGS)/sizeof(HONDA_BG_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
}
|
||||
if (!honda_bosch_hardware && !addr_allowed(addr, bus, HONDA_N_TX_MSGS, sizeof(HONDA_N_TX_MSGS)/sizeof(HONDA_N_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
if (relay_malfunction) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
|
||||
// and the the latching controls_allowed flag is True
|
||||
int pedal_pressed = honda_gas_prev || (gas_interceptor_prev > HONDA_GAS_INTERCEPTOR_THRESHOLD) ||
|
||||
@@ -170,13 +198,15 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
static void honda_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = 0;
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
honda_bosch_hardware = false;
|
||||
honda_alt_brake_msg = false;
|
||||
}
|
||||
|
||||
static void honda_bosch_init(int16_t param) {
|
||||
controls_allowed = 0;
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
honda_bosch_hardware = true;
|
||||
// Checking for alternate brake override from safety parameter
|
||||
honda_alt_brake_msg = (param == 1) ? true : false;
|
||||
@@ -189,20 +219,22 @@ static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
// 0x39f is radar hud
|
||||
int bus_fwd = -1;
|
||||
|
||||
if (bus_num == 0) {
|
||||
bus_fwd = 2;
|
||||
}
|
||||
if (bus_num == 2) {
|
||||
// block stock lkas messages and stock acc messages (if OP is doing ACC)
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
bool is_lkas_msg = (addr == 0xE4) || (addr == 0x194) || (addr == 0x33D);
|
||||
bool is_acc_hud_msg = (addr == 0x30C) || (addr == 0x39F);
|
||||
bool is_brake_msg = addr == 0x1FA;
|
||||
bool block_fwd = is_lkas_msg ||
|
||||
(is_acc_hud_msg && long_controls_allowed) ||
|
||||
(is_brake_msg && long_controls_allowed && !honda_fwd_brake);
|
||||
if (!block_fwd) {
|
||||
bus_fwd = 0;
|
||||
if (!relay_malfunction) {
|
||||
if (bus_num == 0) {
|
||||
bus_fwd = 2;
|
||||
}
|
||||
if (bus_num == 2) {
|
||||
// block stock lkas messages and stock acc messages (if OP is doing ACC)
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
bool is_lkas_msg = (addr == 0xE4) || (addr == 0x194) || (addr == 0x33D);
|
||||
bool is_acc_hud_msg = (addr == 0x30C) || (addr == 0x39F);
|
||||
bool is_brake_msg = addr == 0x1FA;
|
||||
bool block_fwd = is_lkas_msg ||
|
||||
(is_acc_hud_msg && long_controls_allowed) ||
|
||||
(is_brake_msg && long_controls_allowed && !honda_fwd_brake);
|
||||
if (!block_fwd) {
|
||||
bus_fwd = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bus_fwd;
|
||||
@@ -213,14 +245,16 @@ static int honda_bosch_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
int bus_rdr_cam = (board_has_relay()) ? 2 : 1; // radar bus, camera side
|
||||
int bus_rdr_car = (board_has_relay()) ? 0 : 2; // radar bus, car side
|
||||
|
||||
if (bus_num == bus_rdr_car) {
|
||||
bus_fwd = bus_rdr_cam;
|
||||
}
|
||||
if (bus_num == bus_rdr_cam) {
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
int is_lkas_msg = (addr == 0xE4) || (addr == 0x33D);
|
||||
if (!is_lkas_msg) {
|
||||
bus_fwd = bus_rdr_car;
|
||||
if (!relay_malfunction) {
|
||||
if (bus_num == bus_rdr_car) {
|
||||
bus_fwd = bus_rdr_cam;
|
||||
}
|
||||
if (bus_num == bus_rdr_cam) {
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
int is_lkas_msg = (addr == 0xE4) || (addr == 0x33D);
|
||||
if (!is_lkas_msg) {
|
||||
bus_fwd = bus_rdr_car;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bus_fwd;
|
||||
|
||||
@@ -6,9 +6,8 @@ const int HYUNDAI_MAX_RATE_DOWN = 7;
|
||||
const int HYUNDAI_DRIVER_TORQUE_ALLOWANCE = 50;
|
||||
const int HYUNDAI_DRIVER_TORQUE_FACTOR = 2;
|
||||
|
||||
bool hyundai_camera_detected = 0;
|
||||
bool hyundai_giraffe_switch_2 = 0; // is giraffe switch 2 high?
|
||||
int hyundai_camera_bus = 0;
|
||||
const AddrBus HYUNDAI_TX_MSGS[] = {{832, 0}, {1265, 0}};
|
||||
|
||||
int hyundai_rt_torque_last = 0;
|
||||
int hyundai_desired_torque_last = 0;
|
||||
int hyundai_cruise_engaged_last = 0;
|
||||
@@ -25,15 +24,9 @@ static void hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
update_sample(&hyundai_torque_driver, torque_driver_new);
|
||||
}
|
||||
|
||||
// check if stock camera ECU is still online
|
||||
if ((bus == 0) && (addr == 832)) {
|
||||
hyundai_camera_detected = 1;
|
||||
controls_allowed = 0;
|
||||
}
|
||||
|
||||
// Find out which bus the camera is on
|
||||
if (addr == 832) {
|
||||
hyundai_camera_bus = bus;
|
||||
// check if stock camera ECU is on bus 0
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == 832)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
|
||||
// enter controls on rising edge of ACC, exit controls on ACC off
|
||||
@@ -48,20 +41,19 @@ static void hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
}
|
||||
hyundai_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
|
||||
// 832 is lkas cmd. If it is on camera bus, then giraffe switch 2 is high
|
||||
if ((addr == 832) && (bus == hyundai_camera_bus) && (hyundai_camera_bus != 0)) {
|
||||
hyundai_giraffe_switch_2 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
int tx = 1;
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
// There can be only one! (camera)
|
||||
if (hyundai_camera_detected) {
|
||||
if (!addr_allowed(addr, bus, HYUNDAI_TX_MSGS, sizeof(HYUNDAI_TX_MSGS)/sizeof(HYUNDAI_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
if (relay_malfunction) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
@@ -115,12 +107,11 @@ static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
// FORCE CANCEL: safety check only relevant when spamming the cancel button.
|
||||
// ensuring that only the cancel button press is sent (VAL 4) when controls are off.
|
||||
// This avoids unintended engagements while still allowing resume spam
|
||||
// TODO: fix bug preventing the button msg to be fwd'd on bus 2
|
||||
//if ((addr == 1265) && !controls_allowed && (bus == 0) {
|
||||
// if ((GET_BYTES_04(to_send) & 0x7) != 4) {
|
||||
// tx = 0;
|
||||
// }
|
||||
//}
|
||||
if ((addr == 1265) && !controls_allowed) {
|
||||
if ((GET_BYTES_04(to_send) & 0x7) != 4) {
|
||||
tx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 1 allows the message through
|
||||
return tx;
|
||||
@@ -129,29 +120,22 @@ static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
static int hyundai_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
|
||||
int bus_fwd = -1;
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
// forward cam to ccan and viceversa, except lkas cmd
|
||||
if (hyundai_giraffe_switch_2) {
|
||||
if (!relay_malfunction) {
|
||||
if (bus_num == 0) {
|
||||
bus_fwd = hyundai_camera_bus;
|
||||
bus_fwd = 2;
|
||||
}
|
||||
if (bus_num == hyundai_camera_bus) {
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
if (addr != 832) {
|
||||
bus_fwd = 0;
|
||||
}
|
||||
if ((bus_num == 2) && (addr != 832)) {
|
||||
bus_fwd = 0;
|
||||
}
|
||||
}
|
||||
return bus_fwd;
|
||||
}
|
||||
|
||||
static void hyundai_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = 0;
|
||||
hyundai_giraffe_switch_2 = 0;
|
||||
}
|
||||
|
||||
const safety_hooks hyundai_hooks = {
|
||||
.init = hyundai_init,
|
||||
.init = nooutput_init,
|
||||
.rx = hyundai_rx_hook,
|
||||
.tx = hyundai_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
|
||||
@@ -30,12 +30,6 @@ uint32_t mazda_ts_last = 0;
|
||||
struct sample_t mazda_torque_driver; // last few driver torques measured
|
||||
|
||||
// track msgs coming from OP so that we know what CAM msgs to drop and what to forward
|
||||
int mazda_op_lkas_detected = 0;
|
||||
int mazda_op_laneinfo_detected = 0;
|
||||
|
||||
int mazda_forward_cam = 0;
|
||||
int mazda_giraffe_switch_2_on = 0;
|
||||
|
||||
void mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
@@ -51,7 +45,7 @@ void mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int cruise_engaged = GET_BYTE(to_push, 0) & 8;
|
||||
if (cruise_engaged != 0) {
|
||||
if (!mazda_cruise_engaged_last) {
|
||||
controls_allowed = 1;
|
||||
controls_allowed = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -60,17 +54,9 @@ void mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
mazda_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
|
||||
// we have msgs on bus MAZDA_CAM
|
||||
if (bus == MAZDA_CAM) {
|
||||
// the stock CAM is connected
|
||||
if (addr == MAZDA_LKAS) {
|
||||
mazda_forward_cam = 1;
|
||||
}
|
||||
// if we see wheel speed msgs on MAZDA_CAM bus then giraffe switch 2 is high
|
||||
// (hardware passthru)
|
||||
if (addr == MAZDA_WHEEL_SPEED) {
|
||||
mazda_giraffe_switch_2_on = 1;
|
||||
}
|
||||
// if we see wheel speed msgs on MAZDA_CAM bus then relay is closed
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == MAZDA_CAM) && (addr == MAZDA_WHEEL_SPEED)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,15 +65,12 @@ static int mazda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (relay_malfunction) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// Check if msg is sent on the main BUS
|
||||
if (bus == MAZDA_MAIN) {
|
||||
if ((addr == MAZDA_LKAS) && !mazda_op_lkas_detected){
|
||||
mazda_op_lkas_detected = 1;
|
||||
}
|
||||
if ((addr == MAZDA_LANEINFO) && !mazda_op_laneinfo_detected){
|
||||
mazda_op_laneinfo_detected = 1;
|
||||
}
|
||||
|
||||
// steer cmd checks
|
||||
if (addr == MAZDA_LKAS) {
|
||||
int desired_torque = (((GET_BYTE(to_send, 0) & 0x0f) << 8) | GET_BYTE(to_send, 1)) - MAZDA_MAX_STEER;
|
||||
@@ -96,42 +79,42 @@ static int mazda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
if (controls_allowed) {
|
||||
|
||||
// *** global torque limit check ***
|
||||
violation |= max_limit_check(desired_torque, MAZDA_MAX_STEER, -MAZDA_MAX_STEER);
|
||||
// *** global torque limit check ***
|
||||
violation |= max_limit_check(desired_torque, MAZDA_MAX_STEER, -MAZDA_MAX_STEER);
|
||||
|
||||
// *** torque rate limit check ***
|
||||
int desired_torque_last = mazda_desired_torque_last;
|
||||
violation |= driver_limit_check(desired_torque, desired_torque_last, &mazda_torque_driver,
|
||||
MAZDA_MAX_STEER, MAZDA_MAX_RATE_UP, MAZDA_MAX_RATE_DOWN,
|
||||
MAZDA_DRIVER_TORQUE_ALLOWANCE, MAZDA_DRIVER_TORQUE_FACTOR);
|
||||
// used next time
|
||||
mazda_desired_torque_last = desired_torque;
|
||||
// *** torque rate limit check ***
|
||||
int desired_torque_last = mazda_desired_torque_last;
|
||||
violation |= driver_limit_check(desired_torque, desired_torque_last, &mazda_torque_driver,
|
||||
MAZDA_MAX_STEER, MAZDA_MAX_RATE_UP, MAZDA_MAX_RATE_DOWN,
|
||||
MAZDA_DRIVER_TORQUE_ALLOWANCE, MAZDA_DRIVER_TORQUE_FACTOR);
|
||||
// used next time
|
||||
mazda_desired_torque_last = desired_torque;
|
||||
|
||||
// *** torque real time rate limit check ***
|
||||
violation |= rt_rate_limit_check(desired_torque, mazda_rt_torque_last, MAZDA_MAX_RT_DELTA);
|
||||
// *** torque real time rate limit check ***
|
||||
violation |= rt_rate_limit_check(desired_torque, mazda_rt_torque_last, MAZDA_MAX_RT_DELTA);
|
||||
|
||||
// every RT_INTERVAL set the new limits
|
||||
uint32_t ts_elapsed = get_ts_elapsed(ts, mazda_ts_last);
|
||||
if (ts_elapsed > ((uint32_t) MAZDA_RT_INTERVAL)) {
|
||||
mazda_rt_torque_last = desired_torque;
|
||||
mazda_ts_last = ts;
|
||||
}
|
||||
// every RT_INTERVAL set the new limits
|
||||
uint32_t ts_elapsed = get_ts_elapsed(ts, mazda_ts_last);
|
||||
if (ts_elapsed > ((uint32_t) MAZDA_RT_INTERVAL)) {
|
||||
mazda_rt_torque_last = desired_torque;
|
||||
mazda_ts_last = ts;
|
||||
}
|
||||
}
|
||||
|
||||
// no torque if controls is not allowed
|
||||
if (!controls_allowed && (desired_torque != 0)) {
|
||||
violation = 1;
|
||||
violation = 1;
|
||||
}
|
||||
|
||||
// reset to 0 if either controls is not allowed or there's a violation
|
||||
if (violation || !controls_allowed) {
|
||||
mazda_desired_torque_last = 0;
|
||||
mazda_rt_torque_last = 0;
|
||||
mazda_ts_last = ts;
|
||||
mazda_desired_torque_last = 0;
|
||||
mazda_rt_torque_last = 0;
|
||||
mazda_ts_last = ts;
|
||||
}
|
||||
|
||||
if (violation) {
|
||||
tx = 0;
|
||||
tx = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,16 +123,14 @@ static int mazda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
static int mazda_fwd_hook(int bus, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
int bus_fwd = -1;
|
||||
if (mazda_forward_cam && !mazda_giraffe_switch_2_on) {
|
||||
if (!relay_malfunction) {
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
if (bus == MAZDA_MAIN) {
|
||||
bus_fwd = MAZDA_CAM;
|
||||
}
|
||||
else if (bus == MAZDA_CAM) {
|
||||
// drop stock CAM_LKAS and CAM_LANEINFI if OP is sending them
|
||||
if (!((addr == MAZDA_LKAS) && mazda_op_lkas_detected) &&
|
||||
!((addr == MAZDA_LANEINFO) && mazda_op_laneinfo_detected)) {
|
||||
bus_fwd = MAZDA_MAIN;
|
||||
if (!(addr == MAZDA_LKAS)) {
|
||||
bus_fwd = MAZDA_MAIN;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -8,6 +8,8 @@ const int SUBARU_MAX_RATE_DOWN = 70;
|
||||
const int SUBARU_DRIVER_TORQUE_ALLOWANCE = 60;
|
||||
const int SUBARU_DRIVER_TORQUE_FACTOR = 10;
|
||||
|
||||
const AddrBus SUBARU_TX_MSGS[] = {{0x122, 0}, {0x164, 0}, {0x221, 0}, {0x322, 0}};
|
||||
|
||||
int subaru_cruise_engaged_last = 0;
|
||||
int subaru_rt_torque_last = 0;
|
||||
int subaru_desired_torque_last = 0;
|
||||
@@ -38,11 +40,24 @@ static void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
}
|
||||
subaru_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && ((addr == 0x122) || (addr == 0x164))) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int tx = 1;
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (!addr_allowed(addr, bus, SUBARU_TX_MSGS, sizeof(SUBARU_TX_MSGS) / sizeof(SUBARU_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
if (relay_malfunction) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// steer cmd checks
|
||||
if ((addr == 0x122) || (addr == 0x164)) {
|
||||
@@ -98,23 +113,24 @@ static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
}
|
||||
|
||||
static int subaru_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
|
||||
int bus_fwd = -1;
|
||||
if (bus_num == 0) {
|
||||
bus_fwd = 2; // Camera CAN
|
||||
}
|
||||
if (bus_num == 2) {
|
||||
// 290 is LKAS for Global Platform
|
||||
// 356 is LKAS for outback 2015
|
||||
// 545 is ES_Distance
|
||||
// 802 is ES_LKAS
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
int block_msg = (addr == 290) || (addr == 356) || (addr == 545) || (addr == 802);
|
||||
if (!block_msg) {
|
||||
bus_fwd = 0; // Main CAN
|
||||
|
||||
if (!relay_malfunction) {
|
||||
if (bus_num == 0) {
|
||||
bus_fwd = 2; // Camera CAN
|
||||
}
|
||||
if (bus_num == 2) {
|
||||
// 290 is LKAS for Global Platform
|
||||
// 356 is LKAS for outback 2015
|
||||
// 545 is ES_Distance
|
||||
// 802 is ES_LKAS
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
int block_msg = (addr == 290) || (addr == 356) || (addr == 545) || (addr == 802);
|
||||
if (!block_msg) {
|
||||
bus_fwd = 0; // Main CAN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to do not forward
|
||||
return bus_fwd;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,16 @@ const int TOYOTA_MIN_ACCEL = -3000; // 3.0 m/s2
|
||||
|
||||
const int TOYOTA_GAS_INTERCEPTOR_THRESHOLD = 475; // ratio between offset and gain from dbc file
|
||||
|
||||
// allowed DSU messages on bus 0 and 1
|
||||
const AddrBus TOYOTA_TX_MSGS[] = {{0x283, 0}, {0x2E6, 0}, {0x2E7, 0}, {0x33E, 0}, {0x344, 0}, {0x365, 0}, {0x366, 0}, {0x4CB, 0}, // DSU bus 0
|
||||
{0x128, 1}, {0x141, 1}, {0x160, 1}, {0x161, 1}, {0x470, 1}, // DSU bus 1
|
||||
{0x2E4, 0}, {0x411, 0}, {0x412, 0}, {0x343, 0}, {0x1D2, 0}, // LKAS + ACC
|
||||
{0x200, 0}}; // interceptor
|
||||
|
||||
// global actuation limit states
|
||||
int toyota_dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file
|
||||
|
||||
// states
|
||||
int toyota_giraffe_switch_1 = 0; // is giraffe switch 1 high?
|
||||
int toyota_camera_forwarded = 0; // should we forward the camera bus?
|
||||
int toyota_desired_torque_last = 0; // last desired steer torque
|
||||
int toyota_rt_torque_last = 0; // last desired torque for real time check
|
||||
uint32_t toyota_ts_last = 0;
|
||||
@@ -87,14 +91,9 @@ static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
toyota_gas_prev = gas;
|
||||
}
|
||||
|
||||
// msgs are only on bus 2 if panda is connected to frc
|
||||
if (bus == 2) {
|
||||
toyota_camera_forwarded = 1;
|
||||
}
|
||||
|
||||
// 0x2E4 is lkas cmd. If it is on bus 0, then giraffe switch 1 is high
|
||||
if ((addr == 0x2E4) && (bus == 0)) {
|
||||
toyota_giraffe_switch_1 = 1;
|
||||
// 0x2E4 is lkas cmd. If it is on bus 0, then relay is unexpectedly closed
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (addr == 0x2E4) && (bus == 0)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,14 +103,17 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (!addr_allowed(addr, bus, TOYOTA_TX_MSGS, sizeof(TOYOTA_TX_MSGS)/sizeof(TOYOTA_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
if (relay_malfunction) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// Check if msg is sent on BUS 0
|
||||
if (bus == 0) {
|
||||
|
||||
// no IPAS in non IPAS mode
|
||||
if ((addr == 0x266) || (addr == 0x167)) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// GAS PEDAL: safety check
|
||||
if (addr == 0x200) {
|
||||
if (!controls_allowed || !long_controls_allowed) {
|
||||
@@ -185,28 +187,26 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
}
|
||||
}
|
||||
|
||||
// 1 allows the message through
|
||||
return tx;
|
||||
}
|
||||
|
||||
static void toyota_init(int16_t param) {
|
||||
controls_allowed = 0;
|
||||
toyota_giraffe_switch_1 = 0;
|
||||
toyota_camera_forwarded = 0;
|
||||
relay_malfunction = 0;
|
||||
toyota_dbc_eps_torque_factor = param;
|
||||
}
|
||||
|
||||
static int toyota_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
|
||||
int bus_fwd = -1;
|
||||
if (toyota_camera_forwarded && !toyota_giraffe_switch_1) {
|
||||
if (!relay_malfunction) {
|
||||
if (bus_num == 0) {
|
||||
bus_fwd = 2;
|
||||
}
|
||||
if (bus_num == 2) {
|
||||
int addr = GET_ADDR(to_fwd);
|
||||
// block stock lkas messages and stock acc messages (if OP is doing ACC)
|
||||
// in TSS2, 0.191 is LTA which we need to block to avoid controls collision
|
||||
// in TSS2, 0x191 is LTA which we need to block to avoid controls collision
|
||||
int is_lkas_msg = ((addr == 0x2E4) || (addr == 0x412) || (addr == 0x191));
|
||||
// in TSS2 the camera does ACC as well, so filter 0x343
|
||||
int is_acc_msg = (addr == 0x343);
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
// Safety-relevant CAN messages for the Volkswagen MQB platform.
|
||||
#define MSG_EPS_01 0x09F
|
||||
#define MSG_MOTOR_20 0x121
|
||||
#define MSG_ACC_06 0x122
|
||||
#define MSG_HCA_01 0x126
|
||||
#define MSG_GRA_ACC_01 0x12B
|
||||
#define MSG_LDW_02 0x397
|
||||
|
||||
const int VOLKSWAGEN_MAX_STEER = 250; // 2.5 Nm (EPS side max of 3.0Nm with fault if violated)
|
||||
const int VOLKSWAGEN_MAX_RT_DELTA = 75; // 4 max rate up * 50Hz send rate * 250000 RT interval / 1000000 = 50 ; 50 * 1.5 for safety pad = 75
|
||||
const uint32_t VOLKSWAGEN_RT_INTERVAL = 250000; // 250ms between real time checks
|
||||
@@ -6,26 +14,15 @@ const int VOLKSWAGEN_MAX_RATE_DOWN = 10; // 5.0 Nm/s available rate o
|
||||
const int VOLKSWAGEN_DRIVER_TORQUE_ALLOWANCE = 80;
|
||||
const int VOLKSWAGEN_DRIVER_TORQUE_FACTOR = 3;
|
||||
|
||||
// MSG_GRA_ACC_01 is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration
|
||||
const AddrBus VOLKSWAGEN_TX_MSGS[] = {{MSG_HCA_01, 0}, {MSG_GRA_ACC_01, 0}, {MSG_GRA_ACC_01, 2}, {MSG_LDW_02, 0}};
|
||||
|
||||
struct sample_t volkswagen_torque_driver; // last few driver torques measured
|
||||
int volkswagen_rt_torque_last = 0;
|
||||
int volkswagen_desired_torque_last = 0;
|
||||
uint32_t volkswagen_ts_last = 0;
|
||||
int volkswagen_gas_prev = 0;
|
||||
|
||||
// Safety-relevant CAN messages for the Volkswagen MQB platform.
|
||||
#define MSG_EPS_01 0x09F
|
||||
#define MSG_MOTOR_20 0x121
|
||||
#define MSG_ACC_06 0x122
|
||||
#define MSG_HCA_01 0x126
|
||||
#define MSG_GRA_ACC_01 0x12B
|
||||
#define MSG_LDW_02 0x397
|
||||
#define MSG_KLEMMEN_STATUS_01 0x3C0
|
||||
|
||||
static void volkswagen_init(int16_t param) {
|
||||
UNUSED(param); // May use param in the future to indicate MQB vs PQ35/PQ46/NMS vs MLB, or wiring configuration.
|
||||
controls_allowed = 0;
|
||||
}
|
||||
|
||||
static void volkswagen_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
@@ -58,6 +55,10 @@ static void volkswagen_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
}
|
||||
volkswagen_gas_prev = gas;
|
||||
}
|
||||
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == MSG_HCA_01)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int volkswagen_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -65,6 +66,14 @@ static int volkswagen_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int bus = GET_BUS(to_send);
|
||||
int tx = 1;
|
||||
|
||||
if (!addr_allowed(addr, bus, VOLKSWAGEN_TX_MSGS, sizeof(VOLKSWAGEN_TX_MSGS)/sizeof(VOLKSWAGEN_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
if (relay_malfunction) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
// Safety check for HCA_01 Heading Control Assist torque.
|
||||
if (addr == MSG_HCA_01) {
|
||||
bool violation = false;
|
||||
@@ -118,7 +127,7 @@ static int volkswagen_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
// FORCE CANCEL: ensuring that only the cancel button press is sent when controls are off.
|
||||
// This avoids unintended engagements while still allowing resume spam
|
||||
if ((bus == 2) && (addr == MSG_GRA_ACC_01) && !controls_allowed) {
|
||||
if ((addr == MSG_GRA_ACC_01) && !controls_allowed) {
|
||||
// disallow resume and set: bits 16 and 19
|
||||
if ((GET_BYTE(to_send, 2) & 0x9) != 0) {
|
||||
tx = 0;
|
||||
@@ -135,31 +144,32 @@ static int volkswagen_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
|
||||
// NOTE: Will need refactoring for other bus layouts, such as no-forwarding at camera or J533 running-gear CAN
|
||||
|
||||
switch (bus_num) {
|
||||
case 0:
|
||||
// Forward all traffic from J533 gateway to Extended CAN devices.
|
||||
bus_fwd = 2;
|
||||
break;
|
||||
case 2:
|
||||
if ((addr == MSG_HCA_01) || (addr == MSG_LDW_02)) {
|
||||
// OP takes control of the Heading Control Assist and Lane Departure Warning messages from the camera.
|
||||
if (!relay_malfunction) {
|
||||
switch (bus_num) {
|
||||
case 0:
|
||||
// Forward all traffic from J533 gateway to Extended CAN devices.
|
||||
bus_fwd = 2;
|
||||
break;
|
||||
case 2:
|
||||
if ((addr == MSG_HCA_01) || (addr == MSG_LDW_02)) {
|
||||
// OP takes control of the Heading Control Assist and Lane Departure Warning messages from the camera.
|
||||
bus_fwd = -1;
|
||||
} else {
|
||||
// Forward all remaining traffic from Extended CAN devices to J533 gateway.
|
||||
bus_fwd = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// No other buses should be in use; fallback to do-not-forward.
|
||||
bus_fwd = -1;
|
||||
} else {
|
||||
// Forward all remaining traffic from Extended CAN devices to J533 gateway.
|
||||
bus_fwd = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// No other buses should be in use; fallback to do-not-forward.
|
||||
bus_fwd = -1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bus_fwd;
|
||||
}
|
||||
|
||||
const safety_hooks volkswagen_hooks = {
|
||||
.init = volkswagen_init,
|
||||
.init = nooutput_init,
|
||||
.rx = volkswagen_rx_hook,
|
||||
.tx = volkswagen_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
|
||||
@@ -11,6 +11,11 @@ struct lookup_t {
|
||||
float y[3];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int addr;
|
||||
int bus;
|
||||
} AddrBus;
|
||||
|
||||
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
|
||||
int safety_tx_lin_hook(int lin_num, uint8_t *data, int len);
|
||||
@@ -25,6 +30,7 @@ bool driver_limit_check(int val, int val_last, struct sample_t *val_driver,
|
||||
const int MAX_ALLOWANCE, const int DRIVER_FACTOR);
|
||||
bool rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA);
|
||||
float interpolate(struct lookup_t xy, float x);
|
||||
bool addr_allowed(int addr, int bus, const AddrBus addr_list[], int len);
|
||||
|
||||
typedef void (*safety_hook_init)(int16_t param);
|
||||
typedef void (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
@@ -40,13 +46,19 @@ typedef struct {
|
||||
fwd_hook fwd;
|
||||
} safety_hooks;
|
||||
|
||||
// This can be set by the safety hooks.
|
||||
bool controls_allowed = 0;
|
||||
bool gas_interceptor_detected = 0;
|
||||
// This can be set by the safety hooks
|
||||
bool controls_allowed = false;
|
||||
bool relay_malfunction = false;
|
||||
bool gas_interceptor_detected = false;
|
||||
int gas_interceptor_prev = 0;
|
||||
|
||||
// This is set by USB command 0xdf
|
||||
bool long_controls_allowed = 1;
|
||||
bool long_controls_allowed = true;
|
||||
|
||||
// time since safety mode has been changed
|
||||
uint32_t safety_mode_cnt = 0U;
|
||||
// allow 1s of transition timeout after relay changes state before assessing malfunctioning
|
||||
const uint32_t RELAY_TRNS_TIMEOUT = 1U;
|
||||
|
||||
// avg between 2 tracks
|
||||
#define GET_INTERCEPTOR(msg) (((GET_BYTE((msg), 0) << 8) + GET_BYTE((msg), 1) + ((GET_BYTE((msg), 2) << 8) + GET_BYTE((msg), 3)) / 2 ) / 2)
|
||||
|
||||
@@ -65,7 +65,12 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
// so it's blocked over wifi
|
||||
switch (setup->b.wValue.w) {
|
||||
case 0:
|
||||
#ifdef ALLOW_DEBUG
|
||||
if (hardwired) {
|
||||
#else
|
||||
// no more bootstub on UNO
|
||||
if (hardwired && hw_type != HW_TYPE_UNO) {
|
||||
#endif
|
||||
puts("-> entering bootloader\n");
|
||||
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
NVIC_SystemReset();
|
||||
@@ -151,7 +156,7 @@ int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) {
|
||||
#define CAN_BL_INPUT 0x1
|
||||
#define CAN_BL_OUTPUT 0x2
|
||||
|
||||
void CAN1_TX_IRQHandler(void) {
|
||||
void CAN1_TX_IRQ_Handler(void) {
|
||||
// clear interrupt
|
||||
CAN->TSR |= CAN_TSR_RQCP0;
|
||||
}
|
||||
@@ -178,7 +183,7 @@ void bl_can_send(uint8_t *odat) {
|
||||
CAN->sTxMailBox[0].TIR = (CAN_BL_OUTPUT << 21) | 1;
|
||||
}
|
||||
|
||||
void CAN1_RX0_IRQHandler(void) {
|
||||
void CAN1_RX0_IRQ_Handler(void) {
|
||||
while (CAN->RF0R & CAN_RF0R_FMP0) {
|
||||
if ((CAN->sFIFOMailBox[0].RIR>>21) == CAN_BL_INPUT) {
|
||||
uint8_t dat[8];
|
||||
@@ -253,13 +258,19 @@ void CAN1_RX0_IRQHandler(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void CAN1_SCE_IRQHandler(void) {
|
||||
void CAN1_SCE_IRQ_Handler(void) {
|
||||
llcan_clear_send(CAN);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void soft_flasher_start(void) {
|
||||
#ifdef PEDAL
|
||||
REGISTER_INTERRUPT(CAN1_TX_IRQn, CAN1_TX_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_RX0_IRQn, CAN1_RX0_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
REGISTER_INTERRUPT(CAN1_SCE_IRQn, CAN1_SCE_IRQ_Handler, CAN_INTERRUPT_RATE, FAULT_INTERRUPT_RATE_CAN_1)
|
||||
#endif
|
||||
|
||||
puts("\n\n\n************************ FLASHER START ************************\n");
|
||||
|
||||
enter_bootloader_mode = 0;
|
||||
|
||||
Reference in New Issue
Block a user