ScuGicSelfTestExample
static XScuGic_Config *GicConfig;
typedef struct
{
u16 DevicedId;
u32 CpuBaseAddress;
u32 DistBaseAddress;
XScuGic_VectorTableEntry HandlerTable[XSCUGIC_MAX_NUM_INTR_INPUTS];
} XScuGic_Config;
typedef struct
{
Xil_InterruptHandler Handler;
void *CallBackRef;
} XScuGic_VectorTableEntry;
typedef void (*Xil_InterruptHandler)(void *data);
GicConfig = XScuGic_LookpConfig(DeviceID);
XscuGic_Config *XScuGic_LookpConfig(u16 DeviceId)
{
XscuGic_Config *CfgPtr = NULL;
u32 Index;
for (Index = 0U;Index <(u32)XPAR_SCUGIC_NUM_INSTANCES;Index++){
if (XScuGic_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XScuGic_ConfigTable[Index];
break;
}
}
return (XScuGic_Config *)CfgPtr;
}
XScuGic_Config XScuGic_ConfigTable[] =
{
{
XPAR_PS7_SCUGIC_0_DEVICE_ID,
XPAR_PS7_SCUGIC_0_BASEADDR,
XPAR_PS7_SCUGIC_0_DIST_BASEADDR
}
};
if (NULL == GicConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&IntcInstance, GicConfig,
GicConfig->CpuBaseAddress);
static XScuGic IntcInstance;/* Instance of the Interrupt Controller */
typedef struct
{
XScuGic_Config *Config; /**< Configuration table entry */
u32 IsReady; /**< Device is initialized and ready */
u32 UnhandledInterrupts; /**< Intc Statistics */
} XScuGic;
s32 XScuGic_CfgInitialize(XScuGic *InstancePtr,
XScuGic_Config *ConfigPtr,
u32 EffectiveAddr)
{
u32 Int_Id;
u32 Cpu_Id = (u32)XPAR_CPU_ID + (u32)1;
(void) EffectiveAddr;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(ConfigPtr != NULL);
/*
* Detect Zynq-7000 base silicon configuration,Dual or Single CPU.
* If it is single CPU cnfiguration then invoke assert for CPU ID=1
*/
#ifdef ARMA9
if ( XPAR_CPU_ID == 0x01 )
{
Xil_AssertNonvoid((Xil_In32(XPS_EFUSE_BASEADDR + EFUSE_STATUS_OFFSET)
& EFUSE_STATUS_CPU_MASK ) == 0);
}
#endif
if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) {
InstancePtr->IsReady = 0U;
InstancePtr->Config = ConfigPtr;
for (Int_Id = 0U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id++) {
/*
* Initalize the handler to point to a stub to handle an
* interrupt which has not been connected to a handler. Only
* initialize it if the handler is 0 which means it was not
* initialized statically by the tools/user. Set the callback
* reference to this instance so that unhandled interrupts
* can be tracked.
*/
if ((InstancePtr->Config->HandlerTable[Int_Id].Handler == NULL)) {
InstancePtr->Config->HandlerTable[Int_Id].Handler =
StubHandler;
}
InstancePtr->Config->HandlerTable[Int_Id].CallBackRef =
InstancePtr;
}
DistributorInit(InstancePtr, Cpu_Id);
CPUInitialize(InstancePtr);
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
}
return XST_SUCCESS;
}
static void DistributorInit(XScuGic *InstancePtr, u32 CpuID)
{
u32 Int_Id;
u32 LocalCpuID = CpuID;
u32 RegValue;
#if USE_AMP==1 && (defined (ARMA9) || defined(__aarch64__))
#warning "Building GIC for AMP"
/*
* GIC initialization is taken care by master CPU in
* openamp configuration, so do nothing and return.
*/
return;
#endif
RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET);
if (!(RegValue & XSCUGIC_EN_INT_MASK)) {
Xil_AssertVoid(InstancePtr != NULL);
DoDistributorInit(InstancePtr, CpuID);
return;
}
/*
* The overall distributor should not be initialized in AMP case where
* another CPU is taking care of it.
*/
LocalCpuID |= LocalCpuID << 8U;
LocalCpuID |= LocalCpuID << 16U;
for (Int_Id = 32U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+4U) {
RegValue = XScuGic_DistReadReg(InstancePtr,
XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id));
RegValue |= LocalCpuID;
XScuGic_DistWriteReg(InstancePtr,
XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id),
RegValue);
}
}
static void CPUInitialize(XScuGic *InstancePtr)
{
/*
* Program the priority mask of the CPU using the Priority mask register
*/
XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_CPU_PRIOR_OFFSET, 0xF0U);
/*
* If the CPU operates in both security domains, set parameters in the
* control_s register.
* 1. Set FIQen=1 to use FIQ for secure interrupts,
* 2. Program the AckCtl bit
* 3. Program the SBPR bit to select the binary pointer behavior
* 4. Set EnableS = 1 to enable secure interrupts
* 5. Set EnbleNS = 1 to enable non secure interrupts
*/
/*
* If the CPU operates only in the secure domain, setup the
* control_s register.
* 1. Set FIQen=1,
* 2. Set EnableS=1, to enable the CPU interface to signal secure interrupts.
* Only enable the IRQ output unless secure interrupts are needed.
*/
XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_CONTROL_OFFSET, 0x07U);
}
#define XScuGic_CPUWriteReg(InstancePtr, RegOffset, Data) \
(XScuGic_WriteReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset), \
((u32)(Data))))
typedef struct
{
u16 DevicedId;
u32 CpuBaseAddress;
u32 DistBaseAddress;
XScuGic_VectorTableEntry HandlerTable[XSCUGIC_MAX_NUM_INTR_INPUTS];
} XScuGic_Config;
typedef struct
{
Xil_InterruptHandler Handler;
void *CallBackRef;
} XScuGic_VectorTableEntry;
typedef void (*Xil_InterruptHandler)(void *data);
GicConfig = XScuGic_LookpConfig(DeviceID);
XscuGic_Config *XScuGic_LookpConfig(u16 DeviceId)
{
XscuGic_Config *CfgPtr = NULL;
u32 Index;
for (Index = 0U;Index <(u32)XPAR_SCUGIC_NUM_INSTANCES;Index++){
if (XScuGic_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XScuGic_ConfigTable[Index];
break;
}
}
return (XScuGic_Config *)CfgPtr;
}
XScuGic_Config XScuGic_ConfigTable[] =
{
{
XPAR_PS7_SCUGIC_0_DEVICE_ID,
XPAR_PS7_SCUGIC_0_BASEADDR,
XPAR_PS7_SCUGIC_0_DIST_BASEADDR
}
};
if (NULL == GicConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&IntcInstance, GicConfig,
GicConfig->CpuBaseAddress);
static XScuGic IntcInstance;/* Instance of the Interrupt Controller */
typedef struct
{
XScuGic_Config *Config; /**< Configuration table entry */
u32 IsReady; /**< Device is initialized and ready */
u32 UnhandledInterrupts; /**< Intc Statistics */
} XScuGic;
s32 XScuGic_CfgInitialize(XScuGic *InstancePtr,
XScuGic_Config *ConfigPtr,
u32 EffectiveAddr)
{
u32 Int_Id;
u32 Cpu_Id = (u32)XPAR_CPU_ID + (u32)1;
(void) EffectiveAddr;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(ConfigPtr != NULL);
/*
* Detect Zynq-7000 base silicon configuration,Dual or Single CPU.
* If it is single CPU cnfiguration then invoke assert for CPU ID=1
*/
#ifdef ARMA9
if ( XPAR_CPU_ID == 0x01 )
{
Xil_AssertNonvoid((Xil_In32(XPS_EFUSE_BASEADDR + EFUSE_STATUS_OFFSET)
& EFUSE_STATUS_CPU_MASK ) == 0);
}
#endif
if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) {
InstancePtr->IsReady = 0U;
InstancePtr->Config = ConfigPtr;
for (Int_Id = 0U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id++) {
/*
* Initalize the handler to point to a stub to handle an
* interrupt which has not been connected to a handler. Only
* initialize it if the handler is 0 which means it was not
* initialized statically by the tools/user. Set the callback
* reference to this instance so that unhandled interrupts
* can be tracked.
*/
if ((InstancePtr->Config->HandlerTable[Int_Id].Handler == NULL)) {
InstancePtr->Config->HandlerTable[Int_Id].Handler =
StubHandler;
}
InstancePtr->Config->HandlerTable[Int_Id].CallBackRef =
InstancePtr;
}
DistributorInit(InstancePtr, Cpu_Id);
CPUInitialize(InstancePtr);
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
}
return XST_SUCCESS;
}
static void DistributorInit(XScuGic *InstancePtr, u32 CpuID)
{
u32 Int_Id;
u32 LocalCpuID = CpuID;
u32 RegValue;
#if USE_AMP==1 && (defined (ARMA9) || defined(__aarch64__))
#warning "Building GIC for AMP"
/*
* GIC initialization is taken care by master CPU in
* openamp configuration, so do nothing and return.
*/
return;
#endif
RegValue = XScuGic_DistReadReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET);
if (!(RegValue & XSCUGIC_EN_INT_MASK)) {
Xil_AssertVoid(InstancePtr != NULL);
DoDistributorInit(InstancePtr, CpuID);
return;
}
/*
* The overall distributor should not be initialized in AMP case where
* another CPU is taking care of it.
*/
LocalCpuID |= LocalCpuID << 8U;
LocalCpuID |= LocalCpuID << 16U;
for (Int_Id = 32U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+4U) {
RegValue = XScuGic_DistReadReg(InstancePtr,
XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id));
RegValue |= LocalCpuID;
XScuGic_DistWriteReg(InstancePtr,
XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id),
RegValue);
}
}
static void CPUInitialize(XScuGic *InstancePtr)
{
/*
* Program the priority mask of the CPU using the Priority mask register
*/
XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_CPU_PRIOR_OFFSET, 0xF0U);
/*
* If the CPU operates in both security domains, set parameters in the
* control_s register.
* 1. Set FIQen=1 to use FIQ for secure interrupts,
* 2. Program the AckCtl bit
* 3. Program the SBPR bit to select the binary pointer behavior
* 4. Set EnableS = 1 to enable secure interrupts
* 5. Set EnbleNS = 1 to enable non secure interrupts
*/
/*
* If the CPU operates only in the secure domain, setup the
* control_s register.
* 1. Set FIQen=1,
* 2. Set EnableS=1, to enable the CPU interface to signal secure interrupts.
* Only enable the IRQ output unless secure interrupts are needed.
*/
XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_CONTROL_OFFSET, 0x07U);
}
#define XScuGic_CPUWriteReg(InstancePtr, RegOffset, Data) \
(XScuGic_WriteReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset), \
((u32)(Data))))