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.

LAUNCHXL-F280049C: Missing ePIE file C2000ware

Guru 56063 points
Part Number: LAUNCHXL-F280049C
Other Parts Discussed in Thread: C2000WARE

The header file (DSP28_SWPrioritizedIsrLevels.h) required to control ePIE peripheral core priority levels (TRM 3.5.6 Vector Tables) is missing C2000ware V3.04/4.01 DSP folder. The ePIE MASK priory order document web page specifically states header file (DSP28_SWPrioritizedIsrLevels.h) is required.

C28x Interrupt Nesting

Using the MASK Values

Within an interrupt service routine, the global and group priority can be changed by software to allow other interrupts to be serviced. The steps are the same as described before. The only difference is the mask values for IER and PIEIERx have been managed in the DSP28_SWPrioritizedIsrLevels.h file.

Why was the header file (DSP28_SWPrioritizedIsrLevels.h) remove from C2000ware? 

The peripherals all send ePIE a core priory value in order that higher priority groups are not stomped on by lower slower priority interrupts. Likewise, it should stop a lower priority peripheral from over running a higher priority group CPU instruction decode.

Currently without the header file SCIB INT9.4 overruns ADCA1 INT1.1 (higher core priority) before reaching SW Clear ACK placed at the bottom of INT1.1 ISR. 

 Why is the peripheral core priority values being ignored by ePIE and the CPU?

  • Hi, 

    Your query is forwarded to an expert and you shall receive a response soon.

    Best Regards

    Siddharth

  • In F28004x, the file is split into f28004x_sw_prioritized_isr_levels.h (includes the user defined priority levels) and sw_interrupt_prioritization_logic.h (includes the code that generates the masks, this file should not be updated by user)

    Regards,

    Veena

  • Hi Veena,

    (includes the user defined priority levels)

    I see that user can assign priorities with no explanation of why what or how that is being done inside defined silicon ePIE flags. How can user make personal priority when TRM has already defined the local INT priority levels 3.5.5 and peripheral global core priority levels 3.5.6 Vector Tables. These are hard coded priorities in the ePIE controller not SW. Anyway the local group1 priorities are not working and seemingly peripheral global core priorities are broken as defined in both ePIE tables. So the header file will not help in this issue.

    sw_interrupt_prioritization_logic.h (includes the code that generates the masks, this file should not be updated by user)

    I only have two peripheral global core priority INT sources active, each in a different group. Global group 9 core priority 13 is over running global group 1 core priority 5 even with global plus local controls. Nothing works to stop group 9 INTS from over running Group 1 INTS. The x49c ePIE has more than ADCA errata.

  • BTW that example of CPU timers does not call on other functions within the ISR, only counts INTS at the speed of the timer. The x49c ePIE is not actually being constrained by peripheral core priorities levels (at all) runs peripheral IRQ's right up to the CPU never pends them. How no one at TI has noticed this ePIE errata is baffling to say the least.

  • Hi,

    The hardware priorities in C2000 devices are fixed and nesting is disabled by default. Interrupt nesting and customizing priorities is achieved through software.

    Once the C28x core branches to an ISR code, the global interrupt is disabled by hardware. In software we are re-enabling the interrupts and we disable all those interrupts for which we have assigned a lower priority (in SW). This will ensure only interrupts for which we have configured higher priority can preempt an ISR

    In case of the interrupt_ex3_sw_prioritization example, we have configured CPUTimer interrupts for which the hardware priorities are T0>T1>T2. In software, we configure the priorities as T2>T1>T0. If all 3 interrupts occur at the same time, as per the hardware priorities T0 ISR is hit first. But in the ISR, we re-enable interrupts, resulting in other interrupts to be serviced before T0.

    In the example, yes, we do not call other functions. It is for the sake of demo, we just increment the count. The ISR is added to primarily show how interrupts are enabled and later disabled to enable nesting of higher priority interrupts. You can check the traceISR buffer contents and check the actual order of interrupts being serviced.

    Can you provide more details on the issue you were facing. Would help if you could share the code snippets.

    Regards,

    Veena

  • Can you provide more details on the issue you were facing. Would help if you could share the code snippets.

    See my other post below link: "Instaspin ADC group1 ignores peripheral core priority of other ePIE groups." Code snip at the top of post uses Timer0 with ADCA1. Scroll to post end to see last ditch SW effort to control global PIEIER peripheral core priority where no user SW control should even be required according to these 2 interrupt examples. The peripheral sends core priority (when working correctly) to ePIE services pending IRQ's by global core priority status up to the CPU only after clear ACK, not before.

    (5) TMS320F280049C: ePIE core priority groups Instaspin SDK (FOC) - C2000 microcontrollers forum - C2000Tm︎ microcontrollers - TI E2E support forums

    I also looked at I2C, SCIA, SPI example. It has 2 global peripheral core priorities with no EINT, DINT controls. I had added to SCIB, later ADCA1, ADCC1 ISR's were futile attempts to control ADCA1 ISR being invaded by SCIB. So peripheral core highest core priority (group1) gets overrun by slower lower core priority SCIB with (30ms decimation time) call to function outer loop prior to clear ACK return. Oddly the same issue of ADCA1, ADCC1 overrun occurs by CPUTimer0 with nesting masks (first code snip) above link. My SW core priority control (same link bottom snip) was tested with continuous ADC patch or without but still fails to correctly control peripheral core pends when group1 IRQ's are active and have not issued clear ACK prior to (return) instruction.  

    You can see ISR granularity (below snip) SCIB TX INT9.4. Past effort to push group1 status on stack then Pop prior to DINT was another futile attempt. Either all peripheral core priorities seem broken in silicon or only group 1 (priority 5) is broken or locked up by previous C2000ware driverlib calls. Perhaps Instaspin SDK example projects should refrain from adding folders with driverlib calls that may not be up to date as C2000ware v3.04 or v4.01. Recently this week discovered a driverlib call to enable ePWM SOCA trigger source for x49c ADC modules can only set 1 source via object class (for loop[cnt]) configuration (hal.c). More than one call is infected by this behavior to configure ePWM for ADC trigger source, yet another post.

    (+) TMS320F280049C-Q1: tms320f280049c - C2000 microcontrollers forum - C2000Tm︎ microcontrollers - TI E2E support forums

    /********************************************************
    *!
    *! Nextion Control SCIB TX interrupt handler
    *! This funciton checks the MIS bits to determine the
    *! interrutp souurce from the endabled IS flags.
    *!
    *********************************************************/
    __interrupt void
    NexSCIbTxISR(void)
    {
    
        uint32_t ui32IntStatus = 0;
    	volatile static uint32_t IntCount;
    
        //
        // Save group1 IER register on stack
        //
        //volatile uint16_t tempPIEIER = HWREGH(PIECTRL_BASE + PIE_O_IER1);
    
    	// Set local INT source
        IER |= M_INT4;
        IER &= M_INT4;
    
        /* Enable global group PIER INT */
        HWREGH(PIECTRL_BASE + PIE_O_IER9) &= PIE_IER9_INTX4;
    
        //
        // Enable Interrupts
        //
       // Interrupt_clearACKGroup(0xFFFFU);
       // __asm("  NOP");
        //
        EINT;
    
        /* Get SCIB interrupt flag status */
        ui32IntStatus = SCI_getInterruptStatus(SCIB_BASE);
    
    
    	/* TX FIFO level interrupt full or ready status?  */
    	if(ui32IntStatus &SCI_INT_TXFF)//|| ui32IntStatus &SCI_INT_TXRDY
    	{
    		/*  The TXFF interrupt is cleared by performing
    		 *  a single read of the INT status, or by clearing
    		 *  the interrupt by writing a 1 to the TXIC bit. */
    		SCI_clearInterruptStatus(SCIB_BASE, ui32IntStatus);
    
    		//if(((SCI_getTxFIFOStatus == SCI_FIFO_TX0) &&
    		//(SCIB_BASE + SCI_O_CTL2) == SCI_CTL2_TXRDY)) //SCI_CTL2_TXEMPTY
    
    		/* If the TX FIFO FULL status, turn off the transmit interrupt .*/
    		if((HWREG(SCIB_BASE + SCI_O_FFTX &SCI_FFTX_TXFFST_M) == SCI_FIFO_TX16))
    		{
    			/* Disable SCIB transmit interrupt */
    			SCI_disableInterrupt(SCIB_BASE, SCI_INT_TXFF); //SCI_INT_TXRDY, SCI_INT_TXFF
    		    /* Disable SCIB FIFO PIEIERx interrupt */
    		    Interrupt_disable(INT_SCIB_TX);
    		}
    
    		/* Increment the seconds count */
    		IntCount ++;
    
    		/* Set an call interval */
    		if (IntCount >= 200000)
    		{
    			/* Stop LCD updates false */
    			if(bNexTxHold)
    			{
    				//while(SCI_isTransmitterBusy(SCIB_BASE))
    				//{}
    			    //
    			    // check ISR executing time, roughly 125µs active
    			    //
    			    HAL_setGPIOHigh(halHandle, HAL_GPIO_ISR);
    
    				/* Update LCD widgets */
    				Nextion_vars();
    
    			    //
    			    // check ISR executing time, roughly 125µs active
    			    //
    			    HAL_setGPIOLow(halHandle, HAL_GPIO_ISR);
    				//
    				IntCount = 0;
    			}
    		}
    	}
    
        // Acknowledge interrupt from PIE group 9
    	Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    
        //
        // Disable interrupts and restore registers saved:
        //
        DINT;
        //HWREGH(PIECTRL_BASE + PIE_O_IER1) = tempPIEIER;
    
        return;
    
    }

  • Hi,

    In none of the other examples, we have enabled interrupt nesting, hence you may not find the ISR code with the EINT and other instructions.

    As mentioned earlier, the hardware priorities are fixed, and cannot be changed.

    Regarding code snippet you have shared for SCIB ISR - SCIB interrupt falls under group 9, hence you should be using the macros M_INT9 and MINT9 (note that these are different)

    Should be - 

        IER |= M_INT9;
        IER &= MINT9;
        HWREGH(PIECTRL_BASE + PIE_O_IER9) &= MG9_4;

    Also instead of saving and restoring PIE_O_IER1 register, you need to save and restore PIE_O_IER9, since that is what is updated in the ISR

    Regards,

    Veena

  • You may refer to the file  device_support\f28004x\common\source\f28004x_sw_prioritized_defaultisr.c for the template ISRs for all interrupts that configures the required registers to enable nesting

    Regards,

    Veena

  • Hi Veena,

    Should be - 

        IER |= M_INT9;
        IER &= MINT9;
        HWREGH(PIECTRL_BASE + PIE_O_IER9) &= MG9_4;

    That M_INT9 stops SCIB FIFO INT's to set any pending state on ePIE. Yet none of this code should be required for Non-Nested ISR's in two different core priority groups with no nesting order. According to TRM text,  ePIE handles the pending and un-pending of peripheral core IRQ's, not user added SW. The compiler handles _interrupt steps 1&3 . I added return statement at the bottom of all ISR's only after nothing else worked to stop SCIB over running ADCA1.

    3.5.4.2 Handling Interrupts
    ISRs are similar to normal functions, but must do the following:
    1. Save and restore the state of certain CPU registers (if used).
    2. Clear the PIEACK bit for the interrupt group.
    3. Return using the IRET instruction.
    Requirements 1 and 3 are handled automatically by the TMS320C28x C compiler, if the function is defined using
    the __interrupt keyword.

    BTW: MG9_4 is synonymous with PIE_IER9_INTX4 (hw_pie.h) but causes (lin.h) wacky macro redefined compile error by adding #include "f28004x_device.h" to the motor control SDK project. Hence the alternative PIE_IER9_INTX4 was used.

  • Probably the following document would give more details.

    https://software-dl.ti.com/C2000/docs/c28x_interrupt_nesting/html/index.html

    Definitely, PIE is handling and is responsible for branching to ISR function when an interrupt occurs. In SW, we are manipulating the IER registers to achieve interrupt nesting. By hardware, once the interrupt ISR is entered, the global interrupt is disabled (INTM is set) and the corresponding IER bit is also reset. In the ISR code, we are reenabling that IER bit ( IER |= M_INT9;) and disabling all the lower priority interrupts ( IER &= MINT9;) and re-enabling the global interrupt (EINT) to achieve interrupt nesting for higher priority interrupts.

    MG9_4  and PIE_IER9_INTX4  is NOT the same. MG9_4  is constructed in such way that all interrupts in Group 9 which has higher priority than  9.4 is set

    M_INT9 -> Bit 9 is set

    MINT9 -> Bits corresponding to all INTs with higher priority than INT9 is set

    I would highly recommend to use the code snippets available in the  f28004x_sw_prioritized_defaultisr.c for the correct functioning of interrupt nesting

    Regards,

    Veena

     

  • Just to add, those code snippets where the IER registers are updated, is ONLY required if you need nested interrupts. If it is not a requirement, you can totally skip that piece of code. The interrupts would still be serviced by PIE. Only difference is that, while inside an ISR, all other interrupts remains disabled. If a higher priority interrupt is triggered, it would be serviced only after completing the current ISR code

    Regards,

    Veena

  • If it is not a requirement, you can totally skip that piece of code

    I did comment out all IER codes cleaned project several times. Still peripheral core priority levels are not clear ACK previous slower SCIB pends from over running ADCA1 ISR. It must be driverlib issue as mentioned to Lori in another thread that discusses the same ePIE issue effecting for while loops in these ISR's.

    The higher core priority ADCA1 should put or pull SCIB ISR into holdpend status until ADCA1 has issued clear ACK. That is how a proper IRC handles multiple ISR's where some might be slower than others. This case ADCA1 ISR is roughly 125µs and SCIB ISR roughly 30-40ms and much lower ePIE priority level.

    If ePIE cannot do the above holdpend action, would it then be necessary to rig some kind of SW countermeasures for both ISR's?