mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-02-24 15:23:53 +08:00
2573d86 docs say max is 4, respect the docs 864cd8f failing on some devices 54bcc67 Merge pull request #75 from gregjhogan/j2534-vs-2017-upgrade 1664270 Merge pull request #74 from gregjhogan/j2534-disconnect-fix a7e3a8f bump panda version for serial bug aa0cfad fix UART hang 09ab8f6 add sendaddr support to isotp 40a1883 fix up baud rate 65997ff add PandaSerial and location panda (aka pigeon) test 57d633c upgraded to VS 2017 35cc32a fixed pointer exception on disconnect git-subtree-dir: panda git-subtree-split: 2573d861e605a2dcf456a6421b31e83fdd9ca606
233 lines
5.6 KiB
C
233 lines
5.6 KiB
C
// IRQs: USART1, USART2, USART3, UART5
|
|
|
|
// ***************************** serial port queues *****************************
|
|
|
|
// esp = USART1
|
|
uart_ring esp_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
|
|
.w_ptr_rx = 0, .r_ptr_rx = 0,
|
|
.uart = USART1,
|
|
.callback = NULL};
|
|
|
|
// lin1, K-LINE = UART5
|
|
// lin2, L-LINE = USART3
|
|
uart_ring lin1_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
|
|
.w_ptr_rx = 0, .r_ptr_rx = 0,
|
|
.uart = UART5,
|
|
.callback = NULL};
|
|
uart_ring lin2_ring = { .w_ptr_tx = 0, .r_ptr_tx = 0,
|
|
.w_ptr_rx = 0, .r_ptr_rx = 0,
|
|
.uart = USART3,
|
|
.callback = NULL};
|
|
|
|
// 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 || sr & USART_SR_ORE) {
|
|
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);
|
|
}
|
|
}
|
|
|
|
if (sr & USART_SR_ORE) {
|
|
// set dropped packet flag?
|
|
}
|
|
|
|
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;
|
|
}
|
|
exit_critical_section();
|
|
|
|
uart_ring_process(q);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void clear_uart_buff(uart_ring *q) {
|
|
enter_critical_section();
|
|
q->w_ptr_tx = 0;
|
|
q->r_ptr_tx = 0;
|
|
q->w_ptr_rx = 0;
|
|
q->r_ptr_rx = 0;
|
|
exit_critical_section();
|
|
}
|
|
|
|
// ***************************** 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)
|
|
#define __USART_BRR(_PCLK_, _BAUD_) ((__DIVMANT((_PCLK_), (_BAUD_)) << 4)|(__DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0F))
|
|
|
|
void uart_set_baud(USART_TypeDef *u, int baud) {
|
|
if (u == USART1) {
|
|
// USART1 is on APB2
|
|
u->BRR = __USART_BRR(48000000, baud);
|
|
} else {
|
|
u->BRR = __USART_BRR(24000000, baud);
|
|
}
|
|
}
|
|
|
|
void uart_init(USART_TypeDef *u, int baud) {
|
|
// enable uart and tx+rx mode
|
|
u->CR1 = USART_CR1_UE;
|
|
uart_set_baud(u, baud);
|
|
|
|
u->CR1 |= USART_CR1_TE | USART_CR1_RE;
|
|
//u->CR2 = USART_CR2_STOP_0 | USART_CR2_STOP_1;
|
|
//u->CR2 = USART_CR2_STOP_0;
|
|
// ** UART is ready to work **
|
|
|
|
// enable interrupts
|
|
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) {
|
|
if (has_external_debug_serial) {
|
|
/*while ((debug_ring.uart->SR & USART_SR_TXE) == 0);
|
|
debug_ring.uart->DR = a;*/
|
|
|
|
// assuming debugging is important if there's external serial connected
|
|
while (!putc(&debug_ring, a));
|
|
|
|
//putc(&debug_ring, a);
|
|
} else {
|
|
injectc(&debug_ring, a);
|
|
}
|
|
}
|
|
|
|
int puts(const char *a) {
|
|
for (;*a;a++) {
|
|
if (*a == '\n') putch('\r');
|
|
putch(*a);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void puth(unsigned int i) {
|
|
int pos;
|
|
char c[] = "0123456789abcdef";
|
|
for (pos = 28; pos != -4; pos -= 4) {
|
|
putch(c[(i >> pos) & 0xF]);
|
|
}
|
|
}
|
|
|
|
void puth2(unsigned int i) {
|
|
int pos;
|
|
char c[] = "0123456789abcdef";
|
|
for (pos = 4; pos != -4; pos -= 4) {
|
|
putch(c[(i >> pos) & 0xF]);
|
|
}
|
|
}
|
|
|
|
void hexdump(const void *a, int l) {
|
|
int i;
|
|
for (i=0;i<l;i++) {
|
|
if (i != 0 && (i&0xf) == 0) puts("\n");
|
|
puth2(((const unsigned char*)a)[i]);
|
|
puts(" ");
|
|
}
|
|
puts("\n");
|
|
}
|