UART: coping with hosts not honoring start bit timings

Status
Not open for further replies.

pramilo

Well-known member
Hi all,

We're using teensy 3.2 to work as a bridge to upgrade a slave device connected to it over serial (one wire/half duplex uart). The slave device has a one wire bootloader (tinysafeboot) and main host connects to teensy over USB.
We set up teensy for one wire using the LOOPS, RSRC flags.

We are running into an issue where after resetting the slave device power and sending the bootloader activation characters, the slave device bootloader starts responding too early and teensy gets completely out of frame, recognizing nonsense characters.
Because this is a one wire communication, if the device starts transmitting before teensy shifts to receiving mode (which is the case), the whole thing gets out of sync.


It took us quite a while to get to the bottom of it but using an Osciloscope shows that the bootloader on the slave device attempts to start transmitting a few microseconds too early. Sometimes it does wait the necessary time and communication works; other times it starts too soon and teensy can't get the correct framing.


It is important to note that the slave device bootloader operates properly using an FTDI chip set up for half duplex (we tested it successfully with 2 different ftdi chips); so this is very Teensy-specific.


I've looked at the ILT setting of the processor UART_C1 field and setting it to 0 never works; setting it to 1 works sometimes.
My question - I understand this is not standard - is if you know of any other flag or option that can ease this case.

The only other alternative I can see is using a Bitbanged serial communication but I haven't come across many libraries capable of doing bitbaging and half duplex (one wire) that work on Teensy.

Do you know of any?

Any help would be greatly appreciated.
 
I have had good luck using half duplex talking to TTL level dynamixel servos at 1mbs, and I am using the LOOPS and flag and the UART_C3_TXDIR to set the direction in the C3 field.

The issue that I first ran into was knowing when I could switch the direction from TX to RX. But now days the SerialX.flush() function works properly for this. In particular it waits until the queue is empty and then waits until the bit is set that says that the transfer completed.

If you are setup to use Hardware instead to do the half duplex, there is code in the SerialX ISR that will change the Transmit PIN as soon as the transmission completes. (Set by the SerialX.transmitterEnable(pin) ) call. I have used this in some of my newer boards, as to have the hardware convert the 3.3v TTL signal to a 5v Signal...

But earlier I wondered about trying to hook it up that I switched the UART_C3_TXDIR bit during the Uarts ISR. One hack I thought about doing but have not tried, was wondering what it would do to set the transmitterEnable on some IO pin I don't use, and then setup an interrupt on this IO pin which has this interrupt update the C3_TXDIR... Again I have not tried it....

But again hard to give any concrete ideas without seeing what you are actually doing.

Kurt
 
Hi Kurt,

Thank you for your reply.

I have been using Teensy's half duplex uart capability for quite a while, using the LOOPS mode as well. In my case I have modified the serial1.c and serial2.c (I use both on half duplex) by extending the transmitAssert and transmitdeassert funcitons that are already on the library.

These functions are meant to activate the transmitEnable pin for RS485 (or similar setups) when it's going to transmit so they already have the timing right. I've simply extended them by adding the code to switch from RX to TX and vice versa. It works pretty well and it's really straightforward to set up. (added a few #ifdefs in there so I can quickly switch form the regular full duplex to half duplex/one wire)

As to the issue I'm experiencing, I've come to understand it a little more: teensy's uart shift register will active drive high and low when transmitting. It will active drive all the bits plus the stop bit.
The necessary interrupt to switch from TX to RX only occurs in teensy after the stop bit has been shifted by the UART transmitter.

The problem seems to be that I'm working against a software serial library that has the timing for the stop bit off by a few microsecs. It doesn't wait for the stop bit to complete and starts sending the start bit too early. Because teensy is still activally shifting out the stop bit, it doesn't see the begining of the start bit which basically puts it out of framing.

As I said I don't have this problem with FTDI chips so this is clearly a specific interaction with teensy. Nevertheless, since this will be a very controlled situation, I'm considering just bit banging the UART and not activaely shifting the stop bit (let the pull up keep the signal high for the stop bit) and move into bit banged "receive mode" prematurely, waiting for the start bit.
From what I can see I can't have the Teensy UART do this (which is understandable because you are supposed to shift o) but so far seems the best approach. I don't have control over the other devices but I have over teensy so I guess this is the way I'll go.

Again, fi anyone knows of any software serial library that works with teensy and does half duplex it'd be a great start.

Thank you
Pedro
 
You say that it works sometimes, but not others...

Long shot: Wonder if you have tried raising the interrupt priority for the UART... Example in Serial1
NVIC_SET_PRIORITY(IRQ_UART0_STATUS, IRQ_PRIORITY);

I believe this defaults to 64... So wonder if you change it to something like 20... Does it make a difference?
 
Good point. I'll give it a try and let you know.
( I don't have high hopes though, bc teensy is actually timing correctly; I think this is more of an issue of the other device, but it's definetly worth the shot! Thanks for the suggestion.)
 
Hi Kurt,

I ended up going the road of writing my own bit banged Serial Library to just cope with this. ATMEL AVR305 and 304 (bot mostly 305) application notes have a very good explanation and state diagrams on how to go about writing a bit banged software UART.

I was able to get it running on teensy on a fairly small code base, but have endured a long debugging session until I finally realized the Teensy Serial USB library hogs the processor (interrupts included) for about 100microsecs the first time you send a character. All characters after that don't hog any relevant processor time for us.

In a time sensitive application like bit banging a uart, this is really an issue (I guess an issue for anyone doing control or time sensitive tasks).

We've finally narrowed it down and I made a post in the Bugs forum. We've worked around it by sending a large string on connect, to get the 100microsecs delay out of the way.

The code is not really "pretty-fied" yet so I won't be posting it but if you need something like this, send me a PM.
The main advantage of the code is that, while still respecting time for stop bits, it goes into waiting for start bits at an early stage, which resolved our problem.
The code uses 1 pin interrupt (to detect the falling edge of the start bit) and one IntervalTimer to time the cadence of incoming or outgoing bits.

Best Regards,
Pedro
 
Status
Not open for further replies.
Back
Top