在PCIe中断中,一共存在4种中断分别为:MSI中断、legacy中断、错误中断和电源管理及重启事件中断。比较常用的是MSI中断和legacy中断。当C6678当做EP端时,只能产生MSI和legacy中断中的一种。当C6678作为RC端时,MSI和legacy中断都能处理。
如图 1所示,C6678支持32个MSI中断,每四个中断组成一个中断事件号。需要注意的是核0只能支持4号中断事件号。以此类推,核1只能支持5号中断,核7只能支持11号中断。由此可知,常用的核0只能支持中断vector0、8、16和24,且这四个中断vector共享一个4号中断事件号。
图 1 PCIe中断事件
1.1 MSI中断初始化配置
具体配置过程如下:
(1)配置MSI_EN=1(寄存器MSI_CAP中bit16),使能MSI中断。
(2)配置MULT_MSG_EN=0x5(寄存器MSI_CAP[22:20],见图 2)。
图 2 MULT_MSG_EN的配置
(3)配置MULT_MSG_CAP=0x5(寄存器MSI_CAP[19:17],见图 3)。
图 3 MULT_MSG_CAP的配置
(4)配置INTX_DIS=1(寄存器STATUS_COMMAND中bit10),关闭legacy中断。
(5)配置MEM_SP=1(寄存器STATUS_COMMAND中bit1),使能设备响应存储器访问。
(6)配置BUS_MS=1(寄存器STATUS_COMMAND中bit2),使能总线控制权。
(7) 配置MSIn_IRQ_STATUS寄存器(n=0~7)。这里举例配置核0能响应的中断vector0、8、16和24。配置MSI0_IRQ_STATUS=0xF(见图 4),清除原本寄存器中的值。
图 4 MSI0_IRQ_STATUS的配置
(8)配置MSI0_IRQ_ENABLE_SET寄存器(n=0~7)。这里举例配置核0能响应的中断vector0、8、16和24。配置MSI0_IRQ_ENABLE_SET=0xF(见图 5),使能中断vector0、8、16和24。
图 5 MSI0_IRQ_ENABLE_SET的配置
(9)配置IRQ_EOI寄存器(见图 6),在其写入中断事件号来表明该中断事件的结束。核0能响应的中断事件号为4,故配置IRQ_EOI=0x4。
图 6 IRQ_EOI的配置
1.2 MSI中断发送
C6678中存在寄存器MSI_IRQ(见图 7),该寄存器由外部设备写入。当外部写入的值为0x0时,表示该设备接收到中断vector0。以此类推,当外部写入的值为0x1F,表示该设备接收到中断vector31。
图 7 MSI_IRQ寄存器配置
完整的中断发送和接收过程如下:
假设DSP A向DSP B发送MSI的vector0中断,首先将DSP A中的某个地址赋值为0,然后DSP A将该地址经过outbound后转变为PCIe地址,该PCIe地址经过inbound后转变为DSP B内部地址0x21800054,也就是寄存器MSI_IQR的地址,此时DSP B也就接收到了vector0中断。
需要注意的是寄存器MSI_IQR属于应用寄存器(application register),DSP B在接收中断时只能使用BAR0进行inbound转化。
1.3 MSI中断接收
接收到MSI中断后,应该清除中断vector n和清除中断事件号。
(1)配置MSIn_IRQ_STATUS寄存器(n=0~7)。这里假定核0响应了中断vector0,进入了4号中断事件号。此时应配置MSI0_IRQ_STATUS=0x1(见图 4),清除中断vector0。
(2)配置IRQ_EOI寄存器(见图 6)。这里假定核0响应了中断vector0,进入了4号中断事件号,故配置IRQ_EOI=0x4,手动结束4号中断事件。
*1.4 MSI中断代码示例
中断初始化代码如下:
中断接收代码如下:
中断发送代码其实和数据的outbound是一样的,这里面涉及具体pcie地址转化(具体上一篇文章已经讲过),我就不将代码贴出来了。原则就是将中断vector号写到对端DSP的0x21800054这个寄存器中。