mikrocontroller.net

Forum: Compiler & IDEs Taskswitch auf Arm7 Controller


Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich experimentiere hier gerade etwas mit einem LPC2148 herum und möchte 
einen EInfachen Taskswitch programmieren. Dazu wollte ich folgendes 
machen:

1. Taskswitch im Timerinterrupt durchführen und dazu:
2. Alle Register auf den Stack sichern
3. Stackpointer und Programmcounter sichern
4. Statusregister sichern
5. Statusregister des nächsten Tasks zurückschreiben
6. Programcounter des nächsten Tasks zurückschreiben

Dabei sollen in diesem einfachen Experiment erstmal nur ein Task 
unterbrochen werden und dann in eine fest definierte Funktion gesprungen 
werden, nach abarbeiten dieser soll der unterbrochene Tasks fortgesetzt 
werden.

Folgendes (nichtmal kompilierendes) Fragment wollte ich für das 
Unterbrechen des Tasks nutzen:
void __attribute__ ((interrupt("IRQ"))) timer1_isr(void)
{
  T1IR = 0xff;      // clear all interrupt of Timer1
  asm volatile(
      "STMDB  SP!, {R0}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R1}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R2}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R3}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R4}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R5}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R6}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R7}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R8}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R9}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R10}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R11}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {R12}  \n\t"     // Alle Register der Userapp sichern
      "STMDB  SP!, {LR}  \n\t"     // Alle Register der Userapp sichern
      "MOV  R0, #2    \n\t"     // Unterbrechen der Userapp mit Status=2 kennzeichnen
      "STR  R0, sheduler_back \n\t"     
      "STR R13, userapp_sp \n\t"      // Stackpointer sichern
      "LDR R14, scheduler_main \n\t"  // Rücksprungadresse nach R14
      "LDR R0, scheduler_main_sr \n\t"// Statusregister zurücksichern
      "MSR SPSR, R0 \n\t"
  ); // Interrupt wird abgeschlossen und r14 und CPSR wiederhergestellt
  VICVectAddr=0;  //Dummy write to signal end of interrupt
}

Leider steige ich noch nicht ganz durch die Sntax des Arm Assemblers 
durch.

Meine Hauptsächliche frage ist allerdings, was genau beim Aufruf eines 
Interrupts passiert? Wenn ich das richtig verstanden habe, bleibt der 
Stack völlig unangetastet und der Arm sicher Statusregister und 
Programmcounter in Schattenregister. Ändert der gcc an diesem Verhalten 
etwas?
Kann mein oben skizziertes Vorhaben so funktionieren, oder habe ich 
etwas grundlegendes nicht bedacht?

Vielen Dank für Eure Hilfe,
Stefan

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn ich das richtig verstanden habe, bleibt der Stack völlig
> unangetastet und der Arm sicher Statusregister und Programmcounter in
> Schattenregister.

Ja.

> Ändert der gcc an diesem Verhalten etwas?

Daran wird er wohl nichts ändern, aber er kann auf die Idee kommen, z.B. 
andere Register zu sichern, bevor deine asm-Routine aufgerufen wird. 
Deshalb definiere die Funktion mit __attribute__((naked)). Dann macht er 
da garantiert überhaupt nichts.

> Kann mein oben skizziertes Vorhaben so funktionieren, oder habe ich
> etwas grundlegendes nicht bedacht?

Du kannst mal in den Scheduler-Code von FreeRTOS reinschauen und ihn 
verstehen. Deine Register werden z.B. im IRQ-Stack gespeichert und nicht 
im Task-Stack, wo es sinnvoller wäre.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für Deine Antwort.

Das jeder Task einen eigenen Stack bekommt möchte ich erst als zweiten 
Schritt implementieren. Bisher soll nur der eine (der im Beispiel 
unterbrochene) Task einen Stack haben und der zweite Task bei jedem 
Aufruf einen neuen Stack aufbauen. Ich möchte bevor ich weitermache 
erstmal den Taskswitch genau verstehen. Allerdings habe ich irgendwie 
Probleme mit der Syntax vom Inline-Assembler und vertstehe deshalb den 
Code von FreeRTOS (danke für den Hinweis) auch nicht so ganz...

Obiger Code liefert beim kompilieren immer nur den Fehler:

\LOCALS~1\Temp/ccS8aaaa.s OFFSET_IMM) not fixed up

Grüße, Stefan

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das jeder Task einen eigenen Stack bekommt möchte ich erst als zweiten
> Schritt implementieren.

Es geht mir eher darum, daß auch die ISR einen eigenen Stack hat.
Übrigens: Wo wird eigentlich dein Task-Stackpointer gesichert?

> Allerdings habe ich irgendwie Probleme mit der Syntax vom
> Inline-Assembler

Du wirst nicht darum herumkommen, dich damit zu beschäftigen. 
Insbesondere auch damit, wie man Parameter an den Assembler übergibt.

> und vertstehe deshalb den Code von FreeRTOS (danke für den Hinweis)
> auch nicht so ganz...

Wenn du den verstehst, verstehst du auch, wie du einen Taskwechsel 
machen mußt. ;-)

> Obiger Code liefert beim kompilieren immer nur den Fehler:
>
> \LOCALS~1\Temp/ccS8aaaa.s OFFSET_IMM) not fixed up

In welcher Zeile?


PS:
Du mußt daran denken, daß so Dinge wie z.B.
 T1IR = 0xff;      // clear all interrupt of Timer1
Register benutzen, die also vorher gesichert werden müssen.

Autor: ewiebe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kennt jemand Informationsquellen zu diesem Thema? Tutorials?

Autor: Mork (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, irgendwo in WinARM steckt ein ASM-Tutorial drin, welches alles 
beschreibt.

MfG Mark

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.