#include "packet_interface.h" #include "noise.h" #include "cobs.h" #include "tracing.h" #include #include #include #include volatile struct { struct dma_buf dma; uint8_t data[256]; } uart4_buf = { .dma = { .len = sizeof(uart4_buf.data) } }; struct dma_usart_file uart4_out_s = { .usart = UART4, .baudrate = 115200, .dma = DMA1, .stream = 4, .channel = 4, .irqn = NVIC_DMA_IRQ(1, 4), .buf = &uart4_buf.dma }; struct dma_usart_file *uart4_out = &uart4_out_s; void dma1_stream4_isr(void) { TRACING_SET(TR_HOST_IF_DMA_IRQ); static unsigned int fifo_errors = 0; /* debug */ if (dma_get_interrupt_flag(uart4_out->dma, uart4_out->stream, DMA_FEIF)) { /* Ignore FIFO errors as they're 100% non-critical for UART applications */ dma_clear_interrupt_flags(uart4_out->dma, uart4_out->stream, DMA_FEIF); fifo_errors++; TRACING_CLEAR(TR_HOST_IF_DMA_IRQ); return; } /* Transfer complete interrupt */ dma_clear_interrupt_flags(uart4_out->dma, uart4_out->stream, DMA_TCIF); if (uart4_out->buf->wr_pos != uart4_out->buf->xfr_end) /* buffer not empty */ schedule_dma(uart4_out); TRACING_CLEAR(TR_HOST_IF_DMA_IRQ); } void uart4_isr(void) { TRACING_SET(TR_HOST_IF_USART_IRQ); static struct cobs_decode_state host_cobs_state = {0}; if (UART4_SR & USART_SR_ORE) { /* Overrun handling */ LOG_PRINTF("UART4 data register overrun\n"); /* Clear interrupt flag */ (void)UART4_DR; /* FIXME make sure this read is not optimized out */ host_packet_length = -1; TRACING_CLEAR(TR_HOST_IF_USART_IRQ); return; } uint8_t data = UART4_DR; /* This automatically acknowledges the IRQ */ if (host_packet_length) { LOG_PRINTF("UART4 COBS buffer overrun\n"); host_packet_length = -1; TRACING_CLEAR(TR_HOST_IF_USART_IRQ); return; } ssize_t rv = cobs_decode_incremental(&host_cobs_state, (char *)host_packet_buf, sizeof(host_packet_buf), data); if (rv == 0) { /* good, empty frame */ LOG_PRINTF("Got empty frame from host\n"); host_packet_length = -1; } else if (rv == -1) { /* Decoding frame, wait for next byte */ } else if (rv == -2) { LOG_PRINTF("Host interface COBS framing error\n"); host_packet_length = -1; } else if (rv == -3) { /* invalid empty frame */ LOG_PRINTF("Got double null byte from host\n"); /* FIXME DEBUG host_packet_length = -1; */ } else if (rv == -4) { /* frame too large */ LOG_PRINTF("Got too large frame from host\n"); host_packet_length = -1; } else if (rv > 0) { /* Good, non-empty frame */ host_packet_length = rv; } TRACING_CLEAR(TR_HOST_IF_USART_IRQ); } void send_packet(struct dma_usart_file *f, const uint8_t *data, size_t len) { /* ignore return value as putf is blocking and always succeeds */ (void)cobs_encode_incremental(f, putf, (char *)data, len); flush(f); }