你好:
本论坛提供的Keystone II STK DSP 中的SRIO范例中使用了函数interrupt void SRIO_Doorbell_ISR()。当DSP接收到Doorbell以后,该function将会被执行,然而在范例中,并没有发现 SRIO_Doorbell_ISR()被提及或使用。
问题:该函数是如何被唤醒的?
谢谢!
于熙宁
相关的代码如下所示:
/*define the message convey by doorbell for this test*/
char * doorbell_msg_str[]=
{
"doorbell for latency test.",
"doorbell which indicates NREAD operation done.",
"doorbell which indicates NWRITE operation done.",
"doorbell which indicates NWRITE_R operation done.",
"doorbell which indicates SWRITE operation done."
};
interrupt void SRIO_Doorbell_ISR()
{
Uint32 doorbell;
uiDoorbell_TSC= TSCL;
//read doorbell. this test only use doorbell reg 0
doorbell= gpSRIO_regs->DOORBELL_ICSR_ICCR[0].RIO_DOORBELL_ICSR;
//clear doorbell interrupt
gpSRIO_regs->DOORBELL_ICSR_ICCR[0].RIO_DOORBELL_ICCR= doorbell;
//printf doorbell message
if(doorbell&1)
printf("received %s\n", doorbell_msg_str[0]);
if(doorbell&2)
printf("received %s\n", doorbell_msg_str[1]);
if(doorbell&4)
printf("received %s\n", doorbell_msg_str[2]);
if(doorbell&8)
printf("received %s\n", doorbell_msg_str[3]);
if(doorbell&16)
printf("received %s\n", doorbell_msg_str[4]);
}
The below is the SRIO Interrupt initialization function used in the same example project.
main()
{
......
......
SRIO_Interrupts_Init();
KeyStone_SRIO_Interrupt_init(srio_cfg->interrupt_cfg);
......
......
}
/*Word index of the Interrupt Routing Registers*/
typedef enum
{
DOORBELL0_ICRR1 = (0x00/4),
DOORBELL0_ICRR2 = (0x04/4),
DOORBELL1_ICRR1 = (0x0C/4),
DOORBELL1_ICRR2 = (0x10/4),
DOORBELL2_ICRR1 = (0x18/4),
DOORBELL2_ICRR2 = (0x1C/4),
DOORBELL3_ICRR1 = (0x24/4),
DOORBELL3_ICRR2 = (0x28/4),
LSU_SRCID_ICRR1 = (0x30/4),
LSU_SRCID_ICRR2 = (0x34/4),
LSU_SRCID_ICRR3 = (0x38/4),
LSU_SRCID_ICRR4 = (0x3C/4),
LSU_ICRR1 = (0x40/4),
ERR_RST_EVNT_ICRR1 = (0x50/4),
ERR_RST_EVNT_ICRR2 = (0x54/4),
ERR_RST_EVNT_ICRR3 = (0x58/4)
}SRIO_ICRR_Index;
typedef enum
{
/* SRIO interrupt source constant,
high 16 bits is the ICRR register index,
lower 16 bits is the offset of the field in the register*/
DOORBELL0_0_INT = ((DOORBELL0_ICRR1 << 16) | 0x0000),
DOORBELL0_1_INT = ((DOORBELL0_ICRR1 << 16) | 0x0004),
DOORBELL0_2_INT = ((DOORBELL0_ICRR1 << 16) | 0x0008),
DOORBELL0_3_INT = ((DOORBELL0_ICRR1 << 16) | 0x000C),
DOORBELL0_4_INT = ((DOORBELL0_ICRR1 << 16) | 0x0010),
DOORBELL0_5_INT = ((DOORBELL0_ICRR1 << 16) | 0x0014),
DOORBELL0_6_INT = ((DOORBELL0_ICRR1 << 16) | 0x0018),
DOORBELL0_7_INT = ((DOORBELL0_ICRR1 << 16) | 0x001C),
DOORBELL0_8_INT = ((DOORBELL0_ICRR2 << 16) | 0x0000),
DOORBELL0_9_INT = ((DOORBELL0_ICRR2 << 16) | 0x0004),
DOORBELL0_10_INT = ((DOORBELL0_ICRR2 << 16) | 0x0008),
DOORBELL0_11_INT = ((DOORBELL0_ICRR2 << 16) | 0x000C),
DOORBELL0_12_INT = ((DOORBELL0_ICRR2 << 16) | 0x0010),
DOORBELL0_13_INT = ((DOORBELL0_ICRR2 << 16) | 0x0014),
DOORBELL0_14_INT = ((DOORBELL0_ICRR2 << 16) | 0x0018),
DOORBELL0_15_INT = ((DOORBELL0_ICRR2 << 16) | 0x001C),
.....
}SRIO_Interrupt_Source;
SRIO_Interrupt_Map interrupt_map[]=
{
/*interrupt_event*/ /*INTDST_number*/
{DOORBELL0_0_INT, INTDST_16}, /*route to core 0*/
{DOORBELL0_1_INT, INTDST_16}, /*route to core 0*/
{DOORBELL0_2_INT, INTDST_16}, /*route to core 0*/
{DOORBELL0_3_INT, INTDST_16}, /*route to core 0*/
{DOORBELL0_4_INT, INTDST_16} /*route to core 0*/
};
SRIO_Interrupt_Cfg interrupt_cfg;
void SRIO_Interrupts_Init(void)
{
/* Disable Global host interrupts. */
gpCIC0_regs->GLOBAL_ENABLE_HINT_REG= 0;
uiLow_pri_Q_host_event_num= 18;
/*map INTD1 low priority queue channel 0 interrupt event to CIC0 out 18*/
KeyStone_CIC_event_map(gpCIC0_regs, CSL_CIC0_QMSS_INTD_1_LOW_0, uiLow_pri_Q_host_event_num);
/* Enable Global host interrupts. */
gpCIC0_regs->GLOBAL_ENABLE_HINT_REG= 1;
/*map SRIO doorbell interrupts to INT4.
map message descriptor accumulation low priority channel 0 interrupt
to INT5*/
gpCGEM_regs->INTMUX1 =
(CSL_C66X_COREPAC_SRIO_INTDST16_PLUS_N<<CSL_CGEM_INTMUX1_INTSEL4_SHIFT)|
(CSL_C66X_COREPAC_CIC_OUT18<<CSL_CGEM_INTMUX1_INTSEL5_SHIFT);
//enable INT4, 5
CPU_interrupt_enable((1<<4)|(1<<5));
interrupt_cfg.interrupt_map = interrupt_map;
interrupt_cfg.uiNumInterruptMap =
sizeof(interrupt_map)/sizeof(SRIO_Interrupt_Map);
/*interrupt rate control is not used in this test*/
interrupt_cfg.interrupt_rate= NULL;
interrupt_cfg.uiNumInterruptRateCfg= 0;
interrupt_cfg.doorbell_route_ctl= SRIO_DOORBELL_ROUTE_TO_DEDICATE_INT;
srio_cfg.interrupt_cfg = &interrupt_cfg;
}
void KeyStone_SRIO_Interrupt_init(
SRIO_Interrupt_Cfg * interrupt_cfg)
{
Uint32 i;
Uint32 reg, shift;
volatile Uint32 * ICRR= (volatile Uint32 *)gpSRIO_regs->DOORBELL_ICRR;
if(NULL == interrupt_cfg)
return;
/* Clear all the interrupts */
for(i=0; i<2; i++)
{
gpSRIO_regs->LSU_ICSR_ICCR[i].RIO_LSU_ICCR = 0xFFFFFFFF ;
}
for(i=0; i<4; i++)
{
gpSRIO_regs->DOORBELL_ICSR_ICCR[i].RIO_DOORBELL_ICCR = 0xFFFFFFFF;
}
gpSRIO_regs->RIO_ERR_RST_EVNT_ICCR = 0xFFFFFFFF;
if(NULL != interrupt_cfg->interrupt_map)
{
for(i=0; i<interrupt_cfg->uiNumInterruptMap; i++)
{
/* Get register index for the interrupt source*/
reg = interrupt_cfg->interrupt_map[i].interrupt_event >> 16;
/* Get shift value for the interrupt source*/
shift = interrupt_cfg->interrupt_map[i].interrupt_event & 0x0000FFFF;
ICRR[reg]= (ICRR[reg]&(~(0xF<<shift))) /*clear the field*/
|(interrupt_cfg->interrupt_map[i].INTDST_number<<shift);
}
}
gpSRIO_regs->RIO_INTERRUPT_CTL = interrupt_cfg->doorbell_route_ctl;
/*disable interrupt rate control*/
gpSRIO_regs->RIO_INTDST_RATE_DIS= 0xFFFF;
for(i= 0; i< 16; i++)
{
gpSRIO_regs->RIO_INTDST_RATE_CNT[i]= 0;
}
if(NULL != interrupt_cfg->interrupt_rate)
{
/*setup interrupt rate for specific INTDST*/
for(i= 0; i<interrupt_cfg->uiNumInterruptRateCfg; i++)
{
/*enable rate control for this INTDST*/
gpSRIO_regs->RIO_INTDST_RATE_DIS &=
~(1<<interrupt_cfg->interrupt_rate[i].INTDST_number);
/*set interrupt rate counter for this INTDST*/
gpSRIO_regs->RIO_INTDST_RATE_CNT[i]=
interrupt_cfg->interrupt_rate[i].interrupt_rate_counter;
}
}
return;
}