AVR: problema con el ensamblador en línea

1

WinAVR parece producir una gran cantidad de código inútil, por ejemplo, para el siguiente método de C

ISR(INT0_vect) {
    TCCR1B = 0x09;
}

produce ( -Os )

PUSH      R1             Push register on stack
PUSH      R0             Push register on stack
IN        R0,0x3F        In from I/O location
PUSH      R0             Push register on stack
CLR       R1             Clear Register
PUSH      R24            Push register on stack
LDI       R24,0x09       Load immediate
STS       0x0081,R24     Store direct to data space
POP       R24            Pop register from stack
POP       R0             Pop register from stack
OUT       0x3F,R0        Out to I/O location
POP       R0             Pop register from stack
POP       R1             Pop register from stack
RETI                     Interrupt return

aunque

PUSH      R0            Push register on stack
LDI       R0,0x09       Load immediate
STS       0x0081,R0     Store direct to data space
POP       R0            Pop register from stack
RETI                    Interrupt return

debería ser suficiente. Debido a que estos comandos adicionales llevan tiempo, mi pregunta: ¿cómo decirle al compilador que produzca solo el código requerido? ¿O hay una herramienta que puede optimizar el código de byte directamente?

ACTUALIZACIÓN: Lo he intentado

ISR(INT0_vect, ISR_NAKED) {
    asm volatile(
    "push r0             \n\t"
    "ldi  r0, %[value]   \n\t"
    "sts  %[ioReg], r0   \n\t"
    "pop  r0             \n\t"
    "reti                \n\t"
    : // output
    : // input
       [ioReg] "M" (_SFR_IO_ADDR(TCCR1B)),
       [value] "M" (0 << ICNC1
                  | 0 << ICES1 
                  | 0 << WGM13 
                  | 1 << WGM12
                  | 0 << CS12
                  | 0 << CS11 
                  | 1 << CS10)
    );
}

pero el compilador se queja:

c:\temp/ccjBxDFz.s: Assembler messages:
c:\temp/ccjBxDFz.s:30: Error: register number above 15 required

He leído un montón de documentación / tutoriales de ensambladores en línea de AVR, pero no puedo compilarlos.

    
pregunta Mike L.

3 respuestas

1

El problema fue el uso de r0 . Con r16 funciona:

ISR(INT0_vect, ISR_NAKED) {
    asm volatile(
    "push r16             \n\t"
    "ldi  r16, %[value]   \n\t"
    "sts  %[ioReg], r16   \n\t"
    "pop  r16             \n\t"
    "reti                 \n\t"
    : // output
    : // input
       [ioReg] "M" (_SFR_IO_ADDR(TCCR1B)),
       [value] "M" (0 << ICNC1
                  | 0 << ICES1 
                  | 0 << WGM13 
                  | 1 << WGM12
                  | 0 << CS12
                  | 0 << CS11 
                  | 1 << CS10)
    );
}
    
respondido por el Mike L.
2

¿Por qué no usar una declaración de ensamblado en línea para hacer lo que quiere?

Consulte el libro de cocina de ensamblador en línea

Un ejemplo multilínea simple (legible) desde allí (un retraso muy corto) que puede ir directamente a su programa AVR-GCC:

asm volatile ("nop \ n \ t"              "nop \ n \ t"              "nop \ n \ t"              "nop \ n \ t"              : :);

Como parece que conoce su ensamblaje, también debería estar preparado para mecerse con el ensamblaje en línea.

    
respondido por el Windell Oskay
2

Creo que el atributo naked de GCC hace lo que quieres. Omite la generación de cualquier encabezado o pie de página, por lo que necesitas hacer tu propio reti .

void INT0_vect(void) __attribute__ ((signal, naked)); 

void INT0_vect(void) 
{
    TCCR1B = 0x09;
    asm volatile("reti"); 
} 

