disabling UART break detection in T3.x

Status
Not open for further replies.

JFayer

Member
Does anyone know if it's possible to disable break detection altogether in a T3.x UART? I'm trying to use a T3.x to communicate w/ an established '485 network. But it has terminating resistors in the design that force an undriven line to a 0/spacing state (pull-down on D+, pull-up on D-). Well, to a T3.x, this looks like a break in the line, and that messes up any message that immediately follows. All the '485-to-USB converters seem to ignore breaks, so this hasn't been a problem for anyone else, only me, because I really want to use a T3.x here.
 
So are you connecting to UART (serial1 serial2 serial3) TX RX or USB D+ D-? :confused:
Correct me if I'm wrong but Teensy 3.x does not have Noise Error, Parity Error or Break interrupt implemented by default on any of the uart serial ports.

I'm no expert on USB (Universal Serial Bus) but you did mention (pull-down on D+, pull-up on D-).
I did some Googling and find this:
The pull-up on D+ perform two tasks, connection and speed sensing. Without a pull up resistor, USB assumes there is nothing connected to the bus.
Some devices have this resistor built into its silicon, which can be turned on and off under firmware control, others require an external resistor.
 
Thanks! And sorry for the confusion.
I'm using serial1, hardware serial, on RS-485. (I'm not clever or daring enough to mess with USB.) And labels D+ and D- are sometimes used on the two balanced-voltage lines in RS-485, too.
If I remove the non-standard resistors, my T3.5 works great. If I leave the non-standard resistors in place, any other UART works fine, but not T3.5.
Now, I might be wrong, but my difficulty is not software and interrupts. It seems that with this non-standard pull-up and -down arrangement, the T3.5 hardware has trouble finding the first start bit after the line driver turns on. This could be due to the appearance of a (false) start-bit when the driver turns off, changing my line from a 1 to a zero, and this would mess up character sync for at least 1 character time. But all UARTs would see the false start bit, and most all other UARTs seem to work fine.
So, I speculate that, instead, it might be due to the hardware's seeing break characters when my line isn't driven, and this does mess with error flags whether interrupts are enabled or not, according to the Kinetis user's manual. And that same manual says I can't disable break character detection, only adjust its length. (I should experiment and see if continuous 0s produce repeated break characters. I'm guessing they do.)
I'm hoping someone has a trick up their sleeve.
 
Let's talk of the RS485 signals as "A" and "B" according to this diagram.

rs485.jpg
(click for full size)

Maybe you could describe the circuit again with "A" and "B"?
 
Yes, thanks. In addition to the termination resistors across A and B, there's one pull-down on the A line and one pull-up on the B. As you know, an idle serial1--hardware serial--data line is high, and A would be high while B is low. But, here, when no driver is enabled, the pull-down on A and pull-up on B cause the data line to read low. And, rather than idle, this looks like a break, or an all-zeros character with no stop bit.
 
if the pins are low power mode disabled on startup, why not use the built in pullup/pulldown when activating the uart pins? this way theres no pullups/pulldowns on startup, and then theres pullups/pulldowns after initializing the uart interface and configuring the pin pull direction
 
Ok, I have 2 question for you.

1: First, have you tried connecting the TTL level input of some other device to the same signal Teensy is actually getting from the RS485 chip? For example, have the chip drive both pin 0 (RX1) on Teensy *and* the input to a FTDI-based USB-serial cable. The important question is whether Teensy really is getting a valid TTL level signal. If the signal is idle at logic low when the (low) start bit begins, then no UART could ever hope to detect the beginning of the start bit and receive the following data bits! I know you've said other devices work and Teensy doesn't, but the important question is whether this test was done with both devices receiving the EXACT same signal.

2: If Teensy really is having trouble with a signal other devices can receive, how do I go about setting up a test here to get EXACTLY that same signal? I have some of those RS485 chips and plenty of resistors. But getting the EXACT same signal will require connecting something to the transmitter chip when turns on the DE pin and drives the DI pin with the EXACT same relative timing. Again, I'm going to point out that the transmitter *MUST* turn on DE and allow at least a short time before the start bit, because the improper resistors are holding the line in the non-idle state. Any UART, whether Teensy or a USB-Serial cable, requires detection of the beginning of the start bit, which just can't happen with this connection unless DE turns on first and enough time is allowed before the start bit begins. So if I'm going to try to reproduce the problem here, I need to know how to get the exact same DI & DE signals on the transmit side.
 
I have no experience with RS485 but perhaps you can enable the noise and framing interrupt errors and see if you can detect that situation.
Not tested but should work I believe.
Code:
#define IRQ_ERROR_PRIORITY  48  // 0 = highest priority, 255 = lowest

void setup() {
  delay(1000);

  // Frame error and Noise Error Interrupt Enable
  // Set error IRQ priority lower (higher priority) than that of the status IRQ PRIORITY 64,
  NVIC_SET_PRIORITY(IRQ_UART0_ERROR, IRQ_ERROR_PRIORITY); // E PRIORITY 48, 0 = highest priority, 255 = lowest
  // NVIC_SET_PRIORITY(IRQ_UART0_ERROR, NVIC_GET_PRIORITY(IRQ_UART0_STATUS) - 16); // 0 = highest priority, 255 = lowest
  // Enable UART0 interrupt on (Frame Error, Noise Error) and enable IRQ
  UART0_C3 |= UART_C3_FEIE | UART_C3_NEIE; // Framing Error Interrupt Enable // Noise Error Interrupt Enable
  // UART_C3_PEIE    0x01      // Parity Error Interrupt Enable
  // UART_C3_ORIE    0x08      // Overrun Error Interrupt Enable
  NVIC_ENABLE_IRQ(IRQ_UART0_ERROR);
  attachInterruptVector(IRQ_UART0_ERROR, UART0RxError);

  //Set up Frame error and Noise Error before calling Serial1.begin(..)
  Serial.begin(9600); // USB is always 12 Mbit/sec
  Serial1.begin(9600); // UART0 RS485
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.println("Hello World...");
  delay(2000);  //
}

void UART0RxError(void)
{
  uint8_t E;
  if (UART0_S1 & UART_S1_FE) {
    __disable_irq();
    E = UART0_D; // dummy unload
    UART0_CFIFO = UART_CFIFO_RXFLUSH;
    UART0_D = 0; // dummy upload
    UART0_CFIFO = UART_CFIFO_TXFLUSH;
    __enable_irq();
    Serial.print("BUS Frame Error ");
    Serial.println(E);
  }
  if (UART0_S1 & UART_S1_NF) {
    __disable_irq();
    E = UART0_D; // dummy unload
    UART0_CFIFO = UART_CFIFO_RXFLUSH;
    UART0_D = 0; // dummy upload
    UART0_CFIFO = UART_CFIFO_TXFLUSH;
    __enable_irq();
    Serial.print("BUS Noise Flag ");
    Serial.println(E);
  }
}
 
If you have an oscilloscope or logic analyzer, a capture of the signal Teensy really is receiving at RX1 would also really help.

If I work on investigating this issue (which is contingent on a clear way to reproduce the signal), I'll set up whatever is specified on the transmit side and my very first step will be to capture the real waveform with my scope. To really get to the bottom of what's going wrong here, before guessing what to do about software, we really need to check what waveform is actually arriving at the RX1 pin.

Again I want to stress asynchronous serial communication fundamentally depends on detection of start bits. The timing between the DE pin and start bit on the DI pin of whatever is transmitting the RS485 signal will be critical, because of the wrong resistors holding the line in its non-idle state. If DE isn't driven (active high) significantly before the beginning of the start bit on DI, so that the idle state appears on the line before the start bit begins, then there's no way any receiving devices, whether Teensy or anything else, could ever hope to see a valid start bit.

I know you believe there may be a problem unique to Teensy. Indeed that is possible, and if there is I certainly do want to find and fix it. But this particular case of holding the line in it's non-idle state is very unusual and risks creating invalid waveforms. I know you're said you tested where other devices worked and Teensy didn't... but the details of exactly how the tests were done matters greatly. I need very specific details about how to duplicate your test if I'm going to investigate it here.
 
Last edited:
I appreciate the help you're offering, and thanks, but I need to puzzle it out here. And it isn't worth it, as this is a very unusual situation--very non-standard. It's not a Teensy problem, but almost certainly the Kinetis UART that's so much more capable than I need--and which sees this non-standard bus configuration as an error. It seems the best thing I could do is carefully look at the error bits and the flags set due to break detection and handle them so they don't interfere with the correct processing of what immediately follows. Which I think is what Chris O. was saying. It would be convenient if break detection could be turned off, so I could be sure the issue has nothing to do with UART-vs-break.
I'm using an RS485-to-USB converter that's high-speed, isolated, and has a Silicon Labs CP2104 UART-to-USB.
Here's a 'scope shot of the A and B signals, and RX1, while a single ACK is sent: first the driver is initially disabled, then enabled for a about a bit-time, then a start-bit of 0 and data 0:1:1:0:0:0:0:0, a stop bit (1), then idle (1s) for a couple of character-times, then the driver is disabled.
A_B_and_RX1_ACK.png
As you might be able to see, it's 230,400 baud, and, after the line driver is enabled, there is about 1 bit-time of marking line before the beginning of the start bit. And, yes, the converter gets every character of every message all the time, while, simultaneously, the Teensy 3.5 misses most.
Of course you're right that it all depends on the start bit. But no start bit, no matter how clean, will be detected if, say, a false start bit precedes it by less than a character-time--if it arrives while the UART is in the middle of assembling a character or break.
 
I see what looks like about 1/2 a bit time before the start bit. Do you have control over the DE signal on the transmitter side? Maybe try lengthening the logic high before the start bit.
 
PaulStoffregen~
On close inspection, it can be just under a bit time, at its shortest. And, sadly, I do not have control. What you see is comms between modules in an established product.
But! What I did learn is that breaks (when not in LIN mode) are nothing more than characters with all bits 0, and with a stop-bit of 0, which, of course, produces a framing error (and others maybe.) Starting with Chris O.'s code snippet, I now have (most) messages reading completely and correctly on the T3.5. I'm sure by diving in and understanding in detail the way Teensyduino library handles these errors, I'll be in business in no time.
My thanks, and sorry for having phrased this issue as if it could be a deficiency in T3.5, when it's entirely my lack of familiarity with my issue and the software that handles it. In fact, I love the T3.5, and I'm happy I'm here and not still with T2.0.
Chris O.~
Thanks for the insight. And the code snippet, which worked, and led me down the right path. (I'd bet you understood my issue all along but were too modest to say.)
~Jay
 
Status
Not open for further replies.
Back
Top