diff --git a/libraries/AP_HAL_ChibiOS/GPIO.cpp b/libraries/AP_HAL_ChibiOS/GPIO.cpp index 685fec7b56..5da4aa4427 100644 --- a/libraries/AP_HAL_ChibiOS/GPIO.cpp +++ b/libraries/AP_HAL_ChibiOS/GPIO.cpp @@ -79,6 +79,9 @@ void GPIO::init() } #ifdef HAL_PIN_ALT_CONFIG +// chosen alternative config +uint8_t GPIO::alt_config; + /* alternative config table, selected using BRD_ALT_CONFIG */ @@ -86,6 +89,8 @@ static const struct alt_config { uint8_t alternate; uint16_t mode; ioline_t line; + PERIPH_TYPE periph_type; + uint8_t periph_instance; } alternate_config[] HAL_PIN_ALT_CONFIG; /* @@ -97,22 +102,59 @@ void GPIO::setup_alt_config(void) if (!bc) { return; } - const uint8_t alt = bc->get_alt_config(); - if (alt == 0) { + alt_config = bc->get_alt_config(); + if (alt_config == 0) { // use defaults return; } for (uint8_t i=0; i #include #include "Util.h" +#include "GPIO.h" #if HAL_USE_I2C == TRUE && defined(HAL_I2C_DEVICE_LIST) @@ -29,6 +30,7 @@ static const struct I2CInfo { struct I2CDriver *i2c; + uint8_t instance; uint8_t dma_channel_rx; uint8_t dma_channel_tx; ioline_t scl_line; @@ -90,13 +92,17 @@ void I2CBus::clear_bus(uint8_t busidx) { #if HAL_I2C_CLEAR_ON_TIMEOUT const struct I2CInfo &info = I2CD[busidx]; - const iomode_t mode_saved = palReadLineMode(info.scl_line); - palSetLineMode(info.scl_line, PAL_MODE_OUTPUT_PUSHPULL); + const ioline_t scl_line = GPIO::resolve_alt_config(info.scl_line, PERIPH_TYPE::I2C_SCL, info.instance); + if (scl_line == 0) { + return; + } + const iomode_t mode_saved = palReadLineMode(scl_line); + palSetLineMode(scl_line, PAL_MODE_OUTPUT_PUSHPULL); for(uint8_t j = 0; j < 20; j++) { - palToggleLine(info.scl_line); + palToggleLine(scl_line); hal.scheduler->delay_microseconds(10); } - palSetLineMode(info.scl_line, mode_saved); + palSetLineMode(scl_line, mode_saved); #endif } @@ -107,10 +113,14 @@ void I2CBus::clear_bus(uint8_t busidx) uint8_t I2CBus::read_sda(uint8_t busidx) { const struct I2CInfo &info = I2CD[busidx]; - const iomode_t mode_saved = palReadLineMode(info.sda_line); - palSetLineMode(info.sda_line, PAL_MODE_INPUT); - uint8_t ret = palReadLine(info.sda_line); - palSetLineMode(info.sda_line, mode_saved); + const ioline_t sda_line = GPIO::resolve_alt_config(info.sda_line, PERIPH_TYPE::I2C_SDA, info.instance); + if (sda_line == 0) { + return 0; + } + const iomode_t mode_saved = palReadLineMode(sda_line); + palSetLineMode(sda_line, PAL_MODE_INPUT); + uint8_t ret = palReadLine(sda_line); + palSetLineMode(sda_line, mode_saved); return ret; } #endif diff --git a/libraries/AP_HAL_ChibiOS/UARTDriver.cpp b/libraries/AP_HAL_ChibiOS/UARTDriver.cpp index d9c6c5bf44..8a2961f240 100644 --- a/libraries/AP_HAL_ChibiOS/UARTDriver.cpp +++ b/libraries/AP_HAL_ChibiOS/UARTDriver.cpp @@ -1346,17 +1346,17 @@ uint64_t UARTDriver::receive_time_constraint_us(uint16_t nbytes) void UARTDriver::set_pushpull(uint16_t options) { #if HAL_USE_SERIAL == TRUE && !defined(STM32F1) - if ((options & OPTION_PULLDOWN_RX) && sdef.rx_line) { - palLineSetPushPull(sdef.rx_line, PAL_PUSHPULL_PULLDOWN); + if ((options & OPTION_PULLDOWN_RX) && arx_line) { + palLineSetPushPull(arx_line, PAL_PUSHPULL_PULLDOWN); } - if ((options & OPTION_PULLDOWN_TX) && sdef.tx_line) { - palLineSetPushPull(sdef.tx_line, PAL_PUSHPULL_PULLDOWN); + if ((options & OPTION_PULLDOWN_TX) && atx_line) { + palLineSetPushPull(atx_line, PAL_PUSHPULL_PULLDOWN); } - if ((options & OPTION_PULLUP_RX) && sdef.rx_line) { - palLineSetPushPull(sdef.rx_line, PAL_PUSHPULL_PULLUP); + if ((options & OPTION_PULLUP_RX) && arx_line) { + palLineSetPushPull(arx_line, PAL_PUSHPULL_PULLUP); } - if ((options & OPTION_PULLUP_TX) && sdef.tx_line) { - palLineSetPushPull(sdef.tx_line, PAL_PUSHPULL_PULLUP); + if ((options & OPTION_PULLUP_TX) && atx_line) { + palLineSetPushPull(atx_line, PAL_PUSHPULL_PULLUP); } #endif } @@ -1378,10 +1378,29 @@ bool UARTDriver::set_options(uint16_t options) uint32_t cr3 = sd->usart->CR3; bool was_enabled = (sd->usart->CR1 & USART_CR1_UE); +#ifdef HAL_PIN_ALT_CONFIG + /* + allow for RX and TX pins to be remapped via BRD_ALT_CONFIG + */ + arx_line = GPIO::resolve_alt_config(sdef.rx_line, PERIPH_TYPE::UART_RX, sdef.instance); + atx_line = GPIO::resolve_alt_config(sdef.tx_line, PERIPH_TYPE::UART_TX, sdef.instance); +#else + arx_line = sdef.rx_line; + atx_line = sdef.tx_line; +#endif + #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; + ioline_t rx_line = (options & OPTION_SWAP)?atx_line:arx_line; + ioline_t tx_line = (options & OPTION_SWAP)?arx_line:atx_line; + + // if we are half-duplex then treat either inversion option as + // both being enabled. This is easier to understand for users, who + // can be confused as to which pin is the one that needs inversion + if ((options & OPTION_HDPLEX) && (options & (OPTION_TXINV|OPTION_RXINV)) != 0) { + options |= OPTION_TXINV|OPTION_RXINV; + } + if (options & OPTION_RXINV) { cr2 |= USART_CR2_RXINV; _cr2_options |= USART_CR2_RXINV; diff --git a/libraries/AP_HAL_ChibiOS/UARTDriver.h b/libraries/AP_HAL_ChibiOS/UARTDriver.h index 1deb4201b2..b7ab901194 100644 --- a/libraries/AP_HAL_ChibiOS/UARTDriver.h +++ b/libraries/AP_HAL_ChibiOS/UARTDriver.h @@ -68,6 +68,7 @@ public: struct SerialDef { BaseSequentialStream* serial; + uint8_t instance; bool is_usb; #ifndef HAL_UART_NODMA bool dma_rx; @@ -127,6 +128,12 @@ private: bool rx_dma_enabled; bool tx_dma_enabled; + /* + copy of rx_line and tx_line with alternative configs resolved + */ + ioline_t atx_line; + ioline_t arx_line; + // thread used for all UARTs static thread_t *uart_thread_ctx; diff --git a/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py b/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py index f21c49410d..598428e8ed 100644 --- a/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py +++ b/libraries/AP_HAL_ChibiOS/hwdef/scripts/chibios_hwdef.py @@ -525,6 +525,28 @@ class generic_pin(object): return ret + def periph_type(self): + '''return peripheral type from GPIO_PIN_TYPE class''' + patterns = { + 'USART*RX' : 'PERIPH_TYPE::UART_RX', + 'UART*RX' : 'PERIPH_TYPE::UART_RX', + 'USART*TX' : 'PERIPH_TYPE::UART_TX', + 'UART*TX' : 'PERIPH_TYPE::UART_TX', + 'I2C*SDA' : 'PERIPH_TYPE::I2C_SDA', + 'I2C*SCL' : 'PERIPH_TYPE::I2C_SCL', + } + for k in patterns.keys(): + if fnmatch.fnmatch(self.label, k): + return patterns[k] + return 'PERIPH_TYPE::OTHER' + + def periph_instance(self): + '''return peripheral instance''' + result = re.match(r'[A-Z]*([0-9]*)', self.type) + if result: + return int(result.group(1)) + return 0 + def __str__(self): str = '' if self.af is not None: @@ -1186,19 +1208,19 @@ def write_UART_config(f): if dev.startswith('OTG2'): f.write( - '#define HAL_%s_CONFIG {(BaseSequentialStream*) &SDU2, true, false, 0, 0, false, 0, 0}\n' + '#define HAL_%s_CONFIG {(BaseSequentialStream*) &SDU2, 2, true, false, 0, 0, false, 0, 0}\n' % dev) OTG2_index = uart_list.index(dev) dual_USB_enabled = True elif dev.startswith('OTG'): f.write( - '#define HAL_%s_CONFIG {(BaseSequentialStream*) &SDU1, true, false, 0, 0, false, 0, 0}\n' + '#define HAL_%s_CONFIG {(BaseSequentialStream*) &SDU1, 1, true, false, 0, 0, false, 0, 0}\n' % dev) else: need_uart_driver = True f.write( - "#define HAL_%s_CONFIG { (BaseSequentialStream*) &SD%u, false, " - % (dev, n)) + "#define HAL_%s_CONFIG { (BaseSequentialStream*) &SD%u, %u, false, " + % (dev, n, n)) if mcu_series.startswith("STM32F1"): f.write("%s, %s, %s, " % (tx_line, rx_line, rts_line)) else: @@ -1300,12 +1322,12 @@ def write_I2C_config(f): scl_line = make_line('I2C%u_SCL' % n) f.write(''' #if defined(STM32_I2C_I2C%u_RX_DMA_STREAM) && defined(STM32_I2C_I2C%u_TX_DMA_STREAM) -#define HAL_I2C%u_CONFIG { &I2CD%u, STM32_I2C_I2C%u_RX_DMA_STREAM, STM32_I2C_I2C%u_TX_DMA_STREAM, %s, %s } +#define HAL_I2C%u_CONFIG { &I2CD%u, %u, STM32_I2C_I2C%u_RX_DMA_STREAM, STM32_I2C_I2C%u_TX_DMA_STREAM, %s, %s } #else -#define HAL_I2C%u_CONFIG { &I2CD%u, SHARED_DMA_NONE, SHARED_DMA_NONE, %s, %s } +#define HAL_I2C%u_CONFIG { &I2CD%u, %u, SHARED_DMA_NONE, SHARED_DMA_NONE, %s, %s } #endif ''' - % (n, n, n, n, n, n, scl_line, sda_line, n, n, scl_line, sda_line)) + % (n, n, n, n, n, n, n, scl_line, sda_line, n, n, n, scl_line, sda_line)) f.write('\n#define HAL_I2C_DEVICE_LIST %s\n\n' % ','.join(devlist)) @@ -1657,7 +1679,7 @@ def write_alt_config(f): for alt in altmap.keys(): for pp in altmap[alt].keys(): p = altmap[alt][pp] - f.write(" { %u, %s, PAL_LINE(GPIO%s,%uU)}, /* %s */ \\\n" % (alt, p.pal_modeline(), p.port, p.pin, str(p))) + f.write(" { %u, %s, PAL_LINE(GPIO%s,%uU), %s, %u}, /* %s */ \\\n" % (alt, p.pal_modeline(), p.port, p.pin, p.periph_type(), p.periph_instance(), str(p))) f.write('}\n\n') def write_all_lines(hwdat):