PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Atmega32 Interrupt Timing



FoCus
08.02.2006, 14:05
Hi,
kann mir jemand sagen, wie lange es dauert, wenn eine Flanke auf Int0 gelegt wird, bis mein Interrupthandler angesprungen wird?

Gibt es hierzu irgendwelche Dokumente? Habe leider weder im Datenblatt, noch bei Google was gefunden.

Device: ATMega32
Oszillatorfrequenz: 16MHz
Compiler: Avr-Gcc

Muss ein 100K Signal sampeln, aber irgendwie gehen mir Daten/Interrupts verloren. Die Interruptroutinen sind natürlich as fast as possible, sprich Ein-, bzw. Vierzeiler. Gesamplet wird auf Int0 und Int1, fallende Flanke.

Gruss
Michael

AlexAtRobo
08.02.2006, 14:42
Wieviele Zeilen hat deine Interrupt Routine im hexcode? Eine Zeile in C <> 1 Zeile in Assembler. Und ein Assemblerbefehl <> 1 Takt, manche brauchen 2-3 Takte. Mach mal einen debug deines C Files im AVR Studio dann siehst du wieviele Assemblerbefehle da kommen. Was für ein Signal sampelst du da? Ein 100kHz Signal sollte normalerweise möglich sein. Wie werden die Daten weiterverarbeitet?

lg

Alex

FoCus
08.02.2006, 14:49
Daten werden in einen Ringpuffer geschrieben, und von der Hauptroutine, wenn Zeit ist, in eine MMC Karte geschrieben.
Das Problem ist nicht die Interruptroutine, sondern, dass ich nicht weiss wie lange die Totzeit ist zwischen Signal tritt auf, und Interruptroutine wird angesprungen.

Gruss
Michael

AlexAtRobo
08.02.2006, 16:01
Das bringt uns jetzt aber nicht weiter.
Aber mal aus der Doku des Mega8 gilt sicher auch für Mega32

If edge or toggle interrupt is selected, pulses that last
longer than one clock period will generate an interrupt. Shorter pulses are not guaranteed
to generate an interrupt. If low level interrupt is selected, the low level must be held
until the completion of the currently executing instruction to generate an interrupt.

Also, wenn dein Systemtakt 16Mhz ist sollte bei einem 100khz Signal kein Problem auftreten, wenn das nicht nur sehr kurze Impulse sind, die halt nur im 100kHz Rythmus auftreten.

Was sein kann ist, dass du mit einer anderen Interruptroutine in die Quere kommst. Ich habe mich noch nicth so viel mit c beschäftigt und schreibe alles im assembler, aber ich könnte mir vorstellen, das zu z.B. eine Timerroutine hast. Vielleicht macht der Compiler in die Interruptbehandlungsroutinen ein Cli und Sei? Das könnte deine Verluste erklären. Anders kann ich mir das kaum vorstellen.

lg

Alex

JanB
08.02.2006, 16:08
Wenn das INT-Ereignis auftritt, wird der gerade laufende
Befehl zu Ende abgearbeitet. (Kann max. drei Taktzyklen dauern)
Dann dauert es noch vier weitere Taktzyklen bis der Befehl ausgeführt
wird, der auf der Addresse des INT-Vectors steht.
Dies ist in der Regel ein JMP-Befehl, der auch drei Takte benötigt.

Es dauert also mindestens 7 und maximal 10 Taktzyklen
bis der erste Befehl der Int-Routine zur Ausführung kommt.

Es müssen natürlich alle Vorraussetzungen für den
Interrupt erfüllt sein. (int-Enable usw)



Ist übrigens alles im Datenblatt unter "Interrupt-response time" genau beschrieben.

Gruß Jan

FoCus
08.02.2006, 16:10
Das Ganze ist angeschlossen an den Parallelport.
Beim Strope Signal Werden die 8Bit der Datenleitungen einerseits gelatcht, und andererseits der Interrupt 0 ausgelösst. Hier hole ich die Daten an Port D aus dem Latch in eine Globale Variable.

Die Ack Leitung wird auf Interrupt 1 geführt. Tritt dieser Interrupt auf, so hat der Drucker die Daten verstanden, und Akzeptiert. Das gemerkte Byte wird in einen Ringpuffer geschrieben, der wiederrum vor und nach vom Hauptprogramm abgearbeitet wird.

Es treten also zwei Interrupts kurz hintereinander ausgelösst, wobei ich die erste Interruptroutiene gerade versuch auf das notwendigste zu kürzen, siehe:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=16879&highlight=

Durch die beiden Interrupts ist gewährleistet, dass immer nur, vom Drucker als gültig erkannte Daten, in den Ringpuffer geschrieben werden.

