Skip to content

Nuvoton M480: Aborting a DMA SPI transfer corrupts the next transfer #466

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

Open
multiplemonomials opened this issue May 26, 2025 · 1 comment
Labels
Bug Dis is broken

Comments

@multiplemonomials
Copy link
Collaborator

Seeing the following test failure with the CI shield on M480:

: [+33151ms][CONN][RXD] >>> Running case #32: 'Queueing and Aborting Async SPI via DMA'...
8: [+33162ms][CONN][INF] found KV pair in stream: {{__testcase_start;Queueing and Aborting Async SPI via DMA}}, queued...
8: [+33162ms][CONN][INF] found KV pair in stream: {{start_recording_spi;please}}, queued...
8: [+34217ms][SERI][TXD] {{start_recording_spi;complete}}
8: [+34247ms][CONN][RXD] <greentea test suite>:486::FAIL: Expected 0 Was 4
8: [+34257ms][CONN][INF] found KV pair in stream: {{verify_queue_and_abort_test;please}}, queued...
8: [+34285ms][TEST][INF] Saw on the SPI bus: [mosi: b'0102000000000000000000000000000000000000000000000000000000000000afafafaf080402010201080401020408ff', miso: b'0102000000000000000000000000000000000000000000000000000000000000afafafaf080402010201080401020408ff']
8: [+34285ms][TEST][ERR] Incorrect MOSI data for queue and abort test
8: [+34288ms][SERI][TXD] {{verify_queue_and_abort_test;fail}}
8: [+34299ms][CONN][INF] found KV pair in stream: {{__testcase_finish;Queueing and Aborting Async SPI via DMA;0;1}}, queued...
8: [+34309ms][CONN][RXD] >>> 'Queueing and Aborting Async SPI via DMA': 0 passed, 1 failed with reason 'Test Cases Failed'

Basically, when we abort a DMA SPI transfer partway through and then do another transfer, it keeps the previous source address (halfway through the first transfer buffer) instead of using the new source address. So, the wrong data will get sent (and probably received as well).

I spent around an hour investigating this, and it seems like the Nuvoton PDMA peripheral has some sort of internal state that isn't properly being reset after the first transfer is aborted. The datasheet makes a few mentions of how DMA descriptors aren't loaded until the previous descriptor is "complete":

Note: Before filling new transfer task in the Descriptor Table, user must check the PDMA_INTSTS[1] to make sure the current task is complete. (from the PDMA_DSCTn_CTL.OPMODE register description)

I think what's happening is that because we disable the DMA channel in spi_abort_asynch(), the transfer never completes, so it can't load the new DMA descriptor when we try to do the next transfer.

Unfortunately, I wasn't able to find any information in the documentation on how to fix this issue. There is a "channel reset" register, but using it didn't seem to fix the issue, and also there's an errata saying it can corrupt other concurrently executing DMA channels if they aren't paused first. So, I think more information will be needed from Nuvoton before we can make any progress on this.

@multiplemonomials multiplemonomials added the Bug Dis is broken label May 26, 2025
@multiplemonomials
Copy link
Collaborator Author

Note: Somehow this error only reproduces in Develop build configuration. It works correctly in Debug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Dis is broken
Projects
None yet
Development

No branches or pull requests

1 participant