feat(ACCESS): Configure AUX serial port as "External module" (#2562)

* Enable RX DMA on external module USART

* feat(ACCESS): configure AUX serial port as "External module" (#2562)

This allows configuring the external access mod on runtime rather than by compilation option.

* fix: fetch external module driver
This commit is contained in:
Raphael Coeffic
2022-12-14 18:41:32 +10:00
committed by GitHub
parent efe2ddd2b1
commit 06c359f096
22 changed files with 323 additions and 128 deletions
@@ -32,7 +32,7 @@
#define AUX_SERIAL_TX_BUFFER 512
#if defined(SDRAM)
#define AUX_SERIAL_RX_BUFFER 128
#define AUX_SERIAL_RX_BUFFER 512
#else
#define AUX_SERIAL_RX_BUFFER 32
#endif
@@ -53,8 +53,8 @@ static void* aux_serial_init(const SerialState* st, const etx_serial_init* param
stm32_usart_init(st->usart, params);
if (params->rx_enable && st->usart->rxDMA) {
st->rxFifo->clear();
stm32_usart_init_rx_dma(st->usart, st->rxFifo->buffer(), st->rxFifo->size());
st->rxFifo->clear();
}
return (void*)st;
@@ -62,17 +62,25 @@ static void* aux_serial_init(const SerialState* st, const etx_serial_init* param
static void aux_serial_putc(void* ctx, uint8_t c)
{
// When sending single bytes,
// send is based on IRQ, so that this
// only enables the corresponding IRQ
auto st = (const SerialState*)ctx;
if (st->txFifo->isFull()) return;
st->txFifo->push(c);
// Send is based on IRQ, so that this
// only enables the corresponding IRQ
stm32_usart_send_buffer(st->usart, &c, 1);
stm32_usart_enable_tx_irq(st->usart);
}
static void aux_serial_send_buffer(void* ctx, const uint8_t* data, uint8_t size)
{
auto st = (const SerialState*)ctx;
if (st->usart->txDMA) {
stm32_usart_send_buffer(st->usart, data, size);
return;
}
while(size > 0) {
aux_serial_putc(ctx, *data++);
size--;
@@ -112,15 +120,22 @@ static const LL_GPIO_InitTypeDef auxUSARTPinInit = {
.Alternate = AUX_SERIAL_GPIO_AF_LL,
};
#if !defined(AUX_SERIAL_DMA_TX)
#define AUX_SERIAL_DMA_TX nullptr
#define AUX_SERIAL_DMA_Stream_TX nullptr
#define AUX_SERIAL_DMA_Stream_TX_LL 0
#define AUX_SERIAL_DMA_Channel_TX 0
#endif
static const stm32_usart_t auxUSART = {
.USARTx = AUX_SERIAL_USART,
.GPIOx = AUX_SERIAL_GPIO,
.pinInit = &auxUSARTPinInit,
.IRQn = AUX_SERIAL_USART_IRQn,
.IRQ_Prio = 7, // TODO: define constant
.txDMA = nullptr,
.txDMA_Stream = 0,
.txDMA_Channel = 0,
.txDMA = AUX_SERIAL_DMA_TX,
.txDMA_Stream = AUX_SERIAL_DMA_Stream_TX_LL,
.txDMA_Channel = AUX_SERIAL_DMA_Channel_TX,
.rxDMA = AUX_SERIAL_DMA_RX,
.rxDMA_Stream = AUX_SERIAL_DMA_Stream_RX_LL,
.rxDMA_Channel = AUX_SERIAL_DMA_Channel_RX,
@@ -20,38 +20,60 @@
*/
#include "stm32_hal_ll.h"
#include "stm32_usart_driver.h"
#include "extmodule_serial_driver.h"
#include "board.h"
#if defined(EXTMODULE_USART)
#include "stm32_usart_driver.h"
#include "fifo.h"
typedef Fifo<uint8_t, INTMODULE_FIFO_SIZE> RxFifo;
static RxFifo extmoduleFifo;
struct RxFifo {
uint8_t* buf;
uint16_t size;
uint16_t widx;
uint16_t ridx;
};
struct ExtmoduleCtx
{
RxFifo* rxFifo;
struct ExtmoduleCtx {
RxFifo rxFifo;
const stm32_usart_t* usart;
};
static etx_serial_callbacks_t extmodule_driver = {
static etx_serial_callbacks_t extmodule_callbacks = {
nullptr, nullptr, nullptr
};
void extmoduleFifoReceive(uint8_t data)
static void _fifo_clear(const stm32_usart_t* usart, RxFifo& fifo)
{
extmoduleFifo.push(data);
if (usart->rxDMA) {
auto dma_len = LL_DMA_GetDataLength(usart->rxDMA, usart->rxDMA_Stream);
fifo.ridx = fifo.size - dma_len;
} else {
fifo.widx = fifo.ridx = 0;
}
}
static const etx_serial_init extmoduleSerialParams = {
.baudrate = 0,
.parity = ETX_Parity_None,
.stop_bits = ETX_StopBits_One,
.word_length = ETX_WordLength_8,
.rx_enable = true,
};
static int _fifo_get_byte(const stm32_usart_t* usart, RxFifo& fifo, uint8_t* data)
{
if (usart->rxDMA) {
auto DMAx = usart->rxDMA;
auto stream = usart->rxDMA_Stream;
// DMA stream enabled?
if (!LL_DMA_IsEnabledStream(DMAx, stream)) return 0;
// Anything to read?
auto dma_len = LL_DMA_GetDataLength(DMAx, stream);
if (fifo.size - dma_len == fifo.ridx) return 0;
} else {
if (fifo.ridx == fifo.widx) return 0;
}
*data = fifo.buf[fifo.ridx];
fifo.ridx = (fifo.ridx + 1) & (fifo.size - 1);
return 1;
}
static const LL_GPIO_InitTypeDef extmoduleUSART_PinDef = {
.Pin = EXTMODULE_TX_GPIO_PIN | EXTMODULE_RX_GPIO_PIN,
@@ -71,96 +93,118 @@ static const stm32_usart_t extmoduleUSART = {
.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,
.rxDMA = EXTMODULE_USART_TX_DMA,
.rxDMA_Stream = EXTMODULE_USART_RX_DMA_STREAM_LL,
.rxDMA_Channel = EXTMODULE_USART_RX_DMA_CHANNEL,
};
static const ExtmoduleCtx extmoduleCtx = {
.rxFifo = &extmoduleFifo,
static uint8_t _rx_buffer[INTMODULE_FIFO_SIZE] __DMA;
static ExtmoduleCtx extmoduleCtx = {
.rxFifo = { _rx_buffer, sizeof(_rx_buffer), 0, 0 },
.usart = &extmoduleUSART,
};
static void* extmoduleSerialStart(const etx_serial_init* params)
static void* extmoduleSerialInit(const etx_serial_init* params)
{
if (!params) return nullptr;
extmodule_driver.on_receive = extmoduleFifoReceive;
extmodule_driver.on_error = nullptr;
extmodule_callbacks.on_receive = nullptr;
extmodule_callbacks.on_error = nullptr;
// UART config
stm32_usart_init(&extmoduleUSART, params);
extmoduleCtx.rxFifo->clear();
auto usart = extmoduleCtx.usart;
stm32_usart_init(usart, params);
auto& fifo = extmoduleCtx.rxFifo;
if (params->rx_enable && usart->rxDMA) {
stm32_usart_init_rx_dma(usart, fifo.buf, fifo.size);
}
_fifo_clear(usart, fifo);
return (void*)&extmoduleCtx;
}
void extmoduleInvertedSerialStart(uint32_t baudrate)
void extmoduleSerialStop(void* ctx)
{
EXTERNAL_MODULE_ON();
etx_serial_init params(extmoduleSerialParams);
params.baudrate = baudrate;
extmoduleSerialStart(&params);
}
void extmoduleSerialStop(void*)
{
stm32_usart_deinit(&extmoduleUSART);
auto modCtx = (ExtmoduleCtx*)ctx;
stm32_usart_deinit(modCtx->usart);
// reset callbacks
extmodule_driver.on_receive = nullptr;
extmodule_driver.on_error = nullptr;
extmodule_callbacks.on_receive = nullptr;
extmodule_callbacks.on_error = nullptr;
}
static void extmoduleSendByte(void* ctx, uint8_t byte)
static void extmoduleSerialSendByte(void* ctx, uint8_t byte)
{
auto modCtx = (ExtmoduleCtx*)ctx;
stm32_usart_send_byte(modCtx->usart, byte);
}
static void extmoduleSendBuffer(void* ctx, const uint8_t * data, uint8_t size)
static void extmoduleSerialSendBuffer(void* ctx, const uint8_t * data, uint8_t size)
{
auto modCtx = (ExtmoduleCtx*)ctx;
if (size == 0) return;
stm32_usart_send_buffer(modCtx->usart, data, size);
}
static void extmoduleWaitForTxCompleted(void* ctx)
static void extmoduleSerialWaitForTxCompleted(void* ctx)
{
auto modCtx = (ExtmoduleCtx*)ctx;
stm32_usart_wait_for_tx_dma(modCtx->usart);
}
static int extmoduleGetByte(void* ctx, uint8_t* data)
static int extmoduleSerialGetByte(void* ctx, uint8_t* data)
{
auto modCtx = (ExtmoduleCtx*)ctx;
if (!modCtx->rxFifo) return -1;
return modCtx->rxFifo->pop(*data);
return _fifo_get_byte(modCtx->usart, modCtx->rxFifo, data);
}
static void extmoduleClearRxBuffer(void* ctx)
static void extmoduleSerialClearRxBuffer(void* ctx)
{
auto modCtx = (ExtmoduleCtx*)ctx;
if (!modCtx->rxFifo) return;
modCtx->rxFifo->clear();
_fifo_clear(modCtx->usart, modCtx->rxFifo);
}
const etx_serial_driver_t ExtmoduleSerialDriver = {
.init = extmoduleSerialStart,
static const etx_serial_driver_t extmoduleSerialDriver = {
.init = extmoduleSerialInit,
.deinit = extmoduleSerialStop,
.sendByte = extmoduleSendByte,
.sendBuffer = extmoduleSendBuffer,
.waitForTxCompleted = extmoduleWaitForTxCompleted,
.getByte = extmoduleGetByte,
.clearRxBuffer = extmoduleClearRxBuffer,
.sendByte = extmoduleSerialSendByte,
.sendBuffer = extmoduleSerialSendBuffer,
.waitForTxCompleted = extmoduleSerialWaitForTxCompleted,
.getByte = extmoduleSerialGetByte,
.clearRxBuffer = extmoduleSerialClearRxBuffer,
.getBaudrate = nullptr,
.setReceiveCb = nullptr,
.setBaudrateCb = nullptr,
};
constexpr const etx_serial_driver_t* _default_driver = &extmoduleSerialDriver;
// IRQ based RX/TX: probably obsolete now
extern "C" void EXTMODULE_USART_IRQHandler(void)
{
stm32_usart_isr(&extmoduleUSART, &extmodule_driver);
stm32_usart_isr(extmoduleCtx.usart, &extmodule_callbacks);
}
#else
constexpr const etx_serial_driver_t* _default_driver = nullptr;
#endif // defined(EXTMODULE_USART)
const etx_serial_driver_t* _extmodule_driver = _default_driver;
void extmoduleSetSerialPort(const etx_serial_driver_t* drv)
{
if (drv) {
_extmodule_driver = drv;
} else {
_extmodule_driver = _default_driver;
}
}
const etx_serial_driver_t* extmoduleGetSerialPort()
{
return _extmodule_driver;
}
@@ -26,8 +26,8 @@
#define EXTMODULE_USART_IRQ_PRIORITY 6
// Callbacks using intmoduleFifo
void extmoduleFifoReceive(uint8_t data);
void extmoduleFifoError();
// Use an alternative USART as external module
void extmoduleSetSerialPort(const etx_serial_driver_t* port);
extern const etx_serial_driver_t ExtmoduleSerialDriver;
// Return the serial driver to be used as external module
const etx_serial_driver_t* extmoduleGetSerialPort();
@@ -19,9 +19,52 @@
* GNU General Public License for more details.
*/
#include "stm32_hal_ll.h"
#include "stm32_usart_driver.h"
#include <string.h>
// WARNING:
//
// NVIC_GetEnableIRQ is stolen from "${THIRDPARTY_DIR}/CMSIS/Include/core_cm4.h".
//
// Until we can include the new CMSIS everywhere, this
// needs to be defined here, as the old CMSIS does not define it.
//
// The new CMSIS can be used when StdPeriph is gone, as it mandates
// the old version located in "${STM32LIB_DIR}/CMSIS/Include"
//
static inline uint32_t NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
if ((int32_t)(IRQn) >= 0) {
return ((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] &
(1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL)
? 1UL
: 0UL));
} else {
return (0U);
}
}
static void _enable_usart_irq(const stm32_usart_t* usart)
{
NVIC_SetPriority(usart->IRQn, usart->IRQ_Prio);
NVIC_EnableIRQ(usart->IRQn);
}
void stm32_usart_enable_tx_irq(const stm32_usart_t* usart)
{
if (LL_USART_IsEnabledDMAReq_TX(usart->USARTx)) {
stm32_usart_wait_for_tx_dma(usart);
LL_USART_DisableDMAReq_TX(usart->USARTx);
}
if (!NVIC_GetEnableIRQ(usart->IRQn)) {
_enable_usart_irq(usart);
}
LL_USART_EnableIT_TXE(usart->USARTx);
}
static void enable_usart_clock(USART_TypeDef* USARTx)
{
if (USARTx == USART1) {
@@ -60,6 +103,7 @@ static void disable_usart_clock(USART_TypeDef* USARTx)
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_UART7);
}
#endif
}
void stm32_usart_init_rx_dma(const stm32_usart_t* usart, void* buffer, uint32_t length)
@@ -103,9 +147,7 @@ void stm32_usart_deinit_rx_dma(const stm32_usart_t* usart)
// Enable IRQ based RX
LL_USART_EnableIT_RXNE(usart->USARTx);
NVIC_SetPriority(usart->IRQn, usart->IRQ_Prio);
NVIC_EnableIRQ(usart->IRQn);
_enable_usart_irq(usart);
}
}
@@ -172,8 +214,7 @@ void stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params)
}
if (!usart->txDMA || (params->rx_enable && !usart->rxDMA)) {
NVIC_SetPriority(usart->IRQn, usart->IRQ_Prio);
NVIC_EnableIRQ(usart->IRQn);
_enable_usart_irq(usart);
}
}
@@ -49,6 +49,7 @@ struct stm32_usart_t {
void stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params);
void stm32_usart_init_rx_dma(const stm32_usart_t* usart, void* buffer, uint32_t length);
void stm32_usart_enable_tx_irq(const stm32_usart_t* usart);
void stm32_usart_deinit(const stm32_usart_t* usart);
void stm32_usart_deinit_rx_dma(const stm32_usart_t* usart);
void stm32_usart_send_byte(const stm32_usart_t* usart, uint8_t byte);
@@ -358,23 +358,26 @@ static void* sbus_trainer_ctx = nullptr;
void init_trainer_module_sbus()
{
sbus_trainer_ctx = ExtmoduleSerialDriver.init(&sbusTrainerParams);
auto serial_driver = extmoduleGetSerialPort();
sbus_trainer_ctx = serial_driver->init(&sbusTrainerParams);
}
void stop_trainer_module_sbus()
{
auto serial_driver = extmoduleGetSerialPort();
auto ctx = sbus_trainer_ctx;
if (ctx) {
sbus_trainer_ctx = nullptr;
ExtmoduleSerialDriver.deinit(ctx);
serial_driver->deinit(ctx);
}
}
int trainerModuleSbusGetByte(uint8_t* data)
{
auto serial_driver = extmoduleGetSerialPort();
auto ctx = sbus_trainer_ctx;
if (ctx) {
return ExtmoduleSerialDriver.getByte(ctx, data);
return serial_driver->getByte(ctx, data);
}
return 0;
+6 -2
View File
@@ -434,10 +434,14 @@
#define AUX_SERIAL_USART USART3
#define AUX_SERIAL_USART_IRQHandler USART3_IRQHandler
#define AUX_SERIAL_USART_IRQn USART3_IRQn
#define AUX_SERIAL_DMA_TX DMA1
#define AUX_SERIAL_DMA_Stream_TX DMA1_Stream3
#define AUX_SERIAL_DMA_Stream_TX_LL LL_DMA_STREAM_3
#define AUX_SERIAL_DMA_Channel_TX LL_DMA_CHANNEL_4
#define AUX_SERIAL_DMA_RX DMA1
#define AUX_SERIAL_DMA_Stream_RX DMA1_Stream1
#define AUX_SERIAL_DMA_Stream_RX_LL LL_DMA_STREAM_1
#define AUX_SERIAL_DMA_Channel_RX DMA_Channel_4
#define AUX_SERIAL_DMA_Channel_RX LL_DMA_CHANNEL_4
#if defined(RADIO_TX16S)
#define AUX_SERIAL_PWR_GPIO GPIOA
#define AUX_SERIAL_PWR_GPIO_PIN GPIO_Pin_15 // PA.15
@@ -876,9 +880,9 @@
#define EXTMODULE_USART_TX_DMA_CHANNEL LL_DMA_CHANNEL_4
#define EXTMODULE_USART_TX_DMA_STREAM DMA1_Stream3
#define EXTMODULE_USART_TX_DMA_STREAM_LL LL_DMA_STREAM_3
#define EXTMODULE_USART_TX_DMA_FLAG_TC DMA_FLAG_TCIF3
#define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMA_CHANNEL_4
#define EXTMODULE_USART_RX_DMA_STREAM DMA1_Stream1
#define EXTMODULE_USART_RX_DMA_STREAM_LL LL_DMA_STREAM_1
#elif defined(PCBX10) || PCBREV >= 13
#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2)
#define EXTMODULE_TX_GPIO GPIOA
+1 -8
View File
@@ -462,20 +462,14 @@
#define EXTMODULE_USART_TX_DMA_CHANNEL LL_DMA_CHANNEL_5
#define EXTMODULE_USART_TX_DMA_STREAM DMA2_Stream7
#define EXTMODULE_USART_TX_DMA_STREAM_LL LL_DMA_STREAM_7
#define EXTMODULE_USART_TX_DMA_IRQn DMA2_Stream7_IRQn
#define EXTMODULE_USART_TX_DMA_IRQHandler DMA2_Stream7_IRQHandler
#define EXTMODULE_USART_TX_DMA_FLAG_TC DMA_IT_TCIF7
#define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMA_CHANNEL_5
#define EXTMODULE_USART_RX_DMA_STREAM DMA2_Stream2
#define EXTMODULE_USART_RX_DMA_IRQn DMA2_Stream2_IRQn
#define EXTMODULE_USART_RX_DMA_IRQHandler DMA2_Stream2_IRQHandler
#define EXTMODULE_USART_RX_DMA_FLAG_TC DMA_IT_TCIF2
#define EXTMODULE_USART_RX_DMA_STREAM_LL LL_DMA_STREAM_2
#define EXTMODULE_USART_IRQHandler USART6_IRQHandler
#define EXTMODULE_USART_IRQn USART6_IRQn
#define EXTMODULE_TIMER_DMA_SIZE (DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0)
//TIMER
#define EXTMODULE_TIMER_DMA_CHANNEL LL_DMA_CHANNEL_7
#define EXTMODULE_TIMER_DMA_STREAM DMA2_Stream1
@@ -483,7 +477,6 @@
#define EXTMODULE_TIMER_DMA_STREAM_LL LL_DMA_STREAM_1
#define EXTMODULE_TIMER_DMA_STREAM_IRQn DMA2_Stream1_IRQn
#define EXTMODULE_TIMER_DMA_IRQHandler DMA2_Stream1_IRQHandler
#define EXTMODULE_TIMER_DMA_FLAG_TC DMA_IT_TCIF1
#define EXTMODULE_TX_INVERT_GPIO GPIOE
#define EXTMODULE_TX_INVERT_GPIO_PIN GPIO_Pin_3 // PE.03
+20 -1
View File
@@ -80,7 +80,8 @@ const etx_serial_driver_t IntmoduleSerialDriver = {
.setBaudrateCb = nullptr,
};
const etx_serial_driver_t ExtmoduleSerialDriver = {
#if defined(EXTMODULE_USART)
static const etx_serial_driver_t _extmoduleSerialDriver = {
.init = init,
.deinit = deinit,
.sendByte = sendByte,
@@ -92,3 +93,21 @@ const etx_serial_driver_t ExtmoduleSerialDriver = {
.setReceiveCb = nullptr,
.setBaudrateCb = nullptr,
};
constexpr const etx_serial_driver_t* _ext_default_drv = &_extmoduleSerialDriver;
#else
constexpr const etx_serial_driver_t* _ext_default_drv = nullptr;
#endif
const etx_serial_driver_t* _ext_drv = _ext_default_drv;
void extmoduleSetSerialPort(const etx_serial_driver_t* drv)
{
if (drv) _ext_drv = drv;
else _ext_drv = _ext_default_drv;
}
const etx_serial_driver_t* extmoduleGetSerialPort()
{
return _ext_drv;
}
+22 -2
View File
@@ -743,6 +743,26 @@ void rtcSetTime(const struct gtm * t)
const etx_serial_port_t UsbSerialPort = { "USB-VCP", nullptr, nullptr };
#endif
#if defined(AUX_SERIAL) || defined(AUX2_SERIAL)
static void* _fake_drv_init(const etx_serial_init*) { return nullptr; }
static void _fake_drv_fct1(void*) {}
static void _fake_drv_send_byte(void*, uint8_t) {}
static void _fake_drv_send_buffer(void*, const uint8_t*, uint8_t) {}
static int _fake_drv_get_byte(void*, uint8_t*) { return 0; }
static const etx_serial_driver_t _fake_drv = {
.init = _fake_drv_init,
.deinit = _fake_drv_fct1,
.sendByte = _fake_drv_send_byte,
.sendBuffer = _fake_drv_send_buffer,
.waitForTxCompleted = _fake_drv_fct1,
.getByte = _fake_drv_get_byte,
.clearRxBuffer = nullptr,
.getBaudrate = nullptr,
.setReceiveCb = nullptr,
.setBaudrateCb = nullptr,
};
#endif
#if defined(AUX_SERIAL)
#if defined(AUX_SERIAL_PWR_GPIO)
static void _fake_pwr_aux(uint8_t) {}
@@ -750,7 +770,7 @@ const etx_serial_port_t UsbSerialPort = { "USB-VCP", nullptr, nullptr };
#else
#define AUX_SERIAL_PWR nullptr
#endif
const etx_serial_port_t auxSerialPort = { "AUX1", nullptr, AUX_SERIAL_PWR };
static const etx_serial_port_t auxSerialPort = {"AUX1", &_fake_drv, AUX_SERIAL_PWR};
#define AUX_SERIAL_PORT &auxSerialPort
#else
#define AUX_SERIAL_PORT nullptr
@@ -763,7 +783,7 @@ const etx_serial_port_t auxSerialPort = { "AUX1", nullptr, AUX_SERIAL_PWR };
#else
#define AUX2_SERIAL_PWR nullptr
#endif
const etx_serial_port_t aux2SerialPort = { "AUX2", nullptr, AUX2_SERIAL_PWR };
static const etx_serial_port_t aux2SerialPort = {"AUX2", &_fake_drv, AUX2_SERIAL_PWR};
#define AUX2_SERIAL_PORT &aux2SerialPort
#else
#define AUX2_SERIAL_PORT nullptr
+3 -3
View File
@@ -1783,12 +1783,12 @@
#define EXTMODULE_USART_IRQn USART6_IRQn
#define EXTMODULE_USART_IRQHandler USART6_IRQHandler
#define EXTMODULE_USART_TX_DMA DMA2
#define EXTMODULE_USART_TX_DMA_CHANNEL DMA_Channel_5
#define EXTMODULE_USART_TX_DMA_CHANNEL LL_DMA_CHANNEL_5
#define EXTMODULE_USART_TX_DMA_STREAM DMA2_Stream6
#define EXTMODULE_USART_TX_DMA_STREAM_LL LL_DMA_STREAM_6
#define EXTMODULE_USART_TX_DMA_FLAG_TC DMA_FLAG_TCIF6
#define EXTMODULE_USART_RX_DMA_CHANNEL DMA_Channel_5
#define EXTMODULE_USART_RX_DMA_CHANNEL LL_DMA_CHANNEL_5
#define EXTMODULE_USART_RX_DMA_STREAM DMA2_Stream1
#define EXTMODULE_USART_RX_DMA_STREAM_LL LL_DMA_STREAM_1
#else
#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2)
#if defined(RADIO_COMMANDO8)