rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
connector_uart_dma.cpp
Go to the documentation of this file.
1/*
2 * @file connector_uart_dma.cpp
3 *
4 * @date Jun 21, 2020
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
9
10#if HAL_USE_UART && EFI_USE_UART_DMA
11
12/* Common function for all DMA-UART IRQ handlers. */
14 chSysLockFromISR();
15 // get 0-based DMA buffer position
16 int dmaPos = TS_DMA_BUFFER_SIZE - dmaStreamGetTransactionSize(m_driver->dmarx);
17 // if the position is wrapped (circular DMA-mode enabled)
18 if (dmaPos < readPos)
19 dmaPos += TS_DMA_BUFFER_SIZE;
20 // we need to update the current readPos
21 int newReadPos = readPos;
22 for (int i = newReadPos; i < dmaPos; ) {
23 if (iqPutI(&fifoRxQueue, dmaBuffer[newReadPos]) != Q_OK) {
24 break; // todo: ignore overflow?
25 }
26 // the read position should always stay inside the buffer range
27 newReadPos = (++i) & (TS_DMA_BUFFER_SIZE - 1);
28 }
29 readPos = newReadPos;
30 chSysUnlockFromISR();
31}
32
33/* We use the same handler code for both halves. */
34static void tsRxIRQHalfHandler(UARTDriver *uartp, uartflags_t full) {
35 UNUSED(full);
36 reinterpret_cast<UartDmaTsChannel*>(uartp->dmaAdapterInstance)->copyDataFromDMA();
37}
38
39/* This handler is called right after the UART receiver has finished its work. */
40static void tsRxIRQIdleHandler(UARTDriver *uartp) {
41 UNUSED(uartp);
42 reinterpret_cast<UartDmaTsChannel*>(uartp->dmaAdapterInstance)->copyDataFromDMA();
43}
44
46 : UartTsChannel(driver)
47{
48 // Store a pointer to this instance so we can get it back later in the DMA callback
49 driver.dmaAdapterInstance = this;
50
51 iqObjectInit(&fifoRxQueue, buffer, sizeof(buffer), nullptr, nullptr);
52}
53
54void UartDmaTsChannel::start(uint32_t baud) {
55 m_config = {
56 .txend1_cb = NULL,
57 .txend2_cb = NULL,
58 .rxend_cb = NULL,
59 .rxchar_cb = NULL,
60 .rxerr_cb = NULL,
61 .timeout_cb = tsRxIRQIdleHandler,
62 .speed = baud,
63 .cr1 = 0,
64 .cr2 = USART_CR2_STOP1_BITS | USART_CR2_LINEN,
65 .cr3 = 0,
66 .rxhalf_cb = tsRxIRQHalfHandler
67 };
68
69 uartStart(m_driver, &m_config);
70
71 // Start the buffered read process
72 readPos = 0;
73 uartStartReceive(m_driver, sizeof(dmaBuffer), dmaBuffer);
74}
75
76size_t UartDmaTsChannel::readTimeout(uint8_t* p_buffer, size_t size, int timeout) {
77 // Instead of reading from the device, read from our custom RX queue
78 size_t transferred = iqReadTimeout(&fifoRxQueue, p_buffer, size, timeout);
79 bytesIn += transferred;
80 return transferred;
81}
82
83#endif // HAL_USE_UART && EFI_USE_UART_DMA
void start(uint32_t baud) override
UartDmaTsChannel(UARTDriver &uartDriver)
uint8_t buffer[TS_FIFO_BUFFER_SIZE]
input_queue_t fifoRxQueue
size_t readTimeout(uint8_t *buffer, size_t size, int timeout) override
uint8_t dmaBuffer[TS_DMA_BUFFER_SIZE]
UARTDriver *const m_driver
UARTConfig m_config
static void tsRxIRQIdleHandler(UARTDriver *uartp)
static void tsRxIRQHalfHandler(UARTDriver *uartp, uartflags_t full)
uint32_t uartflags_t
UART driver condition flags type.
UNUSED(samplingTimeSeconds)
uartcb_t txend1_cb
End of transmission buffer callback.
Structure representing an UART driver.
composite packet size