在AVR中断中保留SREG

8

AVR微控制器中用于保存状态寄存器sreg的机制是什么?RETI 暗示着这些位不在堆栈上。是否有一个通用寄存器也是sreg或类似的东西?


1
状态寄存器不是通用寄存器。它驻留在I/O寄存器文件中,可以使用“in”和“out”指令进行访问。 - Stefan Paul Noack
2个回答

14

这个在每个AVR数据手册中都有解释。例如,在ATtiny2313数据手册的第8页上写道:

状态寄存器在进入中断例程时不会自动保存并在返回中断时恢复。这必须由软件处理。

您可以通过将其存储在临时寄存器中来实现这一点:

 interrupt:
     in r16, SREG   ; save SREG

     ...

     out SREG, r16  ; restore SREG
     reti

同时请注意,如果您要访问的寄存器不是在此中断例程中专门使用的,您也需要保存这些寄存器。此外,如果您的寄存器不够用,您可以将SREG的值推送到堆栈中:

 interrupt:
     push r16      ; save global registers on stack
     push r17
     push r18
     in r16, SREG  ; save SREG
     push r16      ; do this if you want to use r16 in your interrupt routine

     ...

     pop r16       ; do this if you pushed SREG above
     out SREG, r16 ; restore SREG
     pop r18       ; restore global registers
     pop r17
     pop r16
     reti

更多信息请查看这里


1
另外,保留HTML,不做解释。
PUSH Rn
LDS Rn, SREG
PUSH Rn

并且

POP Rn
STS SREG, Rn
POP Rn

似乎是有效的。


接近了!但是它没有保存SREG——我认为它保存的是EECR寄存器。但至少我已经验证过上面的代码不会保存或恢复SREG。 - Harry Pehkonen
2
IN和OUT助记符对数据寄存器0到0x3F进行操作。当您使用LDS或STS访问相同的位置时,需要将其加上0x20。在这种情况下,您将使用“LDS Rn,SREG + 0x20”和“STS SREG + 0x20,Rn”。我很惊讶五年来没有人发现这个问题! - Harry Pehkonen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接