Teensy 4 IntervallTimer interrupts Serial2Event not working

Status
Not open for further replies.

andi00085

New member
Hi,
I have a rfid reader on the serial2 (115200) and this will be read with the serialevent2() function. Besides I have an IntervallTimer object (1 second) which I use for printing status infos on the serial7.
If I enable the IntervallTimer I always miss randomly bytes on the serial2 and if i disable the IntervallTimer I miss no bytes. Do you have any suggestion how to handle this (set priorities from irq?).
One generall interrupt question. If the priority from interrupt1 is higher than interrupt2, do interrupt 1 will "interrupt" the interrupt2 or will interrupt2 will be finished and after this if more than one interrupt will be activ the interrupt with the higher priority will be fired?

Thanks for your help

Andi
 
Is there a simple repro case with the _isr() timing and data coming into Serial2? For the test sending from Serial1 crossed to Serial2 would be easy. Also details on what is sent out Serial7 for status and at what baud? Not sure of the Tx buffer size offhand - default will be 64 bytes at most. Once that is fill further prints will block to finish - while the Serial2 buffer overflows at 115Kbaud.

<edit> these are the default buffer sizes::
>> SERIAL7_TX_BUFFER_SIZE 40
>> SERIAL2_RX_BUFFER_SIZE 64
Calls with these can add more buffer at runtime:
Code:
void HardwareSerial::addStorageForRead(void *buffer, size_t length) 
void HardwareSerial::addStorageForWrite(void *buffer, size_t length)

115K isn't that fast - but the default Rx buffer of 64 bytes will fill ~180 times per second if not kept emptied - at full speed it fills in ~5.5 ms.

serialEvent2() is only run on the exit of each loop, or delay() or yield(). It can be triggered with a call to yield() - or inserting calls to serialEvent2() in the code. serialEvent2() is not triggered by interrupts.
 
Last edited:
Hi,
Serial2 is the important serial, because no data should be lost from the rfid reader. The Serial7 is only dumping some debug information for me into a file via putty. The serial7 speed is 921600.
After your post I know the serialevent2() isn't called instant if some bytes are received via the serial2. I thought it is a good idea to create an IntervallTimer with 1 ms and in the IntervallTimerFunction I will read the serial2 but that didn't worked.
For sure the logging to serial7 isn't "good" but I need it for debugging purpose. Do the IntervallTimer blocks the serial2 hardware reading int to SERIAL2_RX_BUFFER? Should I use something like DMA to empty the SERIAL2_RX_BUFFER? I thought with interrupts I can handle this smooth getting all data from serial2 and also have a 1 second timer for status infos (lower priority). Furthermore I have a gsm modem via serial1 and the gsm code will block the loop and so I have to use interrupts to get all data from the serial2. Do you have any suggestion? I will test increasing the TX7_buffer and will sent the results in the next post. Thanks
 
Hi. I increased the serial7 tx buffer and it is a little bit better, but I have still some missing bytes over the serial2. I made an progamm overview, maybe it helps a little bit.
2020-05-25 19_21_55-CodeView.pdf - Adobe Acrobat Pro DC.jpg
 
Again sometimes it really helps to see a more complete program to see if there are some obvious solutions.
Like you mention that loop goes into blocking mode with delay...

If it actually calls delay... It will call yield, which should call your serialevent2 function... Again assuming that is where your code is.

Now if your code is doing it on delay stuff, like:
Code:
elapsedMillis em = 0;
while (em < 500) {
...
}
or anything similar, like waiting for (startTime - millis()))... Then yield may not be called and as such your function is not called.

If so one simple fix is to call yield() in your loop, either directly or by calling something like delay();

But maybe your code is hung in processing stuff in an Interrupt handler that has a higher priority (lower number) than the Serial7 Interrupt handler and your code is waiting for something to be done. This can cause issues where maybe more characters arrived at the Serial port than could be buffered in the Hardware queue while waiting for ISR to move the data from hardware queue to software queue and as such the data was lot there. So in that case maybe solution is to change the priority of the SerialX ISR to be higher priority...,

Now if it is hung on waiting for Serial7 or writing to SD Card than maybe other stuff needs to be done. But again hard to say without seeing where it may be hung up.
 
Got pulled away before posting ...

How long is the RFIS data string? If Serial2 is missing bytes, that is the buffer to increase as a stopgap/test/quick fix - but it should be large enough for at least one full message. With Serial7 running at 921600 it will empty 8 times faster than Serial2 fills which is good.

In the end if as the 'overview' indicates the incoming Serial2 data is the "HIGHEST PRIORITY" the code needs to be written with that in mind. Either the Serial2 data is not being read fast enough to prevent overflow, or the reading routine is not properly processing the data.

Other elements of the sketch may be taking significant amounts of time causing delays over 5+ ms between reads of the Serial2 data.

As noted serialEvent2() is NOT interrupt driven but called on loop() exit, yield() - also delay() - but adding any delay() is counter productive in keeping loop() cycling.

Another sketch open here on same speed T_4.1 using all 8 serial ports is working with intervalTimer calling serial processing loop is working - though that seems safe - it should perhaps only pull the data to a buffer for loop() processing.
 
Hi,
after some intensive testing I found the mistake in reading the serial2. For the receiving and decoding afterwards of the rfid reader serial 2 stream I used the Serial2.readBytes() command and the readBytes read a special amount of bytes and also will wait for the bytes to get the amount of bytes. So, I used this in the IntervalTimer ISR function (1ms) and so the call have a duration of > 40ms!. I changed the Serial2.readBytes() to the normal Serial2.read() command and check afterwards if more bytes still available and read again. Now it works perfect :).

Thanks for your help
Andi
 
Status
Not open for further replies.
Back
Top