Forum: Mikrocontroller und Digitale Elektronik Interupt Handler auf Arduino DUE


von Jannus (Gast)


Lesenswert?

Hallo zusammen,

Ich versuche nun seit einiger Zeit einen Interrupt an dem PORTA des 
Arduino bei einem Flankenwechsel zu generieren. Ich arbeite mit der 
Arduino-IDE, möchte dazu aber nicht die funktion attachInterrupt() 
nutzen.
Daher habe ich mich mit Hilfe des Datenblattes an die Konfiguration der 
Interrupts gemacht, jedoch ohne erfolg.
Es wird kein Interrupt generiert. Wenn die Codezeile "Enables Periphal 
Clk" wie unten im Beispiel angegeben genutzt wird ist die Kommunikation 
über den seriellen Port auch nicht mehr möglich. HAt jemand erfahrung 
mit diesen Problemen?
1
volatile boolean a=0;
2
3
void PIOA_handler()
4
{
5
  a=!a;
6
}
7
8
void setup() 
9
{
10
 Serial.begin(115200);
11
12
/*Enables the PIO to control the corresponding pin*/
13
REG_PIOA_PER = REG_PIOA_PER | 0x3018FC80;
14
15
/*Enables the Input Change Interrupt on the I/O line*/
16
REG_PIOA_IER = REG_PIOA_IER | 0x3018FC80;
17
18
/*Enables PIO Controller Clock, Enables Periphal Clk on PIOA-PIOD*/
19
REG_PMC_PCER0 = REG_PMC_PCER0 | 0x00007800; 
20
21
/*Enables Interrupts on PIOA-PIOD*/
22
NVIC_EnableIRQ(PIOA_IRQn);
23
}
24
25
void loop() 
26
{
27
Serial.println(a);
28
}

von Jannus (Gast)


Lesenswert?

Gibt es Probleme wenn ich die Register direkt in der Arduino IDE 
beschreibe?

von Jim M. (turboj)


Lesenswert?

AFAIK muss Du im PIOA_Handler auch das entsprechende Interrupt Flag 
zurück setzen, sonst landest Du sofort wieder im Handler.

Dadurch kann lopp() nicht mehr ausgeführt werden.

von Jannus (Gast)


Lesenswert?

Ok das klingt erstmal sehr gut. Das bit wird ja durch auslesen des "PIO 
Controller Interrupt Status Register" asugeführt. Also müsste es sich 
doch durch hinzufügen in der ISR leicht ändern lassen.
Ich habe folgenden code ergänzt aber das gleiche problem.
1
volatile boolean a = 0;
2
volatile int state=0;
3
4
void PIOD_handler()
5
{
6
  state=REG_PIOD_ISR;
7
  a=!a;
8
}

von Jannus (Gast)


Lesenswert?

Hat irgendjemand erfahrung damit?

von Lassi (Gast)


Lesenswert?

Hallo,

ich bin mir nicht sicher ob das so einfach ist. Du müsstest ja deinen 
Handler erst Registrieren. Dazu müsste dus in die exception_table 
eintragen.

Diese findest du eigentlich in der "startup_sam3xa.c" Datei.
Aber ich kann dir nicht direkt sagen ob diese noch bei Arduino 
existiert.

Sonst hab ich auf GitHub ein Projekt für ein OS für das Due, da kannst 
du dir zumindest etwas abgucken.
https://github.com/CsharpLassi/DueOS im Branch Develop.

Also wenn du die internen Funktionen nicht nutzen möchtest musst du 
direkt den Arduino Quellcode etwas abändern.

viele grüße
Lassi

von Jim M. (turboj)


Lesenswert?

Lassi schrieb:
> ich bin mir nicht sicher ob das so einfach ist. Du müsstest ja deinen
> Handler erst Registrieren. Dazu müsste dus in die exception_table
> eintragen.

Nein, die stehen da normalerweise schon als weak Reference drin.

Aaaber: Damit die korrekt aufgelöst wird, muss der Name stimmen.

Und da dürfte ein Fehler sein: "void PIOD_handler()" ist möglicherweise 
falsch geschrieben.

Versuche es mal mit "void PIOD_Handler()", Groß- und kleinschreibung 
beachten!

Schau ansonsten direkt im Startup Code nach was da für Namen verwendet 
werden.

von Jannus (Gast)


Lesenswert?

Lassi schrieb:
> Diese findest du eigentlich in der "startup_sam3xa.c" Datei.
> Aber ich kann dir nicht direkt sagen ob diese noch bei Arduino
> existiert.

