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
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.
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.
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
>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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.