www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Intteruptprioritäten AVR ändern/umgehen in C


Autor: Robert B. (robertb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich benutze bei einem mega168 das Input-Capture-Int und ein 
Compare-Match-Int des Timer1. Zusatzlich noch UART per Int. Das 
Compare-Match ist vergleichsweise Timing-kritisch (auch unter Ausnutzung 
der automatischen Pin-Funktionen!).

Unter bestimmten Umständen führt das ausführen eines UART-Ints dazu, 
dass ICP-Int und Comp-Match-Int beide getriggert werden. Leider wird 
dann zuerst das ICP-Int ausgeführt (höhere Priorität), was dann dazu 
führt, dass das Compare-Int die Timing-Constraints nicht einhalten kann.

Als Lösung (abgesehen von anderen Optimierungen) hatte ich 
Pseudocode-maßig an folgendes gedacht:
ISR(ICP)
{
   if (CompareMatch)
   {
       "ret" (ohne Int-Flag zurückzusetzen)
   }
   .....
}

Das geht natürlich so nicht ganz, da dann wieder das ICP-Int 
angesprungen würde.

Was habt ihr für Vorschläge?

Grüße
Robert

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Was habt ihr für Vorschläge?

ISRs kürzer machen.

Autor: Robert B. (robertb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mensch danke, darauf wär ich nie gekommen! Du meinst ich soll die 
"_delay_ms(500);" Zeilen entfernen?

Danke Danke Danke!

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Du meinst ich soll die "_delay_ms(500);" Zeilen entfernen?

Wär schon mal ein guter Anfang.

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Du meinst ich soll die "_delay_ms(500);" Zeilen entfernen?
>
> Wär schon mal ein guter Anfang.

Du könntest auch noch mehr machen. Z.b. Code zeigen, deine 
Timingvorgaben mal spezifizieren...
:-)

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne was vom Code zu sehen kann man da schlecht Tipps geben.

Möglicherweise dauert die UART-ISR zu lange, weil sie ne FIFO bedient... 
man weiß es nicht.

Welche Möglichkeiten hast du, die IRQ-Latenz zu verringern?

Autor: Stephan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

mal so ins blaue gesponnen:

u08 ICPFlag= flase;

ISR(ICP)
{
   if (CompareMatch)
   {
       ICPFlag= true;
       return;
   }
   .....
}
ISR(CompareMatch)
{
   .....
   // am ende
   if (ICPFlag == true)
   {
     // setze ICP-Int von Hand
     ....
     ICPFlag= false;
   }
}

Es treten also beide Ints gleichzeitig auf.
Der Input-Int verabschiedet sich und setzt noch vorher ein globales 
Flag.
In der CompareMatch wertest du nach allen anderen Operationen dieses 
Flag aus und setzt von Hand den Input-Intterupt.

Stephan

Autor: Robert B. (robertb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Stephan,

vielen Dank für Deine zur Frage passende Antwort! Hab mal schnell 
nachgeschaut - aber leider täuscht mich meine Erinnerung nicht - das 
Int-Flag läßt sich nicht manuell setzen. Jedoch könnte man das ICP-ISR 
evtl. als Funktion aus dem Comp-Match-Int aufrufen - vielen Dank für die 
gute Idee!

Grüße
Robert

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt mehrere Möglichkeiten:
ISR( TIMER1_CAPT_vect, ISR_NOBLOCK )
{
// ...
}
Dann kann der Interrupt unterbrochen werden.


Den langsamen UART-Interrupt kann man leider nicht unterbrechbar machen, 
da das Flag beim Eintritt nicht gelöscht wird.
Du kannst aber die UART mit nem Timerinterrupt pollen und den dann 
unterbrechbar machen.


Peter

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:


> Den langsamen UART-Interrupt kann man leider nicht unterbrechbar machen,
> da das Flag beim Eintritt nicht gelöscht wird.

Doch geht auch. Allerdings nicht über diesen Mechanismus.

Stattdessen implementirt man es als normale ISR, deaktiviert direkt am 
Anfang die betreffende IRQ und dann folgt ein SEI. Am Ende alles retour.

So hab ich's mal in eienr länglichen Tmer-IRQ gemacht, die den 
IR-Empfang ausbrembste. Hat prima funktioniert. (Inzwischen geht's 
allerdings anders und ohne kaskadierende IRQ indem ich in der Timer-IRQ 
auf den IR polle.)

Wenn die Auswerte-Routinen für ICP/COMP nicht zu lange dauern, sehe ich 
keinen Grund, warum es nicht gehen sollte.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert B. schrieb:
> Mensch danke, darauf wär ich nie gekommen! Du meinst ich soll die
> "_delay_ms(500);" Zeilen entfernen?
>
> Danke Danke Danke!

Wenn das tatsächlich ernst gemeint ist, dann hat es wenig Sinn über 
irgendwelche ausgefuchsten Mechanismen zu debattieren. Dann stimmt 
vorher schon so einiges nicht, das bereinigt werden müsste.

Autor: Robert B. (robertb)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Robert B. schrieb:
>> Mensch danke, darauf wär ich nie gekommen! Du meinst ich soll die
>> "_delay_ms(500);" Zeilen entfernen?
>>
>> Danke Danke Danke!
>
> Wenn das tatsächlich ernst gemeint ist, dann hat es wenig Sinn über
> irgendwelche ausgefuchsten Mechanismen zu debattieren. Dann stimmt
> vorher schon so einiges nicht, das bereinigt werden müsste.

Nein, war es natürlich NICHT! Es sind überhaupt keine _xs_delays in 
meinem ganzen Projekt. Die Antwort war um all jene glücklich zu machen, 
die glauben immer ihr lapidares Basiswissen kundtun zu müssen.

Ich "dekodiere" bzw. "enkodiere" einen seriellen Bus mit engen 
zeitlichen Vorgaben. Leider ist dafür auch mit Klimmzügen der 
Hardware-USART nicht ansatzweise in der Lage, so dass ich eben - extrem 
vereinfacht ausgedrückt - mit dem ICP-Int "dekodieren" und mit dem 
Compare-Match "enkodieren" muss. Da ich die Timing-Constraints einhalten 
muss ist das nicht so einfach. Die einzige "Beschleunigung" wäre es alle 
Bitzeiten vorher zu berechnen, was aber aufgrund von Telegrammlänge zu 
viel Speicher verbraucht: 30 Byte * 10 Bit/Byte * 2 Flanken/Bit * 
16bit/Flanke = 1,2KByte SRAM nur für ein Sende-Paket wenn nur 0xFF 
verschickt werden. Gleiches für RX = geht nicht. Also muss ich es leider 
wohl on-the-fly machen.

Die Möglichkeit Interrupts wieder global freizugeben scheint die Lösung 
zu sein. Es funktioniert alles wie gewünscht!

Vielen Dank!

Grüße
Robert

Autor: g457 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Die Möglichkeit Interrupts wieder global freizugeben scheint die Lösung
> zu sein. Es funktioniert alles wie gewünscht!

Damit bestätigst Du mein Statement von gaanz oben: Deine ISRs dauern zu 
lang. Schön dass Du das doch noch zugeben konntest :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.