Fahrrad Kettenschaltung Schaltgeschwindigkeit messen: HW-SPI mit USI im Test
von
am 21.01.2018 um 17:17 (1824 Hits)
Hallo,
auf der Suche nach mehr Speed bei dem SPI-Transfer zum Flashspeicher zur Vereinfachung der Verkürzung des Abstandes der ADC-Messungen, bin ich dabei meine bisherigen eigenen ASM Soft-SPI Routinen durch HW-SPI des µC zu ersetzen.
Auf dem ATtiny861 läßt sich mit BASCOM keine HW-SPI konfigurieren. Nach Datenblatt ist dort auch nur ein USI (Universal Serial Interface) vorhanden, das man aber auch für SPI nutzen kann. Dazu habe ich aus dem Datenblatt Document: 8197C–AVR–05/11, Kapitel "13.3.2 SPI Master Operation Example" das ASM Beispiel nach BASCOM übertragen und im Datenblatt einen Fehler festgestellt.
Das grün markierte r17 in der Subroutine Spitransfer im Code ist im Datenblattoriginal ein r16 -> Fehler! Routine kommt nicht zum Ende, wenn einmal gestartet. Mit r17 geht es. In Datenblättern zu anderen AVR ist die entsprechende Routine oft mit kleinen Variationen vorhanden.
Die USI Register im ATtiny861 sind mit den Ein-Zyklus Befehlen IN und OUT erreichbar (STS als Ein-Zyklus Befehl ist im ATtiny861 nicht verfügbar. Bei Verwendung von STS wird die Zwei-Zyklus Version verwendet). SBIS kann direkt im I/O Register checken ohne das I/O vorher ins Registerfile laden zu müssen. Dadurch lassen sich hier auch Verbesserungen erreichen, die ich mal im Spitransfer_mod unterzubringen versucht habe.
Die Routine Spitransfer erzeugt einen SPI Takt auf Pin PB2 von gemessenen 1,16MHz. Die Spitransfer_mod von 2,0MHz. Systemtakt:16MHzCode:$regfile = "ATtiny861.DAT" $framesize = 32 $swstack = 32 $hwstack = 38 $crystal = 16000000 'internal PLL clock is used Porta.5 = 1 'pullup for push button Porta.6 = 1 'pullup for push button 'Config Portb.0 = Input 'DI (SPI input, port default operation mode is input) Config Portb.1 = Output 'DO (SPI output) Config Portb.2 = Output 'USCK (spi clock) Do Debounce Pina.5 , 0 , Spitransfer , Sub Debounce Pina.6 , 0 , Spitransfer_mod , Sub Loop '#### Datasheet for ATtiny861A '#### Document: 8197C–AVR–05/11 '#### modeled on 13.3.2 SPI Master Operation Example Spitransfer: 'corrected sample from datasheet $asm ldi r16 , &b10101010 'data to be send sts USIDR,r16 'data to data register ldi r16,&b01000000 'ldi r16,(1<<USIOIF) sts USISR,r16 'preventive clearing USIOIF (USI overflow interrupt flag) ldi r17,&b00011011 'USIWM0,USICS1,USICLK,USITC Spitransfer_loop: sts USICR,r17 'USI mode and clock strobe lds r16, USISR 'load register with USI overflow flag sbrs r16, USIOIF 'skip next instr. if overflow occured, transfer complete rjmp SPITransfer_loop lds r16,USIDR 'data received during transfer in USIDR ret $end Asm Spitransfer_mod: 'modified sample from datasheet $asm ldi r16 , &b10101010 'data to be send Out Usidr , R16 ldi r16,&b01000000 'USIOIF Out Usisr , R16 'preventive clearing USIOIF (USI overflow interrupt flag) ldi r16,&b00011011 'USIWM0,USICS1,USICLK,USITC Spitransfer_loop_mod: Out Usicr , R16 'USI mode and clock strobe sbis usisr, USIOIF 'skip next instr. if overflow occured, transfer complete rjmp SPITransfer_loop_mod in r16,USIDR 'data received during transfer in USIDR ret $end Asm End 'end program
Als nächstes liegt wohl an, dem externen Flash über USI etwas Sinnvolles zu entlocken.
PS: Habe noch das zweite Beispiel im Datenblatt "SPITransfer_Fast" ausprobiert. Das lief ohne Probleme und hat glatt 8MHz SPI Takt geliefert. Da werde ich wohl erstmal dranbleiben obwohl das Oszi aus den, vom Steckbrett abgenommenen Signalen in erster Näherung schon ziemlich zerfranste Recheckruinen gezeichnet hat
.
.