How to do fast forwarding of data between two serial ports

Status
Not open for further replies.

KurtE

Senior Member+
Quick background: I am playing around with my own board, that semi emulates a Trossen Robotics Arbotix-Pro which emulates a Robotis CM-730 controller.
What is basically does is to receive packets from the host like a PC or a linux board such as an Raspberry pi or Odroid...
With PC's it uses USB port, but with Linux boards I am setting up to use TTL serial (experimenting currently at 2mbs)

What it basically does is receive a packet from the host, that looks something like: 0xff 0xff <id> <length> ... <chksum>. The board itself has it's own logical ID and if the packet is addressed to board it responds, else it sends the packet out the Dynamixel Buss (Half duplex 1mbs), and if it receives anything back from the target, it forwards the response to the host. A goal is to minimize the time it takes for the host to send a packet and get the response back.

At the simplest code if we disregard the packets we intercept a main loop may look something like:
Code:
void loop() {
    int data;
    if ((data = Serial1.read()) != -1)
        Serial2.write(data);
    if ((data = Serial2.read()) != -1)
        Serial1.write(data);
}
Which can work fine in the basic case. There is also some other stuff going on, like checking voltages to see if the battery is going low, or maybe checking the state of an IMU...

But I am trying to decide between two different approaches here.

Currently the code works as a state machine, where it looks for the: 0xff 0xff <ID> and sees if the ID is for the board. If so it does not output any of this packet over the AX Buss. (This works like some other controllers, I have looked at incluing USBTOAX. So at best, the AX Buss will be at least three characters behind the Host for those packets not meant for the board.

The Arbotix-pro/CM730 does this different. They forward all of the bytes from the host to the AXBUS, and they do this within the interrupt handler. The plus of this is that a delay is about one character, and this happens regardless if I am busy doing something else. But the downside is we are sending more data over the AX-BUS, which most of the time is not really an issue, but in some small cases, might slow how fast I can retrieve data from the board. But probably not that major of a downside.

So the question is, suppose I wish to go the second route. Is there an any easy way to do this level of data forwarding at the interrupt time, preferably without having to write my own interrupt handlers?

Thanks
 
Look at File > Examples > Teensy > USB_Serial > USBtoSerial. It uses the relatively new availableForWrite() and traditional available() to detect the maximum block size which can be moved without delay. Teensyduino optimizes some of these block read/write calls too, so some are a lot faster than moving 1 byte at a time. Even the ones not yet optimized are still slightly more efficient than 1 byte per loop.

On Teensy 3.2, you can probably achieve 1 Mbit/sec speeds pretty easily without this optimization, but it will free up more CPU time for your program do to other work.
 
Thanks Paul,

Again I really appreciate all of the stuff you do here and I am aware of availableForWrite (and earlier names), which is great for being able to doing high throughput stuff. What I am interested in doing is more on reducing the latency for when command packets come in and how long it takes to get the response back to the host. Here is an example logic analyzer output for current stuff:
screenshot2.jpg
The top line is showing the AX Buss (1mbs). The next two lines is showing the RX and TX pins for the USART going to AX Buss and the direction signal. Currently testing out new board with level shifter IC to convert to 5v... The last two lines are showing the Usart (2mbs) communications to the host, which in this case for testing Odroid C1+. What you can see here is I received the whole request from the host before any data was output on the AX Buss. Now part of this is because the code is setup to receive the first 3 bytes, to see if the command is ours or not. Again I am trying to decide if that is buying anything versus immediately output all data received to AX..

I have also been trying to improve the Arbotix Pro talking to Linux boards. This board has an FTDI chip on it and issues with latency with USB driver where lots of responses would time out at 3 or 5ms... So added code to again talk over TTL Usart. Still debugging it, but I had zero experience with SMT32 programming/debugging... In their code they have the Interrupt handler for the Usarts do the forwarding. Again no experience with these chips, also no bootloader so have to use programmer... I have been trying to improve some of the code, example their Usart code does not make use of the Transmit register empty to output next byte, but waits for transmit complete... But now to the point: With their stuff updated to talk to other usart, I see:
LA-AXBUS-XU3-Dynamixel_analyzer.jpg
In this one you can see again top line is AX, host is repeated twice (checking level shifter), but you can see that there is about a 1 byte difference from seeing bytes from host go out on AX...
Again sort of off topic, but again showing issue that they were not double buffering on Arbotix-Pro...
screenshot.jpg
You can see gaps between bytes even though there were ones available...

Thanks again
 
Status
Not open for further replies.
Back
Top