UART interrupt for teensy 3.5

Arup

Member
Dear members
I am currently using Teensy 3.5 for uart (RS232) reading from another device. I am using the arduino environment for programming the Teensy 3.5
Please tell me how to create a serial interrupt reading when a byte is received by the Teensy. I dont want to use the polling method of the Arduino.
Every time a byte is receive the program will jump to serial interrupt to read it and clear the FIFO.
I should also be able to send bytes as TX when ever my application demands.
Please suggest how to do it.
Regards
Arup
 
Teensy UART reads use interrupt support of the hardware for FIFO to Empty on Rx or Fill on Tx.

This happens using the Serial# {#=1,2,3,4,5,6} functions.

In both cases a circular RAM buffer holds the Rx or Tx data after Rx or until Tx.

The interrupt code manages the circular buffers for read/write access by those dedicated functions.
 
Thank you for the update ! I want a code sample with uart receive interrupt enabled to test it!
Similarly for the transmit function !
 
Have you looked through https://www.pjrc.com/teensy/td_uart.html? The non-blocking functions Serial1.availableForWrite() and Serial1.available() might help. The setup functions Serial1.addMemoryForRead(buffer, size), Serial1.addMemoryForWrite(buffer, size), Serial1.attachRts(pin), and Serial1.attachCts(pin) might also help.

Is it the Serial1.available() polling call that's bothering you, or is it the potential blocking of a Serial1.read()?
 
First you should know, just in case you haven't already found it, this page has the documentation for hardware serial on Teensy.

https://www.pjrc.com/teensy/td_uart.html

The documentation explains interrupts with only this:

All serial ports on all Teensy boards use interrupt-based transmit and receive buffering, to allow your program to avoid waiting when writing short messages, and to allow data to be reliably received even if your program must spend time performing other tasks.

I do not 100% understand your question. Especially this part isn't clear to me:


Please tell me how to create a serial interrupt reading when a byte is received by the Teensy. I dont want to use the polling method of the Arduino.

The normal usage is the HardwareSerial interrupt function receives data from the serial port and places it into a buffer in memory. Then your program can poll the amount of data in the buffer with Serial1.available() and remove it from the buffer with Serial1.read(). If the buffer is not large enough to store incoming data while your program performs other works, you can use Serial1.addMemoryForWrite() to increase the size. Full details are on that documentation page.

Likewise for transmitting, a buffer is used where Serial1.print() and Serial1.write() store data into the buffer and interrupts are later used to actually transmit it at the speed the hardware runs. Your program can use Serial1.availableForWrite() to check how much space the buffer has, if you wish to avoid waiting due to transmitting more than the buffer can immediately accept.

Now for guesswork (because I do not fully understand your question), my guess is you may wish to have your code run when the interrupt occurs, rather than the normal behavior of the interrupt merely depositing the incoming data into a buffer. This behavior is only partially supported, using the serialEvent1() function. However, this is not documented on the serial page, as it is not normally recommended. But we do include this because it is defined by Arduino. You can find documentation on these pages:

https://arduinogetstarted.com/reference/serial-serialevent

https://docs.arduino.cc/built-in-examples/communication/SerialEvent

I said this is only partially supported, because the serial event function is *not* called by the interrupt function. Instead it is called when any function you use calls yield(), or if your program calls yield(). This design is not as immediate as if the function call had been made from within the interrupt, but it does avoid some very thorny race condition issues, which I'll explain in a moment....


I want a code sample with uart receive interrupt enabled to test it!
Similarly for the transmit function !

A code sample which meets all your desires may not exist. It is difficult to answer when I do not fully understand your needs.

But I can point you to the interrupt-based code which implements the receive into a buffer.

https://github.com/PaulStoffregen/cores/blob/master/teensy3/serial1.c

I'm not going to write a unique code sample just for you (especially when I lack full understand of your application) but I can at least offer some advice about how you might modify the serail1.c code. The code which reads the incoming data from the serial port FIFO begins at line #625. You can see only several lines later it writes the data to either rx_buffer[] or rx_buffer_storage_[]. Those arrays are the built in buffer, and the additional buffer which can be optionally added by Serial1.availableForWrite(). If you wanted to create a program where the serial interrupt does not put the incoming data into a buffer, but instead does something with it immediately as part of the interrupt, this is the most likely location where you would modify the code.

You could make a copy of all this code into your program. Perhaps you would change all global scope names, so it can't accidentally conflict with the code inside the core library. Or maybe just editing the core library code already installed on your computer would be simplest. If you go that route, please be careful to make a backup copy, just in case a future install of the software might overwrite it. (of course, everyone should always make backups of important work... but few people seem to spend the extra effort needed)

I'm going to spent just a few moments to add a cautionary note to this already lengthy message. Sharing data between interrupts and main program context is difficult to design properly. It is explained on the IntervalTimer page, under "Interrupt Context Issues"

https://www.pjrc.com/teensy/td_timing_IntervalTimer.html#interrupts

Many people have built programs which usually work but then suffer rare and difficult to reproduce timing or race condition bugs when data is shared between interrupts and the main program. The reason why Teensy's serial port code, and the interrupt-based serial port code on most other systems is built around the paradigm of the interrupt storing data into a buffer and the main program reading data from that buffer is because that type of error is so easy to make and so difficult to troubleshoot. If you attempt using the data directly from the interrupt function, perhaps your code will be bug free, but before you attempt it (if that is what you really wanted.... again, this is guesswork on my part based on only a few words in your question) please be aware this sort of design is rarely used in practice because of the tendency for subtle bugs which are extremely difficult to troubleshoot.

Hopefully this answered your question? And if you do attempt to modify the interrupt function to directly process the incoming data, hopefully you can avoid sharing data between the interrupt and main program. Or if you do go down that path, at least know before you start that it at first appears to be deceptively easy, but in practice the race condition bugs that usually occur are almost impossible to reliably reproduce and fix.
 
Back
Top