From 025659ac36bd2c6d6ffd412da72177d1a7b3ac1e Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 25 Nov 2021 10:20:10 +0100 Subject: [PATCH] Add support for RX DMA --- radio/src/cli.cpp | 2 + radio/src/hal/serial_driver.h | 3 + radio/src/io/frsky_firmware_update.cpp | 2 + radio/src/io/multi_firmware_update.cpp | 2 + radio/src/pulses/afhds2.cpp | 2 + radio/src/pulses/crossfire.cpp | 2 + radio/src/pulses/multi.cpp | 2 + radio/src/pulses/pxx1.cpp | 2 + radio/src/pulses/pxx2.cpp | 4 + .../arm/stm32/extmodule_serial_driver.cpp | 11 ++- .../arm/stm32/intmodule_serial_driver.cpp | 9 ++- .../common/arm/stm32/stm32_usart_driver.cpp | 73 +++++++++++++------ .../common/arm/stm32/stm32_usart_driver.h | 11 ++- 13 files changed, 92 insertions(+), 33 deletions(-) diff --git a/radio/src/cli.cpp b/radio/src/cli.cpp index 46e83a11c..b08cc51ef 100644 --- a/radio/src/cli.cpp +++ b/radio/src/cli.cpp @@ -928,6 +928,8 @@ static const etx_serial_init spIntmoduleSerialInitParams = { .stop_bits = ETX_StopBits_One, .word_length = ETX_WordLength_8, .rx_enable = true, + .rx_dma_buf = nullptr, + .rx_dma_buf_len = 0, .on_receive = intmoduleFifoReceive, .on_error = intmoduleFifoError, }; diff --git a/radio/src/hal/serial_driver.h b/radio/src/hal/serial_driver.h index e3d19672a..a1aad2263 100644 --- a/radio/src/hal/serial_driver.h +++ b/radio/src/hal/serial_driver.h @@ -47,6 +47,9 @@ struct etx_serial_init { uint8_t word_length; // = ETX_WordLength_8; bool rx_enable; // = false; + void* rx_dma_buf; + uint32_t rx_dma_buf_len; + void (*on_receive)(uint8_t data); // = nullptr; void (*on_error)(); // = nullptr; }; diff --git a/radio/src/io/frsky_firmware_update.cpp b/radio/src/io/frsky_firmware_update.cpp index 8ff142cb5..5a94ec8ff 100644 --- a/radio/src/io/frsky_firmware_update.cpp +++ b/radio/src/io/frsky_firmware_update.cpp @@ -316,6 +316,8 @@ static const etx_serial_init serialInitParams = { .stop_bits = ETX_StopBits_One, .word_length = ETX_WordLength_8, .rx_enable = true, + .rx_dma_buf = nullptr, + .rx_dma_buf_len = 0, .on_receive = intmoduleFifoReceive, .on_error = intmoduleFifoError, }; diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp index 3e5738b6e..90d8dd9c2 100644 --- a/radio/src/io/multi_firmware_update.cpp +++ b/radio/src/io/multi_firmware_update.cpp @@ -78,6 +78,8 @@ static const etx_serial_init serialInitParams = { .stop_bits = ETX_StopBits_One, .word_length = ETX_WordLength_8, .rx_enable = true, + .rx_dma_buf = nullptr, + .rx_dma_buf_len = 0, .on_receive = intmoduleFifoReceive, .on_error = intmoduleFifoError, }; diff --git a/radio/src/pulses/afhds2.cpp b/radio/src/pulses/afhds2.cpp index 3c1b7b5f9..93b1bebdf 100644 --- a/radio/src/pulses/afhds2.cpp +++ b/radio/src/pulses/afhds2.cpp @@ -45,6 +45,8 @@ const etx_serial_init afhds2SerialInitParams = { .stop_bits = ETX_StopBits_One, .word_length = ETX_WordLength_8, .rx_enable = true, + .rx_dma_buf = nullptr, + .rx_dma_buf_len = 0, .on_receive = intmoduleFifoReceive, .on_error = intmoduleFifoError, }; diff --git a/radio/src/pulses/crossfire.cpp b/radio/src/pulses/crossfire.cpp index 6aea05704..a176e8ccd 100644 --- a/radio/src/pulses/crossfire.cpp +++ b/radio/src/pulses/crossfire.cpp @@ -134,6 +134,8 @@ static const etx_serial_init intmoduleCrossfireInitParams = { .stop_bits = ETX_StopBits_One, .word_length = ETX_WordLength_8, .rx_enable = true, + .rx_dma_buf = nullptr, + .rx_dma_buf_len = 0, .on_receive = intmoduleCRSF_rx, .on_error = nullptr, }; diff --git a/radio/src/pulses/multi.cpp b/radio/src/pulses/multi.cpp index 60915bfc0..d1190be5a 100644 --- a/radio/src/pulses/multi.cpp +++ b/radio/src/pulses/multi.cpp @@ -60,6 +60,8 @@ etx_serial_init multiSerialInitParams = { .stop_bits = ETX_StopBits_Two, .word_length = ETX_WordLength_9, .rx_enable = true, + .rx_dma_buf = nullptr, + .rx_dma_buf_len = 0, .on_receive = intmoduleFifoReceive, .on_error = intmoduleFifoError, }; diff --git a/radio/src/pulses/pxx1.cpp b/radio/src/pulses/pxx1.cpp index fe9de7b12..bb592760b 100644 --- a/radio/src/pulses/pxx1.cpp +++ b/radio/src/pulses/pxx1.cpp @@ -231,6 +231,8 @@ static const etx_serial_init pxx1SerialInit = { .stop_bits = ETX_StopBits_One, .word_length = ETX_WordLength_8, .rx_enable = false, + .rx_dma_buf = nullptr, + .rx_dma_buf_len = 0, .on_receive = intmoduleFifoReceive, .on_error = intmoduleFifoError, }; diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp index dedcf9936..bab20cb05 100644 --- a/radio/src/pulses/pxx2.cpp +++ b/radio/src/pulses/pxx2.cpp @@ -36,6 +36,8 @@ const etx_serial_init pxx2SerialInitParams = { .stop_bits = ETX_StopBits_One, .word_length = ETX_WordLength_8, .rx_enable = true, + .rx_dma_buf = nullptr, + .rx_dma_buf_len = 0, .on_receive = intmoduleFifoReceive, .on_error = intmoduleFifoError, }; @@ -719,6 +721,8 @@ static const etx_serial_init pxx2ExtSerialInitParams = { .stop_bits = ETX_StopBits_One, .word_length = ETX_WordLength_8, .rx_enable = true, + .rx_dma_buf = nullptr, + .rx_dma_buf_len = 0, .on_receive = extmoduleFifoReceive, .on_error = extmoduleFifoError, }; diff --git a/radio/src/targets/common/arm/stm32/extmodule_serial_driver.cpp b/radio/src/targets/common/arm/stm32/extmodule_serial_driver.cpp index 6329eedac..edd277928 100644 --- a/radio/src/targets/common/arm/stm32/extmodule_serial_driver.cpp +++ b/radio/src/targets/common/arm/stm32/extmodule_serial_driver.cpp @@ -49,6 +49,8 @@ static const etx_serial_init extmoduleSerialParams = { .stop_bits = ETX_StopBits_One, .word_length = ETX_WordLength_8, .rx_enable = true, + .rx_dma_buf = nullptr, + .rx_dma_buf_len = 0, .on_receive = extmoduleFifoReceive, .on_error = extmoduleFifoError, }; @@ -68,9 +70,12 @@ static const stm32_usart_t extmoduleUSART = { .pinInit = &extmoduleUSART_PinDef, .IRQn = EXTMODULE_USART_IRQn, .IRQ_Prio = EXTMODULE_USART_IRQ_PRIORITY, - .DMAx = EXTMODULE_USART_TX_DMA, - .DMA_Stream = EXTMODULE_USART_TX_DMA_STREAM_LL, - .DMA_Channel = EXTMODULE_USART_TX_DMA_CHANNEL, + .txDMA = EXTMODULE_USART_TX_DMA, + .txDMA_Stream = EXTMODULE_USART_TX_DMA_STREAM_LL, + .txDMA_Channel = EXTMODULE_USART_TX_DMA_CHANNEL, + .rxDMA = nullptr, + .rxDMA_Stream = 0, + .rxDMA_Channel = 0, }; static void extmoduleSerialStart(const etx_serial_init* params) diff --git a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp index 4c91af469..126cb58d4 100755 --- a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp +++ b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp @@ -79,9 +79,12 @@ static const stm32_usart_t intmoduleUSART = { .pinInit = &intmoduleUSART_PinDef, .IRQn = INTMODULE_USART_IRQn, .IRQ_Prio = INTMODULE_USART_IRQ_PRIORITY, - .DMAx = INTMODULE_DMA, - .DMA_Stream = INTMODULE_DMA_STREAM_LL, - .DMA_Channel = INTMODULE_DMA_CHANNEL, + .txDMA = INTMODULE_DMA, + .txDMA_Stream = INTMODULE_DMA_STREAM_LL, + .txDMA_Channel = INTMODULE_DMA_CHANNEL, + .rxDMA = nullptr, + .rxDMA_Stream = 0, + .rxDMA_Channel = 0, }; void intmoduleStop() diff --git a/radio/src/targets/common/arm/stm32/stm32_usart_driver.cpp b/radio/src/targets/common/arm/stm32/stm32_usart_driver.cpp index 43a5c592c..aa29225b9 100644 --- a/radio/src/targets/common/arm/stm32/stm32_usart_driver.cpp +++ b/radio/src/targets/common/arm/stm32/stm32_usart_driver.cpp @@ -22,6 +22,25 @@ #include "stm32_usart_driver.h" #include +static void stm32_usart_init_rx_dma(const stm32_usart_t* usart, void* buffer, uint32_t length) +{ + LL_DMA_InitTypeDef dmaInit; + LL_DMA_StructInit(&dmaInit); + dmaInit.Channel = usart->rxDMA_Channel; + dmaInit.PeriphOrM2MSrcAddress = (uint32_t)&usart->USARTx->DR; + dmaInit.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; + dmaInit.MemoryOrM2MDstAddress = (uint32_t)buffer; + dmaInit.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; + dmaInit.Mode = LL_DMA_MODE_CIRCULAR; + dmaInit.NbData = length; + dmaInit.Priority = LL_DMA_PRIORITY_LOW; // TODO: make it configurable + LL_DMA_Init(usart->rxDMA, usart->rxDMA_Stream, &dmaInit); + LL_USART_EnableDMAReq_RX(usart->USARTx); + + // Stream can be enable as the USART has alread been enabled + LL_DMA_EnableStream(usart->rxDMA, usart->rxDMA_Stream); +} + void stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params) { LL_USART_DeInit(usart->USARTx); @@ -71,17 +90,23 @@ void stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params) LL_USART_Enable(usart->USARTx); // Enable TX DMA request - if (usart->DMAx) { + if (usart->txDMA) { LL_USART_EnableDMAReq_TX(usart->USARTx); } // Enable RX IRQ if (params->rx_enable) { - LL_USART_EnableIT_RXNE(usart->USARTx); + if (usart->rxDMA) { + // RX DMA + stm32_usart_init_rx_dma(usart, params->rx_dma_buf, + params->rx_dma_buf_len); + } else { + // IRQ based RX + LL_USART_EnableIT_RXNE(usart->USARTx); + } } - if (!usart->DMAx || params->rx_enable) { - // TODO: configurable priority ??? + if (!usart->txDMA || (params->rx_enable && !usart->rxDMA)) { NVIC_SetPriority(usart->IRQn, usart->IRQ_Prio); NVIC_EnableIRQ(usart->IRQn); } @@ -89,8 +114,8 @@ void stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params) void stm32_usart_deinit(const stm32_usart_t* usart) { - if (usart->DMAx) { - LL_DMA_DeInit(usart->DMAx, usart->DMA_Stream); + if (usart->txDMA) { + LL_DMA_DeInit(usart->txDMA, usart->txDMA_Stream); } NVIC_DisableIRQ(usart->IRQn); LL_USART_DeInit(usart->USARTx); @@ -114,22 +139,22 @@ void stm32_usart_send_byte(const stm32_usart_t* usart, uint8_t byte) void stm32_usart_send_buffer(const stm32_usart_t* usart, const uint8_t * data, uint32_t size) { - if (usart->DMAx) { - LL_DMA_DeInit(usart->DMAx, usart->DMA_Stream); + if (usart->txDMA) { + LL_DMA_DeInit(usart->txDMA, usart->txDMA_Stream); LL_DMA_InitTypeDef dmaInit; LL_DMA_StructInit(&dmaInit); - dmaInit.Channel = usart->DMA_Channel; + dmaInit.Channel = usart->txDMA_Channel; dmaInit.PeriphOrM2MSrcAddress = (uint32_t)&usart->USARTx->DR; dmaInit.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; dmaInit.MemoryOrM2MDstAddress = (uint32_t)data; dmaInit.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; dmaInit.NbData = size; - dmaInit.Priority = LL_DMA_PRIORITY_VERYHIGH; + dmaInit.Priority = LL_DMA_PRIORITY_VERYHIGH; // TODO: make it configurable - LL_DMA_Init(usart->DMAx, usart->DMA_Stream, &dmaInit); - LL_DMA_EnableStream(usart->DMAx, usart->DMA_Stream); + LL_DMA_Init(usart->txDMA, usart->txDMA_Stream, &dmaInit); + LL_DMA_EnableStream(usart->txDMA, usart->txDMA_Stream); return; } else { @@ -144,28 +169,28 @@ void stm32_usart_wait_for_tx_dma(const stm32_usart_t* usart) { // TODO: check if everything is properly initialised, this seems to block when // the port has been initialised with a zero baudrate - if (LL_DMA_IsEnabledStream(usart->DMAx, usart->DMA_Stream)) { + if (LL_DMA_IsEnabledStream(usart->txDMA, usart->txDMA_Stream)) { - switch(usart->DMA_Stream) { + switch(usart->txDMA_Stream) { case LL_DMA_STREAM_1: - while (LL_DMA_IsActiveFlag_TC1(usart->DMAx)); - LL_DMA_ClearFlag_TC1(usart->DMAx); + while (LL_DMA_IsActiveFlag_TC1(usart->txDMA)); + LL_DMA_ClearFlag_TC1(usart->txDMA); break; case LL_DMA_STREAM_3: - while (LL_DMA_IsActiveFlag_TC3(usart->DMAx)); - LL_DMA_ClearFlag_TC3(usart->DMAx); + while (LL_DMA_IsActiveFlag_TC3(usart->txDMA)); + LL_DMA_ClearFlag_TC3(usart->txDMA); break; case LL_DMA_STREAM_5: - while (LL_DMA_IsActiveFlag_TC5(usart->DMAx)); - LL_DMA_ClearFlag_TC5(usart->DMAx); + while (LL_DMA_IsActiveFlag_TC5(usart->txDMA)); + LL_DMA_ClearFlag_TC5(usart->txDMA); break; case LL_DMA_STREAM_6: - while (LL_DMA_IsActiveFlag_TC6(usart->DMAx)); - LL_DMA_ClearFlag_TC6(usart->DMAx); + while (LL_DMA_IsActiveFlag_TC6(usart->txDMA)); + LL_DMA_ClearFlag_TC6(usart->txDMA); break; case LL_DMA_STREAM_7: - while (LL_DMA_IsActiveFlag_TC7(usart->DMAx)); - LL_DMA_ClearFlag_TC7(usart->DMAx); + while (LL_DMA_IsActiveFlag_TC7(usart->txDMA)); + LL_DMA_ClearFlag_TC7(usart->txDMA); break; } } diff --git a/radio/src/targets/common/arm/stm32/stm32_usart_driver.h b/radio/src/targets/common/arm/stm32/stm32_usart_driver.h index a662f388a..d1a0d7eed 100644 --- a/radio/src/targets/common/arm/stm32/stm32_usart_driver.h +++ b/radio/src/targets/common/arm/stm32/stm32_usart_driver.h @@ -37,9 +37,14 @@ struct stm32_usart_t { uint8_t IRQ_Prio; // TX DMA defs - DMA_TypeDef* DMAx; - uint32_t DMA_Stream; - uint32_t DMA_Channel; + DMA_TypeDef* txDMA; + uint32_t txDMA_Stream; + uint32_t txDMA_Channel; + + // RX DMA defs + DMA_TypeDef* rxDMA; + uint32_t rxDMA_Stream; + uint32_t rxDMA_Channel; }; void stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params);