Hallo!
Zuerst einmal: ich benutze CCE v3.1 und will dort das Flash Monitor
Programm von Texas Instruments zum Laufen kriegen (ist eigentlich für
den IAR geschrieben).
Das Programm besteht aus einem C- und einem Assembler-Code (der
eigentliche Flash Monitor).
Nun habe ich soweit alle Befehle umgeschrieben, so dass beide Programme
einzeln (!) unter CCE laufen (und zumindest theoretisch funktionieren
g). Doch sobald ich beide Codes in einem Projekt habe, kriege ich
Fehler, weil beide (Assembler und C) scheinbar Speicher für die
Interrupt Vektoren reservieren und daher diese nicht korrekt
angesprochen werden können.
Hier habe ich den Rat bekommen, ein link map file zu erzeugen, das mir
anzeigt, was wieviel Speicher benötigt und siehe da, die Interrupt
Vektoren für TimerA (int05) und UART1 (int03) sowie der Reset Vektor
brauchen 4 Byte anstatt 2. Laut Anleitung muss man dies im Linker
Command File einfach ändern, was ich auch gemacht habe (sprich die Länge
der entsprechenden Vektoren auf 4 Bytes erhöht und dann noch die
jeweiligen Startadressen anpassen, da sie sich sonst überlappen würden).
Nun kriege ich zwar keine Fehler mehr, aber beim Debuggen springt der
PC, wenn der Interrupt ausgelöst wird ins Nichts!?
Nun hab ich noch am Ende der msp430x44x.h Header Datei folgende Zeilen:
Also wenn du 4 Bytes auf dem Vektor unterbringen willst, hast du was
falsch gemacht. Da ist für jeden Interrupt nur 2 Byte Platz. Und da
ändert auch kein Linker-File etwas. Da scheint in deinem ASM was falsch
zu sein, normal gehört ja da nur die Sprungadresse der entsprechenden
ISR hin und sonst nix anderes.
Die Hardware legt fest, wo die Interruptvektoren liegen und wie groß
sie sind. Das kann man nicht nach belieben umdefinieren.
Interruptvektoren sind in einer Tabelle am oberen Ende des
64K-Adressraumes im Flash gespeichert, ihre genaue Bedeutung ist im
Datenblatt/User's Guide des jeweiligen MSP430-Derivates aufgelistet.
Dein Problem scheint zu sein, daß sowohl im Assemblerprogramm die
Interruptvektortabelle mit Inhalt gefüllt wird als auch im C-Programm.
Es gibt aber nur eine, und --wie bereits gesagt--, was in ihr wo steht,
ist durch den Prozessor vorgegeben.
Du musst also die Mischung C/Assembler irgendwie auseinander"tüddeln".
Eine Möglichkeit bestünde darin, Interruptvektoren nur in einer der
beiden Sprachen zu behandeln und gegebenenfalls aus dem Interrupthandler
heraus den 'eigentlichen' Interrupthandler der anderen Sprache
aufzurufen, der dann allerdings zur reinen Funktion degradiert werden
muss.
Der Artikel beschreibt nicht die ganz besondere Behandlung von
Interruptvektortabellen und ist daher wenig hilfreich. Was dort
beschrieben ist, darfst Du eben nicht machen.
Naja gut, aber ich habe diesen Fehler "placement fails for object..."
für eben '.int03' (UART1_RX), '.int05' (TIMERA1) und '.reset'
Aus diesem Grund habe ich ja obiges Problem, was wohl daran liegt, dass
ich die Anleitung zum Beheben des Fehlers falsch verstanden habe...ich
darf also nicht den Speicher ändern, sondern das Segment...aber wie?
Im Linker Command File steht folgendes:
1
SECTIONS
2
{
3
.bss:{}>RAM/* GLOBAL & STATIC VARS */
4
.sysmem:{}>RAM/* DYNAMIC MEMORY ALLOCATION AREA */
5
.stack:{}>RAM(HIGH)/* SOFTWARE SYSTEM STACK */
6
.text:{}>FLASH/* CODE */
7
.cinit:{}>FLASH/* INITIALIZATION TABLES */
8
.const:{}>FLASH/* CONSTANT DATA */
9
.cio:{}>RAM/* C I/O BUFFER */
10
.pinit:{}>FLASH/* C++ CONSTRUCTOR TABLES */
11
.infoA:{}>INFOA/* MSP430 INFO FLASH MEMORY SEGMENTS */
12
.infoB:{}>INFOB
13
.int00:{}>INT00/* MSP430 INTERRUPT VECTORS */
14
.int01:{}>INT01
15
.int02:{}>INT02
16
.int03:{}>INT03
17
.int04:{}>INT04
18
.int05:{}>INT05
19
.int06:{}>INT06
20
.int07:{}>INT07
21
.int08:{}>INT08
22
.int09:{}>INT09
23
.int10:{}>INT10
24
.int11:{}>INT11
25
.int12:{}>INT12
26
.int13:{}>INT13
27
.int14:{}>INT14
28
.reset:{}>RESET/* MSP430 RESET VECTOR */
29
}
sowie:
1
MEMORY
2
{
3
SFR:origin=0x0000,length=0x0010
4
PERIPHERALS_8BIT:origin=0x0010,length=0x00F0
5
PERIPHERALS_16BIT:origin=0x0100,length=0x0100
6
RAM:origin=0x0200,length=0x0800
7
INFOA:origin=0x1080,length=0x0080
8
INFOB:origin=0x1000,length=0x0080
9
FLASH:origin=0x1100,length=0xEEE0
10
INT00:origin=0xFFE0,length=0x0002
11
INT01:origin=0xFFE2,length=0x0002
12
INT02:origin=0xFFE4,length=0x0002
13
INT03:origin=0xFFE6,length=0x0002
14
INT04:origin=0xFFE8,length=0x0002
15
INT05:origin=0xFFEA,length=0x0002
16
INT06:origin=0xFFEC,length=0x0002
17
INT07:origin=0xFFEE,length=0x0002
18
INT08:origin=0xFFF0,length=0x0002
19
INT09:origin=0xFFF2,length=0x0002
20
INT10:origin=0xFFF4,length=0x0002
21
INT11:origin=0xFFF6,length=0x0002
22
INT12:origin=0xFFF8,length=0x0002
23
INT13:origin=0xFFFA,length=0x0002
24
INT14:origin=0xFFFC,length=0x0002
25
RESET:origin=0xFFFE,length=0x0002
26
}
So, wie ist jetzt die Anweisung "... Here you can verify if the size of
the .int09 section is larger than 0x2, and if so, the section allocation
in the linker command file should be modified to avoid the error." zu
verstehen?
Ich glaube du doktorst an einer völlig falschen Stelle herum. Du musst
dafür sorgen, dass eine ISR immer nur einmal deklariert wird. Die
Fehlermeldung lässt darauf schließen, dass du im ASM und im C jeweils
die 3 ISRs definiert hast. Somit hat der Linker dann einen Konflikt,
weil 2 (verschiedene) Sprungadressen in die Vektortabelle eingetragen
werden sollen.
Das .reset benötigt sicher eine Sonderbehandlung. Entweder wirfst du es
aus dem ASM raus, oder verbietest dem C-Compiler, die Reset-Routine
anzulegen. In beiden Fällen muss man aber ganz genau wissen, was man
macht. Die beiden anderen ISRs hast du ja selber in der Hand. Poste doch
mal ein Zip mit allen Quelltexten.
Naja, der Witz ist doch soweit ich verstanden habe der, dass eben beide
Programme selbstständig laufen können.
Der Asm Code ist der eigentliche Flash Monitor, der ja immer laufen
können soll. Mit dem C Code Beispiel soll ja nur demonstriert werden,
wie aus einem belibiegen Programm eben der flash monitor gestartet
werden kann.
D.h. theoretisch muss ich im C-Code keinen USART nutzen und
initialisieren, aber dann muss das der Asm Code machen...der braucht das
ja.
Die Beispiele sind für den IAR Compiler gemacht und laufen da auch
einwandfrei (hab mal die kostenlose Version installiert), ich muss es
halt hier unter CCE zum Laufen kriegen.
Naja, dann hast du nicht richtig gelesen. In 3.2.1 des Manuals steht
doch, dass du deinem C-Compiler beibringen musst, dass er die
Interrupt-Vektoren an einer anderen stelle speichern soll als üblich.
Wie das beim CCE dann aber geht, weiß ich nicht. Sollte aber recht
einfach über das Linker-Script gehen. Deine C-Applikation hat dann
völlig andere Interrupt-Vektoren, auf den originalen sitzt der Flash
Monitor.
Meinst du 3.2.1 aus "A Flash Monitor for the MSP420" (SLAA341) ?
Wenn ja, dann lese ich dort, dass man das "linker command file"
modifizieren muss und der folgende Code dann entsprechend für den IAR
Linker gedacht ist.
Oben habe ich doch aber schon den entsprechenden Auszug aus dem "linker
command file" für den CCE gepostet aber es hieß, da darf ich nix dran
ändern!?
Rufus t. Firefly wrote:
> Die Hardware legt fest, wo die Interruptvektoren liegen und wie groß> sie sind. Das kann man nicht nach belieben umdefinieren.
Komischerweise mache ich aber doch genau das, wenn ich nach 3.2.1
vorgehe und das funktioniert im IAR einwandfrei!?
Wenn Du ein anderes 3.2.1 meinst, dann vergiss, was ich geschrieben hab
:-)
Ja, das meine ich. Du musst die Position der Interrupt-Vektoren
verändern, aber nur die Position, nicht die Größe. Die bleibt nach wie
vor bei 2 Byte pro Interrupt. Wenn du die Adressen verändert hast, kann
das ASM Programm durch die org Anweisung die ISRs direkt in der
originalen Position platzieren, und der Linker des C-Programm platziert
die ISRs deines User-Programms dann an der neuen Position. Dann darf
auch keine Fehlermeldung kommen, da der Linker ja für jedes extra
Positionen hat, und sich nix überlappt. Du musst auch die Größe der TXT
Section anpassen, denn der Monitor braucht seinen komplett eigenen
Speicherbereich. Ebenso die Data Section für die Variablen. Aber die
Größe der Interrupt-Vektor-Tabelle bleibt bei 32 Byte für die 16
Vektoren und 2 Byte für den Reset.
So, nachdem ich die Magen-Darm-Grippe überstanden habe, habe ich
immernoch Kopfschmerzen ;-)
Also wenn ich das jetzt richtig verstanden habe, habe ich durch das
modifizierte Linker Command File eine andere Interrupt Vektor Tabelle
für meinen C-Code als für den Assembler Code, in dem ja (siehe Anhang)
am Ende die "originalen" Adressen benutzt werden.
Soweit so gut, aber mein Problem ist ja jetzt, das ganze mit dem CCE zu
machen. Da gibt es keine solche Speichersegmentkontrolle:
"The CCE Asm430 assembler does not support any of the IAR A430 segment
control directives such as ORG, ASEG, RSEG, and COMMON."
"To allocate code and data sections to specific addresses with the CCE
assembler, it is necessary to create/use memory sections defined in the
linker command files." (D.2 in SLAU157H)
In dem Beispiel dort wird dann anstelle von
1
ORG 0FFF2h
2
DW TA0_ISR
die Information aus dem Linker Command File benutzt:
1
.sect ".int09"
2
.short TA0_ISR
Das Linker Command File wird doch aber auch für/vom C-Code benutzt! Wie
kann ich hier also für C und Assembler "getrennt" die Interrupt Vektor
Tabelle definieren?
Wenn jemand ne Idee hat...
Ich hirne einfach mal weiter. Wenn ich was finde, poste ichs natürlich!
Achso....da liegt das Problem. Nun ja, dann wirst du diese (eh nicht
besonders elegante) Methode mit dem CCE nicht benutzen können. Schreib
dir einen eigenen kleinen Bootloader und gut ist. Das hätte bisher
weniger Zeit in Anspruch genommen als das hier auf Krampf zu versuchen.
Ich hab mir auch einen "Bootloader" gemacht, da kann ich den MSP430 über
Funk mit dem CC2420 Updaten (außer den Funkloader natürlich)
Naja, ich sitze hier als Student an einem Firmenprojekt und soll das
halt so machen...hatte vorher noch nur mal einen PIC16F690 programmiert
und sonst keine Erfahrung mit der ganzen Materie.
Bis ich mal dahintergestiegen bin, was das Programm überhaupt auf dem µC
macht, wie der µC überhaupt und das alles funktioniert, hat ja schon
gedauert. Sitz da schon fast 2 Wochen dran.
Also gut, ich werd mal schauen, wie ich dass meinem Betreuer beibringen
kann...
Danke trotzdem für die tolle und schnelle Hilfe!!!
Hab doch einiges gelernt!
Wie muss man denn beim CCE3 Assembler die Interrupts deklarieren?
Vielleicht kann man ja einfach noch einen 2. 16er Block erstellen, und
die dann meinetwegen .int109 statt .int09 nennen. Genauso dann im
Linker-Command File.
supachris, Du bist SUPER!!!
So gehts: im Linker Command File einen zweiten Satz Interrupt Vektoren
erstellen und die passenden Segmente dazu (hab sie so benannt wie Du es
vorgeschlagen hast ;-) ). Natürlich noch den Flash-Speicher anpassen
(Länge muss gekürzt werden).
Dann einfach im Assembler Code die "neuen" Vektoren benutzen:
1
.sect ".int100"
2
.short Int_Priority_0
3
.sect ".int101"
4
.short Int_Priority_1
usw.
Und schon laufen C- und Assembler im selben Projekt.
Ich hatte noch erst Probleme, vom Assembler in den C-Code zurück zu
springen, weil beim IAR einfach der Reset-Vektor geladen wird. Da beim
CCE die ganze Sache vertauscht ist (hier benutzt der Assembler Code die
"verschobene" Vektor Tabelle und der C-Code die "originale") musste ich
anstatt 0xFBFE (reset vector vom Assembler) einfach 0xFFFE in den PC
schreiben und schon hats geklappt!
Ich kann jetzt wie beim IAR zwischen Applikation (C-Programm) und
Monitor (Assembler) schön hin und her springen, die Checksum berechnen,
den Speicher anzeigen lassen etc!!!
Jetzt ist nur noch ein kleines Schönheitsproblem:
Im Assembler-Code sind wie folgt Zeichenfolgen gespeichert:
1
CmdTable: .byte "CDEGIU"
2
Prompt: .byte "\r\n?"
3
Pass: .byte "PW?"
4
CRLF .byte "\r\n"
5
ProgErr .byte "ERR\r\n"
6
NotBlank .byte "NB\r\n"
7
FilePrompt .byte "@?"
Diese werden je nach Bedarf Zeichen für Zeichen via UART an den
Hyperterminal gesendet. Beim IAR funktioniert das super, \r\n läßt den
Cursor an den Zeilenanfang einer neuen Zeile springen und wenn die
Zeichenfolge vorbei ist kommt ein "Null"-Zeichen (einfach 0x00), so dass
das Senden abgebrochen wird.
Beim CCE funktioniert zum einen \r\n nicht (die Zeichen werden einfach
mit ausgegeben) und zum anderen gibt es anscheinend nicht automatisch
ein Null-Zeichen am Ende eines solchen "Strings", so dass die Funktion
ewig weiter sendet.
Das zweite Problem habe ich gelöst, indem ich einfach nach jeder
Zeichenfolge ein .byte 0 angehängt habe. Klappt auch, ist aber
vielleicht nicht das eleganteste.
Aber warum funktioniert \r\n nicht?
Beim IAR sendet der MSP doch auch einfach nur diese Zeichen via UART!?
Soll ich die Frage vielleicht in einem neuen Post stellen???
(Geht ja immerhin um was ganz anderes jetzt...)
Viele Grüße und vielen, vielen Dank!
Stephan
Na da hättest du doch selber drauf kommen können ;)
Das Problem an \r\n ist eventuell, dass der CCE Assembler das wieder
nicht korrekt versteht. Der nimmt das offensichtlich als einzelne
Zeichen. Auch da müsstest du mal im User Guide schauen, oder bei TI
anfragen. Dass das Null-Byte am Ende automatisch ist, ist ebenso
Assembler-abhängig. Manche machen das, manche nicht.
Hab grad hier im Forum ein Steuerzeichen.pdf gefunden, wo ausführlich
drin steht, welche Zahl für Zeilenvorschub und welche für Wagenrücklauf
steht.
naja, jetzt benutze ich anstelle von