Mi proyecto actual involucra la producción de formas de onda PWM de 200KHz usando el temporizador 1 en modo PWM rápido. Me gustaría incrementar un contador de 16 bits cada vez que el temporizador se desborda (cada 5 μS)
volatile uint16_t count;
ISR(TIMER1_OVF_vect)
{
++count;
}
El microcontrolador es un ATmega8 que funciona a 16MHz, dejando solo 80 ciclos para reparar la interrupción e incrementar la variable antes de que se active la siguiente interrupción. Mirando el código compilado ...
00000890 <__vector_8>:
890: 1f 92 push r1
892: 0f 92 push r0
894: 0f b6 in r0, 0x3f ; 63
896: 0f 92 push r0
898: 11 24 eor r1, r1
89a: 8f 93 push r24
89c: 9f 93 push r25
89e: 80 91 c9 00 lds r24, 0x00C9
8a2: 90 91 ca 00 lds r25, 0x00CA
8a6: 01 96 adiw r24, 0x01 ; 1
8a8: 90 93 ca 00 sts 0x00CA, r25
8ac: 80 93 c9 00 sts 0x00C9, r24
8b0: 9f 91 pop r25
8b2: 8f 91 pop r24
8b4: 0f 90 pop r0
8b6: 0f be out 0x3f, r0 ; 63
8b8: 0f 90 pop r0
8ba: 1f 90 pop r1
8bc: 18 95 reti
... Descubrí que la rutina de servicio de interrupción generada podría optimizarse aún más fácilmente. Esta es la primera vez que trato de incluir el ensamblaje en línea en un programa en C, y he descubierto que aprender a hacerlo es es innecesariamente frustrante y requiere entender una sintaxis bastante esotérica. Me gustaría saber cómo acceder a uint8_t count
dentro del ensamblaje en línea (ya que la variable se asigna estáticamente a diferencia de cada respuesta que tengo visto en la web). ¿El código está bien de otra manera, o me he perdido algo más?
ISR(TIMER1_OVF_vect, ISR_NAKED)
{
asm volatile("push r24" "\n\t"
"in r24, __SREG__" "\n\t"
"push r24" "\n\t"
"push r25" "\n\t"
"lds r24, %A0" "\n\t"
"lds r25, %B0" "\n\t"
"adiw r24, 1" "\n\t"
"sts %B0, r25" "\n\t"
"sts %A0, r24" "\n\t"
"pop r25" "\n\t"
"pop r24" "\n\t"
"out __SREG__, r24" "\n\t"
"pop r24" "\n\t"
"reti" "\n\t"
: "=r" (count) /*this does*/
: "0" (count)); /*not work*/
}
Como nota al margen, ¿hay una manera de hacer que el compilador reserve un par de registros específicamente para uint8_t count
, ya que permitiría reducir la longitud del ISR en al menos 6 instrucciones (eliminando las instrucciones de pds y pts, un empuje)? apilar, y un pop de la pila)?