Einen kleinen Tip für Interrupts...

SIxO Sourcecode, Programmieren und Entwicklungswerkzeuge allgemein
Antworten
Ansgar
Beiträge: 177
Registriert: 03 Mär 2004 - 16:36
Wohnort: München
Kontaktdaten:

Einen kleinen Tip für Interrupts...

Beitrag von Ansgar »

... brauch ich.

Ich blicke hier bei den ganzen Referenzen so langsam nicht mehr durch. Wenn ich in das Appl.-Sheet für das schreiben von Interrupt routinen schaue, bin ich gezwungen den aufruf durch den interruptvector in der sect30.inc datei zu machen.
Im C-File:
#pragma INTERRUPT /B KeyInput_ISR
void KeyInput_ISR(void)
{
...
}

Im Assembler File:
.lword dummy_int ; DMA0 (for user)
.lword dummy_int ; DMA1 (for user)
.glb _KeyInput_ISR
.lword _KeyInput_ISR ; Key-on wakeup (for user)
.lword dummy_int ; AD Convert (for user)
Schaue ich aber in das C-Manual vom Mai 2003 so steht es anders dort:
int c_func(unsigned int, unsigned int);
#pragma INTCALL 25 c_func()
Die 25 ist angeblich der Interrupt Nummer in dezimal. und sie weisen explizit drauf hin, das man keine register verwenden sollt. Das würde doch bedeuten, das der Compiler und der linker den interruptvector anhand dieser anweisung im C-File erstellen.

Kann mir da mal einer kurz uter die arme greifen. Beim C51 gibt's auch derartige möglichkeiten.

Gruß Ansgar

markus
Site Admin
Beiträge: 160
Registriert: 19 Feb 2004 - 15:49
Wohnort: Ammersee
Kontaktdaten:

Beitrag von markus »

Hi Ansgar,

huuuuh, Du hast's aber eilig :wink:

Arnold hat Recht, hab wirklich viel zu tun. Aber was noch schlimmer ist: ich hab keine Ahnung wg. Deines Interrupt-Problems, ich hab noch keine Interruptgeschichten mit dem M16 gemacht.

Ich weiss ja jetzt auch nicht genau was Du vor hast, generell scheint mir der Compiler aber viel hinter den Kulissen zu machen (z.B. #pragma ADDRESS: setze ein Bit in einem Register und alles mögliche passiert...). Wenn's im C-Handbuch so steht, wird's scho stimmen - ausprobieren!

Sorry, ich kann Dir glaub ich nich helfen.

Gruß
Markus

Ansgar
Beiträge: 177
Registriert: 03 Mär 2004 - 16:36
Wohnort: München
Kontaktdaten:

Beitrag von Ansgar »

huuuuh, Du hast's aber eilig
Tja, da ich momentan in der Firma Problem mit dem Hitex Debugger habe, entsteht die eine oder andere Wartezeit... die ich sinnvoll nutzen will ;)
Wenn's im C-Handbuch so steht, wird's scho stimmen - ausprobieren!
Das ist ja der Hacken... im C-Handbuch stehts anders drinnen als es in den Aplication Notes steht und als der Andre und der Ralf es Programmiert haben. Es scheint mir aber weniger "gefährlich" zu sein es zu machen wie's im C-Handbuch steht, da ich denke das der Compiler alles berücksichtigt, was wichtig ist. Jetzt hätte ich einfach nur gerne gehört ob irgendeiner von euch schon Erfahrungen darin gesammelt hat.

Gruß Ansgar

Ralf
Beiträge: 575
Registriert: 20 Feb 2004 - 11:27
Wohnort: Hannover

(Kopie einer Mail an Ansgar vom 9.3.04)

Beitrag von Ralf »

Hi Ansgar!

Das ist garnicht so kompliziert, wie es für dich zu sein scheint.