FreeRTOS usa este esquema para el cambio de contexto en AVR, almacenan explícitamente todos los registros. Es posible que solo desee un subconjunto:

    #define portSAVE_CONTEXT()      \
    asm volatile (  "push   r0                                              \n\t"   \
                                    "in             r0, __SREG__                    \n\t"   \
                                    "cli                                                    \n\t"   \
                                    "push   r0                                              \n\t"   \
                                    "push   r1                                              \n\t"   \
                                    "clr    r1                                              \n\t"   \
                                    "push   r2                                              \n\t"   \
                                    "push   r3                                              \n\t"   \
                                    "push   r4                                              \n\t"   \
                                    "push   r5                                              \n\t"   \
                                    "push   r6                                              \n\t"   \
                                    "push   r7                                              \n\t"   \
                                    "push   r8                                              \n\t"   \
                                    "push   r9                                              \n\t"   \
                                    "push   r10                                             \n\t"   \
                                    "push   r11                                             \n\t"   \
                                    "push   r12                                             \n\t"   \
                                    "push   r13                                             \n\t"   \
                                    "push   r14                                             \n\t"   \
                                    "push   r15                                             \n\t"   \
                                    "push   r16                                             \n\t"   \
                                    "push   r17                                             \n\t"   \
                                    "push   r18                                             \n\t"   \
                                    "push   r19                                             \n\t"   \
                                    "push   r20                                             \n\t"   \
                                    "push   r21                                             \n\t"   \
                                    "push   r22                                             \n\t"   \
                                    "push   r23                                             \n\t"   \
                                    "push   r24                                             \n\t"   \
                                    "push   r25                                             \n\t"   \
                                    "push   r26                                             \n\t"   \
                                    "push   r27                                             \n\t"   \
                                    "push   r28                                             \n\t"   \
                                    "push   r29                                             \n\t"   \
                                    "push   r30                                             \n\t"   \
                                    "push   r31                                             \n\t"   \
                                    "lds    r26, pxCurrentTCB               \n\t"   \
                                    "lds    r27, pxCurrentTCB + 1   \n\t"   \
                                    "in             r0, 0x3d                                \n\t"   \
                                    "st             x+, r0                                  \n\t"   \
                                    "in             r0, 0x3e                                \n\t"   \
                                    "st             x+, r0                                  \n\t"   \
                            );

#define portRESTORE_CONTEXT()                                                           \
    asm volatile (  "lds    r26, pxCurrentTCB               \n\t"   \
                                    "lds    r27, pxCurrentTCB + 1   \n\t"   \
                                    "ld             r28, x+                                 \n\t"   \
                                    "out    __SP_L__, r28                   \n\t"   \
                                    "ld             r29, x+                                 \n\t"   \
                                    "out    __SP_H__, r29                   \n\t"   \
                                    "pop    r31                                             \n\t"   \
                                    "pop    r30                                             \n\t"   \
                                    "pop    r29                                             \n\t"   \
                                    "pop    r28                                             \n\t"   \
                                    "pop    r27                                             \n\t"   \
                                    "pop    r26                                             \n\t"   \
                                    "pop    r25                                             \n\t"   \
                                    "pop    r24                                             \n\t"   \
                                    "pop    r23                                             \n\t"   \
                                    "pop    r22                                             \n\t"   \
                                    "pop    r21                                             \n\t"   \
                                    "pop    r20                                             \n\t"   \
                                    "pop    r19                                             \n\t"   \
                                    "pop    r18                                             \n\t"   \
                                    "pop    r17                                             \n\t"   \
                                    "pop    r16                                             \n\t"   \
                                    "pop    r15                                             \n\t"   \
                                    "pop    r14                                             \n\t"   \
                                    "pop    r13                                             \n\t"   \
                                    "pop    r12                                             \n\t"   \
                                    "pop    r11                                             \n\t"   \
                                    "pop    r10                                             \n\t"   \
                                    "pop    r9                                              \n\t"   \
                                    "pop    r8                                              \n\t"   \
                                    "pop    r7                                              \n\t"   \
                                    "pop    r6                                              \n\t"   \
                                    "pop    r5                                              \n\t"   \
                                    "pop    r4                                              \n\t"   \
                                    "pop    r3                                              \n\t"   \
                                    "pop    r2                                              \n\t"   \
                                    "pop    r1                                              \n\t"   \
                                    "pop    r0                                              \n\t"   \
                                    "out    __SREG__, r0                    \n\t"   \
                                    "pop    r0                                              \n\t"   \
                            );
    
respondido por el Toby Jaffey

Lea otras preguntas en las etiquetas