Skip to content

Conversation

2345lug
Copy link

@2345lug 2345lug commented Oct 23, 2024

My work is based on this branch: #40907, but it differs somewhat from it. I have changed the units of measurement for assertion and deassertion times. I have also implemented control of the DE pin (which is specified in the DTS) for stm32_uart in interrupt-driven mode.

@zephyrbot zephyrbot added area: Devicetree area: Samples Samples area: UART Universal Asynchronous Receiver-Transmitter platform: NXP Drivers NXP Semiconductors, drivers labels Oct 23, 2024
Copy link

Hello @2345lug, and thank you very much for your first pull request to the Zephyr project!
Our Continuous Integration pipeline will execute a series of checks on your Pull Request commit messages and code, and you are expected to address any failures by updating the PR. Please take a look at our commit message guidelines to find out how to format your commit messages, and at our contribution workflow to understand how to update your Pull Request. If you haven't already, please make sure to review the project's Contributor Expectations and update (by amending and force-pushing the commits) your pull request if necessary.
If you are stuck or need help please join us on Discord and ask your question there. Additionally, you can escalate the review when applicable. 😊

@2345lug
Copy link
Author

2345lug commented Nov 12, 2024

Hello! @dleach02 I need some advice regarding the RS485 API:
Is it acceptable to control GPIO in this manner for boards whose drivers do not allow direct pin control?
Is it a good idea to use the CTS pin for DE enable in drivers that allow control of this pin (as implemented by colleagues in the NXP driver)?
Thank you in advance!

