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.