Tool/software:
I have a custom board with a C6672, configured as a Root Complex, connected to an external PCIe Endpoint device. The C6672 is running baremetal (no rtos) and I'm using the CSL library to configure interrupts.
During PCIe initialization, I set INTn_EN_SET (0x21800188) and INTn_EN_CLR(0x2180018C) to 1 and all MSIn_IRQ registers to 0 (0x21800100 through 0x21800170)
INTC and CPINTC Configuration results in the following registers being set:
ENABLE_REG unsigned int[32] [0x00000000,0x00040000,0x00000000,0x00000000,0x00000000...] (Hex) 0x02600300
ENABLE_CLR_REG unsigned int[32] [0x00000000,0x00040000,0x00000000,0x00000000,0x00000000...] (Hex) 0x02600380
ENABLE_HINT_REG unsigned int[8] [0x00000001,0x00000000,0x00000000,0x00000000,0x00000000...] (Hex) 0x02601500
GLOBAL_ENABLE_HINT_REG unsigned int 0x00000001 (Hex) 0x02600010
When the external device generates a PCIe Legacy INTA interrupt, I see the following registers are modified:
INTn_RAW_STATUS (0x21800180) = 1
INTn_STATUS (0x21800184) = 1.
RAW_STATUS_REG unsigned int[32] [0x00000000,0x00040000,0x00000000,0x00000000,0x00000000...] (Hex) 0x02600200
ENA_STATUS_REG unsigned int[32] [0x00000000,0x00040000,0x00000000,0x00000000,0x00000000...] (Hex) 0x02600280
However, my ISR connected to the event does not execute.
I can clear the interrupt by writing to a register in the external device, writing a 1 to INTn_STATUS, and writing a 0 to IRQ_EOI (0x21800050). After clearing the interrupt, I verify the interrupt is triggered again by viewing the INTn_RAW_STATUS and INTn_STATUS registers get set back to 1.
I've attached my code below, following the code example in SPRUGW4A KeyStone Architecture Chip Interrupt Controller (CIC) User Guide Section 2.3 Interrupt Servicing.
I would appreciate any advice.
#include <ti/csl/cslr_device.h>
#include <ti/csl/csl_cpIntcAux.h>
#include <csl_intc.h>
#include <csl_intcAux.h>
CSL_IntcContext Intcontext; //For CorePac INTC
CSL_IntcObj intcPCIe; //For CorePac INTC
CSL_IntcHandle hIntcPCIe; //For CorePac INTC
CSL_IntcEventHandlerRecord Record; //For CorePac INTC
CSL_CPINTC_Handle cphnd; //For chip-level CIC
Int16 sys_event;
Int16 host_event;
void InitializeInterrupts( void )
{
CSL_IntcGlobalEnableState state;
/* Setup the global Interrupt */
Intcontext.numEvtEntries = 1;
Intcontext.eventhandlerRecord = &Record;
CSL_intcInit( &Intcontext );
CSL_intcGlobalNmiEnable( ); /* Enable NMIs */
CSL_intcGlobalEnable( &state ); /* Enable Global Interrupts */
cphnd = CSL_CPINTC_open( 0 ); /* Initialize the chip level CIC CSL handle. */
}
/**
* This method connects a System Event to a Core Event.
* @note System Events are listed in SPRS708E Table 7-38 CIC0 Event Inputs (Secondary Interrupts for C66x CorePacs)
* @note Host Events are listed in Figure 7-32 TMS320C6672 System Event Inputs
* @param[in] kusSystemEvent System Event from SPRS708E Table 7-38 CIC0 Event Inputs
* @param[in] kusHostEvent Host Event from SPRS708E Figure 7-32 TMS320C6672 System Event Inputs
* @return This method returns nothing.
*/
void ConnectEvents( uint16_t kusSystemEvent, uint16_t kusHostEvent )
{
CSL_IntcParam vectId1;
/// @par Process Design Language
/// -# Record the System Event, Host Event, and MOL pointer
sys_event = kusSystemEvent;
host_event = kusHostEvent;
/// -# Map the CIC input event to the CorePac input event
/// -# Map the input system event to a channel.
/// - Note, the mapping from channel to Host event is fixed.
/// -# Enable the system interrupt
/// -# Enable the channel (output).
/// -# Enable all host interrupts.
CSL_CPINTC_disableAllHostInterrupt( cphnd );
CSL_CPINTC_setNestingMode( cphnd, CPINTC_NO_NESTING );
CSL_CPINTC_mapSystemIntrToChannel( cphnd, sys_event, 0 );
CSL_CPINTC_enableSysInterrupt( cphnd, sys_event );
CSL_CPINTC_enableHostInterrupt( cphnd, 0 );
CSL_CPINTC_enableAllHostInterrupt( cphnd );
/// -# Hook an ISR to the CorePac input event.
/// -# Hook the ISR (CSL_intcPlugEventHandler)
/// -# Clear the Interrupt
/// -# Enable the Event & the interrupt
vectId1 = CSL_INTC_VECTID_12; //4 through 15 are available
hIntcPCIe =
CSL_intcOpen(
&intcPCIe,
host_event, // selected event ID
&vectId1,
NULL );
Record.handler = ( CSL_IntcEventHandler )&SISR;
Record.arg = ( void* )host_event;
CSL_intcPlugEventHandler( hIntcPCIe, &( Record ) );
CSL_intcHwControl( hIntcPCIe, CSL_INTC_CMD_EVTCLEAR, NULL );
CSL_intcHwControl( hIntcPCIe, CSL_INTC_CMD_EVTENABLE, NULL );
}
void SISR( void* kopEventId )
{
/// @par Process Design Language
/// -# Disable the CIC0 host interrupt output
CSL_CPINTC_disableHostInterrupt( cphnd, 0 );
/// -# Clear the CIC0 system interrupt
CSL_CPINTC_clearSysInterrupt( cphnd, sys_event );
...
/// -# Service the interrupt at source
...
/// -# Clear the CorePac interrupt
CSL_intcHwControl( hIntcPCIe, CSL_INTC_CMD_EVTCLEAR, NULL );
/// -# Enable the CIC0 host interrupt output
CSL_CPINTC_enableHostInterrupt( cphnd, 0 );
}
void main( void )
{
...
InitializeInterrupts( );
ConnectEvents( CSL_INTC0_PCIEXPRESS_LEGACY_INTA, CSL_GEM_CIC0_OUT0_OR_CIC1_OUT0 );
...
}