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

cpu, sam0_common: fix uart TXC check #7638

Merged
merged 1 commit into from
Oct 10, 2017

Conversation

smlng
Copy link
Member

@smlng smlng commented Sep 22, 2017

should fix #7617, and also adapts some register checks to use read-only bits where possible.

Tested with samr21-xpro. @travisgriggs please try this one and verify if that resolves your issue reported in #7617.

@smlng smlng added Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Sep 22, 2017
@smlng smlng self-assigned this Sep 22, 2017
@travisgriggs
Copy link
Contributor

Tested. This works.

@travisgriggs
Copy link
Contributor

FWIW, I've also tested without the check completely, and that works too. And is slightly faster at spewing characters at 230400 (I didn't try any other speeds).

@travisgriggs
Copy link
Contributor

travisgriggs commented Sep 23, 2017

I'd like to suggest a compromise with the TXC test, based on some interaction we had with Microchip/Atmel engineers. We asked them why the ASF version has the TXC check in it:

"If INTFLAG.DRE bit is set, doesn’t mean that data is transmitted (it just moved to tx shift register). To make sure the entire data frame including stop bit(s) has been transmitted and no new data was written to DATA, the Transmit Complete interrupt flag (INTFLAG.TXC) will be set.

If you have 10 bytes to send, you may not need to check TXC bit for every byte transfer. You can check the TXC bit for 10th byte transmission.

In ASF, usart_write_wait() function is to just transmit a character via the USART. This is the reason it checks both bits (DRE and TXC).”

The RIOT uart_write() function actually writes len bytes. I think the correct thing to do would be move the TXC spin check out of the loop, and just do it once after the whole buffer has been written. E.g.

void uart_write(uart_t uart, const uint8_t *data, size_t len)
{
    for (size_t i = 0; i < len; i++) {
        while (!dev(uart)->INTFLAG.bit.DRE) {}
        dev(uart)->DATA.reg = data[i];
    }
    while (!dev(uart)->INTFLAG.bit.TXC) {}
}

I have tested this as well with positive results. It's worth about 1.5% faster for my tests. Obviously, the larger your buffers are, the more savings you get. But it's not really about the speed. It just seems more consistent with what the TXC bit was meant for.

@smlng
Copy link
Member Author

smlng commented Sep 23, 2017

I think the correct thing to do would be move the TXC spin check out of the loop, and just do it once after the whole buffer has been written.

Nice idea, I agree - and thanks for the detailed background info!

@smlng
Copy link
Member Author

smlng commented Sep 26, 2017

rebased and squashed

@photonthunder
Copy link

Be great to see this bug fix get merged

Copy link
Contributor

@haukepetersen haukepetersen left a comment

Choose a reason for hiding this comment

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

The actual fix looks good. I am however not so fond of the bit notation for flag checks and please re-fix the error bit clear...

/* clear error flag */
dev(uartnum)->INTFLAG.reg = SERCOM_USART_INTFLAG_ERROR;
dev(uartnum)->INTFLAG.reg |= SERCOM_USART_INTFLAG_ERROR;
Copy link
Contributor

Choose a reason for hiding this comment

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

Please revert this change, not need for read/modify/write here, a simple write is sufficient: Writing a one to this bit will clear the flag.

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess you are right, I mis-interpreted the usage of it here and thought might be safer to read/write here - just as we do in other places.

@@ -69,18 +69,18 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)

/* reset the UART device */
dev(uart)->CTRLA.reg = SERCOM_USART_CTRLA_SWRST;
while (dev(uart)->SYNCBUSY.reg & SERCOM_USART_SYNCBUSY_SWRST) {}
while (dev(uart)->SYNCBUSY.bit.SWRST) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I like the original check much better, but this might be subjective. At some point we decided to go the the .reg & .. notation consistently for all the sam0 periph drivers...

Copy link
Member Author

Choose a reason for hiding this comment

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

with the updated CMSIS headers from the newer ASF the bit fields are read-only, and reg is RW. So I would guess the compiler could optimise things a bit (more) when using read-only registers for read operations on the bit-field instead of using an RW register when using reg.

Do I make sense here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Plus, I would therefore recommend to adapt all periph drivers accordingly to have it consistent again.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yepp, code size does not change with this, re-checked it. So yes, with them being read only why not change it. Maybe this would be cleaner done in a separate PR, but just leave it here if you want.

@smlng smlng force-pushed the cpu/sam0_common/fix_uart branch from 661b166 to 0d6abe2 Compare October 10, 2017 14:48
@kaspar030
Copy link
Contributor

Maybe this would be cleaner done in a separate PR, but just leave it here if you want.

Yes, please keep the PR fix-only...

@smlng
Copy link
Member Author

smlng commented Oct 10, 2017

factored out into #7709

@smlng smlng removed the Type: cleanup The issue proposes a clean-up / The PR cleans-up parts of the codebase / documentation label Oct 10, 2017
@kaspar030
Copy link
Contributor

Parens missing... Please fix and squash. ACK.

@smlng smlng force-pushed the cpu/sam0_common/fix_uart branch from fc3fa03 to 732e60b Compare October 10, 2017 16:24
@kaspar030 kaspar030 dismissed haukepetersen’s stale review October 10, 2017 16:38

comments addressed

Copy link
Contributor

@kaspar030 kaspar030 left a comment

Choose a reason for hiding this comment

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

ACK.

@kaspar030 kaspar030 merged commit 55b2d48 into RIOT-OS:master Oct 10, 2017
@smlng smlng deleted the cpu/sam0_common/fix_uart branch October 10, 2017 19:27
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 Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

samd21:uart TXC test backwards
5 participants