Hallo,
ich hab da mal ein Problem und zwar komme ich nicht in die
Serviceroutine sobald ich einen Taster (an Pin PC3) drücke.
In der while-schleife(polling) wird der Taster zwar erkannt und schaltet
die entsprechenden leds, aber er springt nicht in die Service-routine,
was
meine Erwartungen jetzt wären :)
Vor paar Tagen habe ich mit der UART gespielt und probiert da hat auch
es
auch mit Polling funktioniert aber nicht mit Interrupt, er sprang auch
da nicht in die Service-routine der UART(Zeichen-empfangen)...
Ich hab das Gefühl die globale Interrupt Freigabe wird nicht gesetzt.
Vielleicht hat ja jemand von euch eine Idee was ich vergessen oder
falsch mache.
1
#include"system_MKL26Z4.h"
2
#include"MKL26Z4.h"
3
#include<stdio.h>
4
#include<stdint.h>
5
#include"isr.h"
6
7
/////////////LED ON///////////////
8
#define LED_RED_ON PTE->PCOR = (1 << 29); //LED red ON
9
#define LED_GREEN_ON PTE->PCOR = (1 << 31); //LED green ON
10
#define LED_BLUE_ON PTD->PCOR = (1 << 5); //LED blue ON
11
12
/////////////LED OFF///////////////
13
#define LED_RED_OFF PTE->PSOR = (1 << 29); //LED rot OFF
14
#define LED_GREEN_OFF PTE->PSOR = (1 << 31); //LED grün OFF
15
#define LED_BLUE_OFF PTD->PSOR = (1 << 5); //LED blau OFF
16
17
#define SWITCH_INPUT PTC->PDIR; //read SWITCH
18
19
//////////PROTOTYPS/////
20
voidPORTC_PORTD_IRQHandler(void);
21
22
23
intmain(void){
24
25
SystemInit();
26
27
/////////PORT'S EINSCHALTEN/////////////////
28
SIM->SCGC5|=SIM_SCGC5_PORTC_MASK;// PORT C einschalten
29
SIM->SCGC5|=SIM_SCGC5_PORTD_MASK;// PORT D einschalten
30
SIM->SCGC5|=SIM_SCGC5_PORTE_MASK;// PORT E einschalten
31
32
////////////ALTERNATIVEN SETZEN//////////////////
33
PORTD->PCR[5]|=PORT_PCR_MUX(1);//Pin PTD 05 auf ALT01(GPIO) LED rot
34
PORTE->PCR[29]|=PORT_PCR_MUX(1);//Pin PTE 29 auf ALT01(GPIO) LED grün
35
PORTE->PCR[31]|=PORT_PCR_MUX(1);//Pin PTE 31 auf ALT01(GPIO) LED blau
36
PORTC->PCR[3]|=PORT_PCR_MUX(1);//Pin PTC 3 auf ALT01(GPIO) taster
probieren. Das setzt das andere Enable Bit für Faults und Interrupts.
Ein Debugger wäre aber besser. Der zeigt Dir dann auch ob er eventuell
im flaschen Handler landet.
Bei den ARM Cortex M würde ich mit dem Systick Handler anfangen, da
braucht man nicht den NVIC zu initialisieren. Und man kann leicht eine
LED blinken lassen.
Ich kenne mich mit Deiner Entwicklungsumgebung nicht aus, aber wenn an
keiner Stelle "__ISR_H" gesetzt wurde, kann es sein, dass ein default
Handler (extern...) genutzt wird. Dieser enthält oft nur einen Return
oder einen Reset.
In der Praxis dürfte das den folgenden Effekt haben: Das Programm stürzt
nicht ab, aber Deine ISR wird nicht angesprungen. Das ein erneuter Reset
erfolgt ist nicht immer ersichtlich.
danke für eure hilfe,
ich habs jetzt mal mit __enable_fault_irq() probiert
leider bringt das mir ein ERROR
... L6218E: Undefined symbol __enable_fault_irq (referred from main.o).
meine Entwicklungsumgebung ist das kostenlose Keil mit (32k
Bergrenzung).
ja wie ich oben bereits erwähnt habe, nur kann ich kein C
beim 8051 muss zB. für einen ext. Int0 die Adresse 03h mit einem
JP ISR Adresse belegt sein.
zB. 003 JMP 0100h, wenn die ISR bei 0100h beginnt.
Die MCU bekommt einen ext. Int und springt an Adresse 03h um den
dort hinterlegten Befehlt auszuführen.
Sofern der Int. dafür frei gegeben ist.
Hier für den 8051:
http://www.keil.com/support/man/docs/c51/c51_le_interruptfuncs.htm
Ist das bei Dir gegeben ?
Stephan H. schrieb:> ja wie ich oben bereits erwähnt habe, nur kann ich kein C>> beim 8051 muss zB. für einen ext. Int0 die Adresse 03h mit einem> JP ISR Adresse belegt sein.> zB. 003 JP 0100h, wenn die ISR bei 0100h beginnt.
Ja, bei Assemblerprogrammierung musst Du auf diese Weise selber dafür
sorgen.
Bei C sorgt üblicherweise der Compiler dafür, dass eine passende
Interrupt-Vektortabelle angelegt wird.
John S. schrieb:> ich hab da mal ein Problem...
Erwartest du jetzt, daß sich alle Leser durch ine gepostete Quelle
quälen?
Also, ein paar generelle Ratschläge von mir:
1. guck dir deinen Startupcode kritisch an
2. bei vielen Kinetis ist der Watchdog ab Reset generell eingeschaltet
und das mit einer ausgesprochen kurzen Ansprechzeit, sodaß man oft genug
nicht mal ausreichend Zeit hat, um den nötigen System-Setup zu machen.
Ich hab mir genau deswegen angewöhnt, den Watchdog als allererstes im
Startupcode auszuschalten - in Assembler versteht sich.
3. bevor du irgendwelches Zeugs benutzen kannst, mußt du es freischalten
und Takt einschalten. Für manches ist das bereits ab Reset gegeben, aber
ob genau DAS dabei ist, was du grad brauchst, ist fraglich. Also
dediziert deine gewünschte Peripherie selbst freischalten und in Gang
setzen.
4. damit deine Interrupts durchkommen, mußt du sie auch richtig im NVIC
einrichten, sonst läuft da nichts.
5. freunde dich mit dem Gedanken an, nicht nur das zugehörige RefMan und
das Datasheet mehrfach gründlichst durchlesen zu müssen, sondern auch
noch allen anderen Kram, den es zu deiner Kinetis-Variante gibt. Gerade
bei Freescale ist die Dokumentation eine unnötig harte Nuß, da man sich
totsuchen muß und trotzdem wichtige Dinge oftmals nur zufällig an ganz
unerwarteter Stelle und auch nur bei aufmerksamstem Lesen findet.
6. die diversen Kinetis-Familien haben deutlich weniger Gemeinsamkeiten
im Detail untereinander, als man es annehmen möchte - wenn man mal von
sowas wie der unsäglichen FLL absieht. Ich habe deswegen z.B. die
MKE-Reihe erstmal auf meine persönliche schwarze Liste gesetzt, obwohl
ich sie wegen ihrer Li-Akku-Verträglichkeit zuerst recht nett gefunden
habe - wohingegen ich mittlerweile mit MK02FN, MK10DN, MK22FN erträglich
zurechtkomme. Deine MKL26Z ist da nicht dabei, weswegen du dort eben
andere böse Überraschungen erwarten kannst als ich sie bei obigen
Reihen erlebt habe.
W.S.
Nicht alle Ports sind interruptfähig, überprüfe das mal im RefMan.
Die Schwarzseherei von ws teile ich nicht, es gibt nicht mehr böse
Überraschungen als bei anderen auch, auch die FLL stört höchstens bei
wenigen exotischen Spezialanwendungen, im Normalfall nicht der Rede
wert. Und der kl26 hat auch ne echte PLL wenns sein muss.
einfach mal ins Blaue:
welcher RUNMODE, d.h. wie ist das MCM_CPO Register gesetzt?
ganz fies: wenn der NMI PIN als GPIO angeschlossen und FOPT falsch
gesetzt ist, geht gar nix.
John S. schrieb:> |PORT_PCR_IRQC(5));
Hmmm.
5 (0101) ist in meinem Manual kein erlaubter (bzw. ein reservierter)
Wert für die Interrupt-Konfiguration. Wie bist Du denn darauf gekommen?
M.E. müsste da 9 (1001) stehen.
Ich hab mir für solche Zwecke im Laufe der Zeit eine zweite Headerdatei
aufgebaut die die fehlenden Defines enthält, so wird das lesbarer und
der Griff zum Reference Manual wird mit der Zeit seltener.
Hier ein Beispiel:
Jedesmal wenn ich über eins von diesen IRGEND_EINE_BITGRUPPE(x) Makros
stolpere und hab noch keine Defines für die einzelnen Werte (wird immer
seltener) hol ich mir einen Kaffee und setz mich hin und nehm die da mit
auf. Was ich einmal hab das hab ich.
Für den KL26 hab ich leider noch keine, obiges ist ein Auszug aus dem
KL05 aber vieles wird gleich sein, daher wirds diesmal viel schneller
gehen, copy-paste und danach eine schnelle Überprüfung auf Richtigkeit.
PS: Ich schreib sie in binärer Form hin wenn sie im RefMan in binär
abgedruckt sind (weniger fehlerträchtig, keine Umrechnung beim abtippen
bzw copy & paste) und wenn sie dezimal im RefMan stehen schreib ich sie
dezimal hin. So kann ichs mit einem Blick auf Korrektheit vergleichen.
Die Idee finde ich super, sollte ich mir auch anwöhnen.
Mir ist gerade aufgefallen das beim debuggen die
funktion __enable_irq(); gar nicht aufgerufen wird.
Auch wenn ich die die Funktion lösche funktioniert mein Interrupt
trotzdem.
Die Funktion hab ich aus der doku und sollte die Globale Interrupt
Freigabe sein.
Es frage ich mich ob es überhaubt die richtige ist bzw. weis jemand
wie die Globale-Interrupt-Freigabe setze?
John S. schrieb:> __enable_irq(); gar nicht aufgerufen wird.> Auch wenn ich die die Funktion lösche funktioniert mein Interrupt> trotzdem.
Diese globale Interruptfreigabe ist ab Reset erstmal eingeschaltet.
Zum kurzzeitigen aus- und wieder einschalten machst Du
1
__disable_irq();
2
code_der_nicht_unterbrochen_werden_darf();
3
__enable_irq();
Einzelne Interrupts schaltest Du explizit mit
1
NVIC_EnableIRQ();
ein, so wie Du es oben schon korrekt gemacht hast, denn die sind ab
Reset erstmal alle aus.
Die Kritik von W.S. an der Kinetis-Dokumentation teile ich übrigens
nicht.
Manuals muß man bei jedem Hersteller aufmerksam lesen und für mich ist
die Kinetis-Doku bislang immer ausreichend und auch ausreichend
übersichtlich gewesen.
Regel #1 beim Programmieren: nie von Annahmen ausgehen. Was man nicht im
Manual findet, darf man gar nicht erst hinschreiben.
Markus F. schrieb:> Regel #1 beim Programmieren: nie von Annahmen ausgehen. Was man nicht im> Manual findet, darf man gar nicht erst hinschreiben.
Das ist sowas von richtig.
Oftmals gibt es sogar eine ganz bestimmte Reihenfolge beim Enablen und
beim Quittieren von Interrupts, die unbedingt einzuhalten ist.
Beim 8051 hat man einfach das entsprechende Enable-Bit gesetzt und beim
Interrupt-Einsprung das Pending-Bit gelöscht bzw. es wurde automatisch
gelöscht.
So einfach geht es bei den komplexen MCs natürlich nicht mehr.
Bernd K. schrieb:> Zum kurzzeitigen aus- und wieder einschalten machst Du>>
1
>__disable_irq();
2
>code_der_nicht_unterbrochen_werden_darf();
3
>__enable_irq();
4
>
>
"Aus- und Einschalten" im eigentlichen Wortsinn ist das nicht.
"Sperren" wäre m.E. richtiger.
Wenn die Interrupts gesperrt sind, laufen Interrupt-Requests trotzdem
auf, Du mußt also damit rechnen, daß die unmittelbar nach __enable_irq()
(verspätet) feuern.
Markus F. schrieb:> ... und für mich ist> die Kinetis-Doku bislang immer ausreichend und auch ausreichend> übersichtlich gewesen.
Dann bist du mental völlig anders gestrickt als ich.
Kleines Beispiel: Clocking Diagram vom MK02.. Dort findet sich eine
Reihe von Clocksignalen mit der lapidaren Bemerkung "Clock options for
some peripherals (see note)" und die Note sieht so aus: "Note: See
subsequent sections for details on where these clocks are used."
Im Klartext: Man hätte im Diagramm oder zumindest darunter hinschreiben
können, zu welchen Peripherie-Cores besagte Signale hingehen - oder
wenigstens deren Kapitelnummern ansagen können. Stattdessen muß man mal
wieder danach SUCHEN.
Genau so sieht da fast überall aus. Immer kommt ein Signal von irgendwo
oder geht nach irgendwo und wer wissen will, woher/wohin, der muß im
RefMan danach suchen. Volltextsuche! Bei diesen Manuals sucht man sich
tot! Genau DAS ärgert mich.
Ebenso ärgert mich sowas, was am Anfang jedes Kapitels steht:
"Introduction NOTE For the chip-specific implementation details of this
module's instances, see the chip configuration information."
Hehe, wir sind gerade im Referenzmanual und zwar am Anfang eben des
Kapitels, wo besagter Modul im Detail erklärt werden soll!
Das Prinzip der Dokumentation ist offenbar so, daß im Kapitel für einen
Peripherie-Core keinesfalls der tatsächliche Core beschrieben wird und
man stattdessen das Geschreibsel im Kopf auf die konkret vorhandenen
Cores und deren tatsächlichen Signale und Register umsetzen muß.
Selbiges ins Referenzmanual tatsächlich HINZUSCHREIBEN, ist den Autoren
unter ihrer Würde - also schon wieder ein Fall für's Suchen.
Bei den Kinetis zieht sich das wie ein brauner Faden durch alle Kapitel.
Ständig Kreuz- und Querverweise anstelle die Sache im zuständigen
Kapitel zu erledigen. Ausreichend und ausreichend übersichtlich ist das
nicht.
Noch ein Beispiel: Wer kann binnen 10 minütigem Draufschauen auf das
Diagramm (Fig.22-1 im obigen RefMan) zum eDMA schildern, was dieser
DMA-Core tatsächlich kann und wie er tatsächlich funktioniert? Dem
ersten geb ich ein Bier aus ;-)
Peter D. schrieb:> Beim 8051 hat man einfach..
Peter, du bist '51 und AVR etc. gewöhnt. Das hier ist ne ganz andere
Schublade.
W.S.
W.S. schrieb:> Immer kommt ein Signal von irgendwo> oder geht nach irgendwo und wer wissen will, woher/wohin, der muß im> RefMan danach suchen.
Nein, das steht alles im Kapitel 3.
W.S. schrieb:> Noch ein Beispiel: Wer kann binnen 10 minütigem Draufschauen auf das> Diagramm (Fig.22-1 im obigen RefMan) zum eDMA schildern, was dieser> DMA-Core tatsächlich kann
Dann lies das Kapitel wenn Du wissen willst wie er funktioniert anstatt
10 min. auf ein Rechteck zu starren. Wenn Du jedoch wissen willst womit
die Signale auf diesem konkreten Chip verbunden sind dann schau in die
entsprechenden Mux-Tabellen in Kapitel 3 wo das hingehört (und auch zu
finden ist). Und außerdem ist Kapitel 22 nur der DMAMUX wenn Du wissen
willst was der DMA kann dann lies das DMA-Kapiltel 23, da ist alles
erschöpfend beschrieben.
Und wenn Du wissen willst welche Sources wo angeschlossen sind: Das
steht wie immer im Kapitel 3 das hab ich Dir schon mehrmals erklärt!
Kapitel 3! Immer! Bei allen Kinetis steht im Kapitel 3 wie die
Peripheriemodule auf diesem konkreten Chip instantiiert wurden, wieviele
davon, mit welchen Optionen und wie sie miteinander verbunden sind,
Mux-Tabellen, etc.
Ab Kapitel 11 werden dann die Module einzeln beschrieben, jedes in
seinem Kapitel.
Die Dokumentation ist sehr logisch aufgebaut, bei allen Kinetis nach dem
immer gleichen Schema und die Logik dahinter ist einfach zu durchschauen
und wenn man dort eine Information braucht dann weiß man sofort
(aufgrund der Art der Information) in welches Kapitel man klicken muss
um es zu finden weil es immer in der selben Form in immer den selben
Kapiteln steht.
Beispiel: Wenn ich wissen will wie der TPM Timer funktioniert und
benutzt wird schau ich im TPM-Kapitel (wie der Name schon sagt), wenn
ich jedoch wissen will wieviele davon auf dem Chip verbaut sind und
wo die auf diesem konkreten Chip angeschlossen sind, oder mit anderen
Worten wenn ich wissen will wie die TPMs oder irgendwas anders auf
diesem konkreten Chip konfiguriert sind schau ich im Kapitel 3 "Chip
configuration" (wie der Name schon vermuten lässt) wo das alles fein
säuberlich aufgeführt ist.
Volltextsuche braucht man kaum. Man klappt einfach das
Inhaltsverzeichnis auf und klickt dort gezielt zum jeweiligen
Kapitel/Unterkapitel.
Manchmal hab ich echt das Gefühl Du stellst Dich absichtlich so dämlich
an, so borniert kann man doch gar nicht versehentlich sein, das geht
doch nur noch mit Vorsatz.
Bernd K. schrieb:> Die Dokumentation ist sehr logisch aufgebaut, bei allen Kinetis nach dem> immer gleichen Schema und die Logik dahinter ist einfach zu durchschauen
Logisch? Nein, ist sie nicht. Da widerspreche ich dir vehement.
Nenne das lieber "sehr formalistisch".
Das trifft es wesentlich besser.
Ich bin Refman's von MicroChip, Fujitsu, NXP und ST gewöhnt, vor Zeiten
auch NEC und Nuvoton. Die sind allesamt wesentlich leserlicher, weil
offenbar mit Kompetenz und für den Leser gemacht. Wenngleich auch mit
unterschiedlicher Denke dahinter. Merkt man besonders bei Nuvoton.
Bei den Kinetis hingegen grinst mich sowas wie Bleistift-Geraderückerei
an, also primäres Anliegen ist bei denen das Durchziehen eines
Formalismus, wohingegen der Leser und dessen Bedarf an eingängiger
Information als zweitrangig erachtet wird. Deren Dokumente sehen alle
nach "lästiger Pflichtübung" aus. Es fehlt jegliche pädagogische
Kompetenz.
In gewisser Weise hast du Recht: Ich quäle mich zwar durch das
Kinetis-Zeugs schon durch und krieg letztendlich ja doch heraus, was ich
suche, aber es widert mich an. OK, das Schreiben von guten Manuals ist
auch eine Kunst. Freescale beherrscht diese eben nicht.
W.S.