-
Notifications
You must be signed in to change notification settings - Fork 8.3k
eDMA loop sg mode and I2S LPUART driver #80584
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
eDMA loop sg mode and I2S LPUART driver #80584
Conversation
|
Hello @Raymond0225, and thank you very much for your first pull request to the Zephyr project! |
|
For the LPUART driver, in our real-life application, we tested the proposed solution and noticed an instability. It depends on the TCD queue size. When a certain amount "x" of buffers is consumed and the next buffer should be used, the LPUART or DMA simply stops. CONFIG_DMA_TCD_QUEUE_SIZE=2 gave 4 working buffer updates And although it seems a bit random, I tried each value at least 5 times and every time exact the same amount, although the uart input was random (at 1mbit/s in this case). CONFIG_DMA_TCD_QUEUE_SIZE=1 actually gave the most stable result, and it looks like your initializing more buffers than needed at: zephyr/drivers/dma/dma_mcux_edma.c:391 I hope this rings a bell... |
|
Possibly silly question, does a similar issue apply to the lpspi implementation? I've been having a lot of trouble getting that writing properly with dma too. In my case I'm seeing junk data coming out the spi when using it with dma channels configured |
drivers/serial/uart_mcux_lpuart.c
Outdated
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.
why remove this, yo actually change the rx_dma_params
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 did not change it. next_rx_buffer is a member of data->async
drivers/serial/uart_mcux_lpuart.c
Outdated
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.
you code indent is wrong should be 8
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.
thanks, I will reformat all the related indent and whitespaces.
|
Hi @Raymond0225 , Thanks |
|
Hi @matt-wood-ct ,
These changes address an issue with the scatter/gather implementation in the eDMA driver, which is not used by the LPSPI driver. So this PR does not impact the LPSPI driver. |
thanks Derek. I wrote the code for DMA V4 based on an old version. I will update the code based on your modifications. |
Thanks for your feedback. I don't understand what you said. I do use all TCDs and linked them together. Can you elaborate how to reproduce the "stops" issue you mentioned here? |
|
@Raymond0225 please clean up the file changes to remove the spaces at beginning of lines. The Zephyr coding standard is to use tabs. |
thanks. I am cleaning up the code, will update the PR later. |
We are building a uart to usb bridge, similar to the usb example. As we need to switch both the DTR and baud rate in real-time, we're using the next-gen usb driver (and have made some fixes for it to make it more robust). Concerning the Rx and TCDs: Concerning the Tx side: Concerning switching the baudrate: Perhaps we could take this discussion offline / beyond this github issue / pull-request. |
drivers/dma/dma_mcux_edma.c
Outdated
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 squash this commit with the earlier commit that changes this file.
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.
thanks for your feedback. I am not familiar with git commands, I will try to it.
thanks for your feedback. I suggest you have a look at the the test code of uart_async_api test case, there is a function "test_double_buffer" which may be close to your use case. block_count is only valid during DMA configuration. I suggest you set it as 1. after that, each time when driver request user rx buffer, callback function will be triggered. Driver would not ask for new buffer until current rx buffer is filled fully. There may be multi rx ready event between 2 buf requests. |
I've ran the proposed tests. The test succeeds only when using the TCM regions for the buffers. Is this mandatory? Tx seems to be working now, by moving "uart_tx(..)" to a work task instead of directly in the callback. This is aparently not allowed. (perhaps something to add to the documentation) Switching baudrate at runtime while DMA is active is still a challenge. Not sure what is actually failing (the dma buffers or the uart settings). Using the fifo api switching baudrate works well. |
|
@Raymond0225 , I rebase you pr to the latest zephyr code. and test on mimxrt1170_evk_cm7 it fails as below log scripts/twister --device-testing --device-serial /dev/ttyACM0 -T tests/drivers/uart/uart_async_api/ last commit after rebase ''' |
|
Hi @SynchronicIT ,
The buffers used by the DMA need to be in non-cached memory, otherwise there may be a cache coherency issue. The TCMs are not cached, which is one option for the buffers. Another option is to use slower memories like external SDRAM or internal OCRAM, but the buffers need to be placed in a
Your use-case to dynamically change the baud rate is beyond the scope of this PR. You can create a GitHub Discussion for that separate topic. Thanks for your feedback with this PR. |
Thanks Hake. I got same error when I try to put TCD pool to DTCM. it is because some fields inside edma_tcd_t is not initialized. |
drivers/dma/dma_mcux_edma.c
Outdated
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.
Are we using write_idx here before we initialize it? Also, do we need to initialize tcd here at all?
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.
no, we don't need initialize tcd here, this line is a typo, I will correct it. thanks
drivers/dma/dma_mcux_edma.c
Outdated
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.
Should we have a check here to see if write_idx == CONFIG_DMA_TCD_QUEUE_SIZE? If we still have blocks to queue at that point, I think we should return an error to the user indicating that they need to raise CONFIG_DMA_TCD_QUEUE_SIZE.
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.
good idea
DerekSnell
left a comment
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.
Hi @Raymond0225 ,
Thank you for all your hard work with these fixes.
I am only blocking this to see your updates to i2s_mcux_sai.c with the loop SG support.
Otherwise, I see no issues with your updates. I do think we can improve with comments to help understand how your eDMA driver works, and provided some comments for you to review.
Also, regarding this note in your commit message:
please set CONFIG_TEST_USERSPACE=n when you do test on RT1170 EVK or
you will get "write access denied" issue. It is another issue not related to LPUART and eDMA drivers.
It's good to include that detail in the PR description (and I see it is already there), so others are aware how to replicate your test. But I would not include in the commit message. Over time, that CONFIG_TEST_USERSPACE=n may no longer apply.
And for the PR description, I would point out the CONFIG_TEST_USERSPACE=n requirement is specifically for the uart_async_api test. The drivers in this PR are not impacted by that Kconfig, but the test app for the LPUART driver will fail today with userspace enabled.
Thanks
212fb78 to
9710450
Compare
thanks, have done |
Pending length should be mainloop count multiply NBYTES of minor loops. Signed-off-by: Raymond Lei <[email protected]>
Existing dynamic SG mode have some issues which cause uart sync api and I2S speed test failed. These issues are: a wrong "Done" bit issue found on UART async api test. An invalid destination address issue found on I2S speed test. By introducing loop SG mode, these issues are all fixed. Some data structures are different between eDMA and eDMA V4, use different macros defined in SDK driver for each of them. Signed-off-by: Raymond Lei <[email protected]>
I2S speed test failed because of "Invalid destination address" issue By use eDMA loop SG mode, this issue is fixed. Fixes: zephyrproject-rtos#70777 Signed-off-by: Raymond Lei <[email protected]>
New implemented eDMA loop SG mode can be used to lpuart driver to fix the conflict of "Done" bit issue which cause uart_async_api test failed when SG mode is enabled. Also, this loop SG mode works well even with a high bandrate(test done on 2000000bps). Fixes: zephyrproject-rtos#78291 Signed-off-by: Raymond Lei <[email protected]>
To reduce the latency of CPU accessing/modifying SW TCD content, it better to put TCD pool to DTCM by default. Signed-off-by: Raymond Lei <[email protected]>
2629163 to
5848889
Compare
DerekSnell
left a comment
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.
Great work, @Raymond0225 . Thanks for all your hard work with this.
danieldegrasse
left a comment
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.
A few minor (nonblocking) nits, overall change looks good to me though. Thanks for your work here!
| if (DEV_CHANNEL_DATA(dev, channel)->busy) { | ||
| status->busy = true; | ||
| /* Be aware that here we need multiply NBYTES for each minor loops */ | ||
| /* pending_length is in bytes. Multiply remaining major loop |
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.
This change should be in prior commit
| EDMA_ClearChannelStatusFlags(DEV_BASE(dev), channel, kEDMA_DoneFlag); | ||
| EDMA_HW_TCD_CSR(dev, channel) |= DMA_CSR_ESG_MASK; | ||
| #elif (CONFIG_DMA_MCUX_EDMA_V3 || CONFIG_DMA_MCUX_EDMA_V4) | ||
| /*We have not verified if this issue exist on V3/V4 HW, jut place a holder here. */ |
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.
| /*We have not verified if this issue exist on V3/V4 HW, jut place a holder here. */ | |
| /*We have not verified if this issue exist on V3/V4 HW, just place a holder here. */ |
|
This PR breaks SAI driver when used with MIMXRT1170_EVK setup as edma error occurs after first transfer. |
|
Hi @RadekPolyend , Can you share more details how to replicate the issue you are seeing? I recommend creating a new Issue, and adding details there to replicate and understand the root cause. You can link that issue to this PR. Thanks for raising this. Best regards |
|
Ok but the test doesn't seem to assume the reload of the tx buffers after the start trigger, it just drains the buffers which were loaded before the trigger. The "real" use case is when data are constantly delivered to the queue once the previous ones are returned. Normal use case is when you have only two buffers, you deliver two buffers first, than start trigger and wait for the first buffer to be returned to slab than fill it and write again and this cycle is repeated all the time. I can see there is long version of the test but it still does not rely on buffers returned to slab. I will provide more details soon. |
This patch is addressing these issues:
Fixes #58888
Fixes #70777
Fixes #78291
Tests done:
I2S speed test on RT1170 EVK
uart async api test on RT1170 EVK with bandrate 115200, 1000000 and 2000000bps
Note that:
Please set CONFIG_TEST_USERSPACE=n when you do test on RT1170 EVK or
you will get "write access denied" issue. It is another issue not
related to LPUART and eDMA drivers.