Skip to content

cpu/atmega_common/periph/uart: use TX_ISR to check TX end#12973

Merged
aabadie merged 2 commits intoRIOT-OS:masterfrom
fjmolinas:pr_atmega_tx_isr
Jan 15, 2020
Merged

cpu/atmega_common/periph/uart: use TX_ISR to check TX end#12973
aabadie merged 2 commits intoRIOT-OS:masterfrom
fjmolinas:pr_atmega_tx_isr

Conversation

@fjmolinas
Copy link
Copy Markdown
Contributor

Contribution description

For atmega boards a TX has not actually completed until UDRn is empty
as well as the Transmit Shift Register.

To avoid resetting an UART before a TX has completed we use the TXCn
flash and ISR to set a variables that indicates TX is ongoing. This
allows not reseting the UART while there are ongoing TX pending.

This fixes an issue where part of the last byte is not shifted out
of the TX shift register causing rubish on the first TX following an
uart_init.

Testing procedure

  • Run BOARD=arduino-uno make -C tests/sys_arduino flash term and see a clean print.
BOARD=arduino-uno make -C tests/sys_arduino flash term
2019-12-17 10:43:41,162 # main(): This is RIOT! (Version: 2020.01-devel-1408-g3ef6d-pr_atmega_tx_isr)
2019-12-17 10:43:41,178 # Hello Arduino!
  • on master you see rubbish:
2019-12-16 11:55:45,764 # main(): This is RIOT! (Version: 2020.01-devel-1406-g615fc-HEAD)!�����Arduino!

Issues/PRs references

@fjmolinas fjmolinas added Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors) Platform: AVR Platform: This PR/issue effects AVR-based platforms labels Dec 17, 2019
@fjmolinas fjmolinas requested a review from maribu December 17, 2019 09:44
@fjmolinas
Copy link
Copy Markdown
Contributor Author

Maybe this should be optional? It adds some code, and is only needed if uart is being initialized a bunch of times.

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Dec 17, 2019

Maybe this should be optional?

Could this be somehow related to the periph_uart_nonblocking used with some sam0 cpus ?

@fjmolinas
Copy link
Copy Markdown
Contributor Author

@aabadie do you think I should add the optional future part?

fixing RIOT_VERSION and with the branch rebased on master.

  • master:
   text	   data	    bss	    dec	    hex	filename
  10362	    282	   1192	  11836	   2e3c	/data/riotbuild/riotbase/tests/sys_arduino/bin/arduino-uno/tests_sys_arduino.elf
  • this PR:
   text	   data	    bss	    dec	    hex	filename
  10478	    282	   1193	  11953	   2eb1	/data/riotbuild/riotbase/tests/sys_arduino/bin/arduino-uno/tests_sys_arduino.elf

There is some change in text but almost none in RAM.

@fjmolinas
Copy link
Copy Markdown
Contributor Author

I'll trigger the CI now to see if there are any other issue and not have to run it tomorrow when it might be a bigger queu.

@fjmolinas fjmolinas added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jan 14, 2020
Copy link
Copy Markdown
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

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

do you think I should add the optional future part?

Maybe not for the moment.

I have a couple of questions, see below.

* @brief Allocate variable to hold transmission status, set when there
* is data in UDRn or in the Transmit Shift Register
*/
static volatile uint8_t _tx_pending = 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is volatile really required ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

AFAIK variables used inside and out of ISR should be volatile.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ok

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AFAIK variables used inside and out of ISR should be volatile.

@fjmolinas: No, they shouldn't. volatile only prevents that access are are optimized and that the order of volatile accesses is not changed in regard to each other. When you need to access a variable from inside and outside ISR the most readable approach is to use C11 atomics, the next best is to use irq_disable() ... irq_restore() when accessing the variable from outside of the ISR.

See https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html and https://blog.regehr.org/archives/28

@aabadie
Copy link
Copy Markdown
Contributor

aabadie commented Jan 15, 2020

I think you can squash now. Unfortunately I can't test so I'll have to trust yours.

@fjmolinas
Copy link
Copy Markdown
Contributor Author

I think you can squash now. Unfortunately I can't test so I'll have to trust yours.

OK I'll do a run of tests on my ci to verify status is the same for avr boards.

For atmega boards a TX has not actually completed until UDRn is empty
as well as the Transmit Shift Register.

To avoid resetting an UART before a TX has completed we use the TXCn
flash and ISR to set a variables that indicates TX is ongoing. This
allows not reseting the UART while there are ongoing TX pending.

This fixes an issue where part of the last byte is not shifted out
of the TX shift register causing rubish on the first TX following an
uart_init.
@fjmolinas
Copy link
Copy Markdown
Contributor Author

Squashed

Copy link
Copy Markdown
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

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

All good here.

ACK

@aabadie aabadie merged commit 76b9cfb into RIOT-OS:master Jan 15, 2020
@fjmolinas fjmolinas deleted the pr_atmega_tx_isr branch January 15, 2020 12:42
@fjmolinas fjmolinas added this to the Release 2020.01 milestone Jan 15, 2020
Copy link
Copy Markdown
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

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

Sorry for the late comment. See inline. I can open a PR to address this.

* @brief Allocate variable to hold transmission status, set when there
* is data in UDRn or in the Transmit Shift Register
*/
static volatile uint8_t _tx_pending = 0;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AFAIK variables used inside and out of ISR should be volatile.

@fjmolinas: No, they shouldn't. volatile only prevents that access are are optimized and that the order of volatile accesses is not changed in regard to each other. When you need to access a variable from inside and outside ISR the most readable approach is to use C11 atomics, the next best is to use irq_disable() ... irq_restore() when accessing the variable from outside of the ISR.

See https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html and https://blog.regehr.org/archives/28

@fjmolinas
Copy link
Copy Markdown
Contributor Author

Hi @maribu thanks for the feedback, if you want to open the PR yourself it would be nice, otherwise I'll do it when I understand your comments better. I'll read those links closely, to get rid of the volatile confusion then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: AVR Platform: This PR/issue effects AVR-based platforms Type: bug The issue reports a bug / The PR fixes a bug (including spelling errors)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants