This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM2634-Q1: Why do disabled interrupts still trigger after IRQ_PRIMSK is set?

Part Number: AM2634-Q1

Hi,experts

When I was using Autosar OS, I would call the critical section protected interface, but I found that at some point my interrupt(priority 15) still triggered after I set IRQ_PRIMSK(0xFF).

As shown in the figure below, I recorded the register information of the exception time and can see that the value of IRQ_PRIMSK was set to 0xFF, but the interrupt with priority 15 was still triggered.

The code to manipulate the IRQ PRIMSK register is shown below

  • Hi,

    Could you tell me the Autosar Vendor you are using?

    Regards,
    Akshit

  • Hi,Akshit!

    I'm using neusar.

    But I did a test :just using the SDK and MCAL (CAN) provided by TI,Exclude neusar ,will also happen this exception.

    This is my interrupt configuration:

    This is my test procedure:

    1. I added the IRQ PRIMSK detection to the interrupt handler.

    2. Mask CanIf callbacks in Mcal(Can_irq)

    3. I set up IRQ PRIMSK in a 1ms task(Use RTI3 timer)

    Os_Isr_SuspendOSInterrupts -》(*(volatile uint32*)0x50F00028U) = 0xFF;

    Os_Isr_ResumeOSInterrupts -》(*(volatile uint32*)0x50F00028U) = 0xFFFF;

    ps:Internally, these two functions just operate on IRQ_PRIMSK and don't involve anything in the OS

    4. Trigger CAN interrupt just by receiving message

  • HI,

    I've been looking into this today but will need to get inputs from other experts.
    I'll be getting clarity from the SDK team and getting back to you!

    Thank you for your patience.

    Regards,
    Akshit

  • Hi,Akshit

    Is there any new result?

  • Hi,Akshit!

    I did two new tests:

    First:I use the FreeRTOS routine provided by Ti to replicate this problem,I even added the following code to the critical section operation.

    Here is my test code:

    I send multiple messages through the host computer to trigger the CAN interrupt

    Second:

    I discussed this issue with Zhang Fan and made the following two guesses:

    1. Setting IRQ_PRIMSK between the interrupt flag set to 1 and the trigger of the interrupt does not effectively disable the trigger of the interrupt?

    Based on the above guesses, I did the following test:I checked the relevant interrupt flag before disabling the interrupt to make sure that no interrupt occurred and that the flag bit was set to identify where the code was executed. The test result shows that my disable_flag=1 and irq_primsk=0xFF, indicating that after I executed 185 and 186 lines of code, the interrupt was still triggered, but this test is not rigorous, the interrupt may be triggered between 183 and 186 lines.

    2. How long does it take for the IRQ_PRIMSK Settings to take effect? Will an interrupt be executed if it is triggered before it takes effect? That's a question I can't verify right now

  • Hi, Akshit,

    I did some test with SDK example and AM263x EVM, and re-produced some issue as customer encountered. I summarized my test results as below, hope it helps in your analysis.

    1. I testes with gpio_input_interrupt example from SDK 09_01_00_41, the priority of GPIO interrupt is 15. By setting VIM_IRQPRIMSK from 0xFFFF to 0xFF, GPIO interrupt will not be triggered, it is the expected behavior, and it indicates VIM_IRQPRIMSK can be used to mask desired priority interrupts.

    2. In real use case, VIM_IRQPRIMSK is changed between 0xFF and 0xFFFF very frequently to mask interrupts with lower priorities when needed. Then, I add some code in the while loop to modify VIM_IRQPRIMSK continuously, and at the same time, press SW button in EVM to trigger GPIO interrupts. In every tests, it can run into the condition that VIM_IRQPRIMSK is 0xFF, but GPIO(priority = 15) interrupt is triggered.

    3. In the test code, I check the GPIO interrupt flag register before change VIM_IRQPRIMSK to 0xFF, to make sure there is no pending GPIO interrupt.

    Attached is my examples\drivers\gpio\gpio_input_interrupt\gpio_input_interrupt.c, you can just use it to overwrite same file in your SDK, then continuously press the SW key in EVM, when the log from UART stops to update, the issue is re-produced.

       

    /*
     *  Copyright (C) 2021 Texas Instruments Incorporated
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    #include <kernel/dpl/DebugP.h>
    #include <kernel/dpl/ClockP.h>
    #include <kernel/dpl/AddrTranslateP.h>
    #include <kernel/dpl/HwiP.h>
    #include "ti_drivers_config.h"
    #include "ti_drivers_open_close.h"
    #include "ti_board_open_close.h"
    
    #include <drivers/hw_include/hw_types.h>
    
    /*
     * This example configures a GPIO pin in input mode
     * and configures it to generate interrupt on rising edge.
     * The application waits for 5 key presses, prints the
     * number of times the keys are pressed and exits.
     */
    
    
    uint32_t            gGpioBaseAddr = GPIO_PUSH_BUTTON_BASE_ADDR;
    HwiP_Object         gGpioHwiObject;
    volatile uint32_t   gGpioIntrDone = 0;
    
    static void GPIO_bankIsrFxn(void *args);
    
    extern void Board_gpioInit(void);
    extern void Board_gpioDeinit(void);
    extern uint32_t Board_getGpioButtonIntrNum(void);
    extern uint32_t Board_getGpioButtonSwitchNum(void);
    
    uint32_t gpio_ir_register = 0;
    uint32_t irqPriMsk_register = 0;
    uint32_t key_pressed = 0;
    uint32_t disable_flag = 0;
    uint32_t enable_flag = 0;
    uint32_t error_flag = 0;
    
    void gpio_input_interrupt_main(void *args)
    {
        int32_t         retVal;
        uint32_t        pinNum, intrNum, buttonNum;
        // uint32_t        waitCount = 5000000;
        HwiP_Params     hwiPrms;
    
        /* Open drivers to open the UART driver for console */
        Drivers_open();
        Board_driversOpen();
        Board_gpioInit();
    
        DebugP_log("GPIO Input Interrupt Test Started ...\r\n");
        DebugP_log("GPIO Interrupt Configured for Rising Edge (Button release will trigger interrupt) ...\r\n");
    
        pinNum          = GPIO_PUSH_BUTTON_PIN;
        intrNum         = Board_getGpioButtonIntrNum();
        buttonNum       = Board_getGpioButtonSwitchNum();
    
        /* Address translate */
        gGpioBaseAddr = (uint32_t) AddrTranslateP_getLocalAddr(gGpioBaseAddr);
    
        /* Register pin interrupt */
        HwiP_Params_init(&hwiPrms);
        hwiPrms.intNum   = intrNum;
        hwiPrms.callback = &GPIO_bankIsrFxn;
        hwiPrms.args     = (void *) pinNum;
        /* GPIO interrupt is a pulse type interrupt */
        hwiPrms.isPulse  = TRUE;
        retVal = HwiP_construct(&gGpioHwiObject, &hwiPrms);
        DebugP_assert(retVal == SystemP_SUCCESS );
    
        DebugP_log("Press and release SW%d button on EVM to trigger GPIO interrupt ...\r\n", buttonNum);
        // while(gGpioIntrDone < waitCount)
        // {
        //     /* Keep printing the current GPIO value */
        //     DebugP_log("Key is pressed %d times\r\n", gGpioIntrDone);
        //     ClockP_sleep(1);
        // }
        while(1)
        {
            disable_flag = 0;
            enable_flag = 0;
    
            gpio_ir_register = GPIO_getBankIntrStatus(gGpioBaseAddr, (((uint32_t) pinNum) >> 4));
    
            // make sure no pending gpio interrupt before change VIM_IRQPRIMSK
            if(gpio_ir_register == 0x00)
            {
                irqPriMsk_register = HW_RD_REG32(0x50F00028);
                disable_flag = 1;
                HW_WR_REG32(0x50F00028, 0x00FF);    // disable partial priorities
                disable_flag = 2;
                irqPriMsk_register = HW_RD_REG32(0x50F00028);
    
                gpio_ir_register = GPIO_getBankIntrStatus(gGpioBaseAddr, (((uint32_t) pinNum) >> 4));
                if(gpio_ir_register != 0x00)
                {
                    error_flag = 1;
                }
                else
                {
                    error_flag = 0;
                } 
    
                enable_flag = 1;
                HW_WR_REG32(0x50F00028, 0xFFFF);    // enable all priorities
                enable_flag = 2;
            }
    
            if(key_pressed == 1)
            {
                key_pressed = 0;
                DebugP_log("Key is pressed %d times\r\n", gGpioIntrDone);
            }
        }
    
        DebugP_log("Key is pressed %d times\r\n", gGpioIntrDone);
    
        DebugP_log("GPIO Input Interrupt Test Passed!!\r\n");
        DebugP_log("All tests have passed!!\r\n");
    
        Board_gpioDeinit();
        Board_driversClose();
        Drivers_close();
    }
    
    static void GPIO_bankIsrFxn(void *args)
    {
        uint32_t    pinNum = (uint32_t) args;
        uint32_t    bankNum =  GPIO_GET_BANK_INDEX(pinNum);
        uint32_t    intrStatus, pinMask = GPIO_GET_BANK_BIT_MASK(pinNum);
    
        uint32_t value = 0x00;
        value = HW_RD_REG32(0x50F00028);
        if(value != 0xFFFF)
        {
            while(1);
        }
    
        key_pressed = 1;
    
        /* Get and clear bank interrupt status */
        intrStatus = GPIO_getBankIntrStatus(gGpioBaseAddr, bankNum);
        GPIO_clearBankIntrStatus(gGpioBaseAddr, bankNum, intrStatus);
    
        /* Per pin interrupt handling */
        if(intrStatus & pinMask)
        {
            gGpioIntrDone++;
        }
    }
    

  • Hi Fan Zhang,

    Apologies for the delay and than you for waiting so patiently.

    You are right!
    There is a detected issue with VIM PRIMASK which  would be able to explain better.

    The SDK team is working on a fix for the issue. 

    Since this fix needs some latency and performance profiling to be done, we will not be able to have it as part of SDK 9.2 release (end of this month). We will have the fix in GitHub soon after 9.2 release and have it as part of SDK 10.0 release (August 15th). We will also share the patch here as soon as the SDK update is done.

    Regards,
    Akshit