Norbert Vagasi

MPC5748G interrupt problem

Discussion created by Norbert Vagasi on Mar 10, 2017
Latest reply on Apr 11, 2017 by Martin Kovar

Dear NXP support,

 

we have the following problem:

Brief bug description:
     After the PIT timer interrupt request raised, it can be cleared by writing the INTC CPR register
     with the same value it already contains. This CPR value is lower, than the PIT interrupt
     request priority.

 

Assumptions:
 * The INTC CPR has lower value than the PIT timer interrupt

 

Scenario:
 * Disable the interrupts globally (EE clear)
 * Start the PIT timer channel
 * Wait the PIT channel to expire and cause an interrupt request
 * Disable the timer channel interrupt (TIE), as the request was already queued
 * Write the same lower value to the INTC CPR
 * Enable the interrupts globally (EE set)
 * (The queued interrupt shall be raised now)

 

If the INTC CPR is not updated, the PIT interrupt happens.
This means the INTC CPR write clears the queued interrupt.

 

Example code:

#include <ppc_ghs.h>
#include "./inc/MPC5748G.h"

 

#define PIT_CH_ID       0U
#define PIT_CH_ID_PSR   226U

 

#define PRODUCE_ISSUE

 

void initPIT(void)
{
    PIT.PITMCR.B.MDIS = (vuint32_t)1U; /* disable the RTI timer module */
    PIT.PITMCR.B.FRZ  = (vuint32_t)1U; /* Timer is stopped in debug mode. Needed for easier debug. */
    PIT.PITMCR.B.MDIS = (vuint32_t)0U; /* enable the PIT timer module */
}

 

void initPIT_CH_ISR(void)
{
    PIT.CH[PIT_CH_ID].TFLG.B.TIF    = (vuint32_t) 1U;           /* Delete any previous interrupts */
    PIT.CH[PIT_CH_ID].LDVAL.R       = (vuint32_t) 0x00FFFFFFU;  /* Set a not so large value */
}

 

int main(void)
{
    initPIT();
    initPIT_CH_ISR();

 

    /* Set the initial 0 value to CPR */
    INTC.CPR[0U].B.PRI = (vuint32_t) 0U;

 

    /* Set PIT channel priority to 1, which is higher than the CPR value */
    INTC.PSR[PIT_CH_ID_PSR].B.PRC_SELN = (vuint32_t) 0U;
    INTC.PSR[PIT_CH_ID_PSR].B.PRIN = (vuint32_t) 1U;

 

    /* Disable interrupts globally (delete EE) */
    __DIR();

 

    /* Start the timer */
    PIT.CH[PIT_CH_ID].TCTRL.B.TEN = (vuint32_t) 1U;

 

    /* Wait for timer to tick */
    while(PIT.CH[PIT_CH_ID].TFLG.B.TIF != (vuint32_t) 1U);

 

    /*
     * The interrupt for PIT timer channel shall be latched in the INTC queue.
     */

 

    /* Disable the timer channel interrupt, as the request was already queued. */
    PIT.CH[PIT_CH_ID].TCTRL.B.TIE = (vuint32_t) 0U;

 


  #ifdef PRODUCE_ISSUE
    /* Set CPR to the same value as it was, and which is lower than the corresponding timer interrupt priority */
    INTC.CPR[0U].B.PRI = (vuint32_t) 0U;
  #endif

 

    /* Re-enable interrupts globally (set EE) */
    __EIR();

 

    /*
     * The timer interrupt shall be raised here
     */

 

    return 0;
}

 

Thank you for your help in advance.

 

Regards,

Janos Bai

Outcomes