Diese Datei ist nicht vorhanden.

Jim M. schrieb:
> Und da dürfte ein Fehler sein: "void PIOD_handler()" ist möglicherweise
> falsch geschrieben.
>
> Versuche es mal mit "void PIOD_Handler()", Groß- und kleinschreibung
> beachten!

Danke das ist auf jedenfall ein wichtiger Fehler gewesen. Allerdings 
läuft es trotzdem noch nicht.
Sobald ich die Periphal CLock wie im obigen Beispiel gezeigt aktiviere 
werden keine Daten mehr über die serielle Schnittstelle gesendet.
1
REG_PMC_PCER0 = REG_PMC_PCER0 | 0x00007800;

von Jannus (Gast)


Lesenswert?

Oder muss ich etwas an der WINterrupts.c Datei ändern?

von Jannus (Gast)


Lesenswert?

OK ich habs. Zunächstmal danke für eure Hilfe.

Jannus schrieb:
> Sobald ich die Periphal CLock wie im obigen Beispiel gezeigt aktiviere
> werden keine Daten mehr über die serielle Schnittstelle gesendet.

Mit einem Multimeter und dem einschalten eines digitalen Pins in der ISR 
habe ich festgestellt, das der Interrupt sehr wohl ausgelöst wird.

Das Problem ist, das die ISR immer wieder aktiv wird und so die loop() 
mit dem Serial.print() gar nicht aktiv wird. Das ist der Grund warum 
keine Daten gesendet werden.

Das näcshte Rätsel ist jetzt jedoch, warum der Interrupt immer wieder 
auslöst, obwohl ich den Pin zur Generierung auf Masse gelegt habe. Evtl. 
wird das ISR Register nicht richtig gelöscht?!

von Stephan (Gast)


Lesenswert?

Hi,
bitte sagt doch mal was das werden soll:
1
REG_PMC_PCER0 = REG_PMC_PCER0 | 0x00007800;

Das Reg PCER0 IST GLEICH Gott und die Welt ODER 0x00007800

'Gott und die Welt' ist für das kleine Register zu groß und wird 
bestimmt nicht beachtet und es bleibt nur dein Wert übrig!
1
REG_PMC_PCER0 = REG_PMC_PCSR0 | 0x00007800;

Sollte doch das eigentlich richtigere sein oder?

Im Datenblatt des SAM3X Seite 538 gibt es eine Tabelle mit den 
Eigenschaften der Register!!! Einige sind nur für das aktivieren oder 
deaktivieren oder das LESEN der Werte zuständig! (unter Access zu 
finden)

von Jannus (Gast)


Lesenswert?

Stephan schrieb:
> 'Gott und die Welt' ist für das kleine Register zu groß und wird
> bestimmt nicht beachtet und es bleibt nur dein Wert übrig!
> REG_PMC_PCER0 = REG_PMC_PCSR0 | 0x00007800;

Das Register REG_PMC_PCSR0 ist für die Aktivierung der Peripheral Clock 
Control zuständig. Diese ist erfprderlich, um am korespondierenden PORT 
Interrupts zu generieren.
Im Kapitel 9.1 Peripheral Identifiers des Datenblattes kann die 
zugehörige ID der gewünschten Peripherie entnommen werden. Für den PIOD 
ist das folgende Adresse: 0x00004000
Die von mir verwendete Adressierung (0x00007800) ist für die aktivierung 
von PIOA-PIOD, wobei hier halt PIOD reichen würde

von Stephan (Gast)


Lesenswert?

Hi Jannus,

Jannus schrieb:
> Das Register REG_PMC_PCSR0 ist für die Aktivierung der Peripheral Clock
> Control zuständig.
NEIN! :-)
1
REG_PMC_PCSR0 -> nur das Status Register, NUR zum Lesen der Information!
2
REG_PMC_PCER0 -> DIES ist für die *Aktivierung* der Peripheral Clock Control zuständig.
3
REG_PMC_PCDR0 -> DIES ist für die *Deaktivierung* der Peripheral Clock Control zuständig.

Mir ging es nur darum das du nicht alle Register lesen kannst, ich weiß 
nicht was dir dein MC zurück gibt. Im besten Fall eine NULL, im 
schlimmsten Fall eine unbekannte Zahl(Zufall).

Um nun dein Peripheral Clock zu aktivieren reicht es eigentlich so zu 
schreiben:
1
REG_PMC_PCER0 = PMC_PCER0_PID10 | PMC_PCER0_PID11 | PMC_PCER0_PID12 | PMC_PCER0_PID13;

