1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-19 14:25:20 +03:00

Tri-state USART TX output if load due to powered down peripheral is detected (#12760)

Tri-state USART TX output if loaded due to powered down peripheral being detected
This commit is contained in:
Steve Evans 2023-05-10 02:53:35 +01:00 committed by GitHub
parent cbaf9b0265
commit 4dc04d6a33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 239 additions and 28 deletions

View file

@ -26,6 +26,7 @@
#include <stdint.h>
#include "platform.h"
#include "build/debug.h"
#ifdef USE_UART
@ -217,9 +218,48 @@ const uartHardware_t uartHardware[UARTDEV_COUNT] = {
#endif
};
bool checkUsartTxOutput(uartPort_t *s)
{
uartDevice_t *uart = container_of(s, uartDevice_t, port);
IO_t txIO = IOGetByTag(uart->tx.pin);
if ((uart->txPinState == TX_PIN_MONITOR) && txIO) {
if (IORead(txIO)) {
// TX is high so we're good to transmit
// Enable USART TX output
uart->txPinState = TX_PIN_ACTIVE;
IOConfigGPIOAF(txIO, IOCFG_AF_PP, uart->hardware->af);
return true;
} else {
// TX line is pulled low so don't enable USART TX
return false;
}
}
return true;
}
void uartTxMonitor(uartPort_t *s)
{
uartDevice_t *uart = container_of(s, uartDevice_t, port);
IO_t txIO = IOGetByTag(uart->tx.pin);
// Switch TX to an input with pullup so it's state can be monitored
uart->txPinState = TX_PIN_MONITOR;
IOConfigGPIO(txIO, IOCFG_IPU);
}
static void handleUsartTxDma(uartPort_t *s)
{
uartDevice_t *uart = container_of(s, uartDevice_t, port);
uartTryStartTxDMA(s);
if (s->txDMAEmpty && (uart->txPinState != TX_PIN_IGNORE)) {
// Switch TX to an input with pullup so it's state can be monitored
uartTxMonitor(s);
}
}
void uartDmaIrqHandler(dmaChannelDescriptor_t* descriptor)
@ -268,6 +308,8 @@ uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode,
s->USARTx = hardware->reg;
s->checkUsartTxOutput = checkUsartTxOutput;
#ifdef USE_DMA
uartConfigureDma(uart);
#endif
@ -279,13 +321,22 @@ uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode,
RCC_ClockCmd(hardware->rcc, ENABLE);
}
uart->txPinState = TX_PIN_IGNORE;
if (options & SERIAL_BIDIR) {
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
IOConfigGPIOAF(txIO, ((options & SERIAL_BIDIR_PP) || (options & SERIAL_BIDIR_PP_PD)) ? IOCFG_AF_PP : IOCFG_AF_OD, hardware->af);
} else {
if ((mode & MODE_TX) && txIO) {
IOInit(txIO, OWNER_SERIAL_TX, RESOURCE_INDEX(device));
IOConfigGPIOAF(txIO, IOCFG_AF_PP_UP, hardware->af);
if ((options & SERIAL_INVERTED) == SERIAL_NOT_INVERTED) {
uart->txPinState = TX_PIN_ACTIVE;
// Switch TX to an input with pullup so it's state can be monitored
uartTxMonitor(s);
} else {
IOConfigGPIOAF(txIO, IOCFG_AF_PP, hardware->af);
}
}
if ((mode & MODE_RX) && rxIO) {
@ -320,6 +371,14 @@ void uartIrqHandler(uartPort_t *s)
}
}
// Detect completion of transmission
if (USART_GetITStatus(s->USARTx, USART_IT_TC) == SET) {
// Switch TX to an input with pullup so it's state can be monitored
uartTxMonitor(s);
USART_ClearITPendingBit(s->USARTx, USART_IT_TC);
}
if (!s->txDMAResource && (USART_GetITStatus(s->USARTx, USART_IT_TXE) == SET)) {
if (s->port.txBufferTail != s->port.txBufferHead) {
USART_SendData(s->USARTx, s->port.txBuffer[s->port.txBufferTail]);