-
-
Notifications
You must be signed in to change notification settings - Fork 283
Enable interrupt mode of UART tx #266
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
Maybe this is a nitpick, but i have a doubt about my current implementation of the irq handler. The first thing i do in the irq handler is to check the IIR register to know the source of interrupt (line status, received data, etc). How this is currently accomplished is by calling first In my opinion, it would be better to read the register in a switch/case, that would guarantee that we read it only once, and would also result in a code easier to understand. However, the existing functions in 16550.c seem to be designed for the current implementation (and the switch/case implementation would require to add another function), so maybe i am missing some advantage of this method? |
@descampsa sorry I took so long to respond on this, I was working on something else. Thanks for the fix, I'll take a look and do a bit of testing here. |
@@ -340,7 +340,7 @@ unsigned char uart_poll_out( | |||
) | |||
{ | |||
/* wait for transmitter to ready to accept a character */ | |||
while ((INBYTE(LSR(which)) & LSR_TEMT) == 0) |
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 is TEMT not sufficient? With our UART configuration it should be set when both THR and FIFO are empty, right?
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.
Nevermind, you're right, TEMT is set when THR and TSR are empty. Since uart_poll_out only places a byte in THR, then THRE is sufficient.
aaaf3db
to
1beffde
Compare
83c76a6
to
77d9086
Compare
Hey @eriknyquist, have you had the time to test it further? |
in regards to your efforts to read the IIR register only once, I have no idea. Can you update the pull request once you've figured it out? Your first comment kind of gave me the idea that this isn't finished yet. So I thought I'd wait for you to finish it. |
You can forget my comment about the IIR register, i just noticed that i misread the code and did not see that it was using a separate cache variable (iirCache). |
@descampsa trying to test but there are conflicts, can you resolve them please, and you also need to re-build libarc32_arduino101.a and add it to the commit (since you changed files in the system/ directory). |
97f2d2e
to
91a53a4
Compare
@eriknyquist Ok, it should be good now. |
@descampsa thanks |
So, I can see a difference with short strings, but longer strings still seem to block for most of the transfer: before applying this patch:
after applying this patch:
|
Strange, with this code : test_serial_tx.txt, i get: Before: After: |
You're timing |
Hmm, yeah, that could have been that, but i still can't reproduce it with print. Could you share the complete code you are using? btw, it is probably a typo, but just to be sure, you mean |
Yes, sorry, I did mean |
Oh, i see, this behaviour is expected, because you exceed the uart buffer size (64 byte) by printing a 22 bytes string 10 times. |
Ah OK, yes I see. OK, can you squash your 4 commits into 1 commit please? I think all these changes belong together, and besides, no commits before 175319e will compile |
Previous version of write will never use the interrupt mode transmission, because it fails to check if holding register is empty. This commit fix that, and several bugs related to interrupt mode serial transmission. When possible, it uses the tx FIFO, in order to reduce the number of interrupts called and the overhead.
d6efbaa
to
d58a929
Compare
Yes of course, commits squashed. |
Please see the below commits that I try to fix it in my branch. |
Current version of Serial1.write will never use the interrupt mode transmission, because it fails to check if the holding register (fifo) is empty. It only check if ring buffer is empty, and use it only if it is not empty, which is a classic chicken and egg problem.
This commit fix that , and several (maybe not all?) bugs related to interrupt mode serial transmission.
This sketch demonstrate the problem, the write time is much lower after the change:
serial4_error.ino.txt
The test sketch Serial1_error.ino.txt pass, but a regression in some edge case is not impossible, interrupt mode is more tricky than poll mode. Feel free to comment, test, and try to break it.
Do not merge yet, this is not complete, i will also change the interrupt handler to send several bytes at a time, to exploit tx fifo and reduce interrupt overhead.Done, the tx fifo should be used correctly now.