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

drivers: serial: nrfx_uarte: Rework driver to support new features #78887

Merged
merged 3 commits into from
Oct 17, 2024

Conversation

nordic-krch
Copy link
Contributor

@nordic-krch nordic-krch commented Sep 23, 2024

Rework driver to support new way of asynchronous RX handling. Previously RX was handled in two modes: using RXDRDY interrupt for byte counting or TIMER + PPI. Both modes had flaws. RXDRDY interrupt mode could miscalculated amount of received bytes when interrupt was not handled on time. Data was not lost but was not reported on time that could lead to issues. PPI+TIMER mode requires additional resources thus it was not the default mode. Often user was not aware of that option and was expiriencing driver RX faults.

New RX mode is switching buffers when there is new data (RXDRDY event not set for given amount of time). It does not require additional resources to get precise byte counting. Additionally, this is in line with new UARTE feature (RX frame timeout) which is present in nRF54X devices. The behavior of the driver is the same for legacy devices and new one. For legacy devices k_timer periodic interrupts are used to check if there are any new bytes and it is not needed when RX frame
timeout is present.

Improved RX mode is enabled by default (CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y) but legacy modes are still
available though not recommended to be used.

Note that new RX mode behaves a bit different because timeout always triggers switch of buffers which means that there will be no UART_RX_RDY events with non-zero offset. It also means that every UART_RX_RDY will be followed by UART_RX_BUF_RELEASED.

After rework, driver is recommended to be used for all platforms as it performs much better and takes much less code than the second UART shim available for Nordic devices.

This PR is main part of #75462 which contains additional changes and significant changes in tests. It is created for ease of review as #75462 is overwhelming. It also contains #78886.

@nordic-krch nordic-krch force-pushed the nrfx_uarte_rework branch 2 times, most recently from 6279c82 to 863a6e2 Compare September 26, 2024 10:25
nordic-krch added a commit to nordic-krch/fw-nrfconnect-zephyr that referenced this pull request Oct 7, 2024
…struct pointer

Refactor RX asynchronous API function to use a pointer to the RX
async data structure instead of top level data structure pointer.
It improves readability with more concise code.

Upstream PR: zephyrproject-rtos/zephyr#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
nordic-krch added a commit to nordic-krch/fw-nrfconnect-zephyr that referenced this pull request Oct 7, 2024
…new features

Rework driver to support new way of asynchronous RX handling.
Previously RX was handled in two modes: using RXDRDY interrupt for byte
counting or TIMER + PPI. Both modes had flaws. RXDRDY interrupt mode
could miscalculated amount of received bytes when interrupt was not
handled on time. Data was not lost but was not reported on time that
could lead to issues. PPI+TIMER mode requires additional resources
thus it was not the default mode. Often user was not aware of that
option and was expiriencing driver RX faults.

New RX mode is switching buffers when there is new data (RXDRDY event
not set for given amount of time). It does not require additional
resources to get precise byte counting. Additionally, this is in line
with new UARTE feature (RX frame timeout) which is present in nRF54X
devices. The behavior of the driver is the same for legacy devices
and new one. For legacy devices k_timer periodic interrupts are used
to check if there are any new bytes and it is not needed when RX frame
timeout is present.

Improved RX mode is enabled by default
(CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y) but legacy modes are still
available though not recommended to be used.

Note that new RX mode behaves a bit different because timeout always
triggers switch of buffers which means that there will be no
UART_RX_RDY events with non-zero offset. It also means that every
UART_RX_RDY will be followed by UART_RX_BUF_RELEASED.

After rework, driver is recommended to be used for all platforms as it
performs much better and takes much less code than the second UART shim
available for Nordic devices.

Upstream PR: zephyrproject-rtos/zephyr#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
nordic-krch added a commit to nordic-krch/fw-nrfconnect-zephyr that referenced this pull request Oct 7, 2024
…eout

Frame timeout is a hardware feature present in newer versions
of UARTE (e.g. in NRF54X platforms) for detecting idle state
on RX line and ending RX after configurable timeout.

Upstream PR: zephyrproject-rtos/zephyr#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
nordic-krch added a commit to nordic-krch/zephyr that referenced this pull request Oct 8, 2024
…struct pointer

