rusefi-1/firmware/console/connector_uart_dma.cpp

77 lines
2.4 KiB
C++
Raw Normal View History

2020-06-21 13:37:33 -07:00
/*
* @file connector_uart_dma.cpp
*
* @date Jun 21, 2020
* @author Andrey Belomutskiy, (c) 2012-2020
*/
2020-06-21 16:48:55 -07:00
#include "connector_uart_dma.h"
2020-06-21 13:37:33 -07:00
#if TS_UART_DMA_MODE || PRIMARY_UART_DMA_MODE
2020-06-22 08:32:47 -07:00
#if TS_UART_DMA_MODE && PRIMARY_UART_DMA_MODE
#error "Only single-DMA implemented right now"
#endif
2020-06-21 16:48:55 -07:00
EXTERN_CONFIG;
2020-06-21 13:37:33 -07:00
// Async. FIFO buffer takes some RAM...
uart_dma_s tsUartDma;
/* Common function for all DMA-UART IRQ handlers. */
2020-06-21 16:48:55 -07:00
static void tsCopyDataFromDMA(UARTDriver *uartp) {
2020-06-21 13:37:33 -07:00
chSysLockFromISR();
// get 0-based DMA buffer position
2020-06-21 16:48:55 -07:00
int dmaPos = TS_DMA_BUFFER_SIZE - dmaStreamGetTransactionSize(uartp->dmarx);
2020-06-21 13:37:33 -07:00
// if the position is wrapped (circular DMA-mode enabled)
if (dmaPos < tsUartDma.readPos)
dmaPos += TS_DMA_BUFFER_SIZE;
// we need to update the current readPos
int newReadPos = tsUartDma.readPos;
for (int i = newReadPos; i < dmaPos; ) {
if (iqPutI(&tsUartDma.fifoRxQueue, tsUartDma.dmaBuffer[newReadPos]) != Q_OK) {
break; // todo: ignore overflow?
}
// the read position should always stay inside the buffer range
newReadPos = (++i) & (TS_DMA_BUFFER_SIZE - 1);
}
tsUartDma.readPos = newReadPos;
chSysUnlockFromISR();
}
/* We use the same handler code for both halves. */
static void tsRxIRQHalfHandler(UARTDriver *uartp, uartflags_t full) {
UNUSED(uartp);
UNUSED(full);
2020-06-21 16:48:55 -07:00
tsCopyDataFromDMA(uartp);
2020-06-21 13:37:33 -07:00
}
/* This handler is called right after the UART receiver has finished its work. */
static void tsRxIRQIdleHandler(UARTDriver *uartp) {
UNUSED(uartp);
2020-06-21 16:48:55 -07:00
tsCopyDataFromDMA(uartp);
2020-06-21 13:37:33 -07:00
}
/* Note: This structure is modified from the default ChibiOS layout! */
static UARTConfig tsDmaUartConfig = {
.txend1_cb = NULL, .txend2_cb = NULL, .rxend_cb = NULL, .rxchar_cb = NULL, .rxerr_cb = NULL,
.speed = 0, .cr1 = 0, .cr2 = 0/*USART_CR2_STOP1_BITS*/ | USART_CR2_LINEN, .cr3 = 0,
.timeout_cb = tsRxIRQIdleHandler, .rxhalf_cb = tsRxIRQHalfHandler
};
void startUartDmaConnector(UARTDriver *uartp DECLARE_CONFIG_PARAMETER_SUFFIX) {
print("Using UART-DMA mode");
// init FIFO queue
iqObjectInit(&tsUartDma.fifoRxQueue, tsUartDma.buffer, sizeof(tsUartDma.buffer), NULL, NULL);
// start DMA driver
tsDmaUartConfig.speed = CONFIG(tunerStudioSerialSpeed);
2020-06-21 16:48:55 -07:00
uartStart(uartp, &tsDmaUartConfig);
2020-06-21 13:37:33 -07:00
// start continuous DMA transfer using our circular buffer
tsUartDma.readPos = 0;
uartStartReceive(uartp, sizeof(tsUartDma.dmaBuffer), tsUartDma.dmaBuffer);
}
#endif // TS_UART_DMA_MODE || PRIMARY_UART_DMA_MODE