-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
fix bugs in mcux i2s and dma #59832
fix bugs in mcux i2s and dma #59832
Conversation
@hakehuang can you run a regression test on RT595 |
the existing testcases i2s_speed can not catch such issue, as I can run pass with i2s_speed test with(zephyr-v3.4.0-976-ge17597821848)/without(zephyr-v3.4.0-974-g7fba7d39575) this fixes
|
* for source and dest. So assert that the source | ||
* and dest sizes are the same. | ||
*/ | ||
assert(config->dest_data_size == config->source_data_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.
This assert may cause failures in some of the other drivers that use this driver. I would suggest removing it and updating the 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.
If the caller has the dest_data_size == source_data_size, then the assert won't trip, and it won't trip if asserts are not enabled.
If the caller has different values for src and dest sizes, then it's a problem they need to think about and fix.
The old driver (prior to the change to support chaining for long transfers) used MIN. The driver
that supports the long transfers used MAX. This changing of behavior already broke existing drivers silently (e.g. the I2S usage). I think it'd be better to detect such problems as soon as possible, instead of silently doing something they might not be expecting and possibly setting the size the opposite of what the caller intended.
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 know we will have to update the SPI driver to address this. Let me know if you would like me to send you a patch.
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 can add that. I thought I had checked the SPI driver, since we use that too, but I think we didn't catch it because our usage of SPI is always using 1-byte dest_data_size (src_data_size is fixed at 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 think also the UART driver will be fine because destination and source data sizes will both be 1 always
@@ -492,6 +498,9 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, | |||
dst_inc, | |||
block_config->block_size); | |||
} | |||
/* DMA controller requires that the address be aligned to transfer 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.
I am not aware of such a alignment requirement. Were you seeing an issue?
There is a requirement for the DMA descriptors which this driver addresses.
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.
In the RT500 Reference Manual, section 16.4.2.4 says:
16.4.2.4 Address alignment for data transfers
Transfers of 16 bit width require an address alignment to a multiple of 2 bytes. Transfers of 32 bit width require an address alignment to a multiple of 4 bytes. Transfers of 8 bit width can be at any address
@@ -19,7 +19,7 @@ | |||
|
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.
Ideally you should add only one patch per issue addressed. This way the code would be much easier to understand and review.
There are exceptions if the changes are tightly related. Not sure if this the case.
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.
The primary bug is the change/regression in the DMA driver. But the fix to the DMA driver includes an assert, which is there to prevent future mistakes from happening silently. That assert would immediately break the I2S driver, which is why the two commits are combined in this PR.
I could take out the I2S one, but it would have to be merged first. I'm still relatively new to Zephyr (and github) development so I don't know if pull requests can be dependent on one another. Let me know if there's still a preference in having the I2S change be a separate Pull Request.
Fix for bugs described in: zephyrproject-rtos#59803 1. the size argument passed to i2s_write() was being ignored. change the code so that the size is queued with the tx mem_block and the dma transfer is configured with this size. 2. change how CONFIG_I2S_MCUX_FLEXCOMM_RX_BLOCK_COUNT and CONFIG_I2S_MCUX_FLEXCOMM_TX_BLOCK_COUNT are used so that the queue buffers are allocated correctly when the two config values are not the same 3. set source_data_size and dest_data_size to be the same since the DMA controller can only set one size per DMA transfer. the driver was already computing a dest_data_size but always passing 1 for the source_data_size. For I2S RX case, I think source_data_size should be set to the expected FIFO read size instead of dest_data_size. Also some smaller improvements like: * don't allocate two dma_blocks for tx in the static dev_mem when it only needs one * memset both rx_dma_blocks together instead of separtely * set dma_cfg block_count for tx and rx statically instead of at runtime Signed-off-by: Mike J. Chen <[email protected]>
@mjchen0. Thank you for submitting the PR. The changes look fine to me. Could you help fix the CI compliance failures. |
The MCUX DMA controller only supports a single data_size for a DMA transfer, not separate ones for source and dest. An older version of the DMA driver used dest_data_size as the DMA transfer size, but the current one uses MIN(dest/source) as the trasnfer size, which breaks case when SPI wants to do 2-byte transfers. Signed-off-by: Mike J. Chen <[email protected]>
Fix for bug: zephyrproject-rtos#59802 The DMA controller only supports one transfer size, but the Zephyr DMA driver api allows specifying a source_data_size and dest_data_size which might be different. An old version was always using dest_data_size for the transfer size (variable is called "width"), but a recent change made the driver use the MIN for the source and dest data sizes. The MIN choice breaks the I2S driver because it always set source_data_size to 1, but dest_data_size was typically 4 for like two-channel 16-bit PCM data. So the old driver worked using dest_data_size, but the new driver broke I2S using MIN since source_data_size was 1. To prevent confusion, change the DMA driver to assert that source_data_size and dest_data_size are the same. Also assert that the source_address and dest_address for each block_config are properly aligned for the transfer size, since that is a documentated requirement for the DMA controller. Also rename max_xfer to max_xfer-bytes to be more clear what the units are, and use this value in many places that are comparing block_size in bytes rather than converting block_size to words by dividing by width and then comparing to NXP_LPC_DMA_MAX_XFER. Signed-off-by: Mike J. Chen <[email protected]>
Fixes #59802
Fixes #59803