Ausgangspunkt ist ein ATmega32U4 mit 16-MHz-Quarz,
verbaut in Arduino Leonardo
und Nachfolgern,
etwa dem sehr preiswerten Pro Micro
.
Für die zeitkritischen Routinen kommt nur Assembler in Frage.
Zur Kombination mit gcc wird der
Gnu-Assembler-Dialekt gas verwendet,
nicht avrasm.
So ungefähr sollte es aussehen:
// Als Makro, Unterprogrammaufrufe sind beim AVR lahm und fressen 9 Takte // Vorgehaltene Register: // R16 = Word-Zähler 32..0, -1 = Commit, -2 = nächster Datenblock // R3 = USB-Block-Zähler, 7..0 (bei Sektorlänge 512 Byte) // X = Datenquelle (Sektordaten) im RAM // UENUM steht bereits richtig .macro usb_write retlbl ;Rücksprungziel als Argument subi r16,1 ;herunterzählen mit Carry-Flag brmi 1f ;(negativ) ld r24,X+ sts UEDATX,r24 ld r24,X+ sts UEDATX,r24 rjmp \retlbl ;Σ 12 Takte (ohne Ansprung) 1: brcs 2f ldi r16,-2 ;-2 wiederherstellen sbrc r3,7 ;Weitere USB-Blöcke? rjmp \retlbl ;Σ 8 Takte (nein wenn negativ) lds r24,UEINTX sbrc r24,7 ;wenn FIFO bereit … ldi r16,32 ;… 32 WORDs schreiben lassen rjmp \retlbl ;Σ 13 Takte 2: ldi r24,0x7E sts UEINTX,r24 ;Commit dec r3 rjmp \retlbl ;Σ 11 Takte .endm