USART Receive interrupt clarification


Active member
Hi in the picture below, it says there's in USART Receive interrupt. But it looks like it is only for Serial1. Is this only for Serial1 or are there ones for Serial2-8?
Screenshot 2023-09-26 125916.png
That table looks like it's for an AVR-based Arduino. For Teensy 4.1, yes, there are separate TX and RX interrupts for each serial 1-8.
No, that name is for Arduino, not for Teensy.

Oh thanks for letting me know! So what should I use for a USART receive interrupt? I'm a little confused on the documentation of the interrupts. Is there some place I can see an example code for the teensy? Especially for the USART interrupt?
Is there some place I can see an example code for the teensy? Especially for the USART interrupt?

You could look at HardwareSerial.cpp.

So what should I use for a USART receive interrupt?

Normally you wouldn't use these interrupt directly. You just use the Serial1 to Serial8 functions, as documented here:

But if you really want to write your own low-level serial code, you certainly can. The hardware is documented by the reference manual. Look for the LPUART chapter starting at page 2893.

You can find the list of all interrupts starting on page 44. Keep in mind the ARM processor also has 16 exceptions, which are pretty much just interrupts, but they don't appear on this list.

On Teensy 4.x, we have the interrupt vector table located in RAM. Normally you would call attachInterruptVector() to write your function's address into that table for whatever interrupt you want to use. You can see HardwareSerial.cpp does this in the begin() function which sets up the hardware.

You can find attachInterruptVector() defined in imxrt.h.

This message probably doesn't answer all your questions, but hopefully these links help you find the places to look for more info.
A couple of additional points, that might help.

As mentioned, there are 8 hardware UARTS (LPUART) objects, but the number of the hardware UART does not necessarily correspond to the Serial object number.
That is Serial1 uses LPUART6.

As mentioned all of the main work is done in HardwareSerial.cpp. All of the hardware specific information that is specific to each Serial port, is contained in an object that is passed into the
constructor of the Serial port. Each serial port is contained in their own files. That is Serial1 is defined in HardwareSerial1.cpp, Serial2 is defined in HardwareSerial2.cpp ...

The format of the Hardware structure is defined in HardwareSerial.h. Here is a portion of the Serial1 setup.
static BUFTYPE tx_buffer1[SERIAL1_TX_BUFFER_SIZE];
static BUFTYPE rx_buffer1[SERIAL1_RX_BUFFER_SIZE];

const HardwareSerial::hardware_t UART6_Hardware = {
	0, IRQ_LPUART6, &IRQHandler_Serial1, 
	#if defined(ARDUINO_TEENSY41)
	{{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}},
	{{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}},
	0xff, // No CTS pin
	0, // No CTS
	IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark
HardwareSerial Serial1(IMXRT_LPUART6_ADDRESS, &UART6_Hardware, tx_buffer1, SERIAL1_TX_BUFFER_SIZE,
	rx_buffer1,  SERIAL1_RX_BUFFER_SIZE);
You probably may not be interested in all of this data, but it does you show that it is using LPUART6. The interrupt number is: IRQ_LPUART6
And there is only one interrupt number for the UART. So if you write your own interrupt handler, it needs to handle everything, or find a way to
pass it back to our handler.

Hope that helps