AGT input edge detection interrupt occasionally missing

Hi,

Using R7FA6E10F2CFP, FSP Configurator Version 5.5.0 and IAR EWARM 9.20.2. This problem is reproducable with a very simple project without any OS.

We are using the r_agt timer to measure the pulse period of an input signal (frequency 100Hz ... 5kHz) connected to pin P404, by getting interrupts on falling edges and timer overflows. The interrupts are handled in a function based on the "AGT Input Capture Example" in the r_agt documentation.

This works fine most of the time, but every now and then it happens that there is no interrupt when a falling edge occurs. This has been verified using an oscilloscope and some debugging code.

It seems like the falling edge interrupt is missing in cases when the timer overflow interrupt (TIMER_EVENT_CYCLE_END) occurs at (or very close to) the falling edge (TIMER_EVENT_CAPTURE_A).

In the generated interrupt service routine agt_int_isr() in r_agt.c, it is checked if there was a timer overflow or not, but it is not explicitly checked if there was a falling edge.
What happens if both timer overflow and falling edge are active at the same time?
Is agt_int_isr() then called twice (does not seem so), or can it somehow be checked if both interrupts are active?

If there is no obvious explanation for this, I can try to create a simple project for the FPB-RA6E1 development board to demonstrate the problem.

Below is the FSP configuration:

  • Hello JohVai,

    A typical sample code that can be implemented on your case is the below:

    This callback on your case is the receive_f_falling_edge callback that you have defined. If you set breakpoints inside the two if cases, you will be able to check if both of the interrupts happen.

    Also, you asked what happens if both of these interrupts are enabled simultaneously. Usually, one of the two interrupts will come with a time difference, because of the very fast counter analysis of the AGT compared to the measured signal. The code above has been designed to check if the underflow comes firstly or not and give to the user the correct pulse time value regarding any pre- existing underflow.

    On a GPT FSP module you can define the priorities of the two interrupts, in order to say to the cpu which interrupt will be serviced firstly (in case of received the two interrupts the same moment), but this doesn't exist for the AGT module. But, it  isn't significant, if you implement something like the code above, because it checks both of the two cases.

    Neverthless, can you send a simple project to make some tests?

    Regards,

    AL_Renesas

  • Hello, and thanks for looking into this.

    My callback receive_f_falling_edge is according to this example, always checking for both interrupts. Most of the time both interrupts occur as expected. But sometimes it happens that there is no falling edge interrupt although there is a falling edge in the signal, i.e. one single falling edge is missed.

    But I will create a simplified example project for the FPB-RA6E1 development board that demonstrates the problem. I will provide that still this week.

     

  • Hello,

    Attached is now an example project to reproduce the problem, and a picture showing the problem on an oscilloscope.

    Instructions for reproducing the problem:
    - Use a FPB-RA6E1 development board.
    - Connect pin 415 to pin 404.
       - Pin 415 is an output providing a frequency signal simulating the real measurement.
       - Pin 404 is the input for the measurement, measuring pulse length.
    - The problem is best seen using an oscilloscope monitoring the following pins:
       - P404 is the input signal (simulated by P415)
       - P601 goes high when the error has occurred (use this to trigger the scope).
       - P602 changes its state each time a falling edge interrupt occur.
       - P600 changes its state when a timer overflow interrupt occur (falling edge timer).
       - The problem will happen with an interval of less than 1 minute.
       - When the problem occur (P601 goes high), you can see that there was a falling edge on the input signal (P404), but no interrupt was detected (P602 did not change its state as it normally does).
    - The problem occurance can also be caught by setting a breakpoint in receiver_f_periodic_callback(), but at that point the problem situation (falling edge missed) is already over.

    MissingInterruptDemo.zip

  • Hello JohVai,

    Thanks for the project.

    One more question from my side:

    In what input signal frequency can you see the failure or it is irrelevant from the input signal frequency and it can be shown any time?

    Regards

  • Hello,

    It does not happen at a specific frequency. The simulated input signal (P415) frequency is sweeping between 125Hz and 250Hz. When you connect that to the input pin (P404), the error happens every now and then, usually within some 10...60 seconds.

    I have not seen it happen if the input frequency does not vary. It can also happen at higher frequencies, but this demo project will not catch that.

  • One more thing I forgot to mention.

    To get falling edge interrupts, I had to add this to the generated r_agt.c at line 843:

    if (p_instance_ctrl->p_cfg->channel == 0)
    {
        // AGT channel 0 uses pin P404
        p_reg_ctrl->AGTIOSEL |= 1;
    }

    Otherwise there is no falling edge interrupts at all.

    Not sure if this is related to the problem, or maybe this indicates that I have some wrong setting in the FSP Configurator(?).

  •  Hello JohVai,

    First of all, about the P404 initialization, the code in line 843 is mandatory, but normally should be created automatically after selecting Generate Code on RA Smart Configurator.

    The setting below is responsible for the pin:

    Secondly, I checked your code and after running it, I didn't observe any faulty behaivour. I running it for 120seconds and the Pin601 never goes high. Also, I located a breakpoint inside the timer_callback which is responsible for the timeout detection and it never be called. Also, all the waveforms of the pins seem to work correctly, according to your needs:

    Running for 120seconds:

    Regards,

    AL_Renesas

  • Hello,

    Strange thing that you could not reproduce the problem, I have a FPB-RA6E1, and with this project the error happens continuously (as well as on our own custom hardware).

    However, I just found out the root cause of the problem and a way to fix it.

    The problem is in the the generated interrupt service routine agt_int_isr() in r_agt.c, and in the example function "AGT Input Capture Example" in the r_agt documentation.

    When agt_int_isr() is running, it can happen that both the overflow and falling edge interrupts are active at the same time. But in the code it is only check for the overflow interrupt (TUNDF bit of AGTCR), so the falling edge interrupt is missed if it is active simultaneously.

    The fix is to also check the TEDGF bit of AGTCR, and separately provide the state of TUNDF and TEDGF to the callback function.

    I have verified that this is the case (both interrupts are occasionally active at the same time), and with this fix, no falling edges are missed anymore.

  • Putting the fix here in case someone else has the same problem.

    Note that this works when using AGT to measure pulse period only. For other modes some additional logic may be needed.

    The following is added to the function agt_int_isr() in r_agt.c, before calling the callback function: p_instance_ctrl->p_callback(p_args). The place depends on BSP_TZ_SECURE_BUILD.

            // MANUAL FIX, Input signal edge interrupts are occasionally missed without this.
            // The original code above only checks if there is a timer overflow interrupt (AGTCR/TUNDF)
            // or not, but there can simultaneusly be a falling edge interrupt (AGTCR/TEDGF) as well.
            // If both are active at the same time, then the falling edge interrupt is missed.
            // This fix separately also checks if there is a falling edge interrupt.
            // See Renesas RA6E1 Group Hardware User's Manual (R01UH0930EJ0110, Rev.1.10, Feb 4, 2022),
            // Chapter 22.2.4 "AGTCR : AGT Control Register".
            // Cannot add parameters to the callback function as its prototype
            // declaration in hal_data.h will be overwritten by the RASC tool.
            // Using the (unused) capture variable instead to pass additional interrupt info.
            p_args->capture = 0;
            if (agtcr & R_AGTX0_AGT16_CTRL_AGTCR_TEDGF_Msk)
            {
                // Edge detected
                p_args->capture |= 1;
            }
            if (agtcr & R_AGTX0_AGT16_CTRL_AGTCR_TUNDF_Msk)
            {
                // Timer overflow occurred
                p_args->capture |= 2;
            }
            else
            {
                // While handling the previous timer overflow interrupt (in this function), it may have
                // happened that there was an input edge after reading AGTCR (in the beginning) but
                // before clearing AGTCR (in the end).
                // In that case there immediately is a new interrupt, but the TEDGF bit is not on as
                // AGTCR was cleared.
                // Set edge detected for the callback.
                p_args->capture |= 1;
            }
            // MANUAL FIX end.
    
            p_instance_ctrl->p_callback(p_args);

    And the callback function is then as follows:

    void receiver_f_falling_edge_callback(timer_callback_args_t *p_args)
    {
            fsp_err_t err;
            IRQn_Type irq_number;
    
            if( p_args->capture & 2)
            {
                    // Timer overflow occurred
                    capture_overflows++;
            }
    
            if( p_args->capture & 1) {
                    // Falling edge occured, calculate and store pulse length...
            }
    }
    

    From my side the problem is solved, Renesas might want to consider a permanent and general fix.