/**
*   @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_servicing_test.c
 *  @version    1.0
 *  @brief      This file has the implementation for the isr cleared check diagnostics
 *  @see        diag_interrupt.h
 *************************************************************************/
#include "diag_interrupt.h"
#include "diag_interrupt_shared.h"
#include "diag.h"

static DIAG_INTERRUPT_SERVICING_RUN_STATUS intrServicingCheckRunningStatus = INTR_SERVICING_DIAG_RUN_FALSE;

static uint32_t intrSupportedByDev[NUM_INTR_REQ_FLAG_REGS] = {0xD7FFFEFEU,0xFFFFFFFFU,
                                                              0xFFFFFFFFU,0xFFFC3FFDU,
                                                              0xE7FE7FFFU,0xFFF81FFFU,
                                                              0xE1FFFE07U,0xFFFE1FFFU,
                                                              0xFFFFFFFFU,0x3C0001FFU,
                                                              0xFFFFF080U,0x0000000FU};

static void DIAG_INTERRUPT_CheckIFSRegister(uint32_t intrReqFlagRegArr[],uint16_t index)
{
    //Get the IFS Register bits which have to be tested
    uint32_t bitPos = 0x00000001U;    
    uint8_t timeOut = IFS_REG_FLAG_RESET_TIMEOUT;
/*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;
    while(bitPos != 0U)
    {
        /*Now check if the corresponding bit has to be tested*/
        if((intrReqFlagRegArr[index] & bitPos) != 0U)
        {
            /*First enable the interrupt in the corresponding IEC register*/
            (*iecRegArrPtr)[index] |= bitPos;
            /*Set the Interrupt Flag register in the corresponding IFS register*/
            (*ifsRegArrPtr)[index] |= bitPos;
            while((((*ifsRegArrPtr)[index] & bitPos) != 0U) && (timeOut != 0U))
            {
/*LDRA_EXCLUDE 151 D <justification start> timeOut variable is reloaded for the next byte, violation is ignored <justification end> */                
                timeOut -= 1U;
            }
            /*Check if the loop exited because of flag reset and not timeout*/
            if(((*ifsRegArrPtr)[index] & bitPos) == 0U)
            {
                /*Reset the corresponding bit in the array, to indicate that the bit passed*/
                intrReqFlagRegArr[index] ^= bitPos;
            }
        }
        /*Move to the next bit*/
        bitPos = bitPos << 1U;
        /*Reload the timeout Value*/
/*LDRA_EXCLUDE 151 D <justification start> timeOut variable is reloaded for the next byte, violation is ignored <justification end> */        
        timeOut = IFS_REG_FLAG_RESET_TIMEOUT;
    }
}

static void DIAG_INTERRUPT_GetifsFlagRegStatus(uint32_t intrReqFlagRegArr[])
{
    volatile uint8_t ifsRegIndex = 0U;
    volatile uint8_t retValue = 0U;
    while(ifsRegIndex < NUM_INTR_REQ_FLAG_REGS)
    {
        if(intrReqFlagRegArr[ifsRegIndex] != 0U)
        {
/*LDRA_EXCLUDE 151 D <justification start>the variable is used to update the return value from the function, hence the violation is ignored <justification end> */                
            retValue = INTR_SERV_TMP_FAIL;
            break;
        }
        else
        {
/*LDRA_EXCLUDE 151 D <justification start>the variable is used to update the return value from the function, hence the violation is ignored <justification end> */
            retValue = INTR_SERV_TMP_PASS;
        }
        /*Check the next IFS register*/
        ifsRegIndex += 1U;
    }
    if(retValue == INTR_SERV_TMP_PASS)
    {
        DIAG_INTERRUPT_SetRetValue(DIAG_PASS);
    }
    else
    {
        DIAG_INTERRUPT_SetRetValue(DIAG_FAIL);
    }
    
}

uint32_t DIAG_INTERRUPT_ServicingTest(uint32_t intrReqFlagRegArr[])
{
    uint32_t retVal;
    volatile uint8_t regValidityStatus = INTERRUPT_SERVICING_REG_BITS_INVALID;     
    uint16_t ifsRegIndex = 0U;
/*LDRA_EXCLUDE 151 D <justification start>the variable is used to control the execution in ISR, hence the violation is ignored <justification end> */    
    intrServicingCheckRunningStatus = INTR_SERVICING_DIAG_RUN_TRUE;
    while(ifsRegIndex < NUM_INTR_REQ_FLAG_REGS)
    {
        if(intrReqFlagRegArr[ifsRegIndex] == 0U)
        {
            //This means there are no interrupt bits in this register to be tested, skip
            ifsRegIndex += 1U;
        }
        else if((intrReqFlagRegArr[ifsRegIndex] & intrSupportedByDev[ifsRegIndex]) != intrReqFlagRegArr[ifsRegIndex])
        {
            break;
        }
        else
        {
            DIAG_INTERRUPT_CheckIFSRegister(intrReqFlagRegArr,ifsRegIndex);
            regValidityStatus = INTERRUPT_SERVICING_REG_BITS_VALID;
            ifsRegIndex += 1U;
        }
                    
    }  
    if(regValidityStatus != INTERRUPT_SERVICING_REG_BITS_INVALID)
    {
        DIAG_INTERRUPT_GetifsFlagRegStatus(intrReqFlagRegArr);
    }
    else
    {
        DIAG_INTERRUPT_SetRetValue(DIAG_INVALID_PARAM);
    }
    retVal = DIAG_INTERRUPT_GetRetValue();
/*LDRA_EXCLUDE 151 D <justification start>the variable is used to control the execution in ISR, hence the violation is ignored <justification end> */    
    intrServicingCheckRunningStatus = INTR_SERVICING_DIAG_RUN_FALSE;
    return(retVal);             
}

DIAG_INTERRUPT_SERVICING_RUN_STATUS DIAG_INTERRUPT_IsInterruptServicingCheckRunning(void)
{
    return (intrServicingCheckRunningStatus);
}

