Question regarding Serial.end() - teensyduino

Status
Not open for further replies.

11douglash

New member
Hello all,

An in-the-weeds question about versions of teensyduino here. Here's the general premise:

I have a teensy 3.5 & xbee pair. They normally communicate over Serial. The xbee is operating in API mode 2, which is a packetized mode. I'm using the XBee library provided in teensyduino.

After boot, the first thing the teensy does is issue a command to change the Xbee's baud rate.

I've had my code (see below) & hardware working for a long time on arduino 1.8.1 & Teensyduino 1.41. We recently upgraded teensydunio versions, and then things started breaking.

With versions 1.8.1 / 1.45, 1.8.5 / 1.45, and 1.8.8 / 1.45, after I change the baud rate, all further communication from the xbee is broken. I went into the xbee library to print out the bytes being recieved: there is actually data flowing back, but it's somehow corrupted, none of it looks like a normal XBee packet. I've confirmed that the XBee is actually recieving messages from the teensy at the new baud rate.

Remove the Xbee_Serial.end() line when changing baud rates, and the code using Teensyduino 1.45 correctly works.

Code: This is normally in a library, i've consolidated the relevant portions here.
Code:
  #define XBee_Serial Serial1


  XBee xbee = XBee();

  XBee_Serial.begin(9600);
  xbee.setSerial(XBee_Serial);


  uint8_t config_value[2];
  config_value[0] = 0x05;
  set_xbee_config("BD", config_value, 1); //this command tells the xbee to change its baud rate.  The Xbee will acknowledge the command at 9600, and then start listening / talking at the new baud rate, 38400.
  delay(100);
  XBee_Serial.end(); //this is the line that causes problems.  It must be removed for Teensyduino 1.45 to correctly work.

  //if it is not removed, all further calls to set_xbee_config result in Serial.println("No xbee response received during configuration.")


  XBee_Serial.begin(38400);
  config_value[0] = 0x11 * ID;
  config_value[1] = 0x11 * ID;
  set_xbee_config("MY", config_value, 2);
  config_value[0] = 0x0C;
  set_xbee_config("CH", config_value, 1);
  config_value[0] = 0xBE;
  config_value[1] = 0xEF;
  set_xbee_config("ID", config_value, 2);

And the function that sets xbee settings:
Code:
Rx16Response rx = Rx16Response();
TxStatusResponse txStatus = TxStatusResponse();

AtCommandRequest atRequest = AtCommandRequest();
AtCommandResponse atResponse = AtCommandResponse();


  void set_xbee_config(String cmd_name, uint8_t value[], uint8_t value_len) {
  uint8_t cmd_char[2];
  cmd_char[0] = cmd_name[0];
  cmd_char[1] = cmd_name[1];

  atRequest.clearCommandValue();

  Serial.print("command: ");
  Serial.println(cmd_name);

  Serial.print("Value length: ");
  Serial.println(value_len);

  Serial.print("value: ");
  for (int i = 0; i < value_len; i++) {
    Serial.print(value[i], HEX);
  }
  Serial.println();
  atRequest.setCommand(cmd_char);
  atRequest.setCommandValue(value);
  atRequest.setCommandValueLength(value_len);
  xbee.send(atRequest);



  if (xbee.readPacket(3000)) {
    if (xbee.getResponse().getApiId() == AT_COMMAND_RESPONSE) {
      xbee.getResponse().getAtCommandResponse(atResponse);
      if (atResponse.isOk()) {
        
        //for the record, the BD command will send back an AT COMMAND RESPONSE at the old baud rate b4 moving to the new BR.
        if (String("BD") == cmd_name) {
        // Changed baud rate, need to restart serial
        return;
        }

        atRequest.clearCommandValue();
        atRequest.setCommand(cmd_char);


        xbee.send(atRequest);
        xbee.readPacket(5000);
        xbee.getResponse().getAtCommandResponse(atResponse);
        Serial.print(cmd_name);
        Serial.print(" set to: ");
        for (int i = 0; i < atResponse.getValueLength(); i++) {
          Serial.print(atResponse.getValue()[i], HEX);
        }
        Serial.println();
        return;
      } else {
        Serial.print("Error code: ");
        Serial.println(atResponse.getStatus());
      }
    } else {
      Serial.print("Expected AT response but got: ");
      Serial.println(xbee.getResponse().getApiId());
    }
  }

As far as I can tell, there is a difference in the serial1/2/etc library between 1.41 and 1.45. It happens on lines 225 / 226, in serial_end() of serial1.c. Notably, serial1.end() is the command that is causing things to break:


The addition is here:
Code:
	UART0_S1;
	UART0_D; // clear leftover error status

I suppose my question here is: are these two extra lines indeed the only things that change when one calls Serial1.end() in the different versions of teensyduino? Were these changes an intended feature fixing some other issue?

I just wanted to bring this to someone's attention in case other mysterious bugs involving Serial1.end() are occurring.

It's also worth pointing out that the Teensyduino's xbee library seems to be out of date, (or at least it has less lines of code) compared to this Xbee library.

Thanks! I'd be happy to answer any questions or turn over the full code base if someone else wants to replicate.
 
Last edited:
Were these changes an intended feature fixing some other issue?

Yes, a very rare bug was discovered months ago. If a byte was received into the UART's FIFO with a framing error, but the UART had not yet generated an interrupt before end() was called, the error state would remain in the hardware. Then later, calling begin() would lock up.


Thanks! I'd be happy to answer any questions or turn over the full code base if someone else wants to replicate.

Just to be realistic, a large program which depends on XBee modules and (maybe) other stuff probably isn't going to allow anyone else to reproduce this problem. I don't have any easy answers here. But if this really is a bug in the serial driver code, a way to reproduce the problem is going to be needed for any sort of investigation.
 
Status
Not open for further replies.
Back
Top