MOD54415 RTS line in Half Duplex Mode

Discussion to talk about software related topics only.
Post Reply
Watzlavick
Posts: 22
Joined: Mon Jan 27, 2014 7:19 pm

MOD54415 RTS line in Half Duplex Mode

Post by Watzlavick »

I'm using a MOD54415 in half duplex wired-or mode to interface to a Dynamixel AX-12A servo using the TX and RTS lines. I have an external mux that is controlled by the UART1 RTS line to switch directions. Occasionally, after a transmit, the RTS line stays asserted (low) and doesn't de-assert back to the high state until the next transmit. It's very intermittent and appears to be somewhat dependent on what else I have running but I haven't been able to isolate it. I'm still looking through serial.cpp but my impression from reading the Freescale manuals is that the driver is supposed to assert RTS, then the hardware will de-assert it after the last bit is transmitted. If that's the case, how could another task interfere with that? Nothing else is mapped to the UART1_RTS line. I'm using some other UART ports and external IRQ lines if that makes a difference. I'm frozen with 2.7.5.
User avatar
pbreed
Posts: 1080
Joined: Thu Apr 24, 2008 3:58 pm

Re: MOD54415 RTS line in Half Duplex Mode

Post by pbreed »

Seems odd, as it should just happen...
What do the serial port registers show?
Watzlavick
Posts: 22
Joined: Mon Jan 27, 2014 7:19 pm

Re: MOD54415 RTS line in Half Duplex Mode

Post by Watzlavick »

I'm checking the UART status register, 0xFC06_4004 (USR1), and it shows 0. But that is after I get the timeout on the subsequent read operation, not immediately after the RTS sticks so any errors are already cleared. I'll see if I can catch the status register after the write call. I was thinking maybe it was a FIFO underrun due to some other task's ISR taking too long but my other ISRs are short (just read a hi-res timer and post to an mbox). The other ISRs are used for a GPS at 1 Hz and an IMU at 819.2 Hz. However, I don't think it's related to the other ISRs since I'm pretty sure I still got it to fail with those tasks compiled out.

I came across a comment in my code from a few years ago where I determined serialsendcomplete() doesn't work correctly in wired-or mode because the transmitter is disabled in the ISR after the operation completes.

A couple of potentially related issues:
viewtopic.php?f=5&t=2229&p=10048&hilit= ... ete#p10048
viewtopic.php?f=5&t=2018&p=8952&hilit=s ... lete#p8952
Watzlavick
Posts: 22
Joined: Mon Jan 27, 2014 7:19 pm

Re: MOD54415 RTS line in Half Duplex Mode

Post by Watzlavick »

I did some more testing today. The UART status register shows 0 immediately after the write call when the problem occurs. I also disabled the other tasks that use interrupts and the problem still occurs, just much less often (once every few minutes), so it seems to be ISR or UART load related. My code automatically retries a command to the servo if it fails to get a response so system-wise there's no issues but I just wonder if this is some other lurking problem that's going to resurface later.
User avatar
pbreed
Posts: 1080
Joined: Thu Apr 24, 2008 3:58 pm

Re: MOD54415 RTS line in Half Duplex Mode

Post by pbreed »

The 485 system is used in a lot of industrial environments.
These are often half duplex 485...

EXACTLY what calls are you making to open the serial connection..

Should be
OpenSerial...
Serial485HalfDupMode( port#, true );

Please note port# is the port number , not the FD returned from openserial.

Also confirm you have no SendBreak anywhere...
Watzlavick
Posts: 22
Joined: Mon Jan 27, 2014 7:19 pm

Re: MOD54415 RTS line in Half Duplex Mode

Post by Watzlavick »

I'm using:
// Configure the UART
fd = OpenSerial (serial_port, k_servo_baud_rate, 1, 8, eParityNone);

// Set RS-485 half-duplex mode
Serial485HalfDupMode (serial_port, 1);

// Set wired-OR mode (TX is used for read/write, RX not used)
sim1.gpio.utxd_wom |= 1 << serial_port; // Wired-OR mode for TX
sim1.gpio.urxd_wom |= 1 << (2 * serial_port + 1); // Automatic internal RX switching based on RTS

// Configuring wired-or mode overwrites the direction bit for PE2 so set it back to an input
sim1.gpio.pddr_e &= ~0x04;
...
num_written = write (fd, reinterpret_cast<const char*>(write_buf), write_buf_len);
...
num_read = ReadWithTimeout (fd, reinterpret_cast<char*>(p_buf), buf_size, 1);

No SendBreak anywhere. If it was a configuration issue, why would it work 99% of the time though?
Watzlavick
Posts: 22
Joined: Mon Jan 27, 2014 7:19 pm

Re: MOD54415 RTS line in Half Duplex Mode

Post by Watzlavick »

I am also writing to Port E on a regular basis but I don't think I'm interfering with the RTS line on PE1
Setup:
J2[36].function (PINJ2_36_GPIO);
sim1.gpio.ppdsdr_e = 0x80;
sim1.gpio.pddr_e |= 0x80;

Writing:
if (mask & (1 << Dig_io_bit_pos_t::gox_solenoid_out))
{
if (data & (1 << Dig_io_bit_pos_t::gox_solenoid_out))
sim1.gpio.ppdsdr_e = 0x80; // Set the bit
else
sim1.gpio.pclrr_e = ~0x80; // Clear the bit
}
User avatar
pbreed
Posts: 1080
Joined: Thu Apr 24, 2008 3:58 pm

Re: MOD54415 RTS line in Half Duplex Mode

Post by pbreed »

Wired or mode is different than the standard usage, alas it should work...
Nothing that looks suspicious in erata... I'll try to assemble a test...
When RTS gets stuck low, does it stay low forever if you don't do anything?

I'm thinking I'll set up uart and tie RTS to gpio pin I sample...
Watzlavick
Posts: 22
Joined: Mon Jan 27, 2014 7:19 pm

Re: MOD54415 RTS line in Half Duplex Mode

Post by Watzlavick »

Yes, when it sticks low, it stays low until the end of the next TX. As a test, I put the task into an infinite loop when I got the read timeout and the RTS line stayed low forever. It always recovers on the next TX and I've never seen it stick twice in a row. I'm able to catch it on a scope with a width trigger setting. When I disabled most of the other tasks, it would take several minutes to show up. I'll try a test later where I disable all UART activity (including my console prints) except for UART1.

I have 4 of the AX-12A servos in my system but I was worried a failure in one could take out all of them so I added a 2:4 mux to isolate them from each other. So I need the RTS line and the mux to switch the direction on the buffers. If I had placed them all on the same bus, I wouldn't have needed RTS and it probably would have just worked.

As a workaround, I was trying to set the set the RTS line high manually in the ISR but I haven't figured out how to do that yet. I'm not sure I can detect when the last data + stop actually gets clocked out though, only that the last word was sent to the shift register.
Post Reply