After doing some more research, I decided to jump into configuring my DARwIn-OP’s Dynamixel Teensy 3.2 Driver Prototype to get rid of the retransmitting loop code:
void loop() { if (Serial1.available()) { uint8_t c = Serial1.read(); Serial1.write(c); } }
This loop just wait for a byte received by the UART and retransmit it with the same UART, which is configured with a hardware direction pin (RTS driven by the transmitter).
If I could use Teensy’s DMA (Direct Memory Access) controller to do the UART retransmission, I could empty the loop so the Teensy can be used in any other tasks without affecting the retransmission performance.
The DMA requirement is very simple:
- To trigger a DMA request when a byte is received by the UART.
- The DMA transfer has to be 1 byte.
- The DMA transfer has to read from the UART DATA register (received data).
- The DMA transfer has to write into the UART DATA register (for retransmission).
- Do not involve the CPU in the process, no interrupt events.
Looking at the DMA capabilities of the Teensy’s ARM MK20DX256VLH7 CPU, it looked feasible, and after a few tries I got it working.
Now the retransmission has a smaller latency and a much smoother timing:

The signals in the chart are:
- RX into the Teensy (from Odroid’s TX).
- TX from the Teensy.
- Hardward Direction Pin.
The coding has a larger setup to configure the DMA and the UART (Teensy’s interrupt driven serial API is no longer useful), but the loop() function is now empty:
#define UART_TXRTSE (2) #define UART_TXRTSPOL (4) #define BAUD_RATE (1000000) void setup() { int divisor = BAUD2DIV(BAUD_RATE); // DMA: // p 415 source address = uart data register DMA_TCD1_SADDR = &UART0_D; // p 415 source address offset DMA_TCD1_SOFF = 0; // p 416 transfer attributes: 8 bits DMA_TCD1_ATTR = 0; // p 417 minor byte count = 1 byte DMA_TCD1_NBYTES_MLNO = 1; // p 420 last source address adjustment = 0 DMA_TCD1_SLAST = 0; // p 420 destination address = uart data register DMA_TCD1_DADDR = &UART0_D; // p 421 destination address offset DMA_TCD1_DOFF = 0; // p 423 channel link disabled DMA_TCD1_CITER_ELINKNO = 1; // p 423 last destination address adjustment = 0 DMA_TCD1_DLASTSGA = 0; // p 427 channel link disabled DMA_TCD1_BITER_ELINKNO = 1; // p 424 control and status = 8 cycle stall, active DMA_TCD1_CSR = DMA_TCD_CSR_BWC(3) | DMA_TCD_CSR_ACTIVE; // p 402 enable DMA REQ channel 1. DMA_SERQ = DMA_SERQ_SERQ(1); // clock setup // p 252-259 system clock gating SIM_SCGC6 |= SIM_SCGC6_DMAMUX; SIM_SCGC7 |= SIM_SCGC7_DMA; SIM_SCGC4 |= SIM_SCGC4_UART0; // wait for clocks to become stable. delay(500); // p366 dma mux channel configuration DMAMUX0_CHCFG1 = DMAMUX_ENABLE | DMAMUX_SOURCE_UART0_RX; // UART: // p 1222 UART0 Control Register 5 request DMA on receiver full UART0_C5 = UART_C5_RDMAS; // RX TX pins CORE_PIN0_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // p 1208 uart0 baud rate UART0_BDH = (divisor >> 13) & 0x1F; UART0_BDL = (divisor >> 5) & 0xFF; UART0_C4 = divisor & 0x1F; UART0_C1 = UART_C1_ILT; UART0_TWFIFO = 2; // tx watermark UART0_RWFIFO = 1; // rx watermark UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE; UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE; // enable PIN 6 as hardware transmitter RTS with active HIGH. CORE_PIN6_CONFIG = PORT_PCR_MUX(3); UART0_MODEM = UART_TXRTSE | UART_TXRTSPOL; } void loop() { }
Actually, now I am running the typical ‘blink’ in the loop() function just so I know the Teensy is running.
Just for an info Dynamixel SDK 3.0 is out.
https://github.com/ROBOTIS-GIT/DynamixelSDK
Did you give a try on Odroid XU4 not sure will it reduce time feedback?
Git hub wiki says it works on Ubuntu 14.04 (please check Odroid part)
https://github.com/ROBOTIS-GIT/DynamixelSDK/wiki/2.1-Dynamixel-Controller
What Ubuntu vs are you using? I think you are doing a good progress.. All the best.
Thanks for the update. I haven’t check the latest SDK yet.
The main issue with the Dynamixel Controller from Robotis is that it uses FTDI which results in low performance. The alternative USB2AX Controller has better performance (and it is smaller). Both these controllers are USB 1.1, so the lag the USB introduces is in milliseconds.
Anyway I am interested in a direct Serial interface which is faster. It can be used with the SDKs directly, it only needs to adjust the name of the Linux device in the source code. By just doing so, the lag is reduced to about 1/3 of a millisecond, which I’ll be working to further reduce it.
Right now on my Odroid-XU4 I am using plain Ubuntu 16.04 and Debian 7, but I will move to a Real Time Kernel to develop a new framework for the DARwIn-OP with better precision in timing events.
A couple of years ago I did try to patch Odroid’s Kernel with the RT patches but it wasn’t straight forward I didn’t have much experience in that.
Now there are some advancements such as the following:
http://forum.odroid.com/viewtopic.php?f=95&t=17954
I’ll be trying it once I finish with the mechanical and electronics stuff later this year, I hope.