Skip to content
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

uart: update meaning of uart_irq_tx_ready return code #70939

Merged
merged 4 commits into from
Oct 2, 2024

Conversation

JordanYates
Copy link
Collaborator

@JordanYates JordanYates commented Apr 1, 2024

Update the documented value range that uart_irq_tx_ready returns in
order to provide more information to the callers about the number of
bytes that could be written with uart_fifo_fill without fragmentation.

Does not break any current users of the API, unless they are explicitly checking for uart_irq_tx_ready() == 1.
Other UART drivers can be updated in the future without violating the API documentation.

Implements #70937.

@JordanYates JordanYates requested a review from anangl as a code owner April 1, 2024 06:02
@JordanYates
Copy link
Collaborator Author

Looking for initial feedback on approach before going through stable API change process

@zephyrbot zephyrbot added platform: nRF Nordic nRFx area: UART Universal Asynchronous Receiver-Transmitter area: USB Universal Serial Bus labels Apr 1, 2024
@dcpleung
Copy link
Member

dcpleung commented Apr 1, 2024

Part of me thinks that the term "ready" is a boolean entity: whether it is ready or not (and in this case if there are any errors). So I think a new API can be introduced in this case to return number of bytes that can be transmitted. uart_irq_tx_ready can then use this API to return true or false. Impact to applications would be limited as this does not change the nature of uart_irq_tx_ready. If you can convert all the drivers to use the new API, you can remove the . element in the driver API struct so there is no impact of wasted space regarding to the API struct. However, this will affect any downstream projects with out of tree drivers.

tmon-nordic
tmon-nordic previously approved these changes Apr 8, 2024
Copy link
Contributor

@tmon-nordic tmon-nordic left a comment

Choose a reason for hiding this comment

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

Looks fine to me, my only concern is about the potential race conditions. What guarantees that there is no concurrent call from other context to uart_fifo_fill() in between uart_irq_tx_ready() and the uart_fifo_fill() using output from uart_irq_tx_ready()?

@JordanYates
Copy link
Collaborator Author

Looks fine to me, my only concern is about the potential race conditions. What guarantees that there is no concurrent call from other context to uart_fifo_fill() in between uart_irq_tx_ready() and the uart_fifo_fill() using output from uart_irq_tx_ready()?

All of these functions are only valid to call inside the interrupt context (triggered by uart_irq_tx_enable), other uses are already specified as undefined behaviour.

@tmon-nordic
Copy link
Contributor

Looks fine to me, my only concern is about the potential race conditions. What guarantees that there is no concurrent call from other context to uart_fifo_fill() in between uart_irq_tx_ready() and the uart_fifo_fill() using output from uart_irq_tx_ready()?

All of these functions are only valid to call inside the interrupt context (triggered by uart_irq_tx_enable), other uses are already specified as undefined behaviour.

What about SMP?

@JordanYates
Copy link
Collaborator Author

Looks fine to me, my only concern is about the potential race conditions. What guarantees that there is no concurrent call from other context to uart_fifo_fill() in between uart_irq_tx_ready() and the uart_fifo_fill() using output from uart_irq_tx_ready()?

All of these functions are only valid to call inside the interrupt context (triggered by uart_irq_tx_enable), other uses are already specified as undefined behaviour.

What about SMP?

Great question, I have no idea. This is not really any different from the current situation though. uart_irq_tx_ready could return 1 to indicate the device is ready to accept more data and then a second core swoops in and makes it not ready.

My suspicion is that the API is not really designed to handle SMP, as the requirement for all operations to be run from an interrupt context sounds like a band-aid to avoid multi-threading issues.

Does the situation of multiple cores trying to access/modify/control a single hardware peripheral even make sense though? That sounds like a recipe for disaster no matter what we do at an API level, short of wrapping everything in mutexes or spinlocks.

@tmon-nordic
Copy link
Contributor

Great question, I have no idea. This is not really any different from the current situation though.

Yes, it is not different from the current situation and this is why I did approve this PR despite this concern.

Does the situation of multiple cores trying to access/modify/control a single hardware peripheral even make sense though? That sounds like a recipe for disaster no matter what we do at an API level, short of wrapping everything in mutexes or spinlocks.

The only case in my mind would be that the interrupt itself is handled by multiple cores. My concern is about the SMP where the interrupt handling can end up in any core, not the heterogeneous multicore systems where there it seems to be out of scope.

On SMP, I believe this can be handled by using spinlocks instead of irq locking, but I don't currently work on any SMP-capable Zephyr target.

@jfischer-no
Copy link
Collaborator

Does not break any current users of the API, unless they are explicitly checking for uart_irq_tx_ready() == 1.
Other UART drivers can be updated in the future without violating the API documentation.

I suggest at least mentioning it in the migration guide.

jfischer-no
jfischer-no previously approved these changes Apr 10, 2024
Copy link
Collaborator

@jfischer-no jfischer-no left a comment

Choose a reason for hiding this comment

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

USB LGTM

NRF_UART_INT_MASK_TXDRDY) &&
!disable_tx_irq &&
event_txdrdy_check();
return ready ? INT_MAX : 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't 1 be returned instead of INT_MAX?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

uart_nrfx_fifo_fill will accept any length buffer without truncating it


return (data->flags & A2I_TX_IRQ_ENABLED) && !(data->flags & A2I_TX_BUSY);
/* async API handles arbitrary sizes */
return ready ? INT_MAX : 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

data->tx.len contains TX buffer size so it should be returned instead of INT_MAX.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah, I thought it was the length of the currently sending buffer, will fix

jfischer-no
jfischer-no previously approved these changes May 28, 2024
@dcpleung dcpleung added the Breaking API Change Breaking changes to stable, public APIs label May 28, 2024
@zephyrbot zephyrbot requested review from kartben and nashif July 29, 2024 09:30
@github-actions github-actions bot removed the Stale label Jul 30, 2024
Copy link

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the Stale label Sep 28, 2024
Update the documented value range that `uart_irq_tx_ready` returns in
order to provide more information to the callers about the number of
bytes that could be writted with `uart_fifo_fill` without fragmentation.

Signed-off-by: Jordan Yates <jordan@embeint.com>
Update the interrupt driver UART drivers that use `struct ring_buf`
internally to report the number of bytes that can be pushed in
`uart_fifo_fill` without fragmentation.

Signed-off-by: Jordan Yates <jordan@embeint.com>
The async IRQ shim supports writes of any size up to the TX buffer size.

Signed-off-by: Jordan Yates <jordan@embeint.com>
tmon-nordic
tmon-nordic previously approved these changes Sep 30, 2024
dcpleung
dcpleung previously approved these changes Sep 30, 2024
dkalowsk
dkalowsk previously approved these changes Sep 30, 2024
Copy link
Contributor

@dkalowsk dkalowsk left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks for the clear migration guide addition!

nordic-krch
nordic-krch previously approved these changes Oct 1, 2024
drivers/serial/uart_nrfx_uart.c Outdated Show resolved Hide resolved
Update nrfx drivers with the minimum number of bytes that can be sent
in a single call to `uart_fifo_fill`.

Signed-off-by: Jordan Yates <jordan@embeint.com>
@aescolar aescolar merged commit 0425b04 into zephyrproject-rtos:main Oct 2, 2024
25 checks passed
@JordanYates JordanYates deleted the 240401_uart_interrupt branch October 2, 2024 09:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: UART Universal Asynchronous Receiver-Transmitter area: USB Universal Serial Bus Breaking API Change Breaking changes to stable, public APIs platform: nRF Nordic nRFx Release Notes To be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants