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.

C6657 - clarification about interrupt settings



Hi all,

I need a clarification about interrupt setting for the C6657 in case of firmware without BIOS.

I would like to clarify the differences between primary interrupts set-up and secondary interrupts set-up.

As per my understanding, primary events are routed directly to the INTC module, while secondary events for the cores are routed trough CIC0 (which in turn has 12 entries in the primary events list). Looking at the following image, I guess that the CIC output channels are the same concept (and then the same number) as Host Interrupts. Is that right? If not, what number shall I use into CSL_CPINTC_mapSystemIntrToChannel and CSL_CPINTC_enableHostInterrupt?

 

Interrupt Topology High-Level Block Diagram.png

I would like to speak about a practical example, to check whether I'm doing the right things while setting up a primary event (let's say interrupt from GPIO8) and a secondary event (let's say interrupt from GPIO16). Please have a look at the following example showing the differences and come back with any suggestion/correction, please. It's supposed to be a logical example rather than a piece of working code.

 

Common initial calls for both cases:
  CSL_intcGlobalNmiEnable();
  CSL_intcGlobalEnable(&state);

 

Primary events (table 8-33 of SPRS814B):
They're directly routed to INTC, so they can be set up directly without additional mapping
  CSL_intcOpen(&IntcObj, EVENT_NUMBER_FROM_TABLE_8_33, &vectId_4_15, NULL)

 

Secondary events (table 8-34 of SPRS814B):
CIC0 is in the middle, so first set up CIC0
  IntcHandler = CSL_CPINTC_open(0);
  CSL_CPINTC_setNestingMode (IntcHandler, CPINTC_NO_NESTING);
  CSL_CPINTC_disableAllHostInterrupt(IntcHandler);
  CSL_CPINTC_clearSysInterrupt (IntcHandler, EVENT_NUMBER_FROM_TABLE_8_34);
  CSL_CPINTC_enableSysInterrupt (IntcHandler, EVENT_NUMBER_FROM_TABLE_8_34);
  CSL_CPINTC_mapSystemIntrToChannel(IntcHandler, EVENT_NUMBER_FROM_TABLE_8_34, CIC0_CHANNEL_0_11 /*channel*/);
  CSL_CPINTC_enableHostInterrupt (IntcHandler, CIC0_CHANNEL_0_11 /*host_event*/);
  CSL_CPINTC_enableAllHostInterrupt(IntcHandler);
Then set up the primary event which will be one of the 12 CIC0 output channels used as primary events
  CSL_intcOpen (&intcObj, EVENT_NUMBER_FROM_TABLE_8_33, &vectId_4_15 , NULL);

It's said that channel are already mapped to host interrupts, so this means I should never call the function CSL_CPINTC_mapChannelToHostInterrupt. Is that right?

Is there any CSL function to get the eventId based on the channel/host_event?

 

Thanks and best regards,

Luca

  • Welcome to the TI E2E forum. I hope you will find many good answers here and in the TI.com documents and in the TI Wiki Pages (for processor issues). Be sure to search those for helpful information and to browse for the questions others may have asked on similar topics (e2e.ti.com). Please read all the links below my signature.

    We will get back to you on the above query shortly. Thank you for your patience.

  • Hi,


    It's said that channel are already mapped to host interrupts, so this means I should never call the function CSL_CPINTC_mapChannelToHostInterrupt. Is that right?

    Yes, CSL_CPINTC_mapChannelToHostInterrupt function required for secondary interrupt mapping only. Primary interrupts are one-to-one mapping between host interrupt and channel, so we do not need to use the CSL_CPINTC_mapChannelToHostInterrupt API.

    This information are clearly documented in Configuring Interrupts on Keystone Devices wiki:
    processors.wiki.ti.com/.../Configuring_Interrupts_on_Keystone_Devices

    Take a look at below GPIO interrupt related thread for your reference:
    e2e.ti.com/.../171824
    e2e.ti.com/.../586767


    Is there any CSL function to get the eventId based on the channel/host_event?

    CpIntc_getEventId() - Returns the event id associated with the host interrupt.

    Thanks,
  • Please note CpIntc_getEventId() is not CSL function, but SYS/BIOS API.  The discussion is dedicated to non-BIOS system, but I happened to create BIOS app code to map event 25 to host interrupt 2 in CIC0, which the host interrupt would be handled by Event Combiner dispatcher. I shared as below. Hope this helps.

    Event 25 would be manually triggered by periodic function and that would invoke eventHanlder.

    Good luck.
    Naoki Kawada

    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    #include <xdc/runtime/Error.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/hal/Hwi.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/family/c64p/EventCombiner.h>
    #include <ti/sysbios/family/c66/tci66xx/CpIntc.h> 
     
    #define CIC0 0
    #define SYS_EVENT_ID 25
    #define HOST_INT_ID 2 
     
    UInt eventTriggerCount = 0;
    UInt interruptCount = 0; 
     
    Void eventTrigger(UArg arg0)
    {
    	eventTriggerCount++;
    	CpIntc_postSysInt(0, SYS_EVENT_ID);
    } 
     
    Void eventHandler(UArg arg0)
    {
    	interruptCount++;
    }
    
    /*
     *  ======== main ========
     */
    Void main()
    {
        Clock_Params clkParams;
        Hwi_Params hwiParams;
        Error_Block eb;
        Int eventId; 
     
        // Initialize the error block
        Error_init(&eb); 
     
        // Disable CIC0 at once
        CpIntc_disableAllHostInts(CIC0); 
     
        // Clear existing event flag and enable it.
        CpIntc_clearSysInt(CIC0, SYS_EVENT_ID); 
     
        // Map system event to host interrupt
        CpIntc_mapSysIntToHostInt(CIC0, SYS_EVENT_ID, HOST_INT_ID); 
     
        // Register eventHandler for SYS_EVENT_ID. An argument is NULL in this example.
        CpIntc_dispatchPlug(SYS_EVENT_ID, &eventHandler, NULL, FALSE); 
     
        // Convert host interrupt to event id for CorePac
        eventId = CpIntc_getEventId(HOST_INT_ID); 
     
        // Register CpIntc dispacher to EventCombiner. An argument should be host interrupt id.
        EventCombiner_dispatchPlug(eventId, &CpIntc_dispatch, HOST_INT_ID, TRUE); 
     
        // Initialize the Hwi parameters. EventCombiner assumes eventId is 0, 1, 2 and 3.
        Hwi_Params_init(&hwiParams);
        hwiParams.eventId = eventId / 32;
        hwiParams.arg = hwiParams.eventId;
        hwiParams.enableInt = TRUE; 
     
        // Register EventCombiner dispacher to INT7
        Hwi_create(7, &EventCombiner_dispatch, &hwiParams, &eb); 
     
        // Enable host interrupt.
        CpIntc_enableHostInt(CIC0, HOST_INT_ID); 
     
        // Enable global host interrupt.
        CpIntc_enableAllHostInts(CIC0); 
     
        // Now setup completed. Enable system event.
        CpIntc_enableSysInt(CIC0, SYS_EVENT_ID); 
     
        // Create a periodic Clock Instance with period = 5 system time units to invoke SYS_EVT_ID.
        Clock_Params_init(&clkParams);
        clkParams.period = 5;
        clkParams.startFlag = TRUE;
        Clock_create(eventTrigger, 5, &clkParams, NULL); 
     
        BIOS_start();
    }
    

  • Hi Naoki,
    Thank you for the additional information and contribution to e2e.
  • Thanks everybody for your answers.

    A last questions about the actions to take inside the ISR to clear the interrupt:

    • if it's an event routed through CIC in a non-BIOS prj:

    CSL_CPINTC_disableHostInterrupt(cic_hnd, 0);

    CSL_CPINTC_clearSysInterrupt(cic_hnd, System_event);

    CSL_intcHwControl(intc_hnd, CSL_INTC_CMD_EVTCLEAR, NULL);

    ... //ISR custom action

    CSL_CPINTC_enableHostInterrupt(cic_hnd, 0);

    • if it's an event routed directly to INTC in a non-BIOS prj:

    CSL_intcHwControl(intc_hnd, CSL_INTC_CMD_EVTCLEAR, NULL);

    ... //ISR custom action

    • if it's an event routed through CIC in a  BIOS prj:

    CpIntc_clearSysInt(0, System_event);

    ... //ISR custom action

    CpIntc_enableSysInt(0, System_event);

    • if it's an event directly to INTC in a BIOS prj:

    ?

     

    What about at the peripheral level? I mean the peripheral interrupt flag in the peripheral registers set. Shall I clean it too? I've never seen it on the various examples here, so I'm wondering who is actually cleaning those flags.

     

    Thanks,

    Luca 

  • Hi Luca,

    Peripheral registers dedicated to its interrupt/event status should be properly cleared by your application code before enabling its interrupt. For example, EDMA has event register (ER and ERH) and these should be cleared by event clear register (ECR and ECRH) before enabling the related interrupt. Also, Interrupt pending register (IPR and IPRH) is same way.

    As for my shared code, it was just an interrupt demonstration for BIOS app, but please note the interrupt was not actually triggered by peripheral, but CPU. So, you should take into account for the peripheral registers.

    Regards,
    Naoki