rusefi-1/firmware/console/connector_uart_dma.cpp

82 lines
2.3 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"
#if HAL_USE_UART && EFI_USE_UART_DMA
2020-06-21 13:37:33 -07:00
/* Common function for all DMA-UART IRQ handlers. */
void UartDmaTsChannel::copyDataFromDMA() {
2020-06-21 13:37:33 -07:00
chSysLockFromISR();
// get 0-based DMA buffer position
int dmaPos = TS_DMA_BUFFER_SIZE - dmaStreamGetTransactionSize(m_driver->dmarx);
2020-06-21 13:37:33 -07:00
// if the position is wrapped (circular DMA-mode enabled)
if (dmaPos < readPos)
2020-06-21 13:37:33 -07:00
dmaPos += TS_DMA_BUFFER_SIZE;
// we need to update the current readPos
int newReadPos = readPos;
2020-06-21 13:37:33 -07:00
for (int i = newReadPos; i < dmaPos; ) {
if (iqPutI(&fifoRxQueue, dmaBuffer[newReadPos]) != Q_OK) {
2020-06-21 13:37:33 -07:00
break; // todo: ignore overflow?
}
// the read position should always stay inside the buffer range
newReadPos = (++i) & (TS_DMA_BUFFER_SIZE - 1);
}
readPos = newReadPos;
2020-06-21 13:37:33 -07:00
chSysUnlockFromISR();
}
/* We use the same handler code for both halves. */
static void tsRxIRQHalfHandler(UARTDriver *uartp, uartflags_t full) {
UNUSED(full);
reinterpret_cast<UartDmaTsChannel*>(uartp->dmaAdapterInstance)->copyDataFromDMA();
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);
reinterpret_cast<UartDmaTsChannel*>(uartp->dmaAdapterInstance)->copyDataFromDMA();
2020-06-21 13:37:33 -07:00
}
UartDmaTsChannel::UartDmaTsChannel(UARTDriver& driver)
: UartTsChannel(driver)
{
// Store a pointer to this instance so we can get it back later in the DMA callback
driver.dmaAdapterInstance = this;
2020-06-21 13:37:33 -07:00
iqObjectInit(&fifoRxQueue, buffer, sizeof(buffer), nullptr, nullptr);
}
void UartDmaTsChannel::start(uint32_t baud) {
m_config = {
.txend1_cb = NULL,
.txend2_cb = NULL,
.rxend_cb = NULL,
.rxchar_cb = NULL,
.rxerr_cb = NULL,
.timeout_cb = tsRxIRQIdleHandler,
.speed = baud,
.cr1 = 0,
.cr2 = 0/*USART_CR2_STOP1_BITS*/ | USART_CR2_LINEN,
.cr3 = 0,
.rxhalf_cb = tsRxIRQHalfHandler
};
2020-06-21 13:37:33 -07:00
uartStart(m_driver, &m_config);
// Start the buffered read process
readPos = 0;
uartStartReceive(m_driver, sizeof(dmaBuffer), dmaBuffer);
}
2020-06-21 13:37:33 -07:00
size_t UartDmaTsChannel::readTimeout(uint8_t* buffer, size_t size, int timeout) {
// Instead of reading from the device, read from our custom RX queue
return iqReadTimeout(&fifoRxQueue, buffer, size, timeout);
2020-06-21 13:37:33 -07:00
}
#endif // HAL_USE_UART && EFI_USE_UART_DMA