Refactor RX asynchronous API function to use a pointer to the RX
async data structure instead of top level data structure pointer.
It improves readability with more concise code.

Upstream PR: zephyrproject-rtos#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
nordic-krch added a commit to nordic-krch/zephyr that referenced this pull request Oct 8, 2024
…new features

Rework driver to support new way of asynchronous RX handling.
Previously RX was handled in two modes: using RXDRDY interrupt for byte
counting or TIMER + PPI. Both modes had flaws. RXDRDY interrupt mode
could miscalculated amount of received bytes when interrupt was not
handled on time. Data was not lost but was not reported on time that
could lead to issues. PPI+TIMER mode requires additional resources
thus it was not the default mode. Often user was not aware of that
option and was expiriencing driver RX faults.

New RX mode is switching buffers when there is new data (RXDRDY event
not set for given amount of time). It does not require additional
resources to get precise byte counting. Additionally, this is in line
with new UARTE feature (RX frame timeout) which is present in nRF54X
devices. The behavior of the driver is the same for legacy devices
and new one. For legacy devices k_timer periodic interrupts are used
to check if there are any new bytes and it is not needed when RX frame
timeout is present.

Improved RX mode is enabled by default
(CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y) but legacy modes are still
available though not recommended to be used.

Note that new RX mode behaves a bit different because timeout always
triggers switch of buffers which means that there will be no
UART_RX_RDY events with non-zero offset. It also means that every
UART_RX_RDY will be followed by UART_RX_BUF_RELEASED.

After rework, driver is recommended to be used for all platforms as it
performs much better and takes much less code than the second UART shim
available for Nordic devices.

Upstream PR: zephyrproject-rtos#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
nordic-krch added a commit to nordic-krch/zephyr that referenced this pull request Oct 8, 2024
…eout

Frame timeout is a hardware feature present in newer versions
of UARTE (e.g. in NRF54X platforms) for detecting idle state
on RX line and ending RX after configurable timeout.

Upstream PR: zephyrproject-rtos#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
nordic-krch added a commit to nordic-krch/fw-nrfconnect-zephyr that referenced this pull request Oct 9, 2024
…struct pointer

Refactor RX asynchronous API function to use a pointer to the RX
async data structure instead of top level data structure pointer.
It improves readability with more concise code.

Upstream PR: zephyrproject-rtos/zephyr#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
nordic-krch added a commit to nordic-krch/fw-nrfconnect-zephyr that referenced this pull request Oct 9, 2024
…new features

Rework driver to support new way of asynchronous RX handling.
Previously RX was handled in two modes: using RXDRDY interrupt for byte
counting or TIMER + PPI. Both modes had flaws. RXDRDY interrupt mode
could miscalculated amount of received bytes when interrupt was not
handled on time. Data was not lost but was not reported on time that
could lead to issues. PPI+TIMER mode requires additional resources
thus it was not the default mode. Often user was not aware of that
option and was expiriencing driver RX faults.

New RX mode is switching buffers when there is new data (RXDRDY event
not set for given amount of time). It does not require additional
resources to get precise byte counting. Additionally, this is in line
with new UARTE feature (RX frame timeout) which is present in nRF54X
devices. The behavior of the driver is the same for legacy devices
and new one. For legacy devices k_timer periodic interrupts are used
to check if there are any new bytes and it is not needed when RX frame
timeout is present.

Improved RX mode is enabled by default
(CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y) but legacy modes are still
available though not recommended to be used.

Note that new RX mode behaves a bit different because timeout always
triggers switch of buffers which means that there will be no
UART_RX_RDY events with non-zero offset. It also means that every
UART_RX_RDY will be followed by UART_RX_BUF_RELEASED.

After rework, driver is recommended to be used for all platforms as it
performs much better and takes much less code than the second UART shim
available for Nordic devices.

Upstream PR: zephyrproject-rtos/zephyr#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
nordic-krch added a commit to nordic-krch/fw-nrfconnect-zephyr that referenced this pull request Oct 9, 2024
…eout

Frame timeout is a hardware feature present in newer versions
of UARTE (e.g. in NRF54X platforms) for detecting idle state
on RX line and ending RX after configurable timeout.

Upstream PR: zephyrproject-rtos/zephyr#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
kl-cruz
kl-cruz previously approved these changes Oct 10, 2024
nordic-krch added a commit to nordic-krch/fw-nrfconnect-zephyr that referenced this pull request Oct 11, 2024
…struct pointer

