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
Show file tree
Hide file tree
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
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion libraries/SrcWrapper/inc/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#define __UART_H

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

Expand Down Expand Up @@ -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);
Expand Down
30 changes: 25 additions & 5 deletions libraries/SrcWrapper/src/stm32/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand Down