From ad2c0e632a0b1a863b9f7d21ae3ed26531a63961 Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Thu, 20 Jul 2017 23:14:27 -0700 Subject: [PATCH] start the refactor --- board/can.h | 269 ++++++++++++++++++++++++++-- board/libc.h | 19 +- board/main.c | 490 +-------------------------------------------------- board/spi.h | 50 ++++++ board/uart.h | 153 ++++++++++++++++ board/usb.h | 32 +++- 6 files changed, 503 insertions(+), 510 deletions(-) diff --git a/board/can.h b/board/can.h index 791e36dc8..d01d28a72 100644 --- a/board/can.h +++ b/board/can.h @@ -1,3 +1,65 @@ +// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE, CAN2_TX, CAN2_RX0, CAN2_SCE, CAN3_TX, CAN3_RX0, CAN3_SCE + +// ********************* instantiate queues ********************* + +typedef struct { + uint32_t w_ptr; + uint32_t r_ptr; + uint32_t fifo_size; + CAN_FIFOMailBox_TypeDef *elems; +} can_ring; + +#define can_buffer(x, size) \ + CAN_FIFOMailBox_TypeDef elems_##x[size]; \ + can_ring can_##x = { .w_ptr = 0, .r_ptr = 0, .fifo_size = size, .elems = (CAN_FIFOMailBox_TypeDef *)&elems_##x }; + +can_buffer(rx_q, 0x1000) +can_buffer(tx1_q, 0x100) +can_buffer(tx2_q, 0x100) + +#ifdef PANDA + can_buffer(tx3_q, 0x100) + can_buffer(txgmlan_q, 0x100) + can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q, &can_txgmlan_q}; +#else + can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q}; +#endif + +// ********************* interrupt safe queue ********************* + +int pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) { + int ret = 0; + + enter_critical_section(); + if (q->w_ptr != q->r_ptr) { + *elem = q->elems[q->r_ptr]; + if ((q->r_ptr + 1) == q->fifo_size) q->r_ptr = 0; + else q->r_ptr += 1; + ret = 1; + } + exit_critical_section(); + + return ret; +} + +int push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) { + int ret = 0; + uint32_t next_w_ptr; + + enter_critical_section(); + if ((q->w_ptr + 1) == q->fifo_size) next_w_ptr = 0; + else next_w_ptr = q->w_ptr + 1; + if (next_w_ptr != q->r_ptr) { + q->elems[q->w_ptr] = *elem; + q->w_ptr = next_w_ptr; + ret = 1; + } + exit_critical_section(); + if (ret == 0) puts("push failed!\n"); + return ret; +} + + // assign CAN numbering // bus num: Can bus number on ODB connector. Sent to/from USB // Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1) @@ -33,13 +95,13 @@ int can_err_cnt = 0; #endif #define CANIF_FROM_CAN_NUM(num) (cans[num]) -//#define CANIF_FROM_BUS_NUM(num) (cans[can_num_lookup[num]]) #define BUS_NUM_FROM_CAN_NUM(num) (bus_lookup[num]) #define CAN_NUM_FROM_BUS_NUM(num) (can_num_lookup[num]) #define CAN_BUS_RET_FLAG 0x80 #define CAN_BUS_NUM_MASK 0x7F +// other option /*#define CAN_QUANTA 16 #define CAN_SEQ1 13 #define CAN_SEQ2 2*/ @@ -54,6 +116,8 @@ int can_err_cnt = 0; // 5000 = 500 kbps #define can_speed_to_prescaler(x) (CAN_PCLK / CAN_QUANTA * 10 / (x)) +void process_can(uint8_t can_number); + void can_init(uint8_t can_number) { if (can_number == 0xff) return; @@ -109,6 +173,26 @@ void can_init(uint8_t can_number) { //CAN->IER = CAN_IER_TMEIE; CAN->IER = CAN_IER_TMEIE | CAN_IER_FMPIE0; + switch (can_number) { + case 0: + NVIC_EnableIRQ(CAN1_TX_IRQn); + NVIC_EnableIRQ(CAN1_RX0_IRQn); + NVIC_EnableIRQ(CAN1_SCE_IRQn); + break; + case 1: + NVIC_EnableIRQ(CAN2_TX_IRQn); + NVIC_EnableIRQ(CAN2_RX0_IRQn); + NVIC_EnableIRQ(CAN2_SCE_IRQn); + break; +#ifdef CAN3 + case 2: + NVIC_EnableIRQ(CAN3_TX_IRQn); + NVIC_EnableIRQ(CAN3_RX0_IRQn); + NVIC_EnableIRQ(CAN3_SCE_IRQn); + break; +#endif + } + // in case there are queued up messages process_can(can_number); } @@ -119,6 +203,46 @@ void can_init_all() { } } +void can_set_gmlan(int bus) { + if (bus == -1) { + // GMLAN OFF + switch (can_num_lookup[3]) { + case 1: + puts("disable GMLAN on CAN2\n"); + set_can_mode(1, 0); + bus_lookup[1] = 1; + can_num_lookup[1] = 1; + can_num_lookup[3] = -1; + can_init(1); + break; + case 2: + puts("disable GMLAN on CAN3\n"); + set_can_mode(2, 0); + bus_lookup[2] = 2; + can_num_lookup[2] = 2; + can_num_lookup[3] = -1; + can_init(2); + break; + } + } else if (bus == 1) { + puts("GMLAN on CAN2\n"); + // GMLAN on CAN2 + set_can_mode(1, 1); + bus_lookup[1] = 3; + can_num_lookup[1] = -1; + can_num_lookup[3] = 1; + can_init(1); + } else if (bus == 2 && revision == PANDA_REV_C) { + puts("GMLAN on CAN3\n"); + // GMLAN on CAN3 + set_can_mode(2, 1); + bus_lookup[2] = 3; + can_num_lookup[2] = -1; + can_num_lookup[3] = 2; + can_init(2); + } +} + // CAN error void can_sce(CAN_TypeDef *CAN) { can_err_cnt += 1; @@ -141,26 +265,137 @@ void can_sce(CAN_TypeDef *CAN) { puts("\n"); #endif - // clear - //CAN->sTxMailBox[0].TIR &= ~(CAN_TI0R_TXRQ); + // clear current send CAN->TSR |= CAN_TSR_ABRQ0; - //CAN->ESR |= CAN_ESR_LEC; - //CAN->MSR &= ~(CAN_MSR_ERRI); CAN->MSR = CAN->MSR; } -int can_cksum(uint8_t *dat, int len, int addr, int idx) { - int i; - int s = 0; - for (i = 0; i < len; i++) { - s += (dat[i] >> 4); - s += dat[i] & 0xF; +// ***************************** CAN ***************************** + +void process_can(uint8_t can_number) { + if (can_number == 0xff) return; + + enter_critical_section(); + + CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number); + uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); + #ifdef DEBUG + puts("process CAN TX\n"); + #endif + + // check for empty mailbox + CAN_FIFOMailBox_TypeDef to_send; + if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) { + // add successfully transmitted message to my fifo + if ((CAN->TSR & CAN_TSR_RQCP0) == CAN_TSR_RQCP0) { + can_txd_cnt += 1; + + if ((CAN->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) { + CAN_FIFOMailBox_TypeDef to_push; + to_push.RIR = CAN->sTxMailBox[0].TIR; + to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000F) | ((CAN_BUS_RET_FLAG | bus_number) << 4); + to_push.RDLR = CAN->sTxMailBox[0].TDLR; + to_push.RDHR = CAN->sTxMailBox[0].TDHR; + push(&can_rx_q, &to_push); + } + + if ((CAN->TSR & CAN_TSR_TERR0) == CAN_TSR_TERR0) { + #ifdef DEBUG + puts("CAN TX ERROR!\n"); + #endif + } + + if ((CAN->TSR & CAN_TSR_ALST0) == CAN_TSR_ALST0) { + #ifdef DEBUG + puts("CAN TX ARBITRATION LOST!\n"); + #endif + } + + // clear interrupt + // careful, this can also be cleared by requesting a transmission + CAN->TSR |= CAN_TSR_RQCP0; + } + + if (pop(can_queues[bus_number], &to_send)) { + can_tx_cnt += 1; + // only send if we have received a packet + CAN->sTxMailBox[0].TDLR = to_send.RDLR; + CAN->sTxMailBox[0].TDHR = to_send.RDHR; + CAN->sTxMailBox[0].TDTR = to_send.RDTR; + CAN->sTxMailBox[0].TIR = to_send.RIR; + } + } + + exit_critical_section(); +} + +void send_can(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number); + +// CAN receive handlers +// blink blue when we are receiving CAN messages +void can_rx(uint8_t can_number) { + CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number); + uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); + while (CAN->RF0R & CAN_RF0R_FMP0) { + can_rx_cnt += 1; + + // can is live + pending_can_live = 1; + + // add to my fifo + CAN_FIFOMailBox_TypeDef to_push; + to_push.RIR = CAN->sFIFOMailBox[0].RIR; + to_push.RDTR = CAN->sFIFOMailBox[0].RDTR; + to_push.RDLR = CAN->sFIFOMailBox[0].RDLR; + to_push.RDHR = CAN->sFIFOMailBox[0].RDHR; + + // forwarding (panda only) + #ifdef PANDA + if (can_forwarding[bus_number] != -1) { + CAN_FIFOMailBox_TypeDef to_send; + to_send.RIR = to_push.RIR | 1; // TXRQ + to_send.RDTR = to_push.RDTR; + to_send.RDLR = to_push.RDLR; + to_send.RDHR = to_push.RDHR; + send_can(&to_send, can_forwarding[bus_number]); + } + #endif + + // modify RDTR for our API + to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4); + safety_rx_hook(&to_push); + + #ifdef PANDA + set_led(LED_GREEN, 1); + #endif + push(&can_rx_q, &to_push); + + // next + CAN->RF0R |= CAN_RF0R_RFOM0; + } +} + +void CAN1_TX_IRQHandler() { process_can(0); } +void CAN1_RX0_IRQHandler() { can_rx(0); } +void CAN1_SCE_IRQHandler() { can_sce(CAN1); } + +void CAN2_TX_IRQHandler() { process_can(1); } +void CAN2_RX0_IRQHandler() { can_rx(1); } +void CAN2_SCE_IRQHandler() { can_sce(CAN2); } + +#ifdef CAN3 +void CAN3_TX_IRQHandler() { process_can(2); } +void CAN3_RX0_IRQHandler() { can_rx(2); } +void CAN3_SCE_IRQHandler() { can_sce(CAN3); } +#endif + +void send_can(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) { + if (bus_number < BUS_MAX) { + // add CAN packet to send queue + // bus number isn't passed through + to_push->RDTR &= 0xF; + push(can_queues[bus_number], to_push); + process_can(CAN_NUM_FROM_BUS_NUM(bus_number)); } - s += (addr>>0)&0xF; - s += (addr>>4)&0xF; - s += (addr>>8)&0xF; - s += idx; - s = 8-s; - return s&0xF; } diff --git a/board/libc.h b/board/libc.h index 6b3f5d274..ed2db40fd 100644 --- a/board/libc.h +++ b/board/libc.h @@ -1,4 +1,3 @@ - #define min(a,b) \ ({ __typeof__ (a) _a = (a); \ __typeof__ (b) _b = (b); \ @@ -73,3 +72,21 @@ int memcmp(const void * ptr1, const void * ptr2, unsigned int num) { } return 0; } + +// ********************* IRQ helpers ********************* + +int critical_depth = 0; +void enter_critical_section() { + __disable_irq(); + // this is safe because interrupts are disabled + critical_depth += 1; +} + +void exit_critical_section() { + // this is safe because interrupts are disabled + critical_depth -= 1; + if (critical_depth == 0) { + __enable_irq(); + } +} + diff --git a/board/main.c b/board/main.c index 829601f94..c573dce2d 100644 --- a/board/main.c +++ b/board/main.c @@ -27,232 +27,6 @@ int did_usb_enumerate = 0; // Declare puts to supress warning int puts ( const char * str ); -// ********************* instantiate queues ********************* - -typedef struct { - uint32_t w_ptr; - uint32_t r_ptr; - uint32_t fifo_size; - CAN_FIFOMailBox_TypeDef *elems; -} can_ring; - -#define can_buffer(x, size) \ - CAN_FIFOMailBox_TypeDef elems_##x[size]; \ - can_ring can_##x = { .w_ptr = 0, .r_ptr = 0, .fifo_size = size, .elems = (CAN_FIFOMailBox_TypeDef *)&elems_##x }; - -can_buffer(rx_q, 0x1000) -can_buffer(tx1_q, 0x100) -can_buffer(tx2_q, 0x100) - -#ifdef PANDA - can_buffer(tx3_q, 0x100) - can_buffer(txgmlan_q, 0x100) - can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q, &can_txgmlan_q}; -#else - can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q}; -#endif - -// ********************* IRQ helpers ********************* - -int critical_depth = 0; -void enter_critical_section() { - __disable_irq(); - // this is safe because interrupts are disabled - critical_depth += 1; -} - -void exit_critical_section() { - // this is safe because interrupts are disabled - critical_depth -= 1; - if (critical_depth == 0) { - __enable_irq(); - } -} - -// ********************* interrupt safe queue ********************* - -int pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) { - int ret = 0; - - enter_critical_section(); - if (q->w_ptr != q->r_ptr) { - *elem = q->elems[q->r_ptr]; - if ((q->r_ptr + 1) == q->fifo_size) q->r_ptr = 0; - else q->r_ptr += 1; - ret = 1; - } - exit_critical_section(); - - return ret; -} - -int push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) { - int ret = 0; - uint32_t next_w_ptr; - - enter_critical_section(); - if ((q->w_ptr + 1) == q->fifo_size) next_w_ptr = 0; - else next_w_ptr = q->w_ptr + 1; - if (next_w_ptr != q->r_ptr) { - q->elems[q->w_ptr] = *elem; - q->w_ptr = next_w_ptr; - ret = 1; - } - exit_critical_section(); - if (ret == 0) puts("push failed!\n"); - return ret; -} - -// ***************************** serial port queues ***************************** - -#define FIFO_SIZE 0x100 - -typedef struct uart_ring { - uint8_t w_ptr_tx; - uint8_t r_ptr_tx; - uint8_t elems_tx[FIFO_SIZE]; - uint8_t w_ptr_rx; - uint8_t r_ptr_rx; - uint8_t elems_rx[FIFO_SIZE]; - USART_TypeDef *uart; - void (*callback)(struct uart_ring*); -} uart_ring; - -int getc(uart_ring *q, char *elem); -int putc(uart_ring *q, char elem); - -// esp = USART1 -uart_ring esp_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, - .w_ptr_rx = 0, .r_ptr_rx = 0, - .uart = USART1 }; - -// lin1, K-LINE = UART5 -// lin2, L-LINE = USART3 -uart_ring lin1_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, - .w_ptr_rx = 0, .r_ptr_rx = 0, - .uart = UART5 }; -uart_ring lin2_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, - .w_ptr_rx = 0, .r_ptr_rx = 0, - .uart = USART3 }; - -// debug = USART2 -void debug_ring_callback(uart_ring *ring); -uart_ring debug_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, - .w_ptr_rx = 0, .r_ptr_rx = 0, - .uart = USART2, - .callback = debug_ring_callback}; - - -uart_ring *get_ring_by_number(int a) { - switch(a) { - case 0: - return &debug_ring; - case 1: - return &esp_ring; - case 2: - return &lin1_ring; - case 3: - return &lin2_ring; - default: - return NULL; - } -} - -// ***************************** serial port ***************************** - -void uart_ring_process(uart_ring *q) { - enter_critical_section(); - // TODO: check if external serial is connected - int sr = q->uart->SR; - - if (q->w_ptr_tx != q->r_ptr_tx) { - if (sr & USART_SR_TXE) { - q->uart->DR = q->elems_tx[q->r_ptr_tx]; - q->r_ptr_tx += 1; - } else { - // push on interrupt later - q->uart->CR1 |= USART_CR1_TXEIE; - } - } else { - // nothing to send - q->uart->CR1 &= ~USART_CR1_TXEIE; - } - - if (sr & USART_SR_RXNE) { - uint8_t c = q->uart->DR; // TODO: can drop packets - uint8_t next_w_ptr = q->w_ptr_rx + 1; - if (next_w_ptr != q->r_ptr_rx) { - q->elems_rx[q->w_ptr_rx] = c; - q->w_ptr_rx = next_w_ptr; - if (q->callback) q->callback(q); - } - } - exit_critical_section(); -} - -// interrupt boilerplate - -void USART1_IRQHandler(void) { - uart_ring_process(&esp_ring); -} - -void USART2_IRQHandler(void) { - uart_ring_process(&debug_ring); -} - -void USART3_IRQHandler(void) { - uart_ring_process(&lin2_ring); -} - -void UART5_IRQHandler(void) { - uart_ring_process(&lin1_ring); -} - -int getc(uart_ring *q, char *elem) { - int ret = 0; - enter_critical_section(); - if (q->w_ptr_rx != q->r_ptr_rx) { - *elem = q->elems_rx[q->r_ptr_rx]; - q->r_ptr_rx += 1; - ret = 1; - } - exit_critical_section(); - return ret; -} - -int injectc(uart_ring *q, char elem) { - int ret = 0; - uint8_t next_w_ptr; - - enter_critical_section(); - next_w_ptr = q->w_ptr_rx + 1; - if (next_w_ptr != q->r_ptr_rx) { - q->elems_rx[q->w_ptr_rx] = elem; - q->w_ptr_rx = next_w_ptr; - ret = 1; - } - exit_critical_section(); - - return ret; -} - -int putc(uart_ring *q, char elem) { - int ret = 0; - uint8_t next_w_ptr; - - enter_critical_section(); - next_w_ptr = q->w_ptr_tx + 1; - if (next_w_ptr != q->r_ptr_tx) { - q->elems_tx[q->w_ptr_tx] = elem; - q->w_ptr_tx = next_w_ptr; - ret = 1; - } - uart_ring_process(q); - exit_critical_section(); - - return ret; -} - // ********************* includes ********************* #include "libc.h" @@ -261,9 +35,9 @@ int putc(uart_ring *q, char elem) { #include "adc.h" #include "timer.h" #include "usb.h" +#include "safety.h" #include "can.h" #include "spi.h" -#include "safety.h" // ********************* debugging ********************* @@ -299,127 +73,6 @@ void debug_ring_callback(uart_ring *ring) { } } - -// ***************************** CAN ***************************** - -void process_can(uint8_t can_number) { - if (can_number == 0xff) return; - - enter_critical_section(); - - CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number); - uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); - #ifdef DEBUG - puts("process CAN TX\n"); - #endif - - // check for empty mailbox - CAN_FIFOMailBox_TypeDef to_send; - if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) { - // add successfully transmitted message to my fifo - if ((CAN->TSR & CAN_TSR_RQCP0) == CAN_TSR_RQCP0) { - can_txd_cnt += 1; - - if ((CAN->TSR & CAN_TSR_TXOK0) == CAN_TSR_TXOK0) { - CAN_FIFOMailBox_TypeDef to_push; - to_push.RIR = CAN->sTxMailBox[0].TIR; - to_push.RDTR = (CAN->sTxMailBox[0].TDTR & 0xFFFF000F) | ((CAN_BUS_RET_FLAG | bus_number) << 4); - to_push.RDLR = CAN->sTxMailBox[0].TDLR; - to_push.RDHR = CAN->sTxMailBox[0].TDHR; - push(&can_rx_q, &to_push); - } - - if ((CAN->TSR & CAN_TSR_TERR0) == CAN_TSR_TERR0) { - #ifdef DEBUG - puts("CAN TX ERROR!\n"); - #endif - } - - if ((CAN->TSR & CAN_TSR_ALST0) == CAN_TSR_ALST0) { - #ifdef DEBUG - puts("CAN TX ARBITRATION LOST!\n"); - #endif - } - - // clear interrupt - // careful, this can also be cleared by requesting a transmission - CAN->TSR |= CAN_TSR_RQCP0; - } - - if (pop(can_queues[bus_number], &to_send)) { - can_tx_cnt += 1; - // only send if we have received a packet - CAN->sTxMailBox[0].TDLR = to_send.RDLR; - CAN->sTxMailBox[0].TDHR = to_send.RDHR; - CAN->sTxMailBox[0].TDTR = to_send.RDTR; - CAN->sTxMailBox[0].TIR = to_send.RIR; - } - } - - exit_critical_section(); -} - -void send_can(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number); - -// CAN receive handlers -// blink blue when we are receiving CAN messages -void can_rx(uint8_t can_number) { - CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number); - uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); - while (CAN->RF0R & CAN_RF0R_FMP0) { - can_rx_cnt += 1; - - // can is live - pending_can_live = 1; - - // add to my fifo - CAN_FIFOMailBox_TypeDef to_push; - to_push.RIR = CAN->sFIFOMailBox[0].RIR; - to_push.RDTR = CAN->sFIFOMailBox[0].RDTR; - to_push.RDLR = CAN->sFIFOMailBox[0].RDLR; - to_push.RDHR = CAN->sFIFOMailBox[0].RDHR; - - // forwarding (panda only) - #ifdef PANDA - if (can_forwarding[bus_number] != -1) { - CAN_FIFOMailBox_TypeDef to_send; - to_send.RIR = to_push.RIR | 1; // TXRQ - to_send.RDTR = to_push.RDTR; - to_send.RDLR = to_push.RDLR; - to_send.RDHR = to_push.RDHR; - send_can(&to_send, can_forwarding[bus_number]); - } - #endif - - // modify RDTR for our API - to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4); - safety_rx_hook(&to_push); - - #ifdef PANDA - set_led(LED_GREEN, 1); - #endif - push(&can_rx_q, &to_push); - - // next - CAN->RF0R |= CAN_RF0R_RFOM0; - } -} - -void CAN1_TX_IRQHandler() { process_can(0); } -void CAN1_RX0_IRQHandler() { can_rx(0); } -void CAN1_SCE_IRQHandler() { can_sce(CAN1); } - -void CAN2_TX_IRQHandler() { process_can(1); } -void CAN2_RX0_IRQHandler() { can_rx(1); } -void CAN2_SCE_IRQHandler() { can_sce(CAN2); } - -#ifdef CAN3 -void CAN3_TX_IRQHandler() { process_can(2); } -void CAN3_RX0_IRQHandler() { can_rx(2); } -void CAN3_SCE_IRQHandler() { can_sce(CAN3); } -#endif - - // ***************************** USB port ***************************** int get_health_pkt(void *dat) { @@ -477,16 +130,6 @@ void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) { } } -void send_can(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) { - if (bus_number < BUS_MAX) { - // add CAN packet to send queue - // bus number isn't passed through - to_push->RDTR &= 0xF; - push(can_queues[bus_number], to_push); - process_can(CAN_NUM_FROM_BUS_NUM(bus_number)); - } -} - // send on CAN void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) { int dpkt = 0; @@ -601,42 +244,12 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { if (setup->b.wValue.w == 1) { // GMLAN ON if (setup->b.wIndex.w == 1) { - puts("GMLAN on CAN2\n"); - // GMLAN on CAN2 - set_can_mode(1, 1); - bus_lookup[1] = 3; - can_num_lookup[1] = -1; - can_num_lookup[3] = 1; - can_init(1); - } else if (setup->b.wIndex.w == 2 && revision == PANDA_REV_C) { - puts("GMLAN on CAN3\n"); - // GMLAN on CAN3 - set_can_mode(2, 1); - bus_lookup[2] = 3; - can_num_lookup[2] = -1; - can_num_lookup[3] = 2; - can_init(2); + can_set_gmlan(1); + } else if (setup->b.wIndex.w == 2) { + can_set_gmlan(2); } } else { - // GMLAN OFF - switch (can_num_lookup[3]) { - case 1: - puts("disable GMLAN on CAN2\n"); - set_can_mode(1, 0); - bus_lookup[1] = 1; - can_num_lookup[1] = 1; - can_num_lookup[3] = -1; - can_init(1); - break; - case 2: - puts("disable GMLAN on CAN3\n"); - set_can_mode(2, 0); - bus_lookup[2] = 2; - can_num_lookup[2] = 2; - can_num_lookup[3] = -1; - can_init(2); - break; - } + can_set_gmlan(-1); } #endif break; @@ -758,27 +371,8 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { return resp_len; } - -void OTG_FS_IRQHandler(void) { - NVIC_DisableIRQ(OTG_FS_IRQn); - //__disable_irq(); - usb_irqhandler(); - //__enable_irq(); - NVIC_EnableIRQ(OTG_FS_IRQn); -} - -void ADC_IRQHandler(void) { - puts("ADC_IRQ\n"); -} - #ifdef ENABLE_SPI -#define SPI_BUF_SIZE 256 -uint8_t spi_buf[SPI_BUF_SIZE]; -int spi_buf_count = 0; -int spi_total_count = 0; -uint8_t spi_tx_buf[0x44]; - void handle_spi(uint8_t *data, int len) { memset(spi_tx_buf, 0xaa, 0x44); // data[0] = endpoint @@ -813,34 +407,6 @@ void handle_spi(uint8_t *data, int len) { GPIOB->ODR &= ~(GPIO_ODR_ODR_0); } -// SPI RX -void DMA2_Stream2_IRQHandler(void) { - // ack - DMA2->LIFCR = DMA_LIFCR_CTCIF2; - handle_spi(spi_buf, 0x14); -} - -// SPI TX -void DMA2_Stream3_IRQHandler(void) { - // ack - DMA2->LIFCR = DMA_LIFCR_CTCIF3; - - // reset handshake back to pull up - GPIOB->MODER &= ~(GPIO_MODER_MODER0); - GPIOB->PUPDR |= GPIO_PUPDR_PUPDR0_0; -} - -void EXTI4_IRQHandler(void) { - int pr = EXTI->PR; - // SPI CS rising - if (pr & (1 << 4)) { - spi_total_count = 0; - spi_rx_dma(spi_buf, 0x14); - //puts("exti4\n"); - } - EXTI->PR = pr; -} - #endif // ***************************** main code ***************************** @@ -850,6 +416,8 @@ void __initialize_hardware_early() { } int main() { + __disable_irq(); + // init devices clock_init(); periph_init(); @@ -890,57 +458,13 @@ int main() { // timer for fan PWM TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; TIM3->CCER = TIM_CCER_CC3E; - - // max value of the timer - // 64 makes it above the audible range - //TIM3->ARR = 64; - - // 10 prescale makes it below the audible range timer_init(TIM3, 10); - puth(DBGMCU->IDCODE); // set PWM set_fan_speed(65535); - puts("**** INTERRUPTS ON ****\n"); - __disable_irq(); - // 4 uarts! - NVIC_EnableIRQ(USART1_IRQn); - NVIC_EnableIRQ(USART2_IRQn); - NVIC_EnableIRQ(USART3_IRQn); - NVIC_EnableIRQ(UART5_IRQn); - - NVIC_EnableIRQ(OTG_FS_IRQn); - NVIC_EnableIRQ(ADC_IRQn); - // CAN has so many interrupts! - - NVIC_EnableIRQ(CAN1_TX_IRQn); - NVIC_EnableIRQ(CAN1_RX0_IRQn); - NVIC_EnableIRQ(CAN1_SCE_IRQn); - - NVIC_EnableIRQ(CAN2_TX_IRQn); - NVIC_EnableIRQ(CAN2_RX0_IRQn); - NVIC_EnableIRQ(CAN2_SCE_IRQn); - -#ifdef CAN3 - NVIC_EnableIRQ(CAN3_TX_IRQn); - NVIC_EnableIRQ(CAN3_RX0_IRQn); - NVIC_EnableIRQ(CAN3_SCE_IRQn); -#endif - -#ifdef ENABLE_SPI - NVIC_EnableIRQ(DMA2_Stream2_IRQn); - NVIC_EnableIRQ(DMA2_Stream3_IRQn); - //NVIC_EnableIRQ(SPI1_IRQn); - - // setup interrupt on falling edge of SPI enable (on PA4) - SYSCFG->EXTICR[2] = SYSCFG_EXTICR2_EXTI4_PA; - EXTI->IMR = (1 << 4); - EXTI->FTSR = (1 << 4); - NVIC_EnableIRQ(EXTI4_IRQn); -#endif __enable_irq(); puts("OPTCR: "); puth(FLASH->OPTCR); puts("\n"); diff --git a/board/spi.h b/board/spi.h index 2b5e4cd10..fb64fc2ea 100644 --- a/board/spi.h +++ b/board/spi.h @@ -1,3 +1,11 @@ +// IRQs: DMA2_Stream2, DMA2_Stream3, EXTI4 + +#define SPI_BUF_SIZE 256 +uint8_t spi_buf[SPI_BUF_SIZE]; +int spi_buf_count = 0; +int spi_total_count = 0; +uint8_t spi_tx_buf[0x44]; + void spi_init() { //puts("SPI init\n"); SPI1->CR1 = SPI_CR1_SPE; @@ -5,6 +13,16 @@ void spi_init() { // 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); + + // setup interrupt on falling edge of SPI enable (on PA4) + SYSCFG->EXTICR[2] = SYSCFG_EXTICR2_EXTI4_PA; + EXTI->IMR = (1 << 4); + EXTI->FTSR = (1 << 4); + NVIC_EnableIRQ(EXTI4_IRQn); } void spi_tx_dma(void *addr, int len) { @@ -45,3 +63,35 @@ void spi_rx_dma(void *addr, int len) { SPI1->CR2 |= SPI_CR2_RXDMAEN; } +// ***************************** SPI IRQs ***************************** + +void handle_spi(uint8_t *data, int len); + +// SPI RX +void DMA2_Stream2_IRQHandler(void) { + // ack + DMA2->LIFCR = DMA_LIFCR_CTCIF2; + handle_spi(spi_buf, 0x14); +} + +// SPI TX +void DMA2_Stream3_IRQHandler(void) { + // ack + DMA2->LIFCR = DMA_LIFCR_CTCIF3; + + // reset handshake back to pull up + GPIOB->MODER &= ~(GPIO_MODER_MODER0); + GPIOB->PUPDR |= GPIO_PUPDR_PUPDR0_0; +} + +void EXTI4_IRQHandler(void) { + int pr = EXTI->PR; + // SPI CS rising + if (pr & (1 << 4)) { + spi_total_count = 0; + spi_rx_dma(spi_buf, 0x14); + //puts("exti4\n"); + } + EXTI->PR = pr; +} + diff --git a/board/uart.h b/board/uart.h index 0c062aa3c..332b2f863 100644 --- a/board/uart.h +++ b/board/uart.h @@ -1,3 +1,146 @@ +// IRQs: USART1, USART2, USART3, UART5 + +// ***************************** serial port queues ***************************** + +#define FIFO_SIZE 0x100 + +typedef struct uart_ring { + uint8_t w_ptr_tx; + uint8_t r_ptr_tx; + uint8_t elems_tx[FIFO_SIZE]; + uint8_t w_ptr_rx; + uint8_t r_ptr_rx; + uint8_t elems_rx[FIFO_SIZE]; + USART_TypeDef *uart; + void (*callback)(struct uart_ring*); +} uart_ring; + +int getc(uart_ring *q, char *elem); +int putc(uart_ring *q, char elem); + +// esp = USART1 +uart_ring esp_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, + .w_ptr_rx = 0, .r_ptr_rx = 0, + .uart = USART1 }; + +// lin1, K-LINE = UART5 +// lin2, L-LINE = USART3 +uart_ring lin1_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, + .w_ptr_rx = 0, .r_ptr_rx = 0, + .uart = UART5 }; +uart_ring lin2_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, + .w_ptr_rx = 0, .r_ptr_rx = 0, + .uart = USART3 }; + +// debug = USART2 +void debug_ring_callback(uart_ring *ring); +uart_ring debug_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0, + .w_ptr_rx = 0, .r_ptr_rx = 0, + .uart = USART2, + .callback = debug_ring_callback}; + + +uart_ring *get_ring_by_number(int a) { + switch(a) { + case 0: + return &debug_ring; + case 1: + return &esp_ring; + case 2: + return &lin1_ring; + case 3: + return &lin2_ring; + default: + return NULL; + } +} + +// ***************************** serial port ***************************** + +void uart_ring_process(uart_ring *q) { + enter_critical_section(); + // TODO: check if external serial is connected + int sr = q->uart->SR; + + if (q->w_ptr_tx != q->r_ptr_tx) { + if (sr & USART_SR_TXE) { + q->uart->DR = q->elems_tx[q->r_ptr_tx]; + q->r_ptr_tx += 1; + } else { + // push on interrupt later + q->uart->CR1 |= USART_CR1_TXEIE; + } + } else { + // nothing to send + q->uart->CR1 &= ~USART_CR1_TXEIE; + } + + if (sr & USART_SR_RXNE) { + uint8_t c = q->uart->DR; // TODO: can drop packets + uint8_t next_w_ptr = q->w_ptr_rx + 1; + if (next_w_ptr != q->r_ptr_rx) { + q->elems_rx[q->w_ptr_rx] = c; + q->w_ptr_rx = next_w_ptr; + if (q->callback) q->callback(q); + } + } + exit_critical_section(); +} + +// interrupt boilerplate + +void USART1_IRQHandler(void) { uart_ring_process(&esp_ring); } +void USART2_IRQHandler(void) { uart_ring_process(&debug_ring); } +void USART3_IRQHandler(void) { uart_ring_process(&lin2_ring); } +void UART5_IRQHandler(void) { uart_ring_process(&lin1_ring); } + +int getc(uart_ring *q, char *elem) { + int ret = 0; + enter_critical_section(); + if (q->w_ptr_rx != q->r_ptr_rx) { + *elem = q->elems_rx[q->r_ptr_rx]; + q->r_ptr_rx += 1; + ret = 1; + } + exit_critical_section(); + return ret; +} + +int injectc(uart_ring *q, char elem) { + int ret = 0; + uint8_t next_w_ptr; + + enter_critical_section(); + next_w_ptr = q->w_ptr_rx + 1; + if (next_w_ptr != q->r_ptr_rx) { + q->elems_rx[q->w_ptr_rx] = elem; + q->w_ptr_rx = next_w_ptr; + ret = 1; + } + exit_critical_section(); + + return ret; +} + +int putc(uart_ring *q, char elem) { + int ret = 0; + uint8_t next_w_ptr; + + enter_critical_section(); + next_w_ptr = q->w_ptr_tx + 1; + if (next_w_ptr != q->r_ptr_tx) { + q->elems_tx[q->w_ptr_tx] = elem; + q->w_ptr_tx = next_w_ptr; + ret = 1; + } + uart_ring_process(q); + exit_critical_section(); + + return ret; +} + +// ***************************** start UART code ***************************** + #define __DIV(_PCLK_, _BAUD_) (((_PCLK_)*25)/(4*(_BAUD_))) #define __DIVMANT(_PCLK_, _BAUD_) (__DIV((_PCLK_), (_BAUD_))/100) #define __DIVFRAQ(_PCLK_, _BAUD_) (((__DIV((_PCLK_), (_BAUD_)) - (__DIVMANT((_PCLK_), (_BAUD_)) * 100)) * 16 + 50) / 100) @@ -24,6 +167,16 @@ void uart_init(USART_TypeDef *u, int baud) { // enable interrupts u->CR1 |= USART_CR1_RXNEIE; + + if (u == USART1) { + NVIC_EnableIRQ(USART1_IRQn); + } else if (u == USART2) { + NVIC_EnableIRQ(USART2_IRQn); + } else if (u == USART3) { + NVIC_EnableIRQ(USART3_IRQn); + } else if (u == UART5) { + NVIC_EnableIRQ(UART5_IRQn); + } } void putch(const char a) { diff --git a/board/usb.h b/board/usb.h index 2abe98161..0b61cf37c 100644 --- a/board/usb.h +++ b/board/usb.h @@ -1,3 +1,5 @@ +// IRQs: OTG_FS + // **** supporting defines **** typedef struct @@ -480,6 +482,9 @@ void usb_init() { // DCTL startup value is 2 on new chip, 0 on old chip // THIS IS FUCKING BULLSHIT USBx_DEVICE->DCTL = 0; + + // enable the IRQ + NVIC_EnableIRQ(OTG_FS_IRQn); } // ***************************** USB port ***************************** @@ -699,15 +704,15 @@ void usb_irqhandler(void) { break; case 1: ////// Interrupt config - // Check if there is anything to actually send. - if (can_rx_q.w_ptr != can_rx_q.r_ptr) { - // *** IN token received when TxFIFO is empty - if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) { - #ifdef DEBUG_USB - puts(" IN PACKET QUEUE\n"); - #endif - // TODO: always assuming max len, can we get the length? - USB_WritePacket((void *)resp, usb_cb_ep1_in(resp, 0x40, 1), 1); + // *** IN token received when TxFIFO is empty + if (USBx_INEP(1)->DIEPINT & USB_OTG_DIEPMSK_ITTXFEMSK) { + #ifdef DEBUG_USB + puts(" IN PACKET QUEUE\n"); + #endif + // TODO: always assuming max len, can we get the length? + int len = usb_cb_ep1_in(resp, 0x40, 1); + if (len > 0) { + USB_WritePacket((void *)resp, len, 1); } } break; @@ -725,3 +730,12 @@ 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) { + NVIC_DisableIRQ(OTG_FS_IRQn); + //__disable_irq(); + usb_irqhandler(); + //__enable_irq(); + NVIC_EnableIRQ(OTG_FS_IRQn); +} +