From faf34970e131d4f63dadf40d36df6db3762cca9d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 3 Dec 2019 09:56:05 +1100 Subject: [PATCH] HAL_ChibiOS: automatically control pullup/pulldown on inverted UARTs this makes setup of sport telemetry much easier --- libraries/AP_HAL_ChibiOS/UARTDriver.cpp | 14 ++++++++++++++ libraries/AP_HAL_ChibiOS/UARTDriver.h | 2 ++ .../AP_HAL_ChibiOS/hwdef/common/stm32_util.c | 13 ++++++++++++- .../AP_HAL_ChibiOS/hwdef/common/stm32_util.h | 8 ++++++++ .../hwdef/scripts/chibios_hwdef.py | 16 +++++++++++++--- 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/libraries/AP_HAL_ChibiOS/UARTDriver.cpp b/libraries/AP_HAL_ChibiOS/UARTDriver.cpp index 1bf082a84b..beef0b7ed5 100644 --- a/libraries/AP_HAL_ChibiOS/UARTDriver.cpp +++ b/libraries/AP_HAL_ChibiOS/UARTDriver.cpp @@ -1302,17 +1302,31 @@ bool UARTDriver::set_options(uint8_t options) #if defined(STM32F7) || defined(STM32H7) || defined(STM32F3) // F7 has built-in support for inversion in all uarts + ioline_t rx_line = (options & OPTION_SWAP)?sdef.tx_line:sdef.rx_line; + ioline_t tx_line = (options & OPTION_SWAP)?sdef.rx_line:sdef.tx_line; if (options & OPTION_RXINV) { cr2 |= USART_CR2_RXINV; _cr2_options |= USART_CR2_RXINV; + if (rx_line != 0) { + palLineSetPushPull(rx_line, PAL_PUSHPULL_PULLDOWN); + } } else { cr2 &= ~USART_CR2_RXINV; + if (rx_line != 0) { + palLineSetPushPull(rx_line, PAL_PUSHPULL_PULLUP); + } } if (options & OPTION_TXINV) { cr2 |= USART_CR2_TXINV; _cr2_options |= USART_CR2_TXINV; + if (tx_line != 0) { + palLineSetPushPull(tx_line, PAL_PUSHPULL_PULLDOWN); + } } else { cr2 &= ~USART_CR2_TXINV; + if (tx_line != 0) { + palLineSetPushPull(tx_line, PAL_PUSHPULL_PULLUP); + } } // F7 can also support swapping RX and TX pins if (options & OPTION_SWAP) { diff --git a/libraries/AP_HAL_ChibiOS/UARTDriver.h b/libraries/AP_HAL_ChibiOS/UARTDriver.h index 163dcb38f3..6baa98d501 100644 --- a/libraries/AP_HAL_ChibiOS/UARTDriver.h +++ b/libraries/AP_HAL_ChibiOS/UARTDriver.h @@ -72,6 +72,8 @@ public: uint8_t dma_tx_stream_id; uint32_t dma_tx_channel_id; #endif + ioline_t tx_line; + ioline_t rx_line; ioline_t rts_line; int8_t rxinv_gpio; uint8_t rxinv_polarity; diff --git a/libraries/AP_HAL_ChibiOS/hwdef/common/stm32_util.c b/libraries/AP_HAL_ChibiOS/hwdef/common/stm32_util.c index eae3314eb0..b9a94d294c 100644 --- a/libraries/AP_HAL_ChibiOS/hwdef/common/stm32_util.c +++ b/libraries/AP_HAL_ChibiOS/hwdef/common/stm32_util.c @@ -342,7 +342,18 @@ iomode_t palReadLineMode(ioline_t line) } return ret; } -#endif + +/* + set pin as pullup, pulldown or floating + */ +void palLineSetPushPull(ioline_t line, enum PalPushPull pp) +{ + ioportid_t port = PAL_PORT(line); + uint8_t pad = PAL_PAD(line); + port->PUPDR = (port->PUPDR & ~(3<<(pad*2))) | (pp<<(pad*2)); +} + +#endif // F7, H7, F4 void stm32_cacheBufferInvalidate(const void *p, size_t size) { diff --git a/libraries/AP_HAL_ChibiOS/hwdef/common/stm32_util.h b/libraries/AP_HAL_ChibiOS/hwdef/common/stm32_util.h index e47c319ec2..0681e6e917 100644 --- a/libraries/AP_HAL_ChibiOS/hwdef/common/stm32_util.h +++ b/libraries/AP_HAL_ChibiOS/hwdef/common/stm32_util.h @@ -80,6 +80,14 @@ void malloc_init(void); */ #if defined(STM32F7) || defined(STM32H7) || defined(STM32F4) iomode_t palReadLineMode(ioline_t line); + +enum PalPushPull { + PAL_PUSHPULL_NOPULL=0, + PAL_PUSHPULL_PULLUP=1, + PAL_PUSHPULL_PULLDOWN=2 +}; + +void palLineSetPushPull(ioline_t line, enum PalPushPull pp); #endif // set n RTC backup registers starting at given idx diff --git a/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py b/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py index 656998a565..13ac42b645 100644 --- a/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py +++ b/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py @@ -985,6 +985,16 @@ def write_UART_config(f): else: error("Invalid element %s in UART_ORDER" % dev) devlist.append('HAL_%s_CONFIG' % dev) + if dev + "_TX" in bylabel: + p = bylabel[dev + '_TX'] + tx_line = 'PAL_LINE(GPIO%s,%uU)' % (p.port, p.pin) + else: + tx_line = "0" + if dev + "_RX" in bylabel: + p = bylabel[dev + '_RX'] + rx_line = 'PAL_LINE(GPIO%s,%uU)' % (p.port, p.pin) + else: + rx_line = "0" if dev + "_RTS" in bylabel: p = bylabel[dev + '_RTS'] rts_line = 'PAL_LINE(GPIO%s,%uU)' % (p.port, p.pin) @@ -1006,10 +1016,10 @@ def write_UART_config(f): "#define HAL_%s_CONFIG { (BaseSequentialStream*) &SD%u, false, " % (dev, n)) if mcu_series.startswith("STM32F1"): - f.write("%s, " % rts_line) + f.write("%s, %s, %s, " % (tx_line, rx_line, rts_line)) else: - f.write("STM32_%s_RX_DMA_CONFIG, STM32_%s_TX_DMA_CONFIG, %s, " % - (dev, dev, rts_line)) + f.write("STM32_%s_RX_DMA_CONFIG, STM32_%s_TX_DMA_CONFIG, %s, %s, %s, " % + (dev, dev, tx_line, rx_line, rts_line)) # add inversion pins, if any f.write("%d, " % get_gpio_bylabel(dev + "_RXINV"))