Comment on lines 2061 to 2267
#ifdef CONFIG_SERIAL_SUPPORT_RS485
if (config->de_enable) {
gpio_pin_configure_dt(&config->de_pin, GPIO_ACTIVE_LOW | GPIO_OUTPUT_ACTIVE);
gpio_pin_set(config->de_pin.port, config->de_pin.pin, config->de_invert);
k_timer_init(&data->rs485_timer, rs485_de_time_expire_callback, NULL);
k_timer_user_data_set(&data->rs485_timer, (void *)config);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why using a GPIO DE bit instead of using the built in DE pin functionality driver by HW (and already implemented, by the way).
At the minimum the PR should explain why introducing this alternate software control method, why one would use it and make it optional (if ever there is a really good reason to have it in the driver)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for your response! If I understand correctly, not all STM32 controllers have hardware support for RS485 (e.g., F0, F1, F4 don't have it), and therefore it is not possible to control the DE pin via hardware on these models. I agree that the API should support hardware control (if the controller supports it), and this needs to be implemented.

My solution proposes an alternative method for controlling the pin for RS485 and a unified API, which, as I understand it, is currently missing in Zephyr. RS485 can be used not only for Modbus, after all. As far as I can tell, people often have the need to use RS485 for other purposes, for example (#32733).

I would appreciate any advice or guidance to successfully integrate this solution.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the API should support hardware control (if the controller supports it), and this needs to be implemented.

My point is that hw control is already implemented in this driver. See

#if HAS_DRIVER_ENABLE
if (config->de_enable) {
if (!IS_UART_DRIVER_ENABLE_INSTANCE(usart)) {
LOG_ERR("%s does not support driver enable", dev->name);
return -EINVAL;
}
uart_stm32_set_driver_enable(dev, true);
LL_USART_SetDEAssertionTime(usart, config->de_assert_time);
LL_USART_SetDEDeassertionTime(usart, config->de_deassert_time);
if (config->de_invert) {
LL_USART_SetDESignalPolarity(usart, LL_USART_DE_POLARITY_LOW);
}
}
#endif

Hence your implementation should take it into account and ensure it could be used by default over SW control if present.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the API should support hardware control (if the controller supports it), and this needs to be implemented.

My point is that hw control is already implemented in this driver. See

#if HAS_DRIVER_ENABLE
if (config->de_enable) {
if (!IS_UART_DRIVER_ENABLE_INSTANCE(usart)) {
LOG_ERR("%s does not support driver enable", dev->name);
return -EINVAL;
}
uart_stm32_set_driver_enable(dev, true);
LL_USART_SetDEAssertionTime(usart, config->de_assert_time);
LL_USART_SetDEDeassertionTime(usart, config->de_deassert_time);
if (config->de_invert) {
LL_USART_SetDESignalPolarity(usart, LL_USART_DE_POLARITY_LOW);
}
}
#endif

Hence your implementation should take it into account and ensure it could be used by default over SW control if present.

Thank you for answer! I agree that this implementation exists, and I will undoubtedly change the approach in my implementation to ensure that the existing HW solution takes priority over SW automatically.

Comment on lines 9 to 11
rs485-de-gpios:
type: phandle-array
description: Output for contactor and relay 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm raising this from STM32 perspective, but I'd be surprised we're the only vendor supporting RS485 HW Support:
It should be easy for user to configure and select use of built-in, RS485 HW support, vs RS485 SW support.
CONFIG_SERIAL_SUPPORT_RS485 isn't the correct way to make this configuration as:
1-Even when disabled HW RS485 is available and supported
2- you're selecting it by default (while IMO the built-in HW support should be the default)

I'd advise exploring the possibility to perform the HW/SW RS485 support selection through the use of rs485-de-gpios property. Being available, SW is used, otherwise user can rely on HW support

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello! RS‑485 DE (Driver Enable) management is now based on the de_enable and de_pin fields:

  • If de_enable is false, no DE control is performed.
  • If de_enable is true and de_pin is NULL, the hardware method is used
    (DE control via driver enable functions).
  • If de_enable is true and de_pin is not NULL, the software method is used
    (GPIO‑based DE control).

typedef void (*poll_out_fn)(USART_TypeDef *usart, void *out);

static void uart_stm32_poll_out_visitor(const struct device *dev, uint16_t out, poll_out_fn set_fn)
static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, poll_out_fn set_fn)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As already mentioned, please limit your changes to RS485 feature.
Other changes should at minimum go in another commit or better a dedicated PR.

@2345lug 2345lug force-pushed the rs485_api branch 2 times, most recently from dcc2cb5 to fa54683 Compare April 21, 2025 12:56
@github-actions github-actions bot added platform: Infineon Infineon Technologies AG platform: Intel ADSP Intel Audio platforms area: DMA Direct Memory Access platform: Silabs Silicon Labs labels Apr 21, 2025
@2345lug 2345lug requested a review from erwango April 25, 2025 10:25
@2345lug
Copy link
Author

2345lug commented May 5, 2025

Hi @erwango, could you please take another look at my updated solution in the PR? I'd really appreciate your feedback. Thanks!

Copy link

@2345lug
Copy link
Author

2345lug commented May 19, 2025

Dear @erwango @dleach02 . I decided to remove the imxrt-related changes from this PR to keep it more compact and focused. I’d really appreciate it if you could take a look at the current version when you have time. Thanks!

@2345lug
Copy link
Author

2345lug commented Jun 9, 2025

Hi @erwango @dleach02,

Just wanted to check if you’ve had a chance to look at the updated PR? I simplified it to focus on the key changes and believe it could be really useful for the project.

Would really appreciate your feedback when you have time! Let me know if anything needs adjusting.

Thanks in advance!

Comment on lines 2303 to 2263
if (config->de_enable) {
if (config->de_pin.port != NULL) {
/* SW method: configure DE pin and initialize timer */
gpio_pin_set(config->de_pin.port, config->de_pin.pin,
config->de_invert);
k_timer_init(&data->rs485_timer, rs485_de_time_expire_callback, NULL);
k_timer_user_data_set(&data->rs485_timer, (void *)config);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last thing that bothers me on this PR:
STM32 SoCs embeds HW to make this feature available at no cost to users, but this implementation add the SW cost by default:

  • whether or not the feature is even used
  • whether or not users prefer relying on HW

To me, SW cost of this feature should be 0 if user don't make use of it or if user prefer HW method.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the discussion! You're absolutely right that for STM32s with built-in DE support (like some H7, F3, and G4 series), we should use the hardware capabilities. However, for popular series like F1, F4, F0, G0, and L0, to my knowledge, automatic DE control isn't available - it always requires manual GPIO implementation.

My proposal simply offers a unified way to handle DE for these cases. What would you suggest:

Should I make this implementation completely optional?

Or perhaps there's a more elegant way to organize this functionality?

I'd really appreciate your input on how to improve this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GPIO DE should be made available only if HW DE is not available. This should be done automatically throught Kconfig or preferably via device tree macros.

Copy link

Copy link

@sjlongland sjlongland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

Firstly, thank-you for looking into RS-485 support. I'm actually in the process of porting Zephyr to a board that requires RS-485 flow control.

As this isn't yet merged, I obviously can't use this as-is, but for now I'm looking to make a dummy "uart-controller" device which is itself a "uart-device" that can "sit over" an existing hardware UART and proxy the traffic through whilst handling the RS-485 handshaking.

A few questions though…

  1. I note there's only a rs485-de-gpios, but no rs485-re-gpios. I know nRE and DE can be wired together (and often are), but on low-power or multi-port devices, it's useful to completely shut down a RS-485 transceiver (that is; DE=low and nRE=high) to reduce its power consumption and to enable communication with another device on the UART. How does one specify that here?
  2. I note the assertion/de-assertion timings are given here as constants, wouldn't this normally be a function of the baud rate or is this in addition to it (i.e. the driver/device factors in the baud rate into the delays)?

@sjlongland
Copy link

Damn, thought Github would link the lines of the changeset I had highlighted, but it seems not… this is in relation to the following:

https://github.com/zephyrproject-rtos/zephyr/pull/80305/files/df5d4fc04dc38cfdf2d15ff67cfe116a13e7529b#diff-b382f07f645aeb233ddbcf912729db72978b32671c775134675a34b9a6ea3ae6R15-R36

Add support for configuring and enabling RS485 signaling by use
software method of pin control.

Signed-off-by: Sergey Grigorovich <[email protected]>

Signed-off-by: Nachiketa Kumar <[email protected]>

Signed-off-by: Antonio Tessarolo <[email protected]>
Copy link

Add support for configuring and enabling RS485 signaling by use
software method of pin control.

Signed-off-by: Sergey Grigorovich <[email protected]>

Signed-off-by: Nachiketa Kumar <[email protected]>

Signed-off-by: Antonio Tessarolo <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: Boards/SoCs area: Devicetree Bindings area: Devicetree area: DMA Direct Memory Access area: Samples Samples area: UART Universal Asynchronous Receiver-Transmitter platform: Infineon Infineon Technologies AG platform: Intel ADSP Intel Audio platforms platform: NXP Drivers NXP Semiconductors, drivers platform: Silabs Silicon Labs platform: STM32 ST Micro STM32

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants