Restricciones de operandos de ensamblaje en línea ATTiny414 para el parámetro de pin IO

1

Estoy intentando utilizar la biblioteca light_ws2812 para controlar los LED de WS2812 desde un ATTiny414. El núcleo de esa biblioteca es un fragmento de ensamblaje en línea que golpea la línea serie. Aquí está con el cronometraje nops eliminado:

void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi)
{
  uint8_t curbyte,ctr,masklo;
  uint8_t sreg_prev;

  ws2812_DDRREG |= maskhi; // Enable output

  masklo  =~maskhi&ws2812_PORTREG;
  maskhi |=        ws2812_PORTREG;

  sreg_prev=SREG;
  cli();  

  while (datlen--) {
    curbyte=*data++;

    asm volatile(
    "       ldi   %0,8  \n\t"
    "loop%=:            \n\t"
    "       out   %2,%3 \n\t"    //  '1' [01] '0' [01] - re
    "       sbrs  %1,7  \n\t"    //  '1' [03] '0' [02]
    "       out   %2,%4 \n\t"    //  '1' [--] '0' [03] - fe-low
    "       lsl   %1    \n\t"    //  '1' [04] '0' [04]
    "       out   %2,%4 \n\t"    //  '1' [+1] '0' [+1] - fe-high

    "       dec   %0    \n\t"    //  '1' [+2] '0' [+2]
    "       brne  loop%=\n\t"    //  '1' [+3] '0' [+4]
    :  "=&d" (ctr)
    :  "r" (curbyte), "I" (_SFR_IO_ADDR(ws2812_PORTREG)), "r" (maskhi), "r" (masklo)
    );
  }

  SREG=sreg_prev;
}

Una diferencia obvia entre el 'AVR regular' y la serie ATTiny * 14  Las definiciones de C son que los registros IO no se llaman DDRx y PORTx, sino PORTx.DIR y PORTx. Ya lo arreglé en el encabezado light_ws2812 y parece que funciona bien.

Después de esto, sin embargo, aparece un error con el operando de ensamblaje 2 ( "I" (_SFR_IO_ADDR(ws2812_PORTREG)) ):

lib/light_ws2812.c: In function 'ws2812_sendarray_mask':
lib/light_ws2812.c:119:5: warning: asm operand 2 probably doesn't match constraints
     asm volatile(
     ^~~
lib/light_ws2812.c:119:5: error: impossible constraint in 'asm'
make: *** [Makefile:28: lib/light_ws2812.o] Error 1

También intenté usar un i en minúscula como la restricción en lugar del I , que cambia el error a

/tmp/ccBR4JKE.s:48: Error: operand out of range: 1028

Mirando la hoja de datos este valor tiene sentido, PORTA comienza en 0x400 (1024) y el registro PORTx.OUT tiene un desplazamiento adicional de 4 bytes, colocando PORTA.OUT en 0x404 = 1028 .

con una restricción de registro de 16 bits como x o w que compila, pero luego aparece un error de vinculador:

avr-ld: lib/light_ws2812.o: in function 'loop32':
light_ws2812.c:(.text+0x38): undefined reference to 'r30'

Estoy compilando esto usando avr-gcc y avr-ld , con un actual avr-libc que agregué manualmente los archivos relevantes del paquete Atmel ATtiny Series Device Support a.

    
pregunta sol

1 respuesta

2

La serie ATTiny 1 tiene los registros GPIO asignados fuera del espacio de registro del puerto io, por lo que no se puede acceder a ellos utilizando out o in . Deberá usar los registros VPORT o cargar la dirección del puerto io en un registro y usar una instrucción st para escribir los datos. Si decide utilizar una instrucción de almacenamiento regular, puede cambiar el tiempo del bucle, por lo que es posible que tenga que ajustar el número de nop s.

    
respondido por el C_Elegans

Lea otras preguntas en las etiquetas