Skip to content

USART interrupt handler, handle Rx timeout - #38

Open
ek-ap wants to merge 9 commits into
Microchip-MPLAB-Harmony:masterfrom
Enerkite:master
Open

USART interrupt handler, handle Rx timeout#38
ek-ap wants to merge 9 commits into
Microchip-MPLAB-Harmony:masterfrom
Enerkite:master

Conversation

@ek-ap

@ek-ap ek-ap commented Dec 17, 2021

Copy link
Copy Markdown

On an ATSAME70N19B, the Harmony 3 USART interrupt handler USARTx_InterruptHandler( void ) currently discards the TIMEOUT interrupt that is generated when the timeout delay period (US_RTOR.TO) expires. Commit acc4c82 therefore adds a hook to the interrupt handler to process the Rx timeout interrupt. I would strongly ask for such a hook (as in the commit or similar) to be included in the next release, as it helps when receiving variable-length messages.

It could also make sense to enable/disable the timeout feature via the Harmony 3 Configuration interface. I'm unfortunately not familiar with how to include such options in the GUI. A similar hook could be implemented for the transmitter timeguard register (US_TTGR), and also for the LIN mode. As I only work with the standard USART mode, these are not included in the patches below.

Additionally, commit f692803 contains user interface functions to set/enable, reset, and clear/disable the Rx timeout for the standard USART interface. These are not as urgently needed as the hook in acc4c82, but it would also be nice to have such an interface.

@vishalnxt

Copy link
Copy Markdown
Collaborator

@ek-ap , thank you for reporting the issue and providing the fix. We will review it. Meanwhile, did you try using the Ring buffer mode of UART PLIB? Based on your description, it seems you are receiving variable length messages and the ring buffer mode is better suited for such requirements. You can find an example application here.

@ek-ap

ek-ap commented Dec 17, 2021

Copy link
Copy Markdown
Author

Yes I did. Unfortunately, the Ring buffer mode does not provide DMA transfer out-of-the-box. All data transfer seems to go through the processor. As we're receiving data at 2 MBaud (not a typo) on one USART interface (and also want to use the processor for other tasks), we rely on DMA data transfer. I would love to see the DMA transfer feature on the PLIB ring buffer off-the-shelf, but meanwhile the above patch will do.

We've found a way to configure the DMA linked-list mode to act similar to a ring buffer. But we need to flush the DMA data transfer after receiving of a full message (i.e. upon Rx timeout). So we need to be able to catch the USART Rx timeout interrupt.

@ek-ap
ek-ap force-pushed the master branch 2 times, most recently from cf63435 to f522e1e Compare July 6, 2022 16:27
@ek-ap

ek-ap commented May 15, 2023

Copy link
Copy Markdown
Author

How is the status of this request?

In the mean time we added cache invalidation code to the MCAN peripheral lib to make it work wit data-cache enabled. Since MCVN uses DMA for the transfers to/from the message RAM, data is corrupted if cache is not cleared/invalidated correctly.

@ek-stsk

ek-stsk commented Jun 8, 2026

Copy link
Copy Markdown

How is the status of this request?

Since the change of harmony content inclusion in MPLAB X IDE 6.3 it is quite combersome to get our custom content into the MCC. Still our system depends on these additions.

Stefan Skutnik added 2 commits July 13, 2026 08:57
SERCOM_I2C_InterruptHandler(), in the SERCOM_I2C_STATE_TRANSFER_DONE branch,
waited for the bus to return to IDLE with no escape:

    while((SERCOM_REGS->I2CM.SERCOM_STATUS & SERCOM_I2CM_STATUS_BUSSTATE_Msk)
            != SERCOM_I2CM_STATUS_BUSSTATE(0x01U))
    { /* Do nothing */ }

A device that keeps SCL low after the transfer has otherwise completed spins
the CPU there forever, at interrupt priority. There is no fault and no log --
the board simply stops, which is far harder to diagnose than a hard fault.
This is reachable in practice: I2C sensors that stretch or wedge the bus are
exactly the case this loop fails to survive.

There is no hardware escape either. CTRLA.LOWTOUTEN cannot release it: the
SERCOM time-outs are clocked from GCLK_SERCOM_SLOW and specified against a
32 kHz clock, and this plib has no time-out support at all -- it never enables
the interrupt, never tests STATUS.LOWTOUT and never clears that write-1-to-clear
bit. Only the I2C slave plib implements LOWTOUT.

Bound the loop. A STOP takes tens of microseconds even at 100 kHz, so the
constant is a very generous margin whose only job is to make the wait finite.
On expiry report SERCOM_I2C_ERROR_BUS, so a stuck bus surfaces to the client as
a failed transfer it can recover from, rather than a transfer reported as
successful on a bus that is still held.

The unbounded wait in SERCOM_I2C_BusScan() is left alone: it is not in an
interrupt and is not used on the affected path.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants