-
Notifications
You must be signed in to change notification settings - Fork 6.7k
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: nrf: Fix nrf uarte fifo_fill function. #11475
drivers: nrf: Fix nrf uarte fifo_fill function. #11475
Conversation
Calling fifo_fill function from uart_nrfx_uarte in the same interrupt more than once, would break previous transmission. Following fix adds checking if previous data was sent, and if not, returns 0. Signed-off-by: Mieszko Mierunski <[email protected]>
Codecov Report
@@ Coverage Diff @@
## master #11475 +/- ##
=======================================
Coverage 48.37% 48.37%
=======================================
Files 270 270
Lines 42080 42080
Branches 10132 10132
=======================================
Hits 20358 20358
Misses 17645 17645
Partials 4077 4077 Continue to review full report at Codecov.
|
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 include a case when user uses fifo fill
and disable interrupts. In current implementation data will not be sent correctly.
drivers/serial/uart_nrfx_uarte.c
Outdated
@@ -70,6 +70,9 @@ static inline NRF_UARTE_Type *get_uarte_instance(struct device *dev) | |||
} | |||
|
|||
#ifdef UARTE_INTERRUPT_DRIVEN | |||
|
|||
volatile bool disable_tx_irq = false; |
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 make it multi instance ;)
ad30298
to
8910b22
Compare
drivers/serial/uart_nrfx_uarte.c
Outdated
@@ -70,6 +71,8 @@ static inline NRF_UARTE_Type *get_uarte_instance(struct device *dev) | |||
} | |||
|
|||
#ifdef UARTE_INTERRUPT_DRIVEN | |||
|
|||
|
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.
Undesirable empty lines.
drivers/serial/uart_nrfx_uarte.c
Outdated
} | ||
|
||
/** Interrupt driven transfer ready function */ | ||
static int uarte_nrfx_irq_tx_ready_complete(struct device *dev) | ||
{ | ||
NRF_UARTE_Type *uarte = get_uarte_instance(dev); | ||
|
||
return nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX); | ||
return nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX) | ||
&& nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK); |
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?
Would the returned status be incorrect without this second condition?
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX); | ||
struct uarte_nrfx_data *data = get_dev_data(dev); | ||
/* TX IRQ will be disabled after current transmission is finished */ | ||
data->disable_tx_irq = true; |
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 should also clear this flag in uarte_nrfx_irq_tx_enable
.
drivers/serial/uart_nrfx_uarte.c
Outdated
NRF_UARTE_Type *uarte = get_uarte_instance(dev); | ||
|
||
if (data->disable_tx_irq | ||
&& nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX)) { |
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.
Move the &&
operator to the end of the previous line to stay consistent with the rest of the code in this file.
Same applies to uarte_nrfx_irq_tx_ready_complete
.
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 does not seem to fix our problem yet :/
I am investigating.
Make sure that TX interrupts are disabled after transmission is finished. Signed-off-by: Mieszko Mierunski <[email protected]>
8910b22
to
507678a
Compare
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.
Works for me.
@anangl can you re-review? |
@@ -28,6 +28,7 @@ struct uarte_nrfx_data { | |||
uart_irq_callback_user_data_t cb; /**< Callback function pointer */ | |||
void *cb_data; /**< Callback function arg */ | |||
u8_t *tx_buffer; | |||
volatile bool disable_tx_irq; |
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 the type should be a atomic_t type.
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.
Only independent load and store operations are used which are itself atomic, there is no need for atomic type.
/* ENDTX flag is always on so that ISR is called when we enable TX IRQ. | ||
* Because of that we have to explicitly check if ENDTX interrupt is | ||
* enabled, otherwise this function would always return true no matter | ||
* what would be the source of interrupt. |
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.
Sorry, I don't get it. This function is supposed to return true exactly when the NRF_UARTE_EVENT_ENDTX
event is set. And it is not true that this event is always set. It is cleared before a transmission is started, see uarte_nrfx_fifo_fill
.
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.
For the application it is a problem if
after disabling interrupts uart_irq_tx_ready()
returns true.
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.
For the application it is a problem if
after disabling interruptsuart_irq_tx_ready()
returns true.
Then perhaps the application should be corrected.
The UART API does not describe such behavior as required or expected, does it?
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.
Application assumes correctly that it is allowed to send data with uarte_nrfx_fifo_fill
and ignore tx interrupt by disabling it. I am pretty sure this is not problem of an application.
When application is used with UART (not UARTE) this works as expected.
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 UART API does not describe such behavior as required or expected, does it?
It does. If it doesn't that's bug. Indeed, uart_irq_tx_ready() should be gated on on interrupts being enabled. Well, I don't know if there're some apps which can be fooled otherwise, but we can't dismiss that. The issue, there's single ISR for both UART RX and TX (and for errors, about which a few people remember). So, ISR can be called by RX interrupt, and should not be wrongly doing TX actions if TX is effectively disabled (and if TX interrupt is disabled, then effectively TX is disabled).
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 created an issue (#11535) for clarification of this.
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 PR fixes current issues with nrf uarte driver acting differently than nrf uart driver. I agree that API has to be clarified and it should be discussed, but changes in this PR don't affect it and are needed now. Also there is ongoing work on new API #10820 which will eventually make current interrupt driven API obsolete and we should focus on that.
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'm +1 on this logic, let me approve.
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.
Agreed. Let's go on with this fix for now.
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.
Approving based on the fact that this improves the situation with consistency of UART drivers.
@carlescufi could you merge? |
Calling fifo_fill function from uart_nrfx_uarte in the same
interrupt more than once, would break previous transmission.
Following fix adds checking if previous data was sent, and
if not, returns 0.