/**
*   @copyright       © 2026 Microchip Technology Inc.
    Microchip Technology Inc. and its subsidiaries. You may use this
    software and any derivatives exclusively with Microchip products.

    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
    WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
    PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP PRODUCTS, COMBINATION
    WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.

    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
    BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE
    FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN
    ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
    THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.

    MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE
    TERMS. 
*
*************************************************************************/

/**
 *  @file       diag_interrupt_isrcleared_check.c
 *  @version    1.0
 *  @brief      This file has the implementation for the interrupt servicing test
 *              diagnostics
 *  @see        diag_interrupt.h
 *************************************************************************/
#include "diag_interrupt.h"
#include "diag_interrupt_shared.h"
#include "diag.h"

static volatile uint32_t IFSBitCleared;

uint32_t DIAG_INTERRUPT_IsrClearedCheck(uint16_t irqNum)
{
    uint32_t timeout = ISR_CLEARED_CHECK_TIMEOUT;
    uint32_t retVal;
    while((IFSBitCleared == DIAG_INTERRUPT_ISR_BIT_CLEARED_FALSE) && (timeout > 0U))
    {
        timeout -= 1U;
    }
    if(timeout == 0U)
    {
        DIAG_INTERRUPT_SetRetValue(DIAG_FAIL); //This is in case the DIAG_INTERRUPT_IsrClearedCheck is called without the corresponding complimentary function from the ISR
    }
    else
    {
        DIAG_INTERRUPT_SetRetValue(DIAG_PASS);
    }
    IFSBitCleared = DIAG_INTERRUPT_ISR_BIT_CLEARED_FALSE;
    retVal = DIAG_INTERRUPT_GetRetValue();
    return(retVal);
}

//Complimentary function called from the corresponding Interrupt Service Routine
void DIAG_INTERRUPT_IfsFlagClearedCheckFromIsr(uint16_t irqNum)
{
    uint32_t regIndex;
    uint32_t bitPos;
    volatile uint32_t bitMask = 0x00000001U;
    volatile uint32_t intrVectorNumber;
    volatile uint32_t tempirqNum;
/*LDRA_EXCLUDE 554 S <justification start> pointer to an SFR with that attribute,violation is ignored <justification end> */	
    volatile uint32_t *intrCtrlStatusRegPtr = (volatile uint32_t *)INTERRUPT_CONTROL_STATUS_REGISTER_ADDR;
/*LDRA_EXCLUDE 606 S <justification start>wrong interpretation as function pointer, violation is ignored <justification end> */    
    interruptIecRegAddr_t iecRegArrPtr = (interruptIecRegAddr_t)INTERRUPT_IEC0_REG_INDEX;
/*LDRA_EXCLUDE 606 S <justification start>wrong interpretation as function pointer, violation is ignored <justification end> */     
    interruptIfsRegAddr_t ifsRegArrPtr = (interruptIfsRegAddr_t)INTERRUPT_IFS0_REG_INDEX;
    tempirqNum = (uint32_t)irqNum;
    /*Each register has 32 bits, so divide by 32 to get the regIndex*/
    regIndex = (tempirqNum >> 5U);
    /*Get the remainder to get the bitPos*/
    bitPos = tempirqNum - (regIndex * 32U);
    /*get the bitMask based on the bitPos*/
    bitMask = bitMask << bitPos;
    
    /*Now check if the ISR that has been entered is the same as the IRQ number*/
    intrVectorNumber = (uint32_t)(*intrCtrlStatusRegPtr & INTERRUPT_VECTOR_NUM_MASK);
            
    if(intrVectorNumber != (tempirqNum + 9U))
    {
        /*If this is entered, it means we are in the wrong ISR, because the IFS triggered a wrong ISR*/
        /*In order to exit will make sure that timeOut happens in the main loop and exits and invalid parameter*/
        IFSBitCleared = DIAG_INTERRUPT_ISR_BIT_CLEARED_FALSE;
    }
    else
    {
        //Check if the corresponding IFS bit is 0
        if(((*ifsRegArrPtr)[regIndex] & bitMask) == 0U)
        {
            IFSBitCleared = DIAG_INTERRUPT_ISR_BIT_CLEARED_TRUE;
        }
        else
        {
            IFSBitCleared = DIAG_INTERRUPT_ISR_BIT_CLEARED_FALSE;
            //Clear the corresponding IERbit to 0, so that the ISR is not in an infinite loop
            /*LDRA_EXCLUDE 105 D <justification start> regIndex is used only as index and not modified,violation is ignored <justification end> */
            /*LDRA_EXCLUDE 554 S <justification start> pointer to an SFR with that attribute,violation is ignored <justification end> */
            (*iecRegArrPtr)[regIndex] &= ~bitMask;
        }

    }
        
    
}