Die beiden Register PMC_PCER0 und PMC_PCDR0 arbeiten nur aktive mit 
einer 1, eine NULL wird ignoriert!!!

von Jannus (Gast)


Lesenswert?

Stephan schrieb:
> Um nun dein Peripheral Clock zu aktivieren reicht es eigentlich so zu
> schreiben:
> REG_PMC_PCER0 = PMC_PCER0_PID10 | PMC_PCER0_PID11 | PMC_PCER0_PID12 |
> PMC_PCER0_PID13;
>
> Die beiden Register PMC_PCER0 und PMC_PCDR0 arbeiten nur aktive mit
> einer 1, eine NULL wird ignoriert!!!

Ja ich meine ja auch das REG_PMC_PCER0 und habe auch dieses verwendet. 
Habe ich irgendwo das REG_PMC_PCSR0 erwähnt? Wenn ja war es ein 
Versehen.

Das aktivieren hat ja auch der Peripheral Clock hat ja auch 
funktioniert. Aber aus für mich unerklärlichen Gründen wird die ISR 
immer und immer wieder ausgeführt, obwohl der zugerhörige Interrupt Pin 
auf Masse liegt.
Das bedeutet nach Meiner Meinung nach, das im Interrupt Status Register 
(REG_PIOC_ISR) der ausgelöste Interrupt nicht gelöscht wird.

von Stephan (Gast)


Lesenswert?

Hi,
könntest du die Init für den PIO Interrupt bitte noch mal zeigen. (das 
von oben also richtig machen)

lt. Datasheet bleibt ja nur noch ein Konfig-Fehler übrig:

>When the software reads PIO_ISR, all the interrupts are automatically cleared.
>This signifies that all the interrupts
>that are pending when PIO_ISR is read must be handled. When an Interrupt is 
>enabled on a “Level”, the interrupt
>is generated as long as the interrupt source is not cleared, even if some read
>accesses in PIO_ISR are performed.

Der MC kann dir ja auch sagen welche Art von INT er gesehen hat:
Flanken Erkennung, Level Erkennung!
Da in den zugehörigen Status Registern könntest du noch nachsehen, 
vielleicht hilft das ja.

von Jannus (Gast)


Lesenswert?

Das war ja soweit schon richtig. Ich habe das nun in eine Funktion zur 
Initialisierung gepackt.
1
void Initalize_Interrupt()
2
{
3
 /*Enables PIO Controller Clock, Enables Periphal Clk on PIOD*/
4
 REG_PMC_PCER0 = REG_PMC_PCER0 | 0x00004000; 
5
6
 /*Enables the PIO to control the corresponding pin*/
7
 REG_PIOD_PER = REG_PIOD_PER | 0x00000001;
8
9
 /*Enables the Input Change Interrupt on the I/O line*/
10
 REG_PIOD_IER = REG_PIOD_IER | 0x00000001;
11
 REG_PIOD_IDR = REG_PIOD_IDR | 0xFFFFFFFE;
12
13
 /*Enables Interrupts on PIOD*/
14
 NVIC_EnableIRQ(PIOD_IRQn);
15
}

Dazu habe ich den Interrupt Handler geändert, wobei der Großteil des 
Codes natürlich nur Dem Testzweck dient.
1
void PIOD_Handler()
2
{
3
  /*Read Interrupt Status Register*/
4
  state=REG_PIOC_ISR;
5
  
6
  a=!a;
7
  if(a==1)
8
  {
9
    REG_PIOC_SODR=0x00000002;
10
  }
11
  else{
12
    REG_PIOC_CODR=0x00000002;
13
  }
14
}

von Stephan (Gast)


Lesenswert?

Hi Jannus,

DIE Register REG_PMC_PCER0 und REG_PIOD_PER kann man NICHT lesen!
(andere hab ich nicht nach gesehen!)

so sollte das aussehen:
1
 /*Enables PIO Controller Clock, Enables Periphal Clk on PIOD*/
2
 REG_PMC_PCER0 = 0x00004000; 
3
4
 /*Enables the PIO to control the corresponding pin*/
5
 REG_PIOD_PER = 0x00000001;

von Jannus (Gast)


Lesenswert?

Selbst wenn ich das ändere bleibt das Problem bestehen.

von Jannus (Gast)


Lesenswert?

Ok das problem ist gelöst. Die Zeile
1
state=REG_PIOD_ISR;

muss durch folgende ersetzt werden. warum das so ist weiss ich nicht. 
Evtl. kann es jemand erkläen
1
state=PIOD->PIO_ISR;

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.