Skip to content

feat(uart): support UART Tx, Rx and Data invert function #2701

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 31, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion cores/arduino/HardwareSerial.cpp
Original file line number Diff line number Diff line change
@@ -446,7 +446,7 @@ void HardwareSerial::begin(unsigned long baud, byte config)
break;
}

uart_init(&_serial, (uint32_t)baud, databits, parity, stopbits);
uart_init(&_serial, (uint32_t)baud, databits, parity, stopbits, _rx_invert, _tx_invert, _data_invert);
enableHalfDuplexRx();
uart_attach_rx_callback(&_serial, _rx_complete_irq);
}
@@ -668,4 +668,19 @@ void HardwareSerial::enableHalfDuplexRx(void)
}
}

void HardwareSerial::setRxInvert(void)
{
_rx_invert = true;
}

void HardwareSerial::setTxInvert(void)
{
_tx_invert = true;
}

void HardwareSerial::setDataInvert(void)
{
_data_invert = true;
}

#endif // HAL_UART_MODULE_ENABLED && !HAL_UART_MODULE_ONLY
9 changes: 9 additions & 0 deletions cores/arduino/HardwareSerial.h
Original file line number Diff line number Diff line change
@@ -95,6 +95,9 @@ class HardwareSerial : public Stream {
protected:
// Has any byte been written to the UART since begin()
bool _written;
bool _rx_invert;
bool _tx_invert;
bool _data_invert;

// Don't put any members after these buffers, since only the first
// 32 bytes of this struct can be accessed quickly using the ldd
@@ -165,6 +168,12 @@ class HardwareSerial : public Stream {
bool isHalfDuplex(void) const;
void enableHalfDuplexRx(void);

// Enable HW Rx/Tx/data inversion
// This needs to be done before the call to begin()
void setRxInvert(void);
void setTxInvert(void);
void setDataInvert(void);

friend class STM32LowPower;

// Interrupt handlers
3 changes: 3 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
@@ -274,6 +274,9 @@ HALF_DUPLEX_ENABLED LITERAL1
setHalfDuplex KEYWORD2
isHalfDuplex KEYWORD2
enableHalfDuplexRx KEYWORD2
setRxInvert KEYWORD2
setTxInvert KEYWORD2
setDataInvert KEYWORD2
Serial4 KEYWORD1
Serial5 KEYWORD1
Serial6 KEYWORD1
3 changes: 2 additions & 1 deletion libraries/SrcWrapper/inc/uart.h
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@
#define __UART_H

/* Includes ------------------------------------------------------------------*/
#include <stdbool.h>
#include "stm32_def.h"
#include "PinNames.h"

@@ -254,7 +255,7 @@ struct serial_s {

/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t parity, uint32_t stopbits);
void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t parity, uint32_t stopbits, bool rx_invert, bool tx_invert, bool data_invert);
void uart_deinit(serial_t *obj);
#if defined(HAL_PWR_MODULE_ENABLED) && (defined(UART_IT_WUF) || defined(LPUART1_BASE))
void uart_config_lowpower(serial_t *obj);
30 changes: 25 additions & 5 deletions libraries/SrcWrapper/src/stm32/uart.c
Original file line number Diff line number Diff line change
@@ -115,7 +115,7 @@ serial_t *get_serial_obj(UART_HandleTypeDef *huart)
* @param obj : pointer to serial_t structure
* @retval None
*/
void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t parity, uint32_t stopbits)
void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t parity, uint32_t stopbits, bool rx_invert, bool tx_invert, bool data_invert)
{
if (obj == NULL) {
return;
@@ -407,11 +407,31 @@ void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
huart->Init.Mode = UART_MODE_TX_RX;
huart->Init.HwFlowCtl = flow_control;
huart->Init.OverSampling = UART_OVERSAMPLING_16;
#if defined(UART_ADVFEATURE_NO_INIT)
// Default value
huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
#if defined(UART_ADVFEATURE_SWAP_INIT)
huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_SWAP_INIT;
huart->AdvancedInit.AdvFeatureInit |= UART_ADVFEATURE_SWAP_INIT;
huart->AdvancedInit.Swap = pin_swap;
#elif defined(UART_ADVFEATURE_NO_INIT)
huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
#endif
#if defined(UART_ADVFEATURE_RXINVERT_INIT)
if (rx_invert) {
huart->AdvancedInit.AdvFeatureInit |= UART_ADVFEATURE_RXINVERT_INIT;
huart->AdvancedInit.RxPinLevelInvert = UART_ADVFEATURE_RXINV_ENABLE;
}
#endif
#if defined(UART_ADVFEATURE_TXINVERT_INIT)
if (tx_invert) {
huart->AdvancedInit.AdvFeatureInit |= UART_ADVFEATURE_TXINVERT_INIT;
huart->AdvancedInit.TxPinLevelInvert = UART_ADVFEATURE_TXINV_ENABLE;
}
#endif
#if defined(UART_ADVFEATURE_DATAINVERT_INIT)
if (data_invert) {
huart->AdvancedInit.AdvFeatureInit |= UART_ADVFEATURE_DATAINVERT_INIT;
huart->AdvancedInit.DataInvert = UART_ADVFEATURE_DATAINV_ENABLE;
}
#endif
#endif
#ifdef UART_ONE_BIT_SAMPLE_DISABLE
huart->Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
@@ -812,7 +832,7 @@ void uart_debug_init(void)
serial_debug.pin_tx = pinmap_pin(DEBUG_UART, PinMap_UART_TX);
#endif
/* serial_debug.pin_rx set by default to NC to configure in half duplex mode */
uart_init(&serial_debug, DEBUG_UART_BAUDRATE, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1);
uart_init(&serial_debug, DEBUG_UART_BAUDRATE, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1, false, false, false);
}
}