Refactor RX asynchronous API function to use a pointer to the RX
async data structure instead of top level data structure pointer.
It improves readability with more concise code.

Upstream PR: zephyrproject-rtos/zephyr#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
nordic-krch added a commit to nordic-krch/fw-nrfconnect-zephyr that referenced this pull request Oct 11, 2024
…new features

Rework driver to support new way of asynchronous RX handling.
Previously RX was handled in two modes: using RXDRDY interrupt for byte
counting or TIMER + PPI. Both modes had flaws. RXDRDY interrupt mode
could miscalculated amount of received bytes when interrupt was not
handled on time. Data was not lost but was not reported on time that
could lead to issues. PPI+TIMER mode requires additional resources
thus it was not the default mode. Often user was not aware of that
option and was expiriencing driver RX faults.

New RX mode is switching buffers when there is new data (RXDRDY event
not set for given amount of time). It does not require additional
resources to get precise byte counting. Additionally, this is in line
with new UARTE feature (RX frame timeout) which is present in nRF54X
devices. The behavior of the driver is the same for legacy devices
and new one. For legacy devices k_timer periodic interrupts are used
to check if there are any new bytes and it is not needed when RX frame
timeout is present.

Improved RX mode is enabled by default
(CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y) but legacy modes are still
available though not recommended to be used.

Note that new RX mode behaves a bit different because timeout always
triggers switch of buffers which means that there will be no
UART_RX_RDY events with non-zero offset. It also means that every
UART_RX_RDY will be followed by UART_RX_BUF_RELEASED.

After rework, driver is recommended to be used for all platforms as it
performs much better and takes much less code than the second UART shim
available for Nordic devices.

Upstream PR: zephyrproject-rtos/zephyr#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
nordic-krch added a commit to nordic-krch/fw-nrfconnect-zephyr that referenced this pull request Oct 11, 2024
…eout

Frame timeout is a hardware feature present in newer versions
of UARTE (e.g. in NRF54X platforms) for detecting idle state
on RX line and ending RX after configurable timeout.

Upstream PR: zephyrproject-rtos/zephyr#78887

Signed-off-by: Krzysztof Chruściński <[email protected]>
@nordic-krch
Copy link
Contributor Author

@masz-nordic can you take a look?

masz-nordic
masz-nordic previously approved these changes Oct 14, 2024
uint32_t divisor = 1000000 / timeout;
uint32_t bauds = baudrate / divisor;

return MIN(bauds, UARTE_FRAMETIMEOUT_COUNTERTOP_Msk);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be replaced with HAL define in next nrfx release.

@nordic-krch
Copy link
Contributor Author

@dcpleung can you take a look?

drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
Refactor RX asynchronous API function to use a pointer to the RX
async data structure instead of top level data structure pointer.
It improves readability with more concise code.

Signed-off-by: Krzysztof Chruściński <[email protected]>
@nordic-krch nordic-krch force-pushed the nrfx_uarte_rework branch 4 times, most recently from 6288a6a to 812e4d8 Compare October 15, 2024 14:28
@nordic-krch
Copy link
Contributor Author

@anangl can you take a look? I've applied your comments.

drivers/serial/uart_nrfx_uarte.c Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
drivers/serial/uart_nrfx_uarte.c Outdated Show resolved Hide resolved
@nordic-krch
Copy link
Contributor Author

@anangl RX_TIMEOUT_DIV - 1 is used because otherwise uart_async_api test was failing as RX was not received after expected timeout where RX timeout was set to 50 ms and RX was arriving after 61ms (and test checks if it is within 60 ms). The reason is following. 50ms RX timeout so k_timer is set to 10ms. First timer is started when transmission starts, TX is only few bytes so it ends almost immediately. After 10ms first timeout expires and it detects RXDRDY so assumes active transmission. 10ms later RXDRDY is not set so counter is reset and if it will start counting to 5 then timeout will come in 60ms.

What would you suggest? Increase tolerance in the test?

which I think is true only when the hardware frame timeout is used.

It is true when CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y.

@nordic-krch
Copy link
Contributor Author

