好人,
我试图在ARM装配上切齿,但我无法完全理解中断的概念。在此之前,我使用过AVR中断,其中编写代码以明确地将中断向量链接到被跳入的子例程或段:
.ORG $0022
RJMP TIMER_INTERRUPT
然而,在使用Atmel SAMA5D3系列时,我无法弄清楚如何完成类似的事情。我知道前8个中断向量位于前8个程序计数器地址(reset
0x00
到fiq
0x1C
},但我还没有能够找到关于各个外设中断(SPI,UART,TC模块)如何映射到标准化ARM向量表的良好,严谨,易于理解的资源。
也就是说,假设在代码中我将UART配置为能够抛出中断。它抛出中断时会发生什么? irq
条目(0x18
)的地址是否包含设备特定向量表的位置?供应商和设备特定的外设如何通过核心标准化表声明中断?
我已经咨询了SAMA5D3以及ARM ARM的数据表,我发现很多东西使得初学者更容易。如果有什么不清楚的话,我很抱歉,并且因为避免集会而感到羞耻。
编辑:
来自SAMA5D3 datasheet, page 118,它声明:
假设:
- 高级中断控制器已编程,AIC_SVR寄存器加载了相应的中断服务程序地址并启用了中断。
- 需要使用ARM中断异常向量地址的指令来处理向量:
醇>
LDR PC, [PC, # -&F20]
当
nIRQ
被置位时,如果CPSR
的位“I”为0,则序列如下:
CPSR
存储在SPSR_irq
中,程序计数器的当前值加载到中断链接寄存器(R14_irq
)和程序计数器(R15
)中加载0x18。在地址0x1C获取期间的下一个周期中,ARM内核调整R14_irq
,将其递减4。- 如果ARM内核尚未进入中断模式,则进入中断模式。
- 当执行加载到地址0x18的指令时,程序计数器加载了
醇>AIC_IVR
中读取的值。
这是可以理解的。从读取此信息并查看寄存器编号,我将外设中断源(即SPI0/1
)编号放入INTSEL
的{{1}}字段,然后听起来像我存储的地址将ISR转换为AIC_SSR
。
有两个问题,其中一个问题是我不理解需要存在的向量指令(AIC_SVR
)并且与{{1}处的LDR PC, [PC, # -&F20]
向量地址兼容}}。
另一个问题是,如何启用多个中断?只有一个irq
字段和源向量寄存器,那么如何在这个系统上运行多个中断处理程序呢?
我继续道歉,伙计们,如果我没有得到这个,但我至少会尝试做我的功课。
答案 0 :(得分:0)
我承认,除了快速浏览链接文档之外,我不知道这个特定的系统,但它似乎很简单。首先,让我们忘记CPU并专注于中断控制器:
不是浪费地址空间和复杂性映射每个中断源的单独控制寄存器,而是向量保持在控制器的内部 - 而是获得一组寄存器,它们充当内部数据的窗口,加上一个选择器注册控制该窗口所指向的 的位置。因此配置序列可能是这样的:
AIC_SSR
AIC_SMR
,将处理程序地址写入AIC_SVR
AIC_SSR
AIC_SMR
,将处理程序地址写入AIC_SVR
AIC_IVR
与窗口的工作方式类似,除了可编程选择器,它由当前活动中断控制。例如,当中断3触发时,AIC_IVR
将读作我们在上面步骤4中编程的地址。
现在,CPU方面更加直截了当。请注意,ARM异常向量的布局意味着每个'处理程序'只有一条指令,因此它们几乎总是分支到其他地方的完整处理程序例程。每种类型的异常都有一个处理程序,因此当IRQ被置位时,CPU只会跳转到“IRQ”。地址1}}。这是外部中断向量发挥作用的地方 - 因为中断控制器已经具有所有细节,CPU不需要顶级IRQ处理程序来确定此IRQ用于哪个中断以及做什么,它只需要加载0x18
中显示的任何地址,跳转到它,它就会在正确的特定于中断的处理程序中。
这意味着' IRQ处理程序'可以简化为魔术指导 - 魔法'因为AIC_IVR
地址(AIC_AVR
)足够接近CPU相对负载的CPU异常向量(由于地址环绕),因此0xFFFFF100
目标PC可以从单个异常向量指令本身执行地址加载和分支,从而最大限度地减少延迟。
当然,你可能不会 这样做,它只是最好的选择 - 我想象这样毫无意义的长篇大论可能会起作用太:
LDR