Serial interrupt patching?

jim lee

Well-known member
How hard would it be to patch the Teensy 3.2's UART "I have a byte ready" interrupt to grab the byte and store it in my buffer as opposed to the little buffer it uses now?

I ask because I'm not well versed in the low level chip stuff. I typically write processor independent c++ code.

Thanks!

-jim lee
 
addMemoryForRead() adds memory. But, only up to 255 bytes. Or so I read in the earlier threads about it. I was hoping to add more. I'm currently testing 255 bytes, as I we type, hoping that'll be enough.

What's going on is I have a GPS module that spits out data at, I believe, 9600 baud. Normally this is no issue at all to keep up with. But now I'm adding a TFT and I suspect that when I go out to update parts of the display (blocking) the buffer overruns. Because it takes too long for my code to return from the updates. I have NOT timed this, it's just my suspicion.

-jim lee
 
In my application, I use a Ublox GPS at 115200 with ubx protocol, at 10Hz updates. And a ILI9341 TFT. I added 64 bytes buffer. No lost bytes from the GPS.

At 9600baud, one byte is 1.04ms. For a buffer of 255, it will overrun after 265ms. It is largely enough to update the complete TFT.
 

Serial1.addMemoryForRead(buffer, size)​

Increase the amount of buffer memory between reception of bytes by the serial hardware and the available() and read() functions. This is useful when your program must spend lengthy times performing other work, like writing to a SD card, before it can return to reading the incoming serial data.
The buffer array must be a global or static variable. Maximum total bufer size is 64K.
 
Looks like the old Teensy 3.x hardware serial code is using only uint8_t for the buffer index.


Before we supported addMemoryForRead() the only way was to edit the code. On Teensy 3.x, you'll still need to edit that core library code to gain support for more that 255 chars in the buffer.
 
Well, I finally did what I should have done a week ago. Ran the simplest code I could

Code:
char  buff[200];
int   buffIndex;

void resetBuff(void) {
 
    buffIndex = 0;
    buff[buffIndex] = '/0';
}

void   checkSum(void) {

   int   i;
   byte  chkSumVal;
   char  sumStr[4];
   byte  sumStrVal;
 
   if (strchr(buff,'*')) {
      i=0;
      chkSumVal = 0;
      while(buff[i]!='*') {
         chkSumVal ^= buff[i];             //xor the incoming char
         i++;
      }
      i++;
      sumStr[0] = buff[i++];
      sumStr[1] = buff[i];
      sumStr[2] = '\0';
      sumStrVal = (byte)strtol(sumStr, NULL, 16);
      if (chkSumVal!=sumStrVal) {
         Serial.println("***** Checksum failed! *****");
         Serial.print("The message [");
         Serial.print(buff);
         Serial.println("]");
         Serial.print("Msg length : ");
         Serial.println(strlen(buff));
         Serial.println(sumStrVal);
         Serial.println(chkSumVal,HEX);
      } else {
         Serial.println("It's ok");
      }
   }  else {
      Serial.println("***** Missing Checksum! *****");
   }
}


void loop() {

   char  aChar;
 
   if (Serial1.available()) {
      Serial.print(Serial1.available());
      Serial.print(" ");
      aChar = Serial1.read();
      if (aChar=='$') {
         Serial.print("Synk!");
         Serial.print(" ");
         resetBuff();
      } else if (aChar=='\n') {
         Serial.println(buff);
         checkSum();
         resetBuff();
      } else {
         buff[buffIndex++] = aChar;
         buff[buffIndex] = '/0';
      }
   }
}

Then looked at what was coming out of the GPS itself. Something's wrong. I can see that I'm consistlnly missing chars that should be coming out of the GPS. I never see more than 4 chars avalible, so it's NOT over running the buffer. At this point I'm thinking hardware. Mine or theirs, most likely mine.

Thanks for the input guys! I really appreciate it!

-jim lee
 
I would probably do differently, but first cut I would probably change your loop code:
Code:
void loop() {

   char  aChar;
 
   if (Serial1.available()) {
      Serial.print(Serial1.available());
      Serial.print(" ");
      while ((achar = Serial1.read()) != -1) {
          if (aChar=='$') {
             Serial.print("Synk!");
             Serial.print(" ");
             resetBuff();
          } else if (aChar=='\n') {
             Serial.println(buff);
             checkSum();
             resetBuff();
          } else {
             buff[buffIndex++] = aChar;
             buff[buffIndex] = '/0';
          }
      }
   }
}
That is I would try to process all of the characters that have already been read and not once per loop call

Longer term, I would probably do it by keeping some form of logical state table code, that sees the start of the message
and parses as it goes... And as @defragster mentioned there are probably several libraries that do this.
 
Just to put closure on all of this.

Got it working! Some remounting hardware in better positions and better mountings. (Wires were taking it hard.) Rewired everything. Added the extra buffer onto the Serial1 buffer bringing it up to 255 bytes. And, as far as I can tell, it's working flawlessly ever since. I was even able to adapt it to Open CPN (Charting software) and use it navigate our boat through a couple of tricky passes last week.

Thanks everyone! I really appreciate it.

-jim lee
 
Back
Top