-
Notifications
You must be signed in to change notification settings - Fork 376
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
T4 uart enhance #419
T4 uart enhance #419
Conversation
Not needed unless you go to half duplex, but added the entries into the hardware tables and if defined will set them during begin
As an experiment added in half duplex mode into the Hardware Serial class. If you pass in the SERIAL_HALF_DUPLEX flag as part of the format on the begin method, it will configure the TX pin to be half duplex mode. When you do writes it will turn the pin to TX pin and when Tx is emplty ... will convert back to RX mode
With T3.x made use of bitband address for the TX Direction setting, so Except for the begin which calls format, no code changed, we simply stored the bitband address of the TXDIR flag into the TXDIR variable that was already used for the set direction flag.
Setting the watermark to 0 has an impact on everyone trying to use fast baud rates, so this isn't a simple or easy decision. |
As you mentioned, there is no complete perfect answer. The set watermark for RX to zero I would assume will cause more interrupts, which will eat up more room, at highest speeds, it might cause us to potentially lose less characters? As there will be more room still available in the FIFO for the RX data. I am assuming that the code currently relies on the input line to go idle and be detected? I need to look to see if that timeout is configurable. That is if we receive one byte, when does it then decide to go ahead and cause the ISR to be called. Probably need to look again, Of some other reason to call the ISR? ... Another option would be to update all of the functions that look at data, Like potentially would change available...
And of course then peek and read would need to be updated as well. Will look at some more... Question is should I add in the stuff to look at the adding the looking and peeking directly into FIFO? |
Hi @PaulStoffregen - I verified as I suspected that the last bytes are reported after a one character idle time. Did a quick and dirty test program:void setup() {
Note: I also ran it on T3.6.. |
If we are using a RX WATER value > 0 Add code to SerialX.avail, read and peek for avail add in count of entries in RX FIFO. For Read, if our queue is empty, and FIFO is not empty, read first element and return it. For Peek if queue is empty and FIFO is not empty, read it and reinitialize queue to have this item as first item in queue and return it.
@PaulStoffregen - I pushed up a change to Hardware Serial for T4, that leaves the WATER > 0 and Add code to SerialX.avail, read and peek for avail add in count of entries in RX FIFO. For Read, if our queue is empty, and FIFO is not empty, read first element and return it. For Peek if queue is empty and FIFO is not empty, read it and reinitialize queue to have this item as first item in queue and return it. I tried the above sample and it is working. I verified that it was grabbing data from FIFO. I also reran the version of the example app that the user on forum was doing for ASYNC tx between two ports back and forth. The one I am running is using the Half duplex support that I have in this PR...
And results are better than the version where I simply disabled the water. |
Do you have pointers to the discussions of these issues?
Um; So? Async communications is ... asynchronous. Code expecting to see serial.available() == 10 immediately after the stop bit of the 10th character is transmitted is IMNSHO broken... Handling the latency vs efficiency tradeoff on uart reception is really tricky (even more so if you try to use DMA.) For Network terminal servers, we used to hacks like "inputPending() returns at least one if DMA has transferred any bytes", and "read() terminates DMAs early", with the idea that if the system was very busy, neither of those would happen and the FIFO or DMA buffer would just continue filling. If the system had adequate cycles, it would end up calling read() and getting the data close to "as soon as possible." This was highly dependent on UART hardware, and didn't always work perfectly, but it seemed like a reasonable goal. The T4 UARTs don't seem very supportive of such techniques; it looks like they only allow idle times and FIFOs to be manipulated when the TX or RX is disabled :-( (So, I don't actually own a T4, and I haven't been following the discussion. Everything I said is based on a sort of "technical purity" viewpoint.) |
@WestfW (and @PaulStoffregen ) A lot of the stuff started out with the discussion in the thread: https://forum.pjrc.com/threads/58231-Teensy-4-0-and-single-wire-serial The code in the last PR, does still maintain the Watermark, so should still help to reduce interrupts. And as mentioned Serial.available() will return counts including what is in the UARTS fifo queue. The good news is the sample programs is working with this. Also I thought one of newer T4 breakout boards was having an issue, and maybe I screwed it up. But so far it now doing a better job talking to Dynamixel Servos at 1mhz Serial. |
@PaulStoffregen - What are your thoughts on adding Half duplex support to the Serial ports. If you are interested in allowing something like this, I would probably need to redo part of it as we took the other approach to fix the latency issue with the serial, by peaking into the hardware FIFO instead of setting the watermark to nothing... |
Migrating the half duplex support I did in the Stagnant and out of date PR to enhance Uarts: PaulStoffregen#419 To try to support Half duplex mode in a similar way like we do for RS485 like support. With T3.x made use of bitband address for the TX Direction setting, so Except for the begin which calls format, no code changed, we simply stored the bitband address of the TXDIR flag into the TXDIR variable that was already used for the set direction flag. For T4.x - it is a little more work as there is no bitband support on M7 processors. For GPIO there is a Set and Clear register which we use, but for the appropriate UART register there is no such setup of registers. So I have to special case we are in that mode and do it... Also since not atomic I cli/sei... Now to start testing again
Migrating the half duplex support I did in the Stagnant and out of date PR to enhance Uarts: PaulStoffregen#419 To try to support Half duplex mode in a similar way like we do for RS485 like support. With T3.x made use of bitband address for the TX Direction setting, so Except for the begin which calls format, no code changed, we simply stored the bitband address of the TXDIR flag into the TXDIR variable that was already used for the set direction flag. For T4.x - it is a little more work as there is no bitband support on M7 processors. For GPIO there is a Set and Clear register which we use, but for the appropriate UART register there is no such setup of registers. So I have to special case we are in that mode and do it... Also since not atomic I cli/sei... Serial Half Duplex - Fix T4Serial1 and T-LC Serial1-3 Updates: T4 T4 Serial 1 did not have proper settings for IOMUXC_LPUART6_TX_SELECT_INPUT Tested T4.1 Serial1-8 Tested T3.5 Serial1-6 T3.6 - Added support for LPUART which is Serial6 which now works. T-LC Make half duplex work on T-LC on Serials1-3 Tested on on T3.5 1-6
@PaulStoffregen - you may want to review this to see what you think.
First part for T4 - set the RX Watermark to 0, which fixed some issues people were running into when the last few bytes did not show up in SerialX.available() (nor read)...
Half duplex support - if the format you pass in to SerialX.begin includes:
#define SERIAL_HALF_DUPLEX 0x200
The begin code, turn on LOOPS and the like, to set the TX pin to support half duplex. I also enable PU resistor on the pin.
On T4 - the code added another check like transmitting pin
And likewise to turn it back to RX mode. For T3.x I added it, but I did not need to add the extra checks and the like in the code. Instead, I use the bit band address.
transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART0_C3, C3_TXDIR_BIT);
And then the code already in place that looked at transmit pin like:
Took care of it for us...
Note: So far T3.x I replicated the changes for Serial1-Serial6. I have not yet done Serial6 of T3.6 as it uses LPUART instead of UART. Thought I would get your input before I did that.