Ich hoffe das hilft zum Verständnis meines Problems.

Gruss
Michael

xanadu
08.02.2006, 16:14
Wenn Du die Interrupthandler mit SIGNAL() definiert hast, werden während des Abarbeitens der ISR (Interrupt Service Soutine) alle Interrupts abgeschaltet.

Eine Alternative ist da eventuell INTERRUPT(), bei der bleiben die Interrupts eingeschaltet.

Vielleicht hilft dieser Ansatz weiter, einfach mal ausprobieren ;-)

FoCus
08.02.2006, 16:49
Habs gerade ausprobiert, kein Unterschied..

SprinterSB
08.02.2006, 17:08
Also: ISQ-Latenz: 4
Sprung in die ISR: 2
Und los geht's.
Valls andere IRQs aktiv sind, kommt die Zeit hinzu, die zum Verlassen gebraucht wird. Plus ein Schritt "normales Progremm". ISRs zu schachteln ist bei der IRQ-Rate nicht unbedingt ratsam (Absturz).

xanadu
08.02.2006, 17:15
Wenn ich das richtig verstehe belauschst Du den Datenverkehr zwischen einem PC und einem Drucker?

Interessant fände ich, wie schnell die IRQs hintereinander ausgelöst werden und wie lange sie jeweils anstehen (insbesonders das ACK).

Mir kommt spontan eine Idee: warum nicht einfach die Kommunikation ausbremsen, indem du dich in die STROBE und ACK Leitungen einschleifst und sie jeweils erst dann weiterreichst, wenn du alles nötige erledigt hast=

AlexAtRobo
08.02.2006, 19:56
Für mich klingt die ganze Sache sehr zeitkritisch - in meinen Augen eine Sache die komplett in Assembler aufgebaut werden sollte, da hast du deutlich einfacher die Kontrolle was passiert. Wie lange zeichnest du da auf und in welchen Speicher? Nur in das Interne Ram? Der ist ja relativ schnell voll. Und wie verarbeitest du das weiter? Bremst du dich da vielleicht aus?

lg
Alex

FoCus
08.02.2006, 20:29
Der Ringpuffer ist 3*512 Bytes groß. Aufgezeichnet wird nonstop. Ein Pc holt dann zyklisch die Daten aus dem Controller. Das Hauptprogramm tut nichts anderes als vor und nach die Daten in eine MMC zu schreiben, die wiederrum wie ein Ringpuffer aufgebaut ist. (So grossen sram, dass er für eine halbe Stunde Aufzeichnung, zu annehmbaren Preisen, ohne Abholen reicht, habe ich nicht gefunden). Ein Druckauftrag hat ein Zeichenvolumen von max 1044Byte.

Die Kontrolle über die Kommunikation zu übernehmen, habe ich mir auch schon überlegt, allerdings kann dann nichtmehr gedruckt werden, wenn ich, warum auch immer, ausfallen sollte. Und die Kommunikation zwischen Drucker und PC muss dringend weitergehen, da dort Prozessdaten einer Baugruppe gedruckt werden, die zwecks Qualitätssicherung aufbewahrt werden müssen.

Der PC Archiviert die Daten in einer Datenbank, es kann allerdings, z.B. durch Stromausfall, vorkommen dass er bis zu einer halben Stunde die Daten nicht abholt, die ich aufzeichne. Ich hingegen (mein Controller ;-) ) hänge zusammen mit der Anlage an einem Notstromaggregat.

Gruss
Michael

FoCus
12.02.2006, 01:44
Falls jemand mal drüber stolpert, ich habe das Timing jetzt mal mit einem Oszi nachgemessen.
Der Code in C (gcc):


void SIG_INTERRUPT0(void){
PORTB &= ~(1<<PB3); //Set to low
asm volatile("NOP"::);
asm volatile("NOP"::);
asm volatile("NOP"::);
asm volatile("NOP"::);
asm volatile("NOP"::);
asm volatile("NOP"::);
asm volatile("NOP"::);
asm volatile("NOP"::);
asm volatile("NOP"::);
asm volatile("NOP"::);
asm volatile("NOP"::);
asm volatile("NOP"::);
PORTB |= (1<<PB3); //Set to High
sei();
}

ergab mit einem 20MHz Quarz:
https://www.roboternetz.de/phpBB2/album_pic.php?pic_id=840


Wobei das Blaue das externe Signal an Int0 ist, und das Rote die Leitung, die ich in der Interruptroutine geschaltet habe.

Das Signal kommt von der Strope Leitung des Druckers.

Grüsse Michael