1、gicv2_spis_configure_defaults
用来配置SPI的一些默认的属性,SPI中断
- SPI:(shared peripheral interrupt),共享外设中断,该中断来源于外设,但是该中断可以对所有的core有效。
在gic的文档里面有写这样一句话,来说明这个中断。
SPIs are routed from the source through the Distributor to the target Redistributor and the associated CPU
interface
SPIs从源通过分发器路由到目标再分发器和相关的CPU接口,这里有个关键词目标。因此这个目标可以是一个或者多个。
/*******************************************************************************
-
Helper function to configure the default attributes of SPIs.
******************************************************************************/
void gicv2_spis_configure_defaults(uintptr_t gicd_base)
{
unsigned int index, num_ints;num_ints = gicd_read_typer(gicd_base);
1-通过GICD_TYPER获得最多支持的SPI中断数量
注:
gicd_read_typer(gicd_base);
static inline unsigned int gicd_read_typer(uintptr_t base)
{
return mmio_read_32(base + GICD_TYPER);
}
GICD_TYPER寄存器:
提供有关GIC实现支持的功能的信息。它表明:
•GIC实施是否支持两种安全状态。
•GIC实施支持的最大INTID数。
•可用作中断目标的PE数量。
num_ints &= TYPER_IT_LINES_NO_MASK;
num_ints = (num_ints + 1U) << 5;
注
the maximum SPI INTID is 32(N+1)-1. For example, 00011 specifies that the maximum SPI
INTID is 127.
从该字段派生的值指定GIC实现可能支持的最大SPI数。一个实现可能无法实现达到此最大值的所有SPI。
/*
* Treat all SPIs as G1NS by default. The number of interrupts is
* calculated as 32 * (IT_LINES + 1). We do 32 at a time.
*/
for (index = MIN_SPI_ID; index < num_ints; index += 32U)
gicd_write_igroupr(gicd_base, index, ~0U);
2-通过IGROUPR设置中断的分组,对每次pe生效
注
*访问器,用于写入与中断“id”对应的GIC分发器IGROUPR,一次32个中断id。
void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val)
{
unsigned int n = id >> IGROUPR_SHIFT;
mmio_write_32(base + GICD_IGROUPR + (n << 2), val);
}
GICD_IGROUPR
**控制相应的中断是在组0还是组1中。**
对于SGI和PPI:
•当中断的安全状态ARE为1时,该中断的字段为RES0,在这种情况下允许实现RAZ/WI字段。(RAZ/WI:read as zero, write ignored)
•GICR_IGROUPR0提供了等效功能。
当GICD_CTLR.DS==0时,寄存器为RAZ/WI,用于非安全访问。
与未实现中断相对应的位是RAZ/WI。
笔记
当未为安全状态启用关联路由时,访问GICD_IGROUPR0访问与GICR_IGROUGR0相同的状态,并且必须更新与执行访问的PE关联的Redistributor状态。
实现必须确保在写入时挂起的中断使用旧值或新值,并且必须确保中断不会丢失或处理多次。变化的影响必须在有限的时间内可见。
配置
这些寄存器在所有GIC配置中都可用。如果GIC实现支持两种安全状态,则这些寄存器是安全的。
实现的GICD_IGROUPR<n>寄存器的数量为**GICD_TYPER.ITLinesNumber**+1。寄存器从0开始编号。
GICD_IGROUPR0为每个连接的PE存储。此寄存器为中断0-31提供组状态位。
属性
GICD_IGROUPR<n>是一个32位寄存器。
后面这段比较 重要,解释了为什么这句代码这么写的。
如果为中断的安全状态启用了关联路由,则与中断对应的位与GICD_IGRPMODR<n>中的等效位连接,以形成定义中断组的2位字段。GICD_IGRPMODR<n>中描述了该字段的编码。
如果针对中断的安全状态禁用了关联路由,则:
•对应的GICD_IGRPMODR<n>位为RES0。
•对于安全中断,中断为安全组0。
•对于非安全中断,中断为非安全组1。
对于INTID m,当DIV和MOD是整数除法和模运算时:
•对应的GICD_IGROUP<n>编号n由n=m DIV 32给出。
•所需GICD_IGROUP的偏移量为(0x080+(4*n))。
•此寄存器中所需的组修饰符位的位数为m MOD 32。
通常,所有GICD_IGROUPR<n>和GICD_IGRPMODR<n>寄存器的重置值均为0,**因此所有中断均为组0,除非通过对适当寄存器的安全访问将其重新编程为组1。**这里是手动把所有的都写成了1,每个中断对于每个pe,所以需要循环。应该是这个中断,对于所有的PE都是1。中断是循环量。
/* Setup the default SPI priorities doing four at a time */
for (index = MIN_SPI_ID; index < num_ints; index += 4U)
gicd_write_ipriorityr(gicd_base,
index,
GICD_IPRIORITYR_DEF_VAL)
3-通过GICD_IPRIORITYR设置了每个SPI中断的优先级
注
寄存器:GICD_IPRIORITYR
保持相应中断的优先级,中断的优先级配置
/* Treat all SPIs as level triggered by default, 16 at a time */
for (index = MIN_SPI_ID; index < num_ints; index += 16U)
gicd_write_icfgr(gicd_base, index, 0U);
}
4-通过GICD_ICFGR确定相应的中断是边缘触发的还是电平触发的。
注:
寄存器 GICD_ICFGR
确定相应的中断是边缘触发的还是电平触发的。