AVR SEI指令(http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_SEI.html)在允许中断之前等待下一条指令完成。
如果我使用另一条指令在SREG中设置I标志,这还会等待1条指令吗?
换句话说:等待是SEI指令或状态寄存器的功能吗?
如果它是SEI指令的功能,那么在执行SEI的周期中或与下一条指令一起在哪一点实际设置该标志?
AVR SEI指令(http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_SEI.html)在允许中断之前等待下一条指令完成。
如果我使用另一条指令在SREG中设置I标志,这还会等待1条指令吗?
换句话说:等待是SEI指令或状态寄存器的功能吗?
如果它是SEI指令的功能,那么在执行SEI的周期中或与下一条指令一起在哪一点实际设置该标志?
Answers:
尽管其他答案都是经过深思熟虑和合理推理的,但它们都是不完整的或仅是推测。在文档不明确的地方,我们必须进行试验,并且必须测试每种情况。
这个问题值得一个肯定的答案,所以让我们拉出AVR并开始设置一些位!
为了测试,我制作了一个小的Arduino(ATMEGA328P)程序,该程序可以...
while (1)
)INT0
低)我使用了一个测试台,在启用中断后,该测试台会在一条指令中打开LED。通过尝试在测试台中启用中断的不同方式并检查LED,我可以判断启用指令之后的指令是否已执行。
如果LED指示灯不亮,那么我知道在允许中断后立即执行(并锁定)了ISR。
如果LED确实点亮,那么我知道在调用ISR之前允许执行下一条指令。
SEI
指令(基本情况)码:
sei
结果:LED亮。执行以下指令。
OUT
指令码:
in r16,0x3f // Get SREG
ori r16,128 // Set I bit
out 0x3f,r16 // Save back to SREG
结果:
带领。执行以下指令。
ST
指令码:
clr r29 // Clear Y high byte
ldi r28,0x5f // Set Y low byte to point to SREG
ld r16, Y // Get SREG
ori r16,128 // Set I bit
st Y,r16 // Put SREG
结果:
带领。执行以下指令。
问:等待是SEI指令或状态寄存器的功能吗?
答:看来,即使有挂起的中断,无论使用什么指令来设置该位,将I
位中的位SREG
从a 更改0
为a 1
都将允许下一条指令继续执行。
这实际上变成了一个非常有趣的问题,并带有许多复杂性。如果您对详细信息感兴趣,请查看...
http://wp.josh.com/2016/01/05/different-ways-to-set-i-bit-in-avr-sreg-besides-sei/
我从文档中了解到,执行sei
指令与直接将1写入SREG的I位没有什么不同。该指令的优点是您无需先将一个值加载1<<I
到工作寄存器中即可更改SREG,从而节省了时间。
要详细说明,请使用sei
:
sei ; One cycle
使用设置该位sbi
(仅当SREG位于寄存器映射的低32字节时才起作用,但似乎在大多数情况下(如果不是全部的话)不是。)
sbi SREG,7 ; Two cycles
直接在SREG中写信给我:
in r24,SREG ;
ori r24,0x80 ;
out SREG,r24 ; Three cycles
指令(或)完成后,I
应在SREG中将该位置1 。但是,直到下一条指令完成后,任何待处理的中断都不会被处理-该位将被置1,但是要使中断使能需要花费额外的时间。由于无法在指令中间处理中断,并且某些指令需要执行一个以上的周期,因此它们指定将其作为一条指令启用所花费的时间。对于所有版本的代码都应该是这种情况-即上述每个都会导致指令的延迟。sei
sbi
out
经过一番搜索,我在Arduino论坛上找到了该线程,在该线程中进行了几种不同的测试以验证行为。这似乎与我上面所说的一致。
此外,根据该线程,如果I
已经设置了该标志,则不存在引起中断的延迟响应,sei
这意味着该延迟响应不是由指令本身引起的,而是由I
标志控制的内部硬件引起的-因此,任何更改SREG中标志的操作,无论是sei
还是out
,sts
都会具有完全相同的行为。
out
是我最初使用的示例。我以为我会遇到一个AVR(可能是ATTiny),它的低32位寄存器中有SREG,但是我可能在想它。