From 022d1c69a14b6f6cfc29d68b0ae9a053b4f8d8fe Mon Sep 17 00:00:00 2001 From: Maxime Desroches Date: Fri, 20 Sep 2024 14:30:45 -0700 Subject: [PATCH] misra8.4: board/drivers (#2025) * drivers * cleanup bootkick * bxcan cleanup * fan cleanup * harness cleanup * interrupts cleanup * registers cleanup * simple_watchdog cleanup * spi cleanup * h7 drivers * no include for now * conflict * reduce scope * cleanup --- board/drivers/bootkick.h | 13 +- board/drivers/bootkick_declarations.h | 5 + board/drivers/bxcan.h | 26 +- board/drivers/bxcan_declarations.h | 22 + board/drivers/can_common.h | 51 +- board/drivers/can_common_declarations.h | 87 +++ board/drivers/clock_source.h | 3 +- board/drivers/clock_source_declarations.h | 7 + board/drivers/fake_siren.h | 10 +- board/drivers/fan.h | 23 +- board/drivers/fan_declarations.h | 20 + board/drivers/fdcan.h | 41 +- board/drivers/fdcan_declarations.h | 28 + board/drivers/harness.h | 27 +- board/drivers/harness_declarations.h | 34 ++ board/drivers/interrupts.h | 30 +- board/drivers/interrupts_declarations.h | 31 + board/drivers/registers.h | 16 +- board/drivers/registers_declarations.h | 24 + board/drivers/simple_watchdog.h | 9 +- board/drivers/simple_watchdog_declarations.h | 10 + board/drivers/spi.h | 49 +- board/drivers/spi_declarations.h | 52 ++ board/drivers/timers.h | 2 +- board/drivers/uart.h | 39 +- board/drivers/uart_declarations.h | 38 ++ board/drivers/usb.h | 602 ++++++++----------- board/drivers/usb_declarations.h | 115 ++++ board/drivers/watchdog.h | 2 +- board/stm32h7/llspi.h | 2 + 30 files changed, 803 insertions(+), 615 deletions(-) create mode 100644 board/drivers/bootkick_declarations.h create mode 100644 board/drivers/bxcan_declarations.h create mode 100644 board/drivers/can_common_declarations.h create mode 100644 board/drivers/clock_source_declarations.h create mode 100644 board/drivers/fan_declarations.h create mode 100644 board/drivers/fdcan_declarations.h create mode 100644 board/drivers/harness_declarations.h create mode 100644 board/drivers/interrupts_declarations.h create mode 100644 board/drivers/registers_declarations.h create mode 100644 board/drivers/simple_watchdog_declarations.h create mode 100644 board/drivers/spi_declarations.h create mode 100644 board/drivers/uart_declarations.h create mode 100644 board/drivers/usb_declarations.h diff --git a/board/drivers/bootkick.h b/board/drivers/bootkick.h index 4b75f0908..eab7da3eb 100644 --- a/board/drivers/bootkick.h +++ b/board/drivers/bootkick.h @@ -1,13 +1,14 @@ -bool bootkick_ign_prev = false; -BootState boot_state = BOOT_BOOTKICK; -uint8_t bootkick_harness_status_prev = HARNESS_STATUS_NC; +#include "bootkick_declarations.h" -uint8_t boot_reset_countdown = 0; -uint8_t waiting_to_boot_countdown = 0; bool bootkick_reset_triggered = false; -uint16_t bootkick_last_serial_ptr = 0; void bootkick_tick(bool ignition, bool recent_heartbeat) { + static uint16_t bootkick_last_serial_ptr = 0; + static uint8_t waiting_to_boot_countdown = 0; + static uint8_t boot_reset_countdown = 0; + static uint8_t bootkick_harness_status_prev = HARNESS_STATUS_NC; + static bool bootkick_ign_prev = false; + static BootState boot_state = BOOT_BOOTKICK; BootState boot_state_prev = boot_state; const bool harness_inserted = (harness.status != bootkick_harness_status_prev) && (harness.status != HARNESS_STATUS_NC); diff --git a/board/drivers/bootkick_declarations.h b/board/drivers/bootkick_declarations.h new file mode 100644 index 000000000..3b55b72ac --- /dev/null +++ b/board/drivers/bootkick_declarations.h @@ -0,0 +1,5 @@ +#pragma once + +extern bool bootkick_reset_triggered; + +void bootkick_tick(bool ignition, bool recent_heartbeat); diff --git a/board/drivers/bxcan.h b/board/drivers/bxcan.h index 89fdd9605..e4c72c61a 100644 --- a/board/drivers/bxcan.h +++ b/board/drivers/bxcan.h @@ -1,9 +1,11 @@ +#include "bxcan_declarations.h" + // IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE // CAN2_TX, CAN2_RX0, CAN2_SCE // CAN3_TX, CAN3_RX0, CAN3_SCE -CAN_TypeDef *cans[] = {CAN1, CAN2, CAN3}; -uint8_t can_irq_number[3][3] = { +CAN_TypeDef *cans[CAN_ARRAY_SIZE] = {CAN1, CAN2, CAN3}; +uint8_t can_irq_number[CAN_IRQS_ARRAY_SIZE][CAN_IRQS_ARRAY_SIZE] = { { CAN1_TX_IRQn, CAN1_RX0_IRQn, CAN1_SCE_IRQn }, { CAN2_TX_IRQn, CAN2_RX0_IRQn, CAN2_SCE_IRQn }, { CAN3_TX_IRQn, CAN3_RX0_IRQn, CAN3_SCE_IRQn }, @@ -63,7 +65,7 @@ void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) { // ***************************** CAN ***************************** // CANx_SCE IRQ Handler -void can_sce(uint8_t can_number) { +static void can_sce(uint8_t can_number) { update_can_health_pkt(can_number, 1U); } @@ -181,17 +183,17 @@ void can_rx(uint8_t can_number) { } } -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(0); } +static void CAN1_TX_IRQ_Handler(void) { process_can(0); } +static void CAN1_RX0_IRQ_Handler(void) { can_rx(0); } +static void CAN1_SCE_IRQ_Handler(void) { can_sce(0); } -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(1); } +static void CAN2_TX_IRQ_Handler(void) { process_can(1); } +static void CAN2_RX0_IRQ_Handler(void) { can_rx(1); } +static void CAN2_SCE_IRQ_Handler(void) { can_sce(1); } -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(2); } +static void CAN3_TX_IRQ_Handler(void) { process_can(2); } +static void CAN3_RX0_IRQ_Handler(void) { can_rx(2); } +static void CAN3_SCE_IRQ_Handler(void) { can_sce(2); } bool can_init(uint8_t can_number) { bool ret = false; diff --git a/board/drivers/bxcan_declarations.h b/board/drivers/bxcan_declarations.h new file mode 100644 index 000000000..c0ed57794 --- /dev/null +++ b/board/drivers/bxcan_declarations.h @@ -0,0 +1,22 @@ +#pragma once + +// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE +// CAN2_TX, CAN2_RX0, CAN2_SCE +// CAN3_TX, CAN3_RX0, CAN3_SCE + +#define CAN_ARRAY_SIZE 3 +#define CAN_IRQS_ARRAY_SIZE 3 +extern CAN_TypeDef *cans[CAN_ARRAY_SIZE]; +extern uint8_t can_irq_number[CAN_IRQS_ARRAY_SIZE][CAN_IRQS_ARRAY_SIZE]; + +bool can_set_speed(uint8_t can_number); +void can_clear_send(CAN_TypeDef *CANx, uint8_t can_number); +void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg); + +// ***************************** CAN ***************************** +// CANx_TX IRQ Handler +void process_can(uint8_t can_number); +// CANx_RX0 IRQ Handler +// blink blue when we are receiving CAN messages +void can_rx(uint8_t can_number); +bool can_init(uint8_t can_number); diff --git a/board/drivers/can_common.h b/board/drivers/can_common.h index 3a829c69a..5a074e775 100644 --- a/board/drivers/can_common.h +++ b/board/drivers/can_common.h @@ -1,54 +1,25 @@ -typedef struct { - volatile uint32_t w_ptr; - volatile uint32_t r_ptr; - uint32_t fifo_size; - CANPacket_t *elems; -} can_ring; - -typedef struct { - uint8_t bus_lookup; - uint8_t can_num_lookup; - int8_t forwarding_bus; - uint32_t can_speed; - uint32_t can_data_speed; - bool canfd_enabled; - bool brs_enabled; - bool canfd_non_iso; -} bus_config_t; +#include "can_common_declarations.h" uint32_t safety_tx_blocked = 0; uint32_t safety_rx_invalid = 0; uint32_t tx_buffer_overflow = 0; uint32_t rx_buffer_overflow = 0; -can_health_t can_health[] = {{0}, {0}, {0}}; - -extern int can_live; -extern int pending_can_live; - -// must reinit after changing these -extern int can_silent; -extern bool can_loopback; +can_health_t can_health[CAN_HEALTH_ARRAY_SIZE] = {{0}, {0}, {0}}; // Ignition detected from CAN meessages bool ignition_can = false; uint32_t ignition_can_cnt = 0U; -#define ALL_CAN_SILENT 0xFF -#define ALL_CAN_LIVE 0 - int can_live = 0; int pending_can_live = 0; int can_silent = ALL_CAN_SILENT; bool can_loopback = false; -// ******************* functions prototypes ********************* -bool can_init(uint8_t can_number); -void process_can(uint8_t can_number); - // ********************* instantiate queues ********************* #define can_buffer(x, size) \ - CANPacket_t elems_##x[size]; \ + static CANPacket_t elems_##x[size]; \ + extern can_ring can_##x; \ can_ring can_##x = { .w_ptr = 0, .r_ptr = 0, .fifo_size = (size), .elems = (CANPacket_t *)&(elems_##x) }; #define CAN_RX_BUFFER_SIZE 4096U @@ -68,11 +39,7 @@ can_buffer(tx3_q, CAN_TX_BUFFER_SIZE) // FIXME: // cppcheck-suppress misra-c2012-9.3 -can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q}; - -// helpers -#define WORD_TO_BYTE_ARRAY(dst8, src32) 0[dst8] = ((src32) & 0xFFU); 1[dst8] = (((src32) >> 8U) & 0xFFU); 2[dst8] = (((src32) >> 16U) & 0xFFU); 3[dst8] = (((src32) >> 24U) & 0xFFU) -#define BYTE_ARRAY_TO_WORD(dst32, src8) ((dst32) = 0[src8] | (1[src8] << 8U) | (2[src8] << 16U) | (3[src8] << 24U)) +can_ring *can_queues[CAN_QUEUES_ARRAY_SIZE] = {&can_tx1_q, &can_tx2_q, &can_tx3_q}; // ********************* interrupt safe queue ********************* bool can_pop(can_ring *q, CANPacket_t *elem) { @@ -163,17 +130,13 @@ void can_clear(can_ring *q) { // Helpers // Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3 -bus_config_t bus_config[] = { +bus_config_t bus_config[BUS_CONFIG_ARRAY_SIZE] = { { .bus_lookup = 0U, .can_num_lookup = 0U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, { .bus_lookup = 1U, .can_num_lookup = 1U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, { .bus_lookup = 2U, .can_num_lookup = 2U, .forwarding_bus = -1, .can_speed = 5000U, .can_data_speed = 20000U, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, { .bus_lookup = 0xFFU, .can_num_lookup = 0xFFU, .forwarding_bus = -1, .can_speed = 333U, .can_data_speed = 333U, .canfd_enabled = false, .brs_enabled = false, .canfd_non_iso = false }, }; -#define CANIF_FROM_CAN_NUM(num) (cans[num]) -#define BUS_NUM_FROM_CAN_NUM(num) (bus_config[num].bus_lookup) -#define CAN_NUM_FROM_BUS_NUM(num) (bus_config[num].can_num_lookup) - void can_init_all(void) { for (uint8_t i=0U; i < PANDA_CAN_CNT; i++) { if (!current_board->has_canfd) { @@ -191,9 +154,11 @@ void can_set_orientation(bool flipped) { bus_config[2].can_num_lookup = flipped ? 0U : 2U; } +#ifdef PANDA_JUNGLE void can_set_forwarding(uint8_t from, uint8_t to) { bus_config[from].forwarding_bus = to; } +#endif void ignition_can_hook(CANPacket_t *to_push) { int bus = GET_BUS(to_push); diff --git a/board/drivers/can_common_declarations.h b/board/drivers/can_common_declarations.h new file mode 100644 index 000000000..1a3518c2a --- /dev/null +++ b/board/drivers/can_common_declarations.h @@ -0,0 +1,87 @@ +#pragma once + +typedef struct { + volatile uint32_t w_ptr; + volatile uint32_t r_ptr; + uint32_t fifo_size; + CANPacket_t *elems; +} can_ring; + +typedef struct { + uint8_t bus_lookup; + uint8_t can_num_lookup; + int8_t forwarding_bus; + uint32_t can_speed; + uint32_t can_data_speed; + bool canfd_enabled; + bool brs_enabled; + bool canfd_non_iso; +} bus_config_t; + +extern uint32_t safety_tx_blocked; +extern uint32_t safety_rx_invalid; +extern uint32_t tx_buffer_overflow; +extern uint32_t rx_buffer_overflow; + +#define CAN_HEALTH_ARRAY_SIZE 3 +extern can_health_t can_health[CAN_HEALTH_ARRAY_SIZE]; + +// Ignition detected from CAN meessages +extern bool ignition_can; +extern uint32_t ignition_can_cnt; + +#define ALL_CAN_SILENT 0xFF +#define ALL_CAN_LIVE 0 + +extern int can_live; +extern int pending_can_live; +extern int can_silent; +extern bool can_loopback; + +// ******************* functions prototypes ********************* +bool can_init(uint8_t can_number); +void process_can(uint8_t can_number); + +// ********************* instantiate queues ********************* +#define CAN_QUEUES_ARRAY_SIZE 3 +extern can_ring *can_queues[CAN_QUEUES_ARRAY_SIZE]; + +// helpers +#define WORD_TO_BYTE_ARRAY(dst8, src32) 0[dst8] = ((src32) & 0xFFU); 1[dst8] = (((src32) >> 8U) & 0xFFU); 2[dst8] = (((src32) >> 16U) & 0xFFU); 3[dst8] = (((src32) >> 24U) & 0xFFU) +#define BYTE_ARRAY_TO_WORD(dst32, src8) ((dst32) = 0[src8] | (1[src8] << 8U) | (2[src8] << 16U) | (3[src8] << 24U)) + +// ********************* interrupt safe queue ********************* +bool can_pop(can_ring *q, CANPacket_t *elem); +bool can_push(can_ring *q, const CANPacket_t *elem); +uint32_t can_slots_empty(const can_ring *q); + +// assign CAN numbering +// bus num: CAN Bus numbers in panda, sent to/from USB +// Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1) +// cans: Look up MCU can interface from bus number +// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc); +// bus_lookup: Translates from 'can number' to 'bus number'. +// can_num_lookup: Translates from 'bus number' to 'can number'. +// forwarding bus: If >= 0, forward all messages from this bus to the specified bus. + +// Helpers +// Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3 +#define BUS_CONFIG_ARRAY_SIZE 4 +extern bus_config_t bus_config[BUS_CONFIG_ARRAY_SIZE]; + +#define CANIF_FROM_CAN_NUM(num) (cans[num]) +#define BUS_NUM_FROM_CAN_NUM(num) (bus_config[num].bus_lookup) +#define CAN_NUM_FROM_BUS_NUM(num) (bus_config[num].can_num_lookup) + +void can_init_all(void); +void can_set_orientation(bool flipped); +#ifdef PANDA_JUNGLE +void can_set_forwarding(uint8_t from, uint8_t to); +#endif +void ignition_can_hook(CANPacket_t *to_push); +bool can_tx_check_min_slots_free(uint32_t min); +uint8_t calculate_checksum(const uint8_t *dat, uint32_t len); +void can_set_checksum(CANPacket_t *packet); +bool can_check_checksum(CANPacket_t *packet); +void can_send(CANPacket_t *to_push, uint8_t bus_number, bool skip_tx_hook); +bool is_speed_valid(uint32_t speed, const uint32_t *all_speeds, uint8_t len); diff --git a/board/drivers/clock_source.h b/board/drivers/clock_source.h index 5d6fdc8a7..18d12d579 100644 --- a/board/drivers/clock_source.h +++ b/board/drivers/clock_source.h @@ -1,5 +1,4 @@ -#define CLOCK_SOURCE_PERIOD_MS 50U -#define CLOCK_SOURCE_PULSE_LEN_MS 2U +#include "clock_source_declarations.h" void clock_source_set_period(uint8_t period) { register_set(&(TIM1->ARR), ((period*10U) - 1U), 0xFFFFU); diff --git a/board/drivers/clock_source_declarations.h b/board/drivers/clock_source_declarations.h new file mode 100644 index 000000000..013f75303 --- /dev/null +++ b/board/drivers/clock_source_declarations.h @@ -0,0 +1,7 @@ +#pragma once + +#define CLOCK_SOURCE_PERIOD_MS 50U +#define CLOCK_SOURCE_PULSE_LEN_MS 2U + +void clock_source_set_period(uint8_t period); +void clock_source_init(void); diff --git a/board/drivers/fake_siren.h b/board/drivers/fake_siren.h index 7c73be0b1..feedd8fe9 100644 --- a/board/drivers/fake_siren.h +++ b/board/drivers/fake_siren.h @@ -2,11 +2,6 @@ #define CODEC_I2C_ADDR 0x10 -// 1Vpp sine wave with 1V offset -const uint8_t fake_siren_lut[360] = { 134U, 135U, 137U, 138U, 139U, 140U, 141U, 143U, 144U, 145U, 146U, 148U, 149U, 150U, 151U, 152U, 154U, 155U, 156U, 157U, 158U, 159U, 160U, 162U, 163U, 164U, 165U, 166U, 167U, 168U, 169U, 170U, 171U, 172U, 174U, 175U, 176U, 177U, 177U, 178U, 179U, 180U, 181U, 182U, 183U, 184U, 185U, 186U, 186U, 187U, 188U, 189U, 190U, 190U, 191U, 192U, 193U, 193U, 194U, 195U, 195U, 196U, 196U, 197U, 197U, 198U, 199U, 199U, 199U, 200U, 200U, 201U, 201U, 202U, 202U, 202U, 203U, 203U, 203U, 203U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 205U, 205U, 205U, 205U, 205U, 205U, 205U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 203U, 203U, 203U, 203U, 202U, 202U, 202U, 201U, 201U, 200U, 200U, 199U, 199U, 199U, 198U, 197U, 197U, 196U, 196U, 195U, 195U, 194U, 193U, 193U, 192U, 191U, 190U, 190U, 189U, 188U, 187U, 186U, 186U, 185U, 184U, 183U, 182U, 181U, 180U, 179U, 178U, 177U, 177U, 176U, 175U, 174U, 172U, 171U, 170U, 169U, 168U, 167U, 166U, 165U, 164U, 163U, 162U, 160U, 159U, 158U, 157U, 156U, 155U, 154U, 152U, 151U, 150U, 149U, 148U, 146U, 145U, 144U, 143U, 141U, 140U, 139U, 138U, 137U, 135U, 134U, 133U, 132U, 130U, 129U, 128U, 127U, 125U, 124U, 123U, 122U, 121U, 119U, 118U, 117U, 116U, 115U, 113U, 112U, 111U, 110U, 109U, 108U, 106U, 105U, 104U, 103U, 102U, 101U, 100U, 99U, 98U, 97U, 96U, 95U, 94U, 93U, 92U, 91U, 90U, 89U, 88U, 87U, 86U, 85U, 84U, 83U, 82U, 82U, 81U, 80U, 79U, 78U, 78U, 77U, 76U, 76U, 75U, 74U, 74U, 73U, 72U, 72U, 71U, 71U, 70U, 70U, 69U, 69U, 68U, 68U, 67U, 67U, 67U, 66U, 66U, 66U, 65U, 65U, 65U, 65U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 63U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 65U, 65U, 65U, 65U, 66U, 66U, 66U, 67U, 67U, 67U, 68U, 68U, 69U, 69U, 70U, 70U, 71U, 71U, 72U, 72U, 73U, 74U, 74U, 75U, 76U, 76U, 77U, 78U, 78U, 79U, 80U, 81U, 82U, 82U, 83U, 84U, 85U, 86U, 87U, 88U, 89U, 90U, 91U, 92U, 93U, 94U, 95U, 96U, 97U, 98U, 99U, 100U, 101U, 102U, 103U, 104U, 105U, 106U, 108U, 109U, 110U, 111U, 112U, 113U, 115U, 116U, 117U, 118U, 119U, 121U, 122U, 123U, 124U, 125U, 127U, 128U, 129U, 130U, 132U, 133U }; - -bool fake_siren_enabled = false; - void fake_siren_codec_enable(bool enabled) { if (enabled) { bool success = true; @@ -33,6 +28,8 @@ void fake_siren_codec_enable(bool enabled) { void fake_siren_set(bool enabled) { + static bool fake_siren_enabled = false; + if (enabled != fake_siren_enabled) { fake_siren_codec_enable(enabled); } @@ -46,6 +43,9 @@ void fake_siren_set(bool enabled) { } void fake_siren_init(void) { + // 1Vpp sine wave with 1V offset + static const uint8_t fake_siren_lut[360] = { 134U, 135U, 137U, 138U, 139U, 140U, 141U, 143U, 144U, 145U, 146U, 148U, 149U, 150U, 151U, 152U, 154U, 155U, 156U, 157U, 158U, 159U, 160U, 162U, 163U, 164U, 165U, 166U, 167U, 168U, 169U, 170U, 171U, 172U, 174U, 175U, 176U, 177U, 177U, 178U, 179U, 180U, 181U, 182U, 183U, 184U, 185U, 186U, 186U, 187U, 188U, 189U, 190U, 190U, 191U, 192U, 193U, 193U, 194U, 195U, 195U, 196U, 196U, 197U, 197U, 198U, 199U, 199U, 199U, 200U, 200U, 201U, 201U, 202U, 202U, 202U, 203U, 203U, 203U, 203U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 205U, 205U, 205U, 205U, 205U, 205U, 205U, 204U, 204U, 204U, 204U, 204U, 204U, 204U, 203U, 203U, 203U, 203U, 202U, 202U, 202U, 201U, 201U, 200U, 200U, 199U, 199U, 199U, 198U, 197U, 197U, 196U, 196U, 195U, 195U, 194U, 193U, 193U, 192U, 191U, 190U, 190U, 189U, 188U, 187U, 186U, 186U, 185U, 184U, 183U, 182U, 181U, 180U, 179U, 178U, 177U, 177U, 176U, 175U, 174U, 172U, 171U, 170U, 169U, 168U, 167U, 166U, 165U, 164U, 163U, 162U, 160U, 159U, 158U, 157U, 156U, 155U, 154U, 152U, 151U, 150U, 149U, 148U, 146U, 145U, 144U, 143U, 141U, 140U, 139U, 138U, 137U, 135U, 134U, 133U, 132U, 130U, 129U, 128U, 127U, 125U, 124U, 123U, 122U, 121U, 119U, 118U, 117U, 116U, 115U, 113U, 112U, 111U, 110U, 109U, 108U, 106U, 105U, 104U, 103U, 102U, 101U, 100U, 99U, 98U, 97U, 96U, 95U, 94U, 93U, 92U, 91U, 90U, 89U, 88U, 87U, 86U, 85U, 84U, 83U, 82U, 82U, 81U, 80U, 79U, 78U, 78U, 77U, 76U, 76U, 75U, 74U, 74U, 73U, 72U, 72U, 71U, 71U, 70U, 70U, 69U, 69U, 68U, 68U, 67U, 67U, 67U, 66U, 66U, 66U, 65U, 65U, 65U, 65U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 63U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 64U, 65U, 65U, 65U, 65U, 66U, 66U, 66U, 67U, 67U, 67U, 68U, 68U, 69U, 69U, 70U, 70U, 71U, 71U, 72U, 72U, 73U, 74U, 74U, 75U, 76U, 76U, 77U, 78U, 78U, 79U, 80U, 81U, 82U, 82U, 83U, 84U, 85U, 86U, 87U, 88U, 89U, 90U, 91U, 92U, 93U, 94U, 95U, 96U, 97U, 98U, 99U, 100U, 101U, 102U, 103U, 104U, 105U, 106U, 108U, 109U, 110U, 111U, 112U, 113U, 115U, 116U, 117U, 118U, 119U, 121U, 122U, 123U, 124U, 125U, 127U, 128U, 129U, 130U, 132U, 133U }; + // Init DAC register_set(&DAC1->MCR, 0U, 0xFFFFFFFFU); register_set(&DAC1->CR, DAC_CR_TEN1 | (6U << DAC_CR_TSEL1_Pos) | DAC_CR_DMAEN1, 0xFFFFFFFFU); diff --git a/board/drivers/fan.h b/board/drivers/fan.h index e0946aac3..daadd2383 100644 --- a/board/drivers/fan.h +++ b/board/drivers/fan.h @@ -1,21 +1,9 @@ -struct fan_state_t { - uint16_t tach_counter; - uint16_t rpm; - uint16_t target_rpm; - uint8_t power; - float error_integral; - uint8_t stall_counter; - uint8_t stall_threshold; - uint8_t total_stall_count; - uint8_t cooldown_counter; -} fan_state_t; +#include "fan_declarations.h" + struct fan_state_t fan_state; -const float FAN_I = 0.001f; - -const uint8_t FAN_TICK_FREQ = 8U; -const uint8_t FAN_STALL_THRESHOLD_MIN = 3U; -const uint8_t FAN_STALL_THRESHOLD_MAX = 8U; +static const uint8_t FAN_TICK_FREQ = 8U; +static const uint8_t FAN_STALL_THRESHOLD_MIN = 3U; void fan_set_power(uint8_t percentage) { @@ -31,6 +19,9 @@ void fan_init(void) { // Call this at FAN_TICK_FREQ void fan_tick(void) { + const float FAN_I = 0.001f; + const uint8_t FAN_STALL_THRESHOLD_MAX = 8U; + if (current_board->fan_max_rpm > 0U) { // Measure fan RPM uint16_t fan_rpm_fast = fan_state.tach_counter * (60U * FAN_TICK_FREQ / 4U); // 4 interrupts per rotation diff --git a/board/drivers/fan_declarations.h b/board/drivers/fan_declarations.h new file mode 100644 index 000000000..4b7c1dc9e --- /dev/null +++ b/board/drivers/fan_declarations.h @@ -0,0 +1,20 @@ +#pragma once + +struct fan_state_t { + uint16_t tach_counter; + uint16_t rpm; + uint16_t target_rpm; + uint8_t power; + float error_integral; + uint8_t stall_counter; + uint8_t stall_threshold; + uint8_t total_stall_count; + uint8_t cooldown_counter; +}; +extern struct fan_state_t fan_state; + +void fan_set_power(uint8_t percentage); +void llfan_init(void); +void fan_init(void); +// Call this at FAN_TICK_FREQ +void fan_tick(void); diff --git a/board/drivers/fdcan.h b/board/drivers/fdcan.h index 00bc1a348..0144aa17c 100644 --- a/board/drivers/fdcan.h +++ b/board/drivers/fdcan.h @@ -1,25 +1,8 @@ -// IRQs: FDCAN1_IT0, FDCAN1_IT1 -// FDCAN2_IT0, FDCAN2_IT1 -// FDCAN3_IT0, FDCAN3_IT1 +#include "fdcan_declarations.h" -#define CANFD +FDCAN_GlobalTypeDef *cans[CANS_ARRAY_SIZE] = {FDCAN1, FDCAN2, FDCAN3}; -typedef struct { - volatile uint32_t header[2]; - volatile uint32_t data_word[CANPACKET_DATA_SIZE_MAX/4U]; -} canfd_fifo; - -FDCAN_GlobalTypeDef *cans[] = {FDCAN1, FDCAN2, FDCAN3}; - -uint8_t can_irq_number[3][2] = { - { FDCAN1_IT0_IRQn, FDCAN1_IT1_IRQn }, - { FDCAN2_IT0_IRQn, FDCAN2_IT1_IRQn }, - { FDCAN3_IT0_IRQn, FDCAN3_IT1_IRQn }, -}; - -#define CAN_ACK_ERROR 3U - -bool can_set_speed(uint8_t can_number) { +static bool can_set_speed(uint8_t can_number) { bool ret = true; FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); @@ -42,6 +25,12 @@ void can_clear_send(FDCAN_GlobalTypeDef *FDCANx, uint8_t can_number) { } void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg) { + uint8_t can_irq_number[3][2] = { + { FDCAN1_IT0_IRQn, FDCAN1_IT1_IRQn }, + { FDCAN2_IT0_IRQn, FDCAN2_IT1_IRQn }, + { FDCAN3_IT0_IRQn, FDCAN3_IT1_IRQn }, + }; + FDCAN_GlobalTypeDef *FDCANx = CANIF_FROM_CAN_NUM(can_number); uint32_t psr_reg = FDCANx->PSR; uint32_t ecr_reg = FDCANx->ECR; @@ -241,14 +230,14 @@ void can_rx(uint8_t can_number) { } } -void FDCAN1_IT0_IRQ_Handler(void) { can_rx(0); } -void FDCAN1_IT1_IRQ_Handler(void) { process_can(0); } +static void FDCAN1_IT0_IRQ_Handler(void) { can_rx(0); } +static void FDCAN1_IT1_IRQ_Handler(void) { process_can(0); } -void FDCAN2_IT0_IRQ_Handler(void) { can_rx(1); } -void FDCAN2_IT1_IRQ_Handler(void) { process_can(1); } +static void FDCAN2_IT0_IRQ_Handler(void) { can_rx(1); } +static void FDCAN2_IT1_IRQ_Handler(void) { process_can(1); } -void FDCAN3_IT0_IRQ_Handler(void) { can_rx(2); } -void FDCAN3_IT1_IRQ_Handler(void) { process_can(2); } +static void FDCAN3_IT0_IRQ_Handler(void) { can_rx(2); } +static void FDCAN3_IT1_IRQ_Handler(void) { process_can(2); } bool can_init(uint8_t can_number) { bool ret = false; diff --git a/board/drivers/fdcan_declarations.h b/board/drivers/fdcan_declarations.h new file mode 100644 index 000000000..9cdc424e6 --- /dev/null +++ b/board/drivers/fdcan_declarations.h @@ -0,0 +1,28 @@ +#pragma once + +// IRQs: FDCAN1_IT0, FDCAN1_IT1 +// FDCAN2_IT0, FDCAN2_IT1 +// FDCAN3_IT0, FDCAN3_IT1 + +#define CANFD + +typedef struct { + volatile uint32_t header[2]; + volatile uint32_t data_word[CANPACKET_DATA_SIZE_MAX/4U]; +} canfd_fifo; + +#define CANS_ARRAY_SIZE 3 +extern FDCAN_GlobalTypeDef *cans[CANS_ARRAY_SIZE]; + +#define CAN_ACK_ERROR 3U + +void can_clear_send(FDCAN_GlobalTypeDef *FDCANx, uint8_t can_number); +void update_can_health_pkt(uint8_t can_number, uint32_t ir_reg); + +// ***************************** CAN ***************************** +// FDFDCANx_IT1 IRQ Handler (TX) +void process_can(uint8_t can_number); +// FDFDCANx_IT0 IRQ Handler (RX and errors) +// blink blue when we are receiving CAN messages +void can_rx(uint8_t can_number); +bool can_init(uint8_t can_number); diff --git a/board/drivers/harness.h b/board/drivers/harness.h index f8f0ccb7d..cfb6965c0 100644 --- a/board/drivers/harness.h +++ b/board/drivers/harness.h @@ -1,30 +1,7 @@ -#define HARNESS_STATUS_NC 0U -#define HARNESS_STATUS_NORMAL 1U -#define HARNESS_STATUS_FLIPPED 2U +#include "harness_declarations.h" -struct harness_t { - uint8_t status; - uint16_t sbu1_voltage_mV; - uint16_t sbu2_voltage_mV; - bool relay_driven; - bool sbu_adc_lock; -}; struct harness_t harness; -struct harness_configuration { - const bool has_harness; - GPIO_TypeDef * const GPIO_SBU1; - GPIO_TypeDef * const GPIO_SBU2; - GPIO_TypeDef * const GPIO_relay_SBU1; - GPIO_TypeDef * const GPIO_relay_SBU2; - const uint8_t pin_SBU1; - const uint8_t pin_SBU2; - const uint8_t pin_relay_SBU1; - const uint8_t pin_relay_SBU2; - const uint8_t adc_channel_SBU1; - const uint8_t adc_channel_SBU2; -}; - // The ignition relay is only used for testing purposes void set_intercept_relay(bool intercept, bool ignition_relay) { if (current_board->harness_config->has_harness) { @@ -74,7 +51,7 @@ bool harness_check_ignition(void) { return ret; } -uint8_t harness_detect_orientation(void) { +static uint8_t harness_detect_orientation(void) { uint8_t ret = harness.status; #ifndef BOOTSTUB diff --git a/board/drivers/harness_declarations.h b/board/drivers/harness_declarations.h new file mode 100644 index 000000000..953941f62 --- /dev/null +++ b/board/drivers/harness_declarations.h @@ -0,0 +1,34 @@ +#pragma once + +#define HARNESS_STATUS_NC 0U +#define HARNESS_STATUS_NORMAL 1U +#define HARNESS_STATUS_FLIPPED 2U + +struct harness_t { + uint8_t status; + uint16_t sbu1_voltage_mV; + uint16_t sbu2_voltage_mV; + bool relay_driven; + bool sbu_adc_lock; +}; +extern struct harness_t harness; + +struct harness_configuration { + const bool has_harness; + GPIO_TypeDef * const GPIO_SBU1; + GPIO_TypeDef * const GPIO_SBU2; + GPIO_TypeDef * const GPIO_relay_SBU1; + GPIO_TypeDef * const GPIO_relay_SBU2; + const uint8_t pin_SBU1; + const uint8_t pin_SBU2; + const uint8_t pin_relay_SBU1; + const uint8_t pin_relay_SBU2; + const uint8_t adc_channel_SBU1; + const uint8_t adc_channel_SBU2; +}; + +// The ignition relay is only used for testing purposes +void set_intercept_relay(bool intercept, bool ignition_relay); +bool harness_check_ignition(void); +void harness_tick(void); +void harness_init(void); diff --git a/board/drivers/interrupts.h b/board/drivers/interrupts.h index 77988f6e4..1188a8ec0 100644 --- a/board/drivers/interrupts.h +++ b/board/drivers/interrupts.h @@ -1,14 +1,4 @@ -typedef struct interrupt { - IRQn_Type irq_type; - void (*handler)(void); - uint32_t call_counter; - uint32_t call_rate; - uint32_t max_call_rate; // Call rate is defined as the amount of calls each second - uint32_t call_rate_fault; -} interrupt; - -void interrupt_timer_init(void); -uint32_t microsecond_timer_get(void); +#include "interrupts_declarations.h" void unused_interrupt_handler(void) { // Something is wrong if this handler is called! @@ -18,23 +8,15 @@ void unused_interrupt_handler(void) { interrupt interrupts[NUM_INTERRUPTS]; -#define REGISTER_INTERRUPT(irq_num, func_ptr, call_rate_max, rate_fault) \ - interrupts[irq_num].irq_type = (irq_num); \ - interrupts[irq_num].handler = (func_ptr); \ - interrupts[irq_num].call_counter = 0U; \ - interrupts[irq_num].call_rate = 0U; \ - interrupts[irq_num].max_call_rate = (call_rate_max); \ - interrupts[irq_num].call_rate_fault = (rate_fault); +static bool check_interrupt_rate = false; -bool check_interrupt_rate = false; - -uint8_t interrupt_depth = 0U; -uint32_t last_time = 0U; -uint32_t idle_time = 0U; -uint32_t busy_time = 0U; +static uint32_t idle_time = 0U; +static uint32_t busy_time = 0U; float interrupt_load = 0.0f; void handle_interrupt(IRQn_Type irq_type){ + static uint8_t interrupt_depth = 0U; + static uint32_t last_time = 0U; ENTER_CRITICAL(); if (interrupt_depth == 0U) { uint32_t time = microsecond_timer_get(); diff --git a/board/drivers/interrupts_declarations.h b/board/drivers/interrupts_declarations.h new file mode 100644 index 000000000..4112453ca --- /dev/null +++ b/board/drivers/interrupts_declarations.h @@ -0,0 +1,31 @@ +#pragma once + +typedef struct interrupt { + IRQn_Type irq_type; + void (*handler)(void); + uint32_t call_counter; + uint32_t call_rate; + uint32_t max_call_rate; // Call rate is defined as the amount of calls each second + uint32_t call_rate_fault; +} interrupt; + +void interrupt_timer_init(void); +uint32_t microsecond_timer_get(void); +void unused_interrupt_handler(void); + +extern interrupt interrupts[NUM_INTERRUPTS]; + +#define REGISTER_INTERRUPT(irq_num, func_ptr, call_rate_max, rate_fault) \ + interrupts[irq_num].irq_type = (irq_num); \ + interrupts[irq_num].handler = (func_ptr); \ + interrupts[irq_num].call_counter = 0U; \ + interrupts[irq_num].call_rate = 0U; \ + interrupts[irq_num].max_call_rate = (call_rate_max); \ + interrupts[irq_num].call_rate_fault = (rate_fault); + +extern float interrupt_load; + +void handle_interrupt(IRQn_Type irq_type); +// Every second +void interrupt_timer_handler(void); +void init_interrupts(bool check_rate_limit); diff --git a/board/drivers/registers.h b/board/drivers/registers.h index 5d5a4257d..92b6b0faa 100644 --- a/board/drivers/registers.h +++ b/board/drivers/registers.h @@ -1,21 +1,11 @@ +#include "registers_declarations.h" -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]; +static 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){ +static uint16_t hash_addr(uint32_t input){ return (((input >> 16U) ^ ((((input + 1U) & 0xFFFFU) * HASHING_PRIME) & 0xFFFFU)) & REGISTER_MAP_SIZE); } diff --git a/board/drivers/registers_declarations.h b/board/drivers/registers_declarations.h new file mode 100644 index 000000000..13180117b --- /dev/null +++ b/board/drivers/registers_declarations.h @@ -0,0 +1,24 @@ +#pragma once + +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))) + +// 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); +// 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); +// 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); +// To be called periodically +void check_registers(void); +void init_registers(void); diff --git a/board/drivers/simple_watchdog.h b/board/drivers/simple_watchdog.h index fe0c856af..f679cb193 100644 --- a/board/drivers/simple_watchdog.h +++ b/board/drivers/simple_watchdog.h @@ -1,11 +1,6 @@ -typedef struct simple_watchdog_state_t { - uint32_t fault; - uint32_t last_ts; - uint32_t threshold; -} simple_watchdog_state_t; - -simple_watchdog_state_t wd_state; +#include "simple_watchdog_declarations.h" +static simple_watchdog_state_t wd_state; void simple_watchdog_kick(void) { uint32_t ts = microsecond_timer_get(); diff --git a/board/drivers/simple_watchdog_declarations.h b/board/drivers/simple_watchdog_declarations.h new file mode 100644 index 000000000..2bda71590 --- /dev/null +++ b/board/drivers/simple_watchdog_declarations.h @@ -0,0 +1,10 @@ +#pragma once + +typedef struct simple_watchdog_state_t { + uint32_t fault; + uint32_t last_ts; + uint32_t threshold; +} simple_watchdog_state_t; + +void simple_watchdog_kick(void); +void simple_watchdog_init(uint32_t fault, uint32_t threshold); diff --git a/board/drivers/spi.h b/board/drivers/spi.h index f21deee89..672aedb83 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -1,13 +1,8 @@ #pragma once +#include "spi_declarations.h" #include "crc.h" -#define SPI_TIMEOUT_US 10000U - -// got max rate from hitting a non-existent endpoint -// in a tight loop, plus some buffer -#define SPI_IRQ_RATE 16000U - #ifdef STM32H7 #define SPI_BUF_SIZE 2048U // H7 DMA2 located in D2 domain, so we need to use SRAM1/SRAM2 @@ -19,44 +14,18 @@ uint8_t spi_buf_rx[SPI_BUF_SIZE]; uint8_t spi_buf_tx[SPI_BUF_SIZE]; #endif -#define SPI_CHECKSUM_START 0xABU -#define SPI_SYNC_BYTE 0x5AU -#define SPI_HACK 0x79U -#define SPI_DACK 0x85U -#define SPI_NACK 0x1FU - -// SPI states -enum { - SPI_STATE_HEADER, - SPI_STATE_HEADER_ACK, - SPI_STATE_HEADER_NACK, - SPI_STATE_DATA_RX, - SPI_STATE_DATA_RX_ACK, - SPI_STATE_DATA_TX -}; - -bool spi_tx_dma_done = false; -uint8_t spi_state = SPI_STATE_HEADER; -uint8_t spi_endpoint; -uint16_t spi_data_len_mosi; -uint16_t spi_data_len_miso; +static uint8_t spi_state = SPI_STATE_HEADER; +static uint16_t spi_data_len_mosi; uint16_t spi_checksum_error_count = 0; -bool spi_can_tx_ready = false; +static bool spi_can_tx_ready = false; -const unsigned char version_text[] = "VERSION"; - -#define SPI_HEADER_SIZE 7U - -// low level SPI prototypes -void llspi_init(void); -void llspi_mosi_dma(uint8_t *addr, int len); -void llspi_miso_dma(uint8_t *addr, int len); +static const unsigned char version_text[] = "VERSION"; void can_tx_comms_resume_spi(void) { spi_can_tx_ready = true; } -uint16_t spi_version_packet(uint8_t *out) { +static uint16_t spi_version_packet(uint8_t *out) { // this protocol version request is a stable portion of // the panda's SPI protocol. its contents match that of the // panda USB descriptors and are sufficent to list/enumerate @@ -100,6 +69,7 @@ uint16_t spi_version_packet(uint8_t *out) { return resp_len; } +#if defined(ENABLE_SPI) || defined(BOOTSTUB) void spi_init(void) { // platform init llspi_init(); @@ -108,8 +78,9 @@ void spi_init(void) { spi_state = SPI_STATE_HEADER; llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); } +#endif -bool validate_checksum(const uint8_t *data, uint16_t len) { +static bool validate_checksum(const uint8_t *data, uint16_t len) { // TODO: can speed this up by casting the bulk to uint32_t and xor-ing the bytes afterwards uint8_t checksum = SPI_CHECKSUM_START; for(uint16_t i = 0U; i < len; i++){ @@ -122,6 +93,8 @@ void spi_rx_done(void) { uint16_t response_len = 0U; uint8_t next_rx_state = SPI_STATE_HEADER_NACK; bool checksum_valid = false; + static uint8_t spi_endpoint; + static uint16_t spi_data_len_miso; // parse header spi_endpoint = spi_buf_rx[1]; diff --git a/board/drivers/spi_declarations.h b/board/drivers/spi_declarations.h new file mode 100644 index 000000000..022892cea --- /dev/null +++ b/board/drivers/spi_declarations.h @@ -0,0 +1,52 @@ +#pragma once + +#include "crc.h" + +#define SPI_TIMEOUT_US 10000U + +// got max rate from hitting a non-existent endpoint +// in a tight loop, plus some buffer +#define SPI_IRQ_RATE 16000U + +#ifdef STM32H7 +#define SPI_BUF_SIZE 2048U +// H7 DMA2 located in D2 domain, so we need to use SRAM1/SRAM2 +__attribute__((section(".sram12"))) extern uint8_t spi_buf_rx[SPI_BUF_SIZE]; +__attribute__((section(".sram12"))) extern uint8_t spi_buf_tx[SPI_BUF_SIZE]; +#else +#define SPI_BUF_SIZE 1024U +extern uint8_t spi_buf_rx[SPI_BUF_SIZE]; +extern uint8_t spi_buf_tx[SPI_BUF_SIZE]; +#endif + +#define SPI_CHECKSUM_START 0xABU +#define SPI_SYNC_BYTE 0x5AU +#define SPI_HACK 0x79U +#define SPI_DACK 0x85U +#define SPI_NACK 0x1FU + +// SPI states +enum { + SPI_STATE_HEADER, + SPI_STATE_HEADER_ACK, + SPI_STATE_HEADER_NACK, + SPI_STATE_DATA_RX, + SPI_STATE_DATA_RX_ACK, + SPI_STATE_DATA_TX +}; + +extern uint16_t spi_checksum_error_count; + +#define SPI_HEADER_SIZE 7U + +// low level SPI prototypes +void llspi_init(void); +void llspi_mosi_dma(uint8_t *addr, int len); +void llspi_miso_dma(uint8_t *addr, int len); + +void can_tx_comms_resume_spi(void); +#if defined(ENABLE_SPI) || defined(BOOTSTUB) +void spi_init(void); +#endif +void spi_rx_done(void); +void spi_tx_done(bool reset); diff --git a/board/drivers/timers.h b/board/drivers/timers.h index d7f3f01fd..49d9f5c4d 100644 --- a/board/drivers/timers.h +++ b/board/drivers/timers.h @@ -1,4 +1,4 @@ -void timer_init(TIM_TypeDef *TIM, int psc) { +static void timer_init(TIM_TypeDef *TIM, int psc) { register_set(&(TIM->PSC), (psc-1), 0xFFFFU); register_set(&(TIM->DIER), TIM_DIER_UIE, 0x5F5FU); register_set(&(TIM->CR1), TIM_CR1_CEN, 0x3FU); diff --git a/board/drivers/uart.h b/board/drivers/uart.h index e9a7c5070..0c3523bf5 100644 --- a/board/drivers/uart.h +++ b/board/drivers/uart.h @@ -1,25 +1,13 @@ +#include "uart_declarations.h" + // IRQs: USART2, USART3, UART5 // ***************************** Definitions ***************************** -#define FIFO_SIZE_INT 0x400U - -typedef struct uart_ring { - volatile uint16_t w_ptr_tx; - volatile uint16_t r_ptr_tx; - uint8_t *elems_tx; - uint32_t tx_fifo_size; - volatile uint16_t w_ptr_rx; - volatile uint16_t r_ptr_rx; - uint8_t *elems_rx; - uint32_t rx_fifo_size; - USART_TypeDef *uart; - void (*callback)(struct uart_ring*); - bool overwrite; -} uart_ring; #define UART_BUFFER(x, size_rx, size_tx, uart_ptr, callback_ptr, overwrite_mode) \ - uint8_t elems_rx_##x[size_rx]; \ - uint8_t elems_tx_##x[size_tx]; \ + static uint8_t elems_rx_##x[size_rx]; \ + static uint8_t elems_tx_##x[size_tx]; \ + extern uart_ring uart_ring_##x; \ uart_ring uart_ring_##x = { \ .w_ptr_tx = 0, \ .r_ptr_tx = 0, \ @@ -34,9 +22,6 @@ typedef struct uart_ring { .overwrite = (overwrite_mode) \ }; -// ***************************** Function prototypes ***************************** -void debug_ring_callback(uart_ring *ring); -void uart_tx_ring(uart_ring *q); // ******************************** UART buffers ******************************** // debug = USART2 @@ -149,20 +134,6 @@ void print(const char *a) { } } -void putui(uint32_t i) { - uint32_t i_copy = i; - char str[11]; - uint8_t idx = 10; - str[idx] = '\0'; - idx--; - do { - str[idx] = (i_copy % 10U) + 0x30U; - idx--; - i_copy /= 10; - } while (i_copy != 0U); - print(&str[idx + 1U]); -} - void puthx(uint32_t i, uint8_t len) { const char c[] = "0123456789abcdef"; for (int pos = ((int)len * 4) - 4; pos > -4; pos -= 4) { diff --git a/board/drivers/uart_declarations.h b/board/drivers/uart_declarations.h new file mode 100644 index 000000000..80fffa210 --- /dev/null +++ b/board/drivers/uart_declarations.h @@ -0,0 +1,38 @@ +#pragma once + +// IRQs: USART2, USART3, UART5 + +// ***************************** Definitions ***************************** +#define FIFO_SIZE_INT 0x400U + +typedef struct uart_ring { + volatile uint16_t w_ptr_tx; + volatile uint16_t r_ptr_tx; + uint8_t *elems_tx; + uint32_t tx_fifo_size; + volatile uint16_t w_ptr_rx; + volatile uint16_t r_ptr_rx; + uint8_t *elems_rx; + uint32_t rx_fifo_size; + USART_TypeDef *uart; + void (*callback)(struct uart_ring*); + bool overwrite; +} uart_ring; + +// ***************************** Function prototypes ***************************** +void debug_ring_callback(uart_ring *ring); +void uart_tx_ring(uart_ring *q); +uart_ring *get_ring_by_number(int a); +// ************************* Low-level buffer functions ************************* +bool get_char(uart_ring *q, char *elem); +bool injectc(uart_ring *q, char elem); +bool put_char(uart_ring *q, char elem); +void clear_uart_buff(uart_ring *q); +// ************************ High-level debug functions ********************** +void putch(const char a); +void print(const char *a); +void puthx(uint32_t i, uint8_t len); +void puth(unsigned int i); +void puth2(unsigned int i); +void puth4(unsigned int i); +void hexdump(const void *a, int l); diff --git a/board/drivers/usb.h b/board/drivers/usb.h index e00637221..cfc9c4fb7 100644 --- a/board/drivers/usb.h +++ b/board/drivers/usb.h @@ -1,361 +1,21 @@ -// IRQs: OTG_FS - -typedef union { - uint16_t w; - struct BW { - uint8_t msb; - uint8_t lsb; - } - bw; -} -uint16_t_uint8_t; - -typedef union _USB_Setup { - uint32_t d8[2]; - struct _SetupPkt_Struc - { - uint8_t bmRequestType; - uint8_t bRequest; - uint16_t_uint8_t wValue; - uint16_t_uint8_t wIndex; - uint16_t_uint8_t wLength; - } b; -} -USB_Setup_TypeDef; +#include "usb_declarations.h" bool usb_enumerated = false; -uint16_t usb_last_frame_num = 0U; -void usb_init(void); -void refresh_can_tx_slots_available(void); - -// **** supporting defines **** - -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C - -#define USB_DESC_TYPE_DEVICE 0x01 -#define USB_DESC_TYPE_CONFIGURATION 0x02 -#define USB_DESC_TYPE_STRING 0x03 -#define USB_DESC_TYPE_INTERFACE 0x04 -#define USB_DESC_TYPE_ENDPOINT 0x05 -#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06 -#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07 -#define USB_DESC_TYPE_BINARY_OBJECT_STORE 0x0f - -// offsets for configuration strings -#define STRING_OFFSET_LANGID 0x00 -#define STRING_OFFSET_IMANUFACTURER 0x01 -#define STRING_OFFSET_IPRODUCT 0x02 -#define STRING_OFFSET_ISERIAL 0x03 -#define STRING_OFFSET_ICONFIGURATION 0x04 -#define STRING_OFFSET_IINTERFACE 0x05 - -// WebUSB requests -#define WEBUSB_REQ_GET_URL 0x02 - -// WebUSB types -#define WEBUSB_DESC_TYPE_URL 0x03 -#define WEBUSB_URL_SCHEME_HTTPS 0x01 -#define WEBUSB_URL_SCHEME_HTTP 0x00 - -// WinUSB requests -#define WINUSB_REQ_GET_COMPATID_DESCRIPTOR 0x04 -#define WINUSB_REQ_GET_EXT_PROPS_OS 0x05 -#define WINUSB_REQ_GET_DESCRIPTOR 0x07 - -#define STS_GOUT_NAK 1 -#define STS_DATA_UPDT 2 -#define STS_XFER_COMP 3 -#define STS_SETUP_COMP 4 -#define STS_SETUP_UPDT 6 - -uint8_t response[USBPACKET_MAX_SIZE]; - -// for the repeating interfaces -#define DSCR_INTERFACE_LEN 9 -#define DSCR_ENDPOINT_LEN 7 -#define DSCR_CONFIG_LEN 9 -#define DSCR_DEVICE_LEN 18 - -// endpoint types -#define ENDPOINT_TYPE_CONTROL 0 -#define ENDPOINT_TYPE_ISO 1 -#define ENDPOINT_TYPE_BULK 2 -#define ENDPOINT_TYPE_INT 3 - -// These are arbitrary values used in bRequest -#define MS_VENDOR_CODE 0x20 -#define WEBUSB_VENDOR_CODE 0x30 - -// BOS constants -#define BINARY_OBJECT_STORE_DESCRIPTOR_LENGTH 0x05 -#define BINARY_OBJECT_STORE_DESCRIPTOR 0x0F -#define WINUSB_PLATFORM_DESCRIPTOR_LENGTH 0x9E - -// Convert machine byte order to USB byte order -#define TOUSBORDER(num)\ - ((num) & 0xFFU), (((uint16_t)(num) >> 8) & 0xFFU) - -// take in string length and return the first 2 bytes of a string descriptor -#define STRING_DESCRIPTOR_HEADER(size)\ - (((((size) * 2) + 2) & 0xFF) | 0x0300) - -uint8_t device_desc[] = { - DSCR_DEVICE_LEN, USB_DESC_TYPE_DEVICE, //Length, Type - 0x10, 0x02, // bcdUSB max version of USB supported (2.1) - 0xFF, 0xFF, 0xFF, 0x40, // Class, Subclass, Protocol, Max Packet Size - TOUSBORDER(USB_VID), // idVendor - TOUSBORDER(USB_PID), // idProduct - 0x00, 0x00, // bcdDevice - 0x01, 0x02, // Manufacturer, Product - 0x03, 0x01 // Serial Number, Num Configurations -}; - -uint8_t device_qualifier[] = { - 0x0a, USB_DESC_TYPE_DEVICE_QUALIFIER, //Length, Type - 0x10, 0x02, // bcdUSB max version of USB supported (2.1) - 0xFF, 0xFF, 0xFF, 0x40, // bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0 - 0x01, 0x00 // bNumConfigurations, bReserved -}; - -#define ENDPOINT_RCV 0x80 -#define ENDPOINT_SND 0x00 - -uint8_t configuration_desc[] = { - DSCR_CONFIG_LEN, USB_DESC_TYPE_CONFIGURATION, // Length, Type, - TOUSBORDER(0x0045U), // Total Len (uint16) - 0x01, 0x01, STRING_OFFSET_ICONFIGURATION, // Num Interface, Config Value, Configuration - 0xc0, 0x32, // Attributes, Max Power - // interface 0 ALT 0 - DSCR_INTERFACE_LEN, USB_DESC_TYPE_INTERFACE, // Length, Type - 0x00, 0x00, 0x03, // Index, Alt Index idx, Endpoint count - 0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol - 0x00, // Interface - // endpoint 1, read CAN - DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type - ENDPOINT_RCV | 1, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type - TOUSBORDER(0x0040U), // Max Packet (0x0040) - 0x00, // Polling Interval (NA) - // endpoint 2, send serial - DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type - ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type - TOUSBORDER(0x0040U), // Max Packet (0x0040) - 0x00, // Polling Interval - // endpoint 3, send CAN - DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type - ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type - TOUSBORDER(0x0040U), // Max Packet (0x0040) - 0x00, // Polling Interval - // interface 0 ALT 1 - DSCR_INTERFACE_LEN, USB_DESC_TYPE_INTERFACE, // Length, Type - 0x00, 0x01, 0x03, // Index, Alt Index idx, Endpoint count - 0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol - 0x00, // Interface - // endpoint 1, read CAN - DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type - ENDPOINT_RCV | 1, ENDPOINT_TYPE_INT, // Endpoint Num/Direction, Type - TOUSBORDER(0x0040U), // Max Packet (0x0040) - 0x05, // Polling Interval (5 frames) - // endpoint 2, send serial - DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type - ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type - TOUSBORDER(0x0040U), // Max Packet (0x0040) - 0x00, // Polling Interval - // endpoint 3, send CAN - DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type - ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type - TOUSBORDER(0x0040U), // Max Packet (0x0040) - 0x00, // Polling Interval -}; - -// STRING_DESCRIPTOR_HEADER is for uint16 string descriptors -// it takes in a string length, which is bytes/2 because unicode -uint16_t string_language_desc[] = { - STRING_DESCRIPTOR_HEADER(1), - 0x0409 // american english -}; - -// these strings are all uint16's so that we don't need to spam ,0 after every character -uint16_t string_manufacturer_desc[] = { - STRING_DESCRIPTOR_HEADER(8), - 'c', 'o', 'm', 'm', 'a', '.', 'a', 'i' -}; - -uint16_t string_product_desc[] = { - STRING_DESCRIPTOR_HEADER(5), - 'p', 'a', 'n', 'd', 'a' -}; - -// default serial number when we're not a panda -uint16_t string_serial_desc[] = { - STRING_DESCRIPTOR_HEADER(4), - 'n', 'o', 'n', 'e' -}; - -// a string containing the default configuration index -uint16_t string_configuration_desc[] = { - STRING_DESCRIPTOR_HEADER(2), - '0', '1' // "01" -}; - -// WCID (auto install WinUSB driver) -// https://github.com/pbatard/libwdi/wiki/WCID-Devices -// https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/winusb-installation#automatic-installation-of--winusb-without-an-inf-file -// WinUSB 1.0 descriptors, this is mostly used by Windows XP -uint8_t string_238_desc[] = { - 0x12, USB_DESC_TYPE_STRING, // bLength, bDescriptorType - 'M',0, 'S',0, 'F',0, 'T',0, '1',0, '0',0, '0',0, // qwSignature (MSFT100) - MS_VENDOR_CODE, 0x00 // bMS_VendorCode, bPad -}; -uint8_t winusb_ext_compatid_os_desc[] = { - 0x28, 0x00, 0x00, 0x00, // dwLength - 0x00, 0x01, // bcdVersion - 0x04, 0x00, // wIndex - 0x01, // bCount - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved - 0x00, // bFirstInterfaceNumber - 0x00, // Reserved - 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID (WINUSB) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subcompatible ID (none) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved -}; -uint8_t winusb_ext_prop_os_desc[] = { - 0x8e, 0x00, 0x00, 0x00, // dwLength - 0x00, 0x01, // bcdVersion - 0x05, 0x00, // wIndex - 0x01, 0x00, // wCount - // first property - 0x84, 0x00, 0x00, 0x00, // dwSize - 0x01, 0x00, 0x00, 0x00, // dwPropertyDataType - 0x28, 0x00, // wPropertyNameLength - 'D',0, 'e',0, 'v',0, 'i',0, 'c',0, 'e',0, 'I',0, 'n',0, 't',0, 'e',0, 'r',0, 'f',0, 'a',0, 'c',0, 'e',0, 'G',0, 'U',0, 'I',0, 'D',0, 0, 0, // bPropertyName (DeviceInterfaceGUID) - 0x4e, 0x00, 0x00, 0x00, // dwPropertyDataLength - '{',0, 'c',0, 'c',0, 'e',0, '5',0, '2',0, '9',0, '1',0, 'c',0, '-',0, 'a',0, '6',0, '9',0, 'f',0, '-',0, '4',0 ,'9',0 ,'9',0 ,'5',0 ,'-',0, 'a',0, '4',0, 'c',0, '2',0, '-',0, '2',0, 'a',0, 'e',0, '5',0, '7',0, 'a',0, '5',0, '1',0, 'a',0, 'd',0, 'e',0, '9',0, '}',0, 0, 0, // bPropertyData ({CCE5291C-A69F-4995-A4C2-2AE57A51ADE9}) -}; - -/* -Binary Object Store descriptor used to expose WebUSB (and more WinUSB) metadata -comments are from the wicg spec -References used: - https://wicg.github.io/webusb/#webusb-platform-capability-descriptor - https://github.com/sowbug/weblight/blob/192ad7a0e903542e2aa28c607d98254a12a6399d/firmware/webusb.c - https://os.mbed.com/users/larsgk/code/USBDevice_WebUSB/file/1d8a6665d607/WebUSBDevice/ - -*/ -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 - 0x39, 0x00, // wTotalLength (LSB, MSB) - 0x02, // bNumDeviceCaps (WebUSB + WinUSB) - - // ------------------------------------------------- - // WebUSB descriptor - // header - 0x18, // bLength, Size of this descriptor. Must be set to 24. - 0x10, // bDescriptorType, DEVICE CAPABILITY descriptor - 0x05, // bDevCapabilityType, PLATFORM capability - 0x00, // bReserved, This field is reserved and shall be set to zero. - - // PlatformCapabilityUUID, Must be set to {3408b638-09a9-47a0-8bfd-a0768815b665}. - 0x38, 0xB6, 0x08, 0x34, - 0xA9, 0x09, 0xA0, 0x47, - 0x8B, 0xFD, 0xA0, 0x76, - 0x88, 0x15, 0xB6, 0x65, - // - - 0x00, 0x01, // bcdVersion, Protocol version supported. Must be set to 0x0100. - WEBUSB_VENDOR_CODE, // bVendorCode, bRequest value used for issuing WebUSB requests. - // there used to be a concept of "allowed origins", but it was removed from the spec - // it was intended to be a security feature, but then the entire security model relies on domain ownership - // https://github.com/WICG/webusb/issues/49 - // other implementations use various other indexed to leverate this no-longer-valid feature. we wont. - // the spec says we *must* reply to index 0x03 with the url, so we'll hint that that's the right index - 0x03, // iLandingPage, URL descriptor index of the device’s landing page. - - // ------------------------------------------------- - // WinUSB descriptor - // header - 0x1C, // Descriptor size (28 bytes) - 0x10, // Descriptor type (Device Capability) - 0x05, // Capability type (Platform) - 0x00, // Reserved - - // MS OS 2.0 Platform Capability ID (D8DD60DF-4589-4CC7-9CD2-659D9E648A9F) - // Indicates the device supports the Microsoft OS 2.0 descriptor - 0xDF, 0x60, 0xDD, 0xD8, - 0x89, 0x45, 0xC7, 0x4C, - 0x9C, 0xD2, 0x65, 0x9D, - 0x9E, 0x64, 0x8A, 0x9F, - - 0x00, 0x00, 0x03, 0x06, // Windows version, currently set to 8.1 (0x06030000) - - WINUSB_PLATFORM_DESCRIPTOR_LENGTH, 0x00, // MS OS 2.0 descriptor size (word) - MS_VENDOR_CODE, 0x00 // vendor code, no alternate enumeration -}; - -// WinUSB 2.0 descriptor. This is what modern systems use -// https://github.com/sowbug/weblight/blob/192ad7a0e903542e2aa28c607d98254a12a6399d/firmware/webusb.c -// http://janaxelson.com/files/ms_os_20_descriptors.c -// https://books.google.com/books?id=pkefBgAAQBAJ&pg=PA353&lpg=PA353 -uint8_t winusb_20_desc[WINUSB_PLATFORM_DESCRIPTOR_LENGTH] = { - // Microsoft OS 2.0 descriptor set header (table 10) - 0x0A, 0x00, // Descriptor size (10 bytes) - 0x00, 0x00, // MS OS 2.0 descriptor set header - - 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) - WINUSB_PLATFORM_DESCRIPTOR_LENGTH, 0x00, // Total size of MS OS 2.0 descriptor set - - // Microsoft OS 2.0 compatible ID descriptor - 0x14, 0x00, // Descriptor size (20 bytes) - 0x03, 0x00, // MS OS 2.0 compatible ID descriptor - 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID (WINUSB) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub-compatible ID - - // Registry property descriptor - 0x80, 0x00, // Descriptor size (130 bytes) - 0x04, 0x00, // Registry Property descriptor - 0x01, 0x00, // Strings are null-terminated Unicode - 0x28, 0x00, // Size of Property Name (40 bytes) "DeviceInterfaceGUID" - - // bPropertyName (DeviceInterfaceGUID) - 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, - 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, - 'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, - - 0x4E, 0x00, // Size of Property Data (78 bytes) - - // Vendor-defined property data: {CCE5291C-A69F-4995-A4C2-2AE57A51ADE9} - '{', 0x00, 'c', 0x00, 'c', 0x00, 'e', 0x00, '5', 0x00, '2', 0x00, '9', 0x00, '1', 0x00, // 16 - 'c', 0x00, '-', 0x00, 'a', 0x00, '6', 0x00, '9', 0x00, 'f', 0x00, '-', 0x00, '4', 0x00, // 32 - '9', 0x00, '9', 0x00, '5', 0x00, '-', 0x00, 'a', 0x00, '4', 0x00, 'c', 0x00, '2', 0x00, // 48 - '-', 0x00, '2', 0x00, 'a', 0x00, 'e', 0x00, '5', 0x00, '7', 0x00, 'a', 0x00, '5', 0x00, // 64 - '1', 0x00, 'a', 0x00, 'd', 0x00, 'e', 0x00, '9', 0x00, '}', 0x00, 0x00, 0x00 // 78 bytes -}; +static uint8_t response[USBPACKET_MAX_SIZE]; // current packet -USB_Setup_TypeDef setup; -uint8_t usbdata[0x100] __attribute__((aligned(4))); -uint8_t* ep0_txdata = NULL; -uint16_t ep0_txlen = 0; -bool outep3_processing = false; +static USB_Setup_TypeDef setup; +static uint8_t* ep0_txdata = NULL; +static uint16_t ep0_txlen = 0; +static bool outep3_processing = false; // Store the current interface alt setting. -int current_int0_alt_setting = 0; +static int current_int0_alt_setting = 0; // packet read and write -void *USB_ReadPacket(void *dest, uint16_t len) { +static void *USB_ReadPacket(void *dest, uint16_t len) { uint32_t *dest_copy = (uint32_t *)dest; uint32_t count32b = ((uint32_t)len + 3U) / 4U; @@ -366,7 +26,7 @@ void *USB_ReadPacket(void *dest, uint16_t len) { return ((void *)dest_copy); } -void USB_WritePacket(const void *src, uint16_t len, uint32_t ep) { +static void USB_WritePacket(const void *src, uint16_t len, uint32_t ep) { #ifdef DEBUG_USB print("writing "); hexdump(src, len); @@ -393,7 +53,7 @@ void USB_WritePacket(const void *src, uint16_t len, uint32_t ep) { // IN EP 0 TX FIFO has a max size of 127 bytes (much smaller than the rest) // so use TX FIFO empty interrupt to send larger amounts of data -void USB_WritePacket_EP0(uint8_t *src, uint16_t len) { +static void USB_WritePacket_EP0(uint8_t *src, uint16_t len) { #ifdef DEBUG_USB print("writing "); hexdump(src, len); @@ -411,7 +71,7 @@ void USB_WritePacket_EP0(uint8_t *src, uint16_t len) { } } -void usb_reset(void) { +static void usb_reset(void) { // unmask endpoint interrupts, so many sets USBx_DEVICE->DAINT = 0xFFFFFFFFU; USBx_DEVICE->DAINTMSK = 0xFFFFFFFFU; @@ -454,7 +114,7 @@ void usb_reset(void) { USBx_OUTEP(0U)->DOEPTSIZ = USB_OTG_DOEPTSIZ_STUPCNT | (USB_OTG_DOEPTSIZ_PKTCNT & (1UL << 19)) | (3U << 3); } -char to_hex_char(uint8_t a) { +static char to_hex_char(uint8_t a) { char ret; if (a < 10U) { ret = '0' + a; @@ -465,12 +125,238 @@ char to_hex_char(uint8_t a) { } void usb_tick(void) { + static uint16_t usb_last_frame_num = 0U; uint16_t current_frame_num = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF_Msk) >> USB_OTG_DSTS_FNSOF_Pos; usb_enumerated = (current_frame_num != usb_last_frame_num); usb_last_frame_num = current_frame_num; } -void usb_setup(void) { +static void usb_setup(void) { + static uint8_t device_desc[] = { + DSCR_DEVICE_LEN, USB_DESC_TYPE_DEVICE, //Length, Type + 0x10, 0x02, // bcdUSB max version of USB supported (2.1) + 0xFF, 0xFF, 0xFF, 0x40, // Class, Subclass, Protocol, Max Packet Size + TOUSBORDER(USB_VID), // idVendor + TOUSBORDER(USB_PID), // idProduct + 0x00, 0x00, // bcdDevice + 0x01, 0x02, // Manufacturer, Product + 0x03, 0x01 // Serial Number, Num Configurations + }; + + static uint8_t device_qualifier[] = { + 0x0a, USB_DESC_TYPE_DEVICE_QUALIFIER, //Length, Type + 0x10, 0x02, // bcdUSB max version of USB supported (2.1) + 0xFF, 0xFF, 0xFF, 0x40, // bDeviceClass, bDeviceSubClass, bDeviceProtocol, bMaxPacketSize0 + 0x01, 0x00 // bNumConfigurations, bReserved + }; + + static uint8_t configuration_desc[] = { + DSCR_CONFIG_LEN, USB_DESC_TYPE_CONFIGURATION, // Length, Type, + TOUSBORDER(0x0045U), // Total Len (uint16) + 0x01, 0x01, STRING_OFFSET_ICONFIGURATION, // Num Interface, Config Value, Configuration + 0xc0, 0x32, // Attributes, Max Power + // interface 0 ALT 0 + DSCR_INTERFACE_LEN, USB_DESC_TYPE_INTERFACE, // Length, Type + 0x00, 0x00, 0x03, // Index, Alt Index idx, Endpoint count + 0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol + 0x00, // Interface + // endpoint 1, read CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_RCV | 1, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval (NA) + // endpoint 2, send serial + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + // endpoint 3, send CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + // interface 0 ALT 1 + DSCR_INTERFACE_LEN, USB_DESC_TYPE_INTERFACE, // Length, Type + 0x00, 0x01, 0x03, // Index, Alt Index idx, Endpoint count + 0XFF, 0xFF, 0xFF, // Class, Subclass, Protocol + 0x00, // Interface + // endpoint 1, read CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_RCV | 1, ENDPOINT_TYPE_INT, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x05, // Polling Interval (5 frames) + // endpoint 2, send serial + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 2, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + // endpoint 3, send CAN + DSCR_ENDPOINT_LEN, USB_DESC_TYPE_ENDPOINT, // Length, Type + ENDPOINT_SND | 3, ENDPOINT_TYPE_BULK, // Endpoint Num/Direction, Type + TOUSBORDER(0x0040U), // Max Packet (0x0040) + 0x00, // Polling Interval + }; + + // STRING_DESCRIPTOR_HEADER is for uint16 string descriptors + // it takes in a string length, which is bytes/2 because unicode + static uint16_t string_language_desc[] = { + STRING_DESCRIPTOR_HEADER(1), + 0x0409 // american english + }; + + // these strings are all uint16's so that we don't need to spam ,0 after every character + static uint16_t string_manufacturer_desc[] = { + STRING_DESCRIPTOR_HEADER(8), + 'c', 'o', 'm', 'm', 'a', '.', 'a', 'i' + }; + + static uint16_t string_product_desc[] = { + STRING_DESCRIPTOR_HEADER(5), + 'p', 'a', 'n', 'd', 'a' + }; + + // a string containing the default configuration index + static uint16_t string_configuration_desc[] = { + STRING_DESCRIPTOR_HEADER(2), + '0', '1' // "01" + }; + + // WCID (auto install WinUSB driver) + // https://github.com/pbatard/libwdi/wiki/WCID-Devices + // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/winusb-installation#automatic-installation-of--winusb-without-an-inf-file + // WinUSB 1.0 descriptors, this is mostly used by Windows XP + static uint8_t string_238_desc[] = { + 0x12, USB_DESC_TYPE_STRING, // bLength, bDescriptorType + 'M',0, 'S',0, 'F',0, 'T',0, '1',0, '0',0, '0',0, // qwSignature (MSFT100) + MS_VENDOR_CODE, 0x00 // bMS_VendorCode, bPad + }; + + static uint8_t winusb_ext_compatid_os_desc[] = { + 0x28, 0x00, 0x00, 0x00, // dwLength + 0x00, 0x01, // bcdVersion + 0x04, 0x00, // wIndex + 0x01, // bCount + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved + 0x00, // bFirstInterfaceNumber + 0x00, // Reserved + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID (WINUSB) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subcompatible ID (none) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved + }; + + static uint8_t winusb_ext_prop_os_desc[] = { + 0x8e, 0x00, 0x00, 0x00, // dwLength + 0x00, 0x01, // bcdVersion + 0x05, 0x00, // wIndex + 0x01, 0x00, // wCount + // first property + 0x84, 0x00, 0x00, 0x00, // dwSize + 0x01, 0x00, 0x00, 0x00, // dwPropertyDataType + 0x28, 0x00, // wPropertyNameLength + 'D',0, 'e',0, 'v',0, 'i',0, 'c',0, 'e',0, 'I',0, 'n',0, 't',0, 'e',0, 'r',0, 'f',0, 'a',0, 'c',0, 'e',0, 'G',0, 'U',0, 'I',0, 'D',0, 0, 0, // bPropertyName (DeviceInterfaceGUID) + 0x4e, 0x00, 0x00, 0x00, // dwPropertyDataLength + '{',0, 'c',0, 'c',0, 'e',0, '5',0, '2',0, '9',0, '1',0, 'c',0, '-',0, 'a',0, '6',0, '9',0, 'f',0, '-',0, '4',0 ,'9',0 ,'9',0 ,'5',0 ,'-',0, 'a',0, '4',0, 'c',0, '2',0, '-',0, '2',0, 'a',0, 'e',0, '5',0, '7',0, 'a',0, '5',0, '1',0, 'a',0, 'd',0, 'e',0, '9',0, '}',0, 0, 0, // bPropertyData ({CCE5291C-A69F-4995-A4C2-2AE57A51ADE9}) + }; + + /* + Binary Object Store descriptor used to expose WebUSB (and more WinUSB) metadata + comments are from the wicg spec + References used: + https://wicg.github.io/webusb/#webusb-platform-capability-descriptor + https://github.com/sowbug/weblight/blob/192ad7a0e903542e2aa28c607d98254a12a6399d/firmware/webusb.c + https://os.mbed.com/users/larsgk/code/USBDevice_WebUSB/file/1d8a6665d607/WebUSBDevice/ + */ + static 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 + 0x39, 0x00, // wTotalLength (LSB, MSB) + 0x02, // bNumDeviceCaps (WebUSB + WinUSB) + + // ------------------------------------------------- + // WebUSB descriptor + // header + 0x18, // bLength, Size of this descriptor. Must be set to 24. + 0x10, // bDescriptorType, DEVICE CAPABILITY descriptor + 0x05, // bDevCapabilityType, PLATFORM capability + 0x00, // bReserved, This field is reserved and shall be set to zero. + + // PlatformCapabilityUUID, Must be set to {3408b638-09a9-47a0-8bfd-a0768815b665}. + 0x38, 0xB6, 0x08, 0x34, + 0xA9, 0x09, 0xA0, 0x47, + 0x8B, 0xFD, 0xA0, 0x76, + 0x88, 0x15, 0xB6, 0x65, + // + + 0x00, 0x01, // bcdVersion, Protocol version supported. Must be set to 0x0100. + WEBUSB_VENDOR_CODE, // bVendorCode, bRequest value used for issuing WebUSB requests. + // there used to be a concept of "allowed origins", but it was removed from the spec + // it was intended to be a security feature, but then the entire security model relies on domain ownership + // https://github.com/WICG/webusb/issues/49 + // other implementations use various other indexed to leverate this no-longer-valid feature. we wont. + // the spec says we *must* reply to index 0x03 with the url, so we'll hint that that's the right index + 0x03, // iLandingPage, URL descriptor index of the device’s landing page. + + // ------------------------------------------------- + // WinUSB descriptor + // header + 0x1C, // Descriptor size (28 bytes) + 0x10, // Descriptor type (Device Capability) + 0x05, // Capability type (Platform) + 0x00, // Reserved + + // MS OS 2.0 Platform Capability ID (D8DD60DF-4589-4CC7-9CD2-659D9E648A9F) + // Indicates the device supports the Microsoft OS 2.0 descriptor + 0xDF, 0x60, 0xDD, 0xD8, + 0x89, 0x45, 0xC7, 0x4C, + 0x9C, 0xD2, 0x65, 0x9D, + 0x9E, 0x64, 0x8A, 0x9F, + + 0x00, 0x00, 0x03, 0x06, // Windows version, currently set to 8.1 (0x06030000) + + WINUSB_PLATFORM_DESCRIPTOR_LENGTH, 0x00, // MS OS 2.0 descriptor size (word) + MS_VENDOR_CODE, 0x00 // vendor code, no alternate enumeration + }; + + // WinUSB 2.0 descriptor. This is what modern systems use + // https://github.com/sowbug/weblight/blob/192ad7a0e903542e2aa28c607d98254a12a6399d/firmware/webusb.c + // http://janaxelson.com/files/ms_os_20_descriptors.c + // https://books.google.com/books?id=pkefBgAAQBAJ&pg=PA353&lpg=PA353 + static uint8_t winusb_20_desc[WINUSB_PLATFORM_DESCRIPTOR_LENGTH] = { + // Microsoft OS 2.0 descriptor set header (table 10) + 0x0A, 0x00, // Descriptor size (10 bytes) + 0x00, 0x00, // MS OS 2.0 descriptor set header + + 0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000) + WINUSB_PLATFORM_DESCRIPTOR_LENGTH, 0x00, // Total size of MS OS 2.0 descriptor set + + // Microsoft OS 2.0 compatible ID descriptor + 0x14, 0x00, // Descriptor size (20 bytes) + 0x03, 0x00, // MS OS 2.0 compatible ID descriptor + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID (WINUSB) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub-compatible ID + + // Registry property descriptor + 0x80, 0x00, // Descriptor size (130 bytes) + 0x04, 0x00, // Registry Property descriptor + 0x01, 0x00, // Strings are null-terminated Unicode + 0x28, 0x00, // Size of Property Name (40 bytes) "DeviceInterfaceGUID" + + // bPropertyName (DeviceInterfaceGUID) + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, + 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, + 'U', 0x00, 'I', 0x00, 'D', 0x00, 0x00, 0x00, + + 0x4E, 0x00, // Size of Property Data (78 bytes) + + // Vendor-defined property data: {CCE5291C-A69F-4995-A4C2-2AE57A51ADE9} + '{', 0x00, 'c', 0x00, 'c', 0x00, 'e', 0x00, '5', 0x00, '2', 0x00, '9', 0x00, '1', 0x00, // 16 + 'c', 0x00, '-', 0x00, 'a', 0x00, '6', 0x00, '9', 0x00, 'f', 0x00, '-', 0x00, '4', 0x00, // 32 + '9', 0x00, '9', 0x00, '5', 0x00, '-', 0x00, 'a', 0x00, '4', 0x00, 'c', 0x00, '2', 0x00, // 48 + '-', 0x00, '2', 0x00, 'a', 0x00, 'e', 0x00, '5', 0x00, '7', 0x00, 'a', 0x00, '5', 0x00, // 64 + '1', 0x00, 'a', 0x00, 'd', 0x00, 'e', 0x00, '9', 0x00, '}', 0x00, 0x00, 0x00 // 78 bytes + }; + int resp_len; ControlPacket_t control_req; @@ -639,7 +525,7 @@ void usb_setup(void) { void usb_irqhandler(void) { //USBx->GINTMSK = 0; - + static uint8_t usbdata[0x100] __attribute__((aligned(4))); unsigned int gintsts = USBx->GINTSTS; unsigned int gotgint = USBx->GOTGINT; unsigned int daint = USBx_DEVICE->DAINT; @@ -914,11 +800,3 @@ void can_tx_comms_resume_usb(void) { } EXIT_CRITICAL(); } - -void usb_soft_disconnect(bool enable) { - if (enable) { - USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS; - } else { - USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS; - } -} diff --git a/board/drivers/usb_declarations.h b/board/drivers/usb_declarations.h new file mode 100644 index 000000000..77f6f5e81 --- /dev/null +++ b/board/drivers/usb_declarations.h @@ -0,0 +1,115 @@ +#pragma once + +// IRQs: OTG_FS + +typedef union { + uint16_t w; + struct BW { + uint8_t msb; + uint8_t lsb; + } + bw; +} uint16_t_uint8_t; + +typedef union _USB_Setup { + uint32_t d8[2]; + struct _SetupPkt_Struc + { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t_uint8_t wValue; + uint16_t_uint8_t wIndex; + uint16_t_uint8_t wLength; + } b; +} USB_Setup_TypeDef; + +extern bool usb_enumerated; + +void usb_init(void); +void refresh_can_tx_slots_available(void); + +// **** supporting defines **** +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C + +#define USB_DESC_TYPE_DEVICE 0x01 +#define USB_DESC_TYPE_CONFIGURATION 0x02 +#define USB_DESC_TYPE_STRING 0x03 +#define USB_DESC_TYPE_INTERFACE 0x04 +#define USB_DESC_TYPE_ENDPOINT 0x05 +#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06 +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07 +#define USB_DESC_TYPE_BINARY_OBJECT_STORE 0x0f + +// offsets for configuration strings +#define STRING_OFFSET_LANGID 0x00 +#define STRING_OFFSET_IMANUFACTURER 0x01 +#define STRING_OFFSET_IPRODUCT 0x02 +#define STRING_OFFSET_ISERIAL 0x03 +#define STRING_OFFSET_ICONFIGURATION 0x04 +#define STRING_OFFSET_IINTERFACE 0x05 + +// WebUSB requests +#define WEBUSB_REQ_GET_URL 0x02 + +// WebUSB types +#define WEBUSB_DESC_TYPE_URL 0x03 +#define WEBUSB_URL_SCHEME_HTTPS 0x01 +#define WEBUSB_URL_SCHEME_HTTP 0x00 + +// WinUSB requests +#define WINUSB_REQ_GET_COMPATID_DESCRIPTOR 0x04 +#define WINUSB_REQ_GET_EXT_PROPS_OS 0x05 +#define WINUSB_REQ_GET_DESCRIPTOR 0x07 + +#define STS_GOUT_NAK 1 +#define STS_DATA_UPDT 2 +#define STS_XFER_COMP 3 +#define STS_SETUP_COMP 4 +#define STS_SETUP_UPDT 6 + +// for the repeating interfaces +#define DSCR_INTERFACE_LEN 9 +#define DSCR_ENDPOINT_LEN 7 +#define DSCR_CONFIG_LEN 9 +#define DSCR_DEVICE_LEN 18 + +// endpoint types +#define ENDPOINT_TYPE_CONTROL 0 +#define ENDPOINT_TYPE_ISO 1 +#define ENDPOINT_TYPE_BULK 2 +#define ENDPOINT_TYPE_INT 3 + +// These are arbitrary values used in bRequest +#define MS_VENDOR_CODE 0x20 +#define WEBUSB_VENDOR_CODE 0x30 + +// BOS constants +#define BINARY_OBJECT_STORE_DESCRIPTOR_LENGTH 0x05 +#define BINARY_OBJECT_STORE_DESCRIPTOR 0x0F +#define WINUSB_PLATFORM_DESCRIPTOR_LENGTH 0x9E + +// Convert machine byte order to USB byte order +#define TOUSBORDER(num)\ + ((num) & 0xFFU), (((uint16_t)(num) >> 8) & 0xFFU) + +// take in string length and return the first 2 bytes of a string descriptor +#define STRING_DESCRIPTOR_HEADER(size)\ + (((((size) * 2) + 2) & 0xFF) | 0x0300) + +#define ENDPOINT_RCV 0x80 +#define ENDPOINT_SND 0x00 + +// packet read and write +void usb_tick(void); +// ***************************** USB port ***************************** +void can_tx_comms_resume_usb(void); diff --git a/board/drivers/watchdog.h b/board/drivers/watchdog.h index 89cf01e07..51337ba6e 100644 --- a/board/drivers/watchdog.h +++ b/board/drivers/watchdog.h @@ -3,7 +3,7 @@ typedef enum { WATCHDOG_500_MS = 4000U, } WatchdogTimeout; -void watchdog_feed(void) { +static void watchdog_feed(void) { IND_WDG->KR = 0xAAAAU; } diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index 5a18a742c..f89eb9752 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -1,3 +1,5 @@ +static bool spi_tx_dma_done = false; + // master -> panda DMA start void llspi_mosi_dma(uint8_t *addr, int len) { // disable DMA + SPI