Regarding RX_TIMEOUT_DIV. Legacy behavior is the same.
When there are new bytes in rx_timeout handler data->async->rx.timeout_left is reset to the initial value:

data->async->rx.timeout_left = data->async->rx.timeout;

but in the same function later on it is decremented by the slab:
data->async->rx.timeout_left -=

So as the result it triggers RX_RDY after 4 timeouts without new bytes.

It added logging to uart_async_api test and it looks like this:

[00:00:00.408,081] <inf> test: tx done
[00:00:00.417,938] <err> uart_nrfx_uarte: new bytes 50000
[00:00:00.417,968] <err> uart_nrfx_uarte: decr left:40000
[00:00:00.427,947] <err> uart_nrfx_uarte: decr left:30000
[00:00:00.437,957] <err> uart_nrfx_uarte: decr left:20000
[00:00:00.447,967] <err> uart_nrfx_uarte: decr left:10000
[00:00:00.457,977] <err> uart_nrfx_uarte: decr left:0

New bytes is detected 9ms after end of TX (first timeout) but in the same timeout it is decremented for the first time. RX_RDY is triggered 49.9ms after TX_DONE.

@anangl
Copy link
Member

anangl commented Oct 17, 2024

@anangl RX_TIMEOUT_DIV - 1 is used because otherwise uart_async_api test was failing as RX was not received after expected timeout where RX timeout was set to 50 ms and RX was arriving after 61ms (and test checks if it is within 60 ms). The reason is following. 50ms RX timeout so k_timer is set to 10ms. First timer is started when transmission starts, TX is only few bytes so it ends almost immediately. After 10ms first timeout expires and it detects RXDRDY so assumes active transmission. 10ms later RXDRDY is not set so counter is reset and if it will start counting to 5 then timeout will come in 60ms.

What would you suggest? Increase tolerance in the test?

I would add a comment that since it is not known when exactly the RXDRDY event was triggered and in the worst case it could have been right at the beginning of the checked timeout part, timeout needs to be triggered at RX_TIMEOUT_DIV - 1, as it's better to trigger it a bit too early than too late (it's about passing the partially received data to user, not finishing the transfer). Just to clarify this for future, when some further improvements/correction will be done in this matter.

which I think is true only when the hardware frame timeout is used.

It is true when CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y.

Right, I got confused with those partial timeout checks. UART_RX_RDY is indeed generated only when the whole timeout expires, so when the buffer is switched in this case. Sorry for the noise.

Rework driver to support new way of asynchronous RX handling.
Previously RX was handled in two modes: using RXDRDY interrupt for byte
counting or TIMER + PPI. Both modes had flaws. RXDRDY interrupt mode
could miscalculated amount of received bytes when interrupt was not
handled on time. Data was not lost but was not reported on time that
could lead to issues. PPI+TIMER mode requires additional resources
thus it was not the default mode. Often user was not aware of that
option and was expiriencing driver RX faults.

New RX mode is switching buffers when there is new data (RXDRDY event
not set for given amount of time). It does not require additional
resources to get precise byte counting. Additionally, this is in line
with new UARTE feature (RX frame timeout) which is present in nRF54X
devices. The behavior of the driver is the same for legacy devices
and new one. For legacy devices k_timer periodic interrupts are used
to check if there are any new bytes and it is not needed when RX frame
timeout is present.

Improved RX mode is enabled by default
(CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y) but legacy modes are still
available though not recommended to be used.

Note that new RX mode (CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y) behaves
a bit different because timeout always triggers switch of buffers
which means that there will be no UART_RX_RDY events with non-zero
offset. It also means that every UART_RX_RDY will be followed by
UART_RX_BUF_RELEASED.

After rework, driver is recommended to be used for all platforms as it
performs much better and takes much less code than the second UART shim
available for Nordic devices.

Signed-off-by: Krzysztof Chruściński <[email protected]>
Frame timeout is a hardware feature present in newer versions
of UARTE (e.g. in NRF54X platforms) for detecting idle state
on RX line and ending RX after configurable timeout.

Signed-off-by: Krzysztof Chruściński <[email protected]>
@nordic-krch
Copy link
Contributor Author

Comment added.

@nashif nashif merged commit 1f96e62 into zephyrproject-rtos:main Oct 17, 2024
25 checks passed
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 platform: nRF Nordic nRFx
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants