Skip to content
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

Merged

Conversation

Mierunski
Copy link
Collaborator

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.

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]>
anangl
anangl previously approved these changes Nov 19, 2018
@jakub-uC jakub-uC added bug The issue is a bug, or the PR is fixing a bug area: Drivers labels Nov 19, 2018
@codecov-io
Copy link

codecov-io commented Nov 19, 2018

Codecov Report

Merging #11475 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           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.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 03c7d9b...507678a. Read the comment docs.

Copy link
Contributor

@jakub-uC jakub-uC left a 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.

@anangl anangl dismissed their stale review November 19, 2018 12:50

New commit added.

@@ -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;
Copy link
Contributor

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 ;)

@@ -70,6 +71,8 @@ static inline NRF_UARTE_Type *get_uarte_instance(struct device *dev)
}

#ifdef UARTE_INTERRUPT_DRIVEN


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Undesirable empty lines.

}

/** 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);
Copy link
Member

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;
Copy link
Member

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.

NRF_UARTE_Type *uarte = get_uarte_instance(dev);

if (data->disable_tx_irq
&& nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX)) {
Copy link
Member

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.

Copy link
Collaborator

@lemrey lemrey left a 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]>
Copy link
Collaborator

@lemrey lemrey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me.

@carlescufi
Copy link
Member

@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;
Copy link
Collaborator

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.

Copy link
Collaborator Author

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.
Copy link
Member

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.

Copy link
Collaborator

@lemrey lemrey Nov 20, 2018

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.

Copy link
Member

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.

Then perhaps the application should be corrected.
The UART API does not describe such behavior as required or expected, does it?

Copy link
Contributor

@jakub-uC jakub-uC Nov 20, 2018

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.

Copy link
Contributor

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).

Copy link
Member

@anangl anangl Nov 20, 2018

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.

Copy link
Collaborator Author

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.

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Contributor

@pfalcon pfalcon left a 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.

@Mierunski
Copy link
Collaborator Author

@carlescufi could you merge?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Drivers bug The issue is a bug, or the PR is fixing a bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants