Forum: Mikrocontroller und Digitale Elektronik Interrupt beim AtSAM4N8B -> ARM Cortex-M4


von Christian M. (chrigi001)


Lesenswert?

Hallo miteinander,

Ich verwende einen AtSAM4N8B und habe ein Problem mit den Interrupts.

Und zwar weis ich nicht wie das Schlüsselwort für die Interrupt Rutine 
lautet, also wo ich meine Interruptrutine hinschreiben muss.

Ich suche also eigentlich das, was bei den AVRs "ISR(irgend_ein_vector)" 
ist.

Das ASF möchte ich eigentlich nicht benutzen.

Hat vielleicht jemand ein kurzes Beispielprogramm oder etwas in der 
Richtung?


Freundliche Grüsse

Christian

von (prx) A. K. (prx)


Lesenswert?

Für die Cortex-M muss der Handler den richtigen von CMSIS/IDE 
definierten Namen haben. Anders als bei AVRs sind das normale 
C-Funktionen ohne besondere Kennzeichnung.

von Schaulus Tiger (Gast)


Lesenswert?

Christian M. schrieb:
> Das ASF möchte ich eigentlich nicht benutzen.

Wenn du dich dann noch ans Linker Script ran traust kannst du dir aus 
dem CMSIS die Rosinen rauspicken und den Rest recyclen. Dann sind deine 
ISRs tatsächlich ganz normale C-Funktionen ohne spezielle Namen oder 
Schlüsselworte. Die einzige Besonderheit: sie müssen in der 
Vektortabelle an der richtigen Stelle eingetragen werden.

Die Vektortabelle kann auch eine normale C-Datei sein, man muss nur 
dafür sorgen, dass sie an die physikalische Adresse 0 gelinkt wird (ja, 
es geht auch flexibler, aber für den Anfang...). Meine sieht z.B. so 
aus:
1
// vector_table.c
2
3
typedef void (isr)(void);
4
5
typedef struct vector_struct {
6
  int  *top_of_stack;
7
  isr  *interrupts[128-1];
8
} vector_struct;
9
10
extern int  top_of_stack;
11
extern isr  crash, crt0, usart1_isr;
12
13
__attribute__((section(".vectors"))) vector_struct
14
vectors =
15
{
16
  &top_of_stack,  //   0  Initial SP, defined in linker script
17
  {
18
    crt0,         //   1  Initial PC = Reset-"Handler"
19
    crash,        //   2  CSS Clock security system (NMI)
20
    crash,        //   3  Hard fault (double fault)
21
    crash,        //   4  Memory protection
22
    crash,        //   5  Bus fault
23
    crash,        //   6  Usage fault
24
    crash,        //   7  -
25
    crash,        //   8  -
26
    crash,        //   9  -
27
    crash,        //  10  -
28
    crash,        //  11  System service call via SVC instruction
29
    crash,        //  12  Debug monitor
30
    crash,        //  13  -
31
    crash,        //  14  Pendable request for system service
32
    crash,        //  15  System tick timer
33
// ab hier wird's Chip-spezifisch...
34
    crash,        //  16   0  Window watchdog interrupt
35
    crash,        //  17   1  PVD thru EXTI line detection
36
// usw.
37
    usart1_isr,   //  53  37  USART1
38
// und so fort...
39
    crash         // 127 111
40
  }
41
};

Sogar die "gefürchtete" crt0 kann eine ganz normale C-Funktion sein. Mit 
"top_of_stack" initialisiert die Hardware als erstes den Stackpointer 
und mehr ist für die ersten Befehle nicht nötig.

An dieser Stelle sind die Cortex-M einfacher als die AVR, jedenfalls, 
wenn man auf CMSIS, StdPeriLib, IDE usw. verzichtet.

von Christian M. (chrigi001)


Lesenswert?

Danke für eure Antworten.

Ich denke ich werde zumindest vorerst noch CMSIS verwenden. Das kann ich 
dann immer noch rausoptimieren sobald ich mich im Umgang mit dem 
Controller etwas sicherer fühle.

Noch eine Frage:

Die Tabelle mit den Interrupt Handlern habe ich gefunden.

Muss ich die Interrupts noch global aktivieren?

In der CMSIS doku steht etwas von __enable_irq() nur scheint es so als 
würde die IDE-Autovervollständigung diese Funktion nicht kennen. 
Compilerfehler habe ich aber keine. __enable_fault_irq(); wird hingegen 
erkannt.

weiter steht da das diese Funktionen nur im "privileged mode" ausgeführt 
werden können. Wie ist das nun zu verstehen und wie komme ich in diesen 
Modus?

danke für eure Hilfe,

Christian

von PG-Format nur für Fotos und Scan (Gast)


Lesenswert?

>weiter steht da das diese Funktionen nur im "privileged mode" ausgeführt
>werden können.

Das ist im Cortex M Ref Manual erklärt.

Wenn der Core einen Interrupt erkennt, wechselt er automatisch
in den "priviledged" aka "handler" mode.

>Wie ist das nun zu verstehen und wie komme ich in diesen
>Modus?

Indem Du einen freigegebenen Interrupt auslöst.

von Schaulus Tiger (Gast)


Lesenswert?

Christian M. schrieb:

> Muss ich die Interrupts noch global aktivieren?

Jein, global sind sie vom Start weg eingeschaltet. Aber du musst sie 
einmal im Control Register des I/O-Moduls und zweitens im NVIC 
einschalten, z.B. für den uart1 Empfänger:
1
  USART1->CR1 = USART_CR1_UE | USART_CR1_RE | USART_CR1_RXNEIE;
2
  NVIC->ISER [USART1_IRQn / 32] = 1 << (USART1_IRQn % 32);

> In der CMSIS doku steht etwas von __enable_irq() nur scheint es so als
> würde die IDE-Autovervollständigung diese Funktion nicht kennen.
Das ist nicht die einzige Fehlstelle :(

> weiter steht da das diese Funktionen nur im "privileged mode" ausgeführt
> werden können. Wie ist das nun zu verstehen und wie komme ich in diesen
> Modus?

Wenn du nichts besonderes machst, bist du immer privileged. Diese 
Umschaltung (und die auf den 2. Stackpointer) passiert im 
Spezialregister CONTROL. Das brauchst du eigentlich nur, wenn du ein 
eigenes Betriebssystem schreiben willst.

Dann gibt es noch den Unterschied "Handler Mode" vs. "Thread Mode". 
Diese Umschaltung passiert automatisch, eine ISR läuft im Handler Mode. 
Das ist ohne weitere Einstellungen aber auch ziemlich egal.

von Jim M. (turboj)


Lesenswert?

Schaulus Tiger schrieb:
> NVIC->ISER [USART1_IRQn / 32] = 1 << (USART1_IRQn % 32);

Das schreibt man so:
1
NVIC_EnableIRQ(USART1_IRQn);

Raus kommt zwar identischer Code, aber es ist IMO wesentlich einfacher 
zu lesen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.