mirror of https://github.com/commaai/panda.git
start the refactor
This commit is contained in:
parent
7d97564796
commit
ad2c0e632a
269
board/can.h
269
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;
|
||||
}
|
||||
|
||||
|
|
19
board/libc.h
19
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
490
board/main.c
490
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");
|
||||
|
|
50
board/spi.h
50
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;
|
||||
}
|
||||
|
||||
|
|
153
board/uart.h
153
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) {
|
||||
|
|
32
board/usb.h
32
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue