/** Returns a lower bound on the number of bytes in the DMA receive buffer. * Also checks for buffer overrun conditions. * \param s The USART DMA state structure. */ u32 usart_n_read_dma(usart_rx_dma_state* s) { s32 n_read = s->rd_wraps * USART_RX_BUFFER_LEN + s->rd; s32 n_written = (s->wr_wraps + 1) * USART_RX_BUFFER_LEN - \ DMA_SNDTR(s->dma, s->stream); s32 n_available = n_written - n_read; if (n_available < 0) /* This strange and rare case occurs when NDTR has rolled over but the flag * hasn't been raised yet and thus n_wraps hasn't been incremented in the * ISR. Simply return 0 this time and the next time this function is called * (or at some point) the interrupt will have been triggered and the number * of bytes available in the buffer will be a sane amount. */ n_available = 0; else if (n_available > USART_RX_BUFFER_LEN) { /* If greater than a whole buffer then we have had an overflow. */ printf("ERROR: DMA RX buffer overrun\n"); n_available = 0; s->errors++; /* Disable and re-enable the DMA channel to get back to a known good * state */ usart_rx_dma_disable(s); usart_rx_dma_setup(s, s->usart, s->dma, s->stream, s->channel); } return n_available; }
/** Disable all USARTs. */ void usarts_disable() { /* Disable DMA channels. */ /* Disable all USARTs. */ if (!all_uarts_enabled) return; usart_tx_dma_disable(&ftdi_state.tx); usart_rx_dma_disable(&ftdi_state.rx); usart_disable(USART6); usart_tx_dma_disable(&uarta_state.tx); usart_rx_dma_disable(&uarta_state.rx); usart_disable(USART1); usart_tx_dma_disable(&uartb_state.tx); usart_rx_dma_disable(&uartb_state.rx); usart_disable(USART3); }