Allerdings bin ich mir nicht ganz sicher, was du da eigentlich für ein
Interupt zusammenbastelst:
> #pragma INTCALL 25 c_func()
Damit deklarierst du eine Funktion, die du als Software(!)-Interrupt
(#25) nutzen willst. Das kann nützlich sein, wenn du aus deiner SW(!)
heraus Interrupts generieren willst, anstatt es die M16C-Peripherie
(z.B. Uart) oder externe Komponenten (z.b. INT-Leitung) erledigen zu
lassen. War das wirklich deine Absicht?

> #pragma INTCALL 29 WheelSensor_ISR();
Dies ist Code aus dem SIxO: Interrupt 29 ist eigentlich der HW-Int0 Eingang des M16C, an dem der Radsensor hängt. Der Interrupt wird also eigentlich durch HW ausgelöst. In meiner 'Vehicle-Simulation' tue ich aber einfach so, als ob das Rad sich dreht, in dem ich (mehr oder weniger) regelmäßig genau diese Int0-ISR aus meiner SW(!) heraus aufrufe. Um dies tun zu können, muss ich o.a. Pragma nutzen, sonst setzt der Compiler nicht die für eine ISR nötige Call-Prozedur auf (Register retten, etc.)

Allgemein zu Interrupts im M16C/NC30:
Wenn du gewöhnliche ISR aufsetzen willst, sind diese Schritte zu erledigen:

0. HW-Interrupt enablen
Die entsprechenden M16C-Register, die den HW-Interrupt lösen können, müssen entsprechend konfiguriert werden. Aber das hast du ja wohl schon herausgesucht?

1. Korrekten Interrupt heraussuchen
Nr.+Funktion des Interrupts heraussuchen, am besten aus sect30.inc, dort sind sowohl Nr. als auch Bedeutung aufgeführt. Wenn es um den Uart1 geht, ist dies z.B. Interrupt Vector 19(Uart1-TX) und 20(Uart1-RX). Dort ist z.Zt nur ein 'dummy_int' abgelegt, die nichts tut und z.Zt. auch nicht aufgerufen wird.

2. InterruptServiceRoutine definieren
Irgendwo im C-Code (oder bei dir Assembler?) muss deine ISR ja implementiert sein. Die nötige Syntax/Einschränkungen findest du NC30 Manual. Sie muss neben der normalen C-Definition auf jeden Fall mit dem 'INTERRUPT'-Pragma (nicht zu verwechseln mit 'INTCALL') versehen werden. Hier als Beispiel die Radsensor-ISR:
> #pragma INTERRUPT WheelSensor_ISR
> void WheelSensor_ISR(void) {...}

3. ISR in InterruptVectorTable (IVT) ablegen
Die ISR selbst ist ja nun deklariert. Im Prinzip kannst du sie jetzt jedem beliebigen HW-Interrupt unterschieben. Wenn du aber den Uart1-RX/TX Interrupt bedienen willst, musst du sie in der IVT anstelle(!) der 'dummy_int' einsetzen, also die Zeilen mit den Vektoren 19+20 in der 'sect30.inc'. Und damit der Assembler (AS30) nicht rummmeckert, weil er das Symbol (ISR-Namen) nicht kennt, muss sie zusätzlich in 'sect30.inc' weiter oben angemeldet werden:
> .glb _WheelSensor_ISR ; as int0 isr vector
Der führende UnderScore vor dem Fkt-Namen ist nur in diesem Assemblerfile nötig, weil nach dem Compilieren alle Funktionsnamen den Underscore verpasst bekommen. ACHTUNG: In der IVT-Definition (sect30.inc) vorsichtig editieren! Man kann eine Menge eigenartiger Efekte generieren, wenn mann aus Versehen eine Zeile zuviel/zuwenig in der IVT stehen hat, alle ISRs verrutschen um eine Stelle...

Das ist alles. Etwas ausführlich beschrieben, ich gebe es zu. Aber lieber zuviel, als zuwenig. Ich hoffe, es hilft dir.

Ralf

Antworten