Assembler External Interrupt Assembler Code

Peacefish

Neues Mitglied
20. Feb. 2012
1
0
0
34
Sprachen
Zunächst mal Hallo an Alle!

Ich beschäftige mich mit der Realisierung eines I²C-Abhörsystems das auf einen ATmega 8 laufen soll.
Dazu habe ich die Clock-Leitung des I²C-Busses auf den externen Interrupt 0 meines AVR-Boards gelegt.
Es stellte sich heraus, dass die 100kHz I²C-Bustakt den ATmega 8 überfordern (läuft bei mir auf 8Mhz).
Denn die Interruptroutine die ich schrieb kann anscheinend nicht in genügend kurzer Zeit abgearbeitet werden.
Um dies nachzuvollziehen wollte ich näher auf den Assembler Code eingehen, der vom AVR-Studio beim compilieren meines C-Codes erzeugt wird.
Allerdings habe ich dabei einpar Verständnis Probleme:
Irgendwann mal habe ich gelernt, dass ein Interrupt folgendermaßen abläuft:

INT 0 -> Register sichern (Push) ->Nachschauen in Interrupt Vektortabelle wo Interrupt routine liegt -> dorthin springen -> ausführen ->zum Programm zurückspringen

(Ich bin sicher ich werde korrigiert wenn ich mit meinen obigen Annahmen falsch liege :) .)

Folgenden Code habe ich nun dem .lss file im default folder meines Projekt entnehmen können:

Code:
ISR(SCL){//Anmerkung Clock muss mit steigender Flanke getriggert werden!
 468:	1f 92       	push	r1
 46a:	0f 92       	push	r0
 46c:	0f b6       	in	r0, 0x3f	; 63
 46e:	0f 92       	push	r0
 470:	11 24       	eor	r1, r1
 472:	2f 93       	push	r18
 474:	3f 93       	push	r19
 476:	4f 93       	push	r20
 478:	5f 93       	push	r21
 47a:	8f 93       	push	r24
 47c:	9f 93       	push	r25

data|=PINC<<clk;
 47e:	23 b3       	in	r18, 0x13	; 19
 480:	40 91 69 00 	lds	r20, 0x0069
 484:	50 91 6a 00 	lds	r21, 0x006A
 488:	30 e0       	ldi	r19, 0x00	; 0
 48a:	04 2e       	mov	r0, r20
 48c:	02 c0       	rjmp	.+4      	; 0x492 <__vector_1+0x2a>
 48e:	22 0f       	add	r18, r18
 490:	33 1f       	adc	r19, r19
 492:	0a 94       	dec	r0
 494:	e2 f7       	brpl	.-8      	; 0x48e <__vector_1+0x26>
 496:	80 91 6d 00 	lds	r24, 0x006D
 49a:	90 91 6e 00 	lds	r25, 0x006E
 49e:	82 2b       	or	r24, r18
 4a0:	93 2b       	or	r25, r19
 4a2:	90 93 6e 00 	sts	0x006E, r25
 4a6:	80 93 6d 00 	sts	0x006D, r24

clk++;
 4aa:	4f 5f       	subi	r20, 0xFF	; 255
 4ac:	5f 4f       	sbci	r21, 0xFF	; 255
 4ae:	50 93 6a 00 	sts	0x006A, r21
 4b2:	40 93 69 00 	sts	0x0069, r20


}
4b6:	9f 91       	pop	r25
 4b8:	8f 91       	pop	r24
 4ba:	5f 91       	pop	r21
 4bc:	4f 91       	pop	r20
 4be:	3f 91       	pop	r19
 4c0:	2f 91       	pop	r18
 4c2:	0f 90       	pop	r0
 4c4:	0f be       	out	0x3f, r0	; 63
 4c6:	0f 90       	pop	r0
 4c8:	1f 90       	pop	r1
 4ca:	18 95       	reti

das mit push und pop befehlen Registerinhalte auf dem Stack gesichert und nachher wiederhergestellt werden ist mir klar.
Mir ist auch klar, dass reti bedeutet dass wieder zum ursprünglichen Programm zurückgesprungen wird.
Aber wo wird denn hier in einer Interrupttabelle nachgeschaut, bzw. wo erfolgt der Sprung zum Interrupt Programm (jmp 0xinterrupt0)?

Wenn ich im Datenblatt des ATmega8 nachschaue ist ja aufgelistet wieviele Clocks die verschiedenen ASM Befehle benötigen.
stimmt folgende Milchmädchenrechnung?

8Mhz=[8*10^6 Clocks/sec]
Wenn ich nun ca. 20 ASM Befehle â 2 Clocks habe führt das zu 40Clocks
also einem Zeitaufwand von (1/8)*10^-6 [sec/clock]*40 [clocks] =5 *10^-6s=5µs
5µs sind bei einem Bustakt von 100kHz eine gesamte Taktflanke.

Hoffentlich werde ich für folgende Frage nicht gleich gebant :):
Kann man evtl. die pushs und pops weglassen wenn einem die Registerinhalte aus der Hauptschleife des Programms wurscht sind?
Oder kann man den Code evtl. anderweitig abspecken?

Eigentlich sollen "nur" 2x9 (Addresse[8]+Ack[1]+Daten[8]+Ack[1]) Bits bei diesem Interrupt nacheinander gesichert werden.
Und das Problem ist, dass das Ding zu lange braucht.

Vielen Dank für euere Hilfe!

Mit freundlichsten Grüßen
Peacefish
 
Hi Peacefish,

Ich beschäftige mich mit der Realisierung eines I²C-Abhörsystems das auf einen ATmega 8 laufen soll.
Dazu habe ich die Clock-Leitung des I²C-Busses auf den externen Interrupt 0 meines AVR-Boards gelegt.
Es stellte sich heraus, dass die 100kHz I²C-Bustakt den ATmega 8 überfordern (läuft bei mir auf 8Mhz).
Denn die Interruptroutine die ich schrieb kann anscheinend nicht in genügend kurzer Zeit abgearbeitet werden.
tja ... das ist auch kein Wunder. Ich hab da nachher auf nen Mega168 mit 20MHz umgestellt und trotzdem ne Hardwarebeschleunigung dazugestrickt. Schau mal in den Projektbereich (I2C-1Wire-Analyzer). Da ist auch genug Assemblercode drin. Ich habs aber nicht zu ende geschrieben da ich mittlerweile nen Logikanalyzer hab. Mal sehen ob ich da nochmal weitermache.

Also mit 8MHz wird das auf jeden Fall garnichts. Da mußt du erstmal mächtig tunen.

Zu den Interrupts. Du schaltest die externen Interrupts in den Interrupt-Kontrollregistern ein und global im MasterControllregister (oder wie das nochmal hieß). Wenn der Interrupt ausgelöst wird in die Interruptvektortabelle am Anfang des Flash gesprungen und der Befehl an der Stelle ausgeführt (das sollte ein Sprungbefehl auf die Interruptserviceroutine sein). Es wird lediglich der Programmcounter gesichert. Man muß also das Statusregister und die anderen in der ISR benutzten Register selber gesichert und wieder hergestellt werden. Wenn du hier blind alle Register sicherst verschenkst du Performance.

Soviel erstmal für den Anfang.

Gruß
Dino
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)