-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Rs485 APIs support #80305
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
base: main
Are you sure you want to change the base?
Rs485 APIs support #80305
Conversation
Hello @2345lug, and thank you very much for your first pull request to the Zephyr project! |
17b5001
to
d2080d2
Compare
Hello! @dleach02 I need some advice regarding the RS485 API: |
drivers/serial/uart_stm32.c
Outdated
#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); | ||
} |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
zephyr/drivers/serial/uart_stm32.c
Lines 2028 to 2043 in 5f418f5
#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.
There was a problem hiding this comment.
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
zephyr/drivers/serial/uart_stm32.c
Lines 2028 to 2043 in 5f418f5
#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.
a74573e
to
01c4dba
Compare
_test_plan_partial.json removed from checked-in files.
drivers/serial/uart_stm32.c
Outdated
if (clock_control_get_rate(data->clock, (clock_control_subsys_t)&config->pclken[1], | ||
&clock_rate) < 0) { | ||
LOG_ERR("Failed call clock_control_get_rate(pclken[1])"); | ||
return; | ||
} | ||
} else { | ||
if (clock_control_get_rate(data->clock, | ||
(clock_control_subsys_t)&config->pclken[0], | ||
if (clock_control_get_rate(data->clock, (clock_control_subsys_t)&config->pclken[0], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't mix format changes and functional changes.
Make a dedicated commit if for format changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I'd actually suggest to drop the format changes as the don't add anything.
Note that if you rebase on top of main, you'll see that they are not suggested anymore
drivers/serial/uart_stm32.c
Outdated
|
||
static int uart_stm32_fifo_fill_visitor(const struct device *dev, const void *tx_data, int size, | ||
fifo_fill_fn fill_fn) | ||
{ | ||
const struct uart_stm32_config *config = dev->config; | ||
USART_TypeDef *usart = config->usart; | ||
int num_tx = 0U; | ||
uint8_t num_tx = 0U; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not linked to RS485. Please make it a dedicated commit.
drivers/serial/uart_stm32.c
Outdated
if (config->de_enable) { | ||
gpio_pin_set(config->de_pin.port, config->de_pin.pin, config->de_invert); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned, DE pins configurations (using alternate functions) are already available and RS485 support should not imply use of GPIO.
If you don't want to make use of built-in RS485 support (for which actually, I don't see specific interest), this should be protected under a dedicated flag as a SW implementation.
There was a problem hiding this comment.
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 the advice! I just don’t understand one point. My implementation is intended for cases where the device does not have hardware support for RS485. In the case of STM, this is already checked by "HAS_DRIVER_ENABLE." Maybe it’s not what I think?
drivers/serial/uart_stm32.c
Outdated
if (config->de_enable) { | ||
if (config->de_deassert_time_us) { | ||
k_timer_start(&data->rs485_timer, K_USEC(config->de_deassert_time_us), | ||
K_NO_WAIT); | ||
} else { | ||
gpio_pin_set(config->de_pin.port, config->de_pin.pin, !config->de_invert); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above comment for dedicated flag as a SW implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@erwango Good afternoon! I think I've taken the current feedback into account. Could you please advise how this idea could be further improved or optimized? Thanks in advance!
1e68707
to
f5477f2
Compare
c7ec712
to
bc56492
Compare
rs485-de-gpios: | ||
type: phandle-array | ||
description: Output for contactor and relay 1 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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).
drivers/serial/uart_stm32.c
Outdated
|
||
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) |
There was a problem hiding this comment.
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.
dcc2cb5
to
fa54683
Compare
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]>
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.