-
Notifications
You must be signed in to change notification settings - Fork 7.4k
DMA: stm32f4: Extend meaning of DMA return value #14809
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #14809 +/- ##
=======================================
Coverage 52.49% 52.49%
=======================================
Files 309 309
Lines 45060 45060
Branches 10431 10431
=======================================
Hits 23656 23656
Misses 16592 16592
Partials 4812 4812 Continue to review full report at Codecov.
|
@@ -151,7 +151,7 @@ struct dma_config { | |||
struct dma_block_config *head_block; | |||
void *callback_arg; | |||
void (*dma_callback)(void *callback_arg, u32_t channel, | |||
int error_code); | |||
int ret_code); |
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 is not compliant with current DMA API:
* dma_callback is the callback function pointer. If enabled, callback function
* will be invoked at transfer completion or when error happens
* (error_code: zero-transfer success, non zero-error happens).
I'm not opposed to the change, but it would require dma API alignment
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.
Ho, I missed that sorry, should not start review before coffee.
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 means that all code using the STM32F4 DMA (I2S driver for example) must be changed as well.
Shouldn't be part of the PR as well?
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 noticed that you change the dma_callback() signature here, but not in "struct dma_stm32_stream" in c file.
I guess you should do that as well.
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.
@erwango do you notice that I’ve changed the api comments as well to make both consistent?
@@ -130,7 +130,7 @@ struct dma_block_config { | |||
* | |||
* dma_callback is the callback function pointer. If enabled, callback function | |||
* will be invoked at transfer completion or when error happens | |||
* (error_code: zero-transfer success, non zero-error happens). | |||
* (ret_code: non negative-transfer success, nenative-error happens). | |||
*/ |
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.
pls fix this typo: 'nenative' into 'negative'.
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've rewritten the comments again to minimize the affect of the changes: define non-zero return value as the one defined by a specific driver since some DMA drivers give positive values as errors as well. As for STM32 DMA, let's define negative as errors, and positive as how many bytes RX DMA has received.
@@ -151,7 +151,7 @@ struct dma_config { | |||
struct dma_block_config *head_block; | |||
void *callback_arg; | |||
void (*dma_callback)(void *callback_arg, u32_t channel, | |||
int error_code); | |||
int ret_code); |
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 means that all code using the STM32F4 DMA (I2S driver for example) must be changed as well.
Shouldn't be part of the PR as well?
Extend the meaning of DMA return value which is fed to user's callback function so that the meaning of non-zero value will be defined by a specific DMA driver, for example, error happens when negative, and how many bytes RX DMA has received when positive. Signed-off-by: Jun Li <[email protected]>
The return value to the callback function is extended to not only represent successful DMA transfer but also how many bytes received for RX DMA cases. And reduced one time wait delay to 50ms and abort after 5 seconds in total when disabling DMA. Signed-off-by: Jun Li <[email protected]>
err_code is redefined as ret_code and it's an error code only when ret_code is negative. Signed-off-by: Jun Li <[email protected]>
@avisconti changed STM32 I2S driver to correspond to the redefinition of the return value. |
@avisconti Hey do you have more comments to the changes? Thanks! |
@cybertale |
Interesting work, but I'm wondering shouldn't we change all dma usage in zephyr's tree since we are changing the api? |
It is only the meaning of the DMA callback variable that is extended so that a SoC's DMA driver will have flexibility to redefine it. However, I'm not sure if other DMA drivers of other SoCs could define the positive return value with the meanings similar to STM32's. This is why the changes to DMA clients is only limited to those of STM32's. |
Hey @cybertale I've just read your PR #13364 for implementing a general DMA driver for STM32 SoCs, nice job! |
Understood. My worry is that for application users, portability of code snippets is going low. What I want to say is that maybe we should make this api change a standalone PR and make it consistent to all the drivers? |
Sure! I added circular mode support but removed it after. That's because I thought circular mode is not suitable for zephyr's api. Since that you want it I can add support for it. But is 'pending' a new api in dma.h? I think api changes should take a bit more time than normal driver changes, right? |
The issue I'm facing on implementing UART RX via DMA is that the DMA buffer could not be filled or half filled up to trigger the interrupt when a message with varying length comes from the peer. In that case, the RX transaction is defined by UART's IDLE interrupt. However, when UART IDLE interrupt happens, UART has no way to figure out how much data UART RX has received. This is why I think we need a new API for DMA's clients to figure out how much data is still pending to be sent or received. |
@jli157 I got it, so in your case we receive unknown long data and when the UART IDLE happened, we ask the DMA how many bytes left to be transfered to know how many bytes has already been received(or transmitted but I think we can easily know how many has been transmitted?). So you don't need DMA interrupts to tell you when to end but for just to alert you when the buffer is full. |
@avisconti @cybertale @erwango The changes in this PR seem not be necessary if we can add one more DMA API function |
@jli157 I agree with the standalone api PR idea, which should make the api changes logically standalone. While this is just my thought, decisions are reviewers to make. Let's see what do they think about this. |
This PR still can't thoroughly address the requirement for querying how many bytes are still left in a specific DMA transaction which is needed by UART RX. So, this one will be closed and another PR will be created to address the requirement. Thanks all for your comments! |
@jli157 Hi, still I have some doubts about this kind of usage. In this scenario, IDLE event happened, then we query through pending() and read data/reset DMA(Or do not reset?). But Zephyr is slow in many situations, so when the UART is fast, new data may come between IDLE event and pending(). If so, we may retrieve data when UART is receiving rather than idle, and if we reset DMA after reading, there is a risk that data may be lost. But if we do not reset DMA, unread data can be read in next read process, while buffer of DMA is limited so memory address will keep increasing and there's also a potential data lost and illegle memory access. Reset DMA means reset it's memory pointer here. Hope you understand what I'm thinking, just some thoughts as an advice! |
I like the idea. I think it would be cleaner adding a new API function rather than changing an existing one which may bring undesirable effects on existing drivers. |
The use case where the IDLE interrupt works actually doesn't reset DMA at all. when the IDLE interrupt happens, only the incremental part of the data between two read operations will be read out, and the buffer is configured as a circular buffer to avoid overflow. You can take a look at my implementation on PR #14916 which is already working well. This is why I'm asking you to add the capability of enabling circular buffer mode. |
@jli157 You're right, that explains everything! 😄 |
Extend the meaning of DMA return value which is fed to user's callback function so that the meaning of non-zero return value will be defined by a specific DMA driver.
Specific to STM32's DMA driver, redefine the return value so that zero means DMA transfer is successful; positive means not only a successful DMA transfer but also how many bytes received for RX DMA cases; negative still means DMA error. Accordingly, updated STM32's I2S driver to correspond to the change.
The PR also fixes a waiting issue in STM32's DMA driver by reducing one time wait delay to 50ms and aborting after 5 seconds in total when disabling DMA.
The PR tries to be the first step for addressing the issue #13955.