Evitar un if
que puede resultar en una rama no debe ser su prioridad,
especialmente en AVR donde las ramas son 1 o 2 ciclos (¡dependiendo del valor de la condición!)
En este caso, su solución probablemente usaría un registro y una operación aritmética, una reescritura a una sentencia if como la respuesta de Harry Svensson usaría solo operaciones de bifurcación de bits y de configuración / borrado de bits que no cambian el registro de estado SREG
).
En ambos casos, si realmente desea un tiempo de ejecución mínimo, podría considerar usar una interrupción "desnuda" ( ISR_NAKED
) para evitar que el compilador almacene un montón de registros y los haga aparecer al regresar.
Cuando no utiliza uso registros (sugerencia de pista) no es necesario guardarlos y su ISR puede ser muy pequeño. Solo asegúrese de que su código generado no use realmente ningún registro como el que tiene previsto al inspeccionar el código generado después de la compilación, o escriba el ISR en ensamblador.
#include <avr/interrupt.h>
ISR(PCINT0_vect)
{
if(PINB&(1<<PB2)){//This is essentially a bit test instruction
PORTB&=~(1<<PB1);//This is essentially a bit clear instruction
}else{
PORTB|=(1<<PB1);//This is essentially a bit set instruction
}
}
int main(int argc, char** argv)
{}
compila con avr-gcc -S -O3 bitwise_not.c -mmcu=attiny10
a:
.file "bitwise_not.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__CCP__ = 0x3c
__tmp_reg__ = 16
__zero_reg__ = 17
.text
.global __vector_2
.type __vector_2, @function
__vector_2:
push r17
push r16
in r16,__SREG__
push r16
ldi __zero_reg__,0
/* prologue: Signal */
/* frame size = 0 */
/* stack size = 3 */
.L__stack_usage = 3
sbic 0,2
rjmp .L5
sbi 0x2,1
/* epilogue start */
pop r16
out __SREG__,r16
pop r16
pop r17
reti
.L5:
cbi 0x2,1
/* epilogue start */
pop r16
out __SREG__,r16
pop r16
pop r17
reti
.size __vector_2, .-__vector_2
.section .text.startup,"ax",@progbits
.global main
.type main, @function
main:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
ldi r24,0
ldi r25,0
ret
.size main, .-main
.ident "GCC: (GNU) 5.4.0"
(note la optimización agresiva de duplicar el epílogo)
#include <avr/interrupt.h>
ISR(PCINT0_vect, ISR_NAKED)
{
if(PINB&(1<<PB2)){//This is essentially a bit test instruction
PORTB&=~(1<<PB1);//This is essentially a bit clear instruction
}else{
PORTB|=(1<<PB1);//This is essentially a bit set instruction
}
reti(); //Must be explicitly called when using ISR_NAKED
}
int main(int argc, char** argv)
{}
compila a (usando el mismo comando)
.file "bitwise_not.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__CCP__ = 0x3c
__tmp_reg__ = 16
__zero_reg__ = 17
.text
.global __vector_2
.type __vector_2, @function
__vector_2:
/* prologue: naked */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
sbis 0,2
rjmp .L2
cbi 0x2,1
rjmp .L3
.L2:
sbi 0x2,1
.L3:
/* #APP */
; 9 "bitwise_not.c" 1
reti
; 0 "" 2
/* epilogue start */
/* #NOAPP */
.size __vector_2, .-__vector_2
.section .text.startup,"ax",@progbits
.global main
.type main, @function
main:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
ldi r24,0
ldi r25,0
ret
.size main, .-main
.ident "GCC: (GNU) 5.4.0"