Forum: Mikrocontroller und Digitale Elektronik [asm] Interruptvektor in anderer Datei angeben


von Sebastian U. (bass-t-rock)


Lesenswert?

Hallo da draußen :)

Bevor wir mit der Frage starten:
Ich benutze zwei AtMega8 - 16PU, programmiert wird in (AVR)Assembler und 
Entwicklungsumgebung ist das Atmel Studio 6.2.

Zur Frage:
Normalerweise werden die Interruptvektoren ja am Anfang des 
Programmcodes definiert, da sie ja an im Programmspeicher eben dort 
stehen.
Mit jeder Zeile Code (wenn sie zu einer Übersetzung in der .hex Datei 
führt) erhöht sich ja nun der Programm-Counter.

Kann man die Interrupt-Vektoren auch an anderer Stelle im Programm-Code 
definieren? Ich stelle mir das in etwa so vor:
1
; some test code
2
test_label:
3
.equ varTest1 = SRAM_START
4
; set interrupt vector for TWI
5
.org TWIaddr
6
        rjmp TWI
7
; continue working after "varTest1"
8
.org (test_label + 1)
In diesem Beispiel wird wahrscheinlich nicht das gewünschte Ergebnis 
eintreten, da ja ".equ" keine Zeile Programmcode (in der .hex Datei) 
erzeugt, und damit der Programm-Counter auch nicht erhöht wird, oder?

Aber die Frage ist, ob es grundsätzlich möglich ist mit der 
".org"-Direktive an den Ort für den Interrupt-Vektor zu springen und 
danach wieder an die Stelle, wo man vorher war (gespeichert durch die 
Sprungmarke). Geht das eventuell auch anders (vielleicht auch 
eleganter)? Also in dem man sich den Programm-Counter irgendwie merkt?

Hintergrund ist folgender:
Ich habe mich an der Kommunikation zweier AVR-Mikrocontroller mittels 
TWI versucht, was auch gelungen ist.
Nun ist mir aufgefallen, dass viele der nächsten geplanten Projekte auch 
die TWI/I2C Schnittstelle verwenden werden. Daher kam mir die Idee, die 
gewonnenen Erkenntnisse in eine "Bibliotheksdatei" zu verlagern, die 
dann nur noch in das jeweilige Projekt eingefügt werden muss und alles 
Notwendige für die Kommunikation mittels TWI/I2C zur Verfügung stellt.
Dafür ist es aber nötig die Sprungadresse für den TWI-Interrupt 
anzugeben, weil ich eben diesen verwenden möchte, statt den Status 
selbst abzufragen.

Und da die Verarbeitung ja in der TWI-Bibliotheksdatei geregelt ist, 
kennt eben diese auch die Adresse, die angelaufen werden muss, wenn es 
zu einem Interrupt durch das TWI-Interface kommt.
Natürlich kann der Programmierer das auch in der Haupt-Datei erledigen, 
nur müsste man dann die Sprungadresse nachschauen, sofern man sie nicht 
aus dem Kopf kennt.
Es geht hier also um die reine Bequemlichkeit, die dem Programmierer (in 
dem Falle mir) etwas die Arbeit erleichtern soll.

So das war ne ganze Menge Text, ich hoffe mein Problem ist ersichtlich. 
Sollte ich was vergessen haben, dann reiche ich das natürlich nach.
Danke schon mal für eure Mühen.

von Peter D. (peda)


Lesenswert?

Ja das geht.
Man kann beliebig den PC hin und her setzen, solange sich Codebereiche 
nicht überlappen.
Am besten schreibt man sich ein entsprechendes Macro für ISRs.

Beitrag "Re: Fehler bei ldi r16, 0b00001111"

von Georg (Gast)


Lesenswert?

Sebastian U. schrieb:
> Kann man die Interrupt-Vektoren auch an anderer Stelle im Programm-Code
> definieren?

Kommt drauf an, was du mit Stelle meinst - die Interrupt-Vektoren müssen 
natürlich im Speicher da stehen, wo sie laut Handbuch eben stehen 
müssen. Wo sie im Programmcode definiert werden, ist dagegen egal, 
solange man mit ORG dafür sorgt, dass der richtige 
Programm-Speicherplatz angegeben ist. Man kann mit ORG auch lustig im 
Adressbereich herumspringen, wenn man dabei was falsch macht, z.B. 
überlappende Programmteile oder Programme ausserhalb des erlaubten 
Bereichs, dann meckert der Assembler schon.

Ausnahme sind ev. Ein-Pass-Assembler, die nicht zuerst alle 
Informationen zusammentragen und dann übersetzen, sondern das in einem 
Rutsch machen, dann muss jedes Symbol zuerst definiert sein, bevor man 
sich drauf beziehen kann. Das kann manchmal schwierig sein, aber die 
sind wohl auch selten.

Sebastian U. schrieb:
> .org (test_label + 1)

der Ausdruck für ORG darf nur Konstanten enthalten, also z.B. auch ein 
Symbol, das mit einem EQU nach einem IFDEF DEBUG festgelegt ist, ein 
häufiger Fall.

Dein test-label hat den Wert TWIaddr, ist das deine Absicht?

Georg

von Sebastian U. (bass-t-rock)


Lesenswert?

Hallo und danke für die schnellen Antworten.

@Peter
Das mit dem Makro schaut interessant aus. Ich denke das werde ich mal so 
umsetzen.

@Georg
Danke für den Hinweis mit den Konstanten.
Das was da oben steht war nur kurz aufgeschrieben, um zu 
veranschaulichen, was ich vor habe.
Wie ich schon oben schrieb, ist mir bewusst, dass dieses Beispiel in 
seiner Sinnhaftigkeit sehr begrenzt ist.
Ich möchte natürlich nicht, dass ich nach dem ".org" mit der Adresse 
TWIaddr weiter machen.

Der eigentliche Anwendungsfall ist eine "Biliotheksdatei" die mir die 
Arbeit mit der TWI/I2C Schnittstelle abnimmt. In dieser Datei soll eben 
auch die Sprungadresse für das Eintreten eines Interrupts des 
TWI-Interfaces festgelegt werden.
Da diese Datei nicht die Haupt-Datei des Projektes ist (Ich glaube im 
Atmel Studio heißt sie "entry-Datei") wird sie, so wie ich glaube, nach 
der Haupt-Datei übersetzt.
Das heißt aber, dass der Programm-Counter beziehungweise halt die 
Adresse, an die mein Programmcode im Speicher geschrieben wird bereits 
vorangeschritten ist.

Wenn ich jetzt in der Datei einen Interruptvektor definieren möchte, 
muss ich ja mit dem entsprechenden Befehl dorthin navigieren.
1
.org TWIaddr
Wenn ich danach dann aber einfach den nächsten Teil weiter schreibe, 
landet ja der Rest des Codes hinter "TWIaddr".
Was im Klartext bedeutet, dass mein Programmcode der Hauptdatei 
überschrieben wird.
Das möchte ich verhindern. Und so wie es aussieht, löst das Makro von 
Peter genau dieses (mein) Problem.

Möge die Nacht mit euch sein
Sebastian

von Georg (Gast)


Lesenswert?

Sebastian U. schrieb:
> .org TWIaddrWenn ich danach dann aber einfach den nächsten Teil weiter
> schreibe,
> landet ja der Rest des Codes hinter "TWIaddr".

Nein. Ich kenne jetzt deinen Assembler nicht, aber in den vielen, die 
ich schon benutzt habe, gibt es üblicherweise Abs und Rel Segmente. Ich 
zitiere hier aus einem eZ80-Macro-Assembler:

Allocating Processor Memory

All memory locations, whether data or code, must be defined within a 
segment. There are two types of segments:

•Absolute segments
An absolute segment is any segment with a fixed origin. The origin of a 
segment is defined with the ORG directive. All data and code in an 
absolute segment are located at the specified physical memory address.

•Relocatable segments
A relocatable segment is a segment without a specified origin. At link 
time, linker commands are used to specify where relocatable segments are 
to be located within their space. Relocatable segments can be assigned 
to different physical memory locations without re-assembling.

So ähnlich ist das fast überall. Normalerweise verwendet man also Abs 
nur für ISRs, für das "normale" Programm nimmt man Rel und gibt nur eine 
Startadresse an fürs Linken, dann ordnet der Linker das nacheinander an.

Dein Assembler-Handbuch weiss Bescheid.

Georg

von Bestromer (Gast)


Lesenswert?

@Peter
sehr interessantes Macro, wo nimmst Du nur immer diese Ideen her :)

@Sebastian
hallo Leidensgenosse :))
...diese Frage stellte ich mir auch oft, man versucht in ASM ein 
sinnvolles Modulkonzept zu bauen und dann stört diese starre 
Interrupttabelle.
Auf der einen Seite ist so eine Tabelle ja schön übersichtlich an einem 
Ort wie in diesem Fall im Dateikopf, aber wenn ich einmal viel 
Gehirnschmalz in ein "Modul" gesteckt habe, dann möchte ich es nur noch 
als "Blackbox" mit Übergabe von Parametern benutzen und mir nicht 
ständig Gedanken über deren korrekte Einbindung machen.
Ein kurzes Include und mal eben fix in der Doku geschaut welche 
Parameter zur Benutzung...fertig!
Ich programmiere noch nicht sehr lange in ASM, aber mir gefällt die 
grenzenlose Freiheit und Formbarkeit des eigenen kleinen Systems mit 
leistungsfähigen Komponenten.
Dank Peters Kreativität wird dieses Vorhaben wieder ein Stück 
perfekter...also in diesem Sinn nochmal Danke das Du uns an Deiner 
Erfahrung teilhaben lässt :)

von Georg (Gast)


Lesenswert?

Bestromer schrieb:
> ein
> sinnvolles Modulkonzept zu bauen und dann stört diese starre
> Interrupttabelle.

Das ist nur mangelnde Beherrschung der Assembler-Möglichkeiten. An den 
festgelegten Adressen muss ja nur ein Sprung an die eigentliche ISR 
stehen - da gibt es zahllose bewährte Konzepte zur modularen 
Programmierung, z.B. kann die feste Interruptvektor-Tabelle auf eine 
zweite verweisen, die im RAM steht und bei der Initialisierung befüllt 
wird, damit kann man sogar zur Laufzeit ladbare I/O-Module realisieren.

Überhaupt ist die Diskussion, was in Assembler geht oder nicht reichlich 
albern - natürlich geht alles, was in irgendeiner Sprache geht, auch in 
Assembler, wie sollte man es denn sonst in der Hochsprache realisieren 
wenn nicht mit einer Assembler-Routine?

Ausserdem ist Programmieren kein Wunschkonzert, wenn ein ADC-Register an 
einer bestimmten Adresse ansprechbar ist, dann ist das eben so, auch 
wenn dir das persönlich nicht gefällt. Was wäre denn besser, wenn das 
Register an einer anderen Adresse eingebaut wäre? Und die 
Programmausführung startet immer an der gleichen Adresse, meistens 0, ob 
dir das nun passt oder nicht. Wenn sich alles nach deinen Wünschen 
richten soll, musst du dir mit FPGAs einen eigenen Prozessor schnitzen.

Georg

von Bestromer (Gast)


Lesenswert?

Hallo Georg,


Georg schrieb:
> Das ist nur mangelnde Beherrschung der Assembler-Möglichkeiten.
Bestromer schrieb:
> Ich programmiere noch nicht sehr lange in ASM
...gut erkannt!

Georg schrieb:
> da gibt es zahllose bewährte Konzepte zur modularen
> Programmierung...
...ich höre Dir gern zu,wenn Du sie mir erläutern möchtest :)

Georg schrieb:
> ...damit kann man sogar zur Laufzeit ladbare I/O-Module realisieren.
...klingt interessant,werde ich mir mal im Kopf zergehen lassen.

Georg schrieb:
> Überhaupt ist die Diskussion, was in Assembler geht oder nicht reichlich
> albern - natürlich geht alles, was in irgendeiner Sprache geht, auch in
> Assembler, wie sollte man es denn sonst in der Hochsprache realisieren
> wenn nicht mit einer Assembler-Routine?
...sind wir da nicht einer Meinung?

Georg schrieb:
> Ausserdem ist Programmieren kein Wunschkonzert, wenn ein ADC-Register an
> einer bestimmten Adresse ansprechbar ist, dann ist das eben so, auch
> wenn dir das persönlich nicht gefällt. Was wäre denn besser, wenn das
> Register an einer anderen Adresse eingebaut wäre? Und die
> Programmausführung startet immer an der gleichen Adresse, meistens 0, ob
> dir das nun passt oder nicht. Wenn sich alles nach deinen Wünschen
> richten soll, musst du dir mit FPGAs einen eigenen Prozessor schnitzen.
...was ist los mit Dir, es scheint mir als wärst Du sehr aufgeregt?

von Georg (Gast)


Lesenswert?

Bestromer schrieb:
> ...was ist los mit Dir, es scheint mir als wärst Du sehr aufgeregt?

Über sowas rege ich mich schon lange nicht mehr auf, aber du hörst dich 
an, als würdest du festgelegte Adressen eines Prozessors als Anschlag 
auf deine gestalterische Freiheit auffassen. Ich programmiere Assembler 
seit mehr als 40 Jahren, wenn ich mich bei jedem neuen Prozessor über 
sein spezielles Adressmapping geärgert hätte, hätte ich das garnicht 
überlebt. Das nimmt man zur Kenntnis und Punkt. Es ändert sich ja auch 
nicht wenn du dich hier im Forum darüber beschwerst.

Georg

von Bestromer (Gast)


Lesenswert?

Georg schrieb:
> aber du hörst dich an, als würdest du festgelegte Adressen eines
> Prozessors als Anschlag auf deine gestalterische Freiheit auffassen...
...nein,im Gegenteil sonst würde ich nicht mit ASM programmieren.
Vielleicht hast Du das nur falsch aufgefasst...ich fand einfach nur 
keinen Weg die Adressen der Interrupthandler innerhalb der Module zu 
definieren, alles Andere lässt sich doch prima handeln...

Georg schrieb:
> Ich programmiere Assembler
> seit mehr als 40 Jahren
...Hut ab...deshalb hast Du sicherlich eine andere 
(globalere?)Sichtweise...

Georg schrieb:
> Es ändert sich ja auch
> nicht wenn du dich hier im Forum darüber beschwerst
...Ich hab mich eigentlich eher gefreut hier im Forum einen neuen Weg 
gefunden zu haben.

So ich lass mir jetzt einen Kaffee ein :o)

von Georg (Gast)


Lesenswert?

Bestromer schrieb:
> ich fand einfach nur
> keinen Weg die Adressen der Interrupthandler innerhalb der Module zu
> definieren

Das muss man ja nur noch selten überhaupt selber machen, die meisten 
Hersteller liefern ja Include-Dateien für ihre Prozessoren, in denen 
alle konstanten Speicher- und Port-Adressen definiert sind. Da muss man 
nur noch wissen wie die symbolisch heissen, z.B. UART1_CTRL, und die 
INC-Datei in alle Module einbinden.

Wohin die Sprungbefehle in der Vektortabelle führen, also wo die 
eigentliche ISR steht, darum kümmert sich der Linker. Dazu muss nur das 
Label in dem Modul, in dem der ISR-Code steht, als Public/Global/Xdef 
oder so ähnlich deklariert werden.

Es gibt also 2 Adressen von Interesse: die des speziellen Interrupts in 
der Vektortabelle ist fest (bei den meisten Controllern), die steht in 
einer Include-Datei. Die der tatsächlichen Interruptroutine ist der Wert 
des Labels am Einsprungspunkt der ISR, der wird mit Public exportiert to 
whom it may concern. Das sammelt alles der Linker ein und trägt das in 
den Sprungbefehl ein, der Programmierer muss die Adresse nicht wissen, 
kann sie sich aber für Debugzwecke aus der MAP-Datei holen.

Georg

von Peter D. (peda)


Lesenswert?

Georg schrieb:
> Ich programmiere Assembler
> seit mehr als 40 Jahren

Das ist aber mächtig lange. Ich habe 10 Jahre gebraucht, um von 
Assembler (8051) auf C zu wechseln und mich dann geärgert, es erst so 
spät gemacht zu haben.

Georg schrieb:
> natürlich geht alles, was in irgendeiner Sprache geht, auch in
> Assembler

Welcher Assembler kann denn bitteschön Arrays, Structs, float, 
Registeroptimierung, Variablen-Overlay mittels Calling-Tree, common 
subexpression elimination usw.?

von Georg (Gast)


Lesenswert?

Peter D. schrieb:
> Das ist aber mächtig lange. Ich habe 10 Jahre gebraucht, um von
> Assembler (8051) auf C zu wechseln

Im Gegensatz zu deinen Jüngern interessiert es mich nicht im geringsten, 
was du von meiner Programmierqualifikation hältst. Unverschämt ist es 
trotzdem, andere niederzumachen, ich äussere mich ja auch nicht über 
deine Qualifikation als selbsternannter Software-Guru mit 
Unfehlbarkeitsanspruch. Von dir kollegialen Respekt zu erwarten ist nach 
deinem Auftreten hier im Forum wohl nur naiv. Es ist einfach traurig, 
wenn tatsächlich vorhandene Kenntnisse und Erfahrung nur zur 
Überheblichkeit führen.

Georg

von Peter D. (peda)


Lesenswert?

Georg schrieb:
> ich äussere mich ja auch nicht über
> deine Qualifikation als selbsternannter Software-Guru mit
> Unfehlbarkeitsanspruch.

Hast Du mal nen Link, wo ich mich selber als Software-Guru bezeichne 
oder Unfehlbarkeit proklamiere?

Ich wollte nur klarstellen, daß man eben nicht alles in Assembler machen 
kann, was Hochsprachen können.

Ich war auch 10 Jahre der Meinung, Assembler rulez. Aber irgendwann ist 
mir einfach die Entwicklungszeit und die Projektgröße davongelaufen.
Und ich benutze auch mehrere Architekturen und will den Code nicht für 
jede neu schreiben müssen.

Dich möchte ich natürlich nicht bekehren, aber Anfängern schon 
nahelegen, nach den ersten Assemblerschritten auch mal C zu probieren.

von Georg (Gast)


Lesenswert?

Peter D. schrieb:
> Dich möchte ich natürlich nicht bekehren

Ich habe nie behauptet, NUR Assembler zu programmieren, ich benutze seit 
Jahrzehnten auch verschiedene Hochsprachen. Das hast du dir nur so 
ausgedacht, um mich lächerlich machen zu können.

Du greifst jeden an, der das Wort Assembler nur in den Mund nimmt, 
c-hater betreibt hier das genaue Gegenteil - ihr seid wie Zwillinge, 
wenn man von der unbedeutenden Tatsache absieht, dass ihr wohl nicht 
beide richtig liegen könnt. Aber ihr habt wohl begriffen, dass nicht 
Sachargumente oder Kenntnisse entscheidend sind, um sich hier im Forum 
durchzusetzen, sondern wer am hemmungslosesten um sich beisst. Auf so 
ein Niveau will ich mich nicht einlassen, ich habe meistens multilingual 
programmiert und ein solcher ideologischer Fanatismus pro C oder pro 
Assembler ist mir völlig fremd.

Georg

von Route_66 H. (route_66)


Lesenswert?

Georg schrieb:
> ein solcher ideologischer Fanatismus pro C oder pro
> Assembler ist mir völlig fremd.

Das ist hier im Forum aber leider meist das Resume jedes Themas über 
Programmierung.

Traurig.

von Axel S. (a-za-z0-9)


Lesenswert?

Peter D. schrieb:

> Ich wollte nur klarstellen, daß man eben nicht alles in Assembler machen
> kann, was Hochsprachen können.

Das ist doch Unsinn. Bzw. einfach nur Nichtverstehenwollen von deiner 
Seite. Selbstverständlich kann man zu jedem Programm in jeder Hoch- 
sprache sofort ein äquivalentes Assembler-Programm angeben.
Einfach indem man den vom Compiler generierten Maschinencode in 
Assembler dupliziert. Und für die allermeisten Compiler und µC kann ein 
erfahrener Programmierer sogar kürzeren und schnelleren Assemblercode 
schreiben.

Wie sinnvoll das ist, steht natürlich auf einem anderen Blatt. Aber es 
ist ganz sicher nicht unmöglich.

> Ich war auch 10 Jahre der Meinung, Assembler rulez. Aber irgendwann ist
> mir einfach die Entwicklungszeit und die Projektgröße davongelaufen.
> Und ich benutze auch mehrere Architekturen und will den Code nicht für
> jede neu schreiben müssen.

Ja. Und? Hat irgend jemand behauptet, man müsse alles in Assembler 
machen? Ach, nicht? Und worüber dann der Streit?

von Peter D. (peda)


Lesenswert?

Ich finds schon recht seltsam, wie schnell sich Leute angegriffen fühlen 
und Sachen behaupten, die ich nie gesagt habe.
In Schrift kann man sich nicht so ausdrücken, wie in einem Gespräch. Es 
ist daher völlig normal, daß Formulierungen anders gemeint sein können, 
als wie sie interpretiert werden. Ich bin ja kein Anwalt, der so 
schreiben muß, daß alles hieb- und stichfest ist.
Man sollte daher nicht immer gleich HB-Männchen spielen, sondern auch 
mal etwas gelassener sein. Das schont auch die eigenen Nerven.

Ich habe überhaupt nichts gegen Assembler, ich praktiziere es nur nicht 
mehr. Wie man sieht, antworte ich ja weiterhin auf Assemblerfragen.

Auch finde ich es beeindruckend, wie einfach Sachen in C sind, für die 
ich mir vorher in Assembler quasi nen Arm ausreißen mußte. Und ich 
widerspreche auch der Mär, daß Assemblerprogramme erheblich kleiner und 
schneller sind.
Aber das ist nur meine persönliche Meinung, die ich niemandem aufdrängen 
will. Jeder muß seine Erfahrungen schon selber machen.

P.S.:
Ich geb ja zu, daß meine Formulierungen manchmal etwas spitz sind.

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.