Forum: Mikrocontroller und Digitale Elektronik MSP430 LinkerFile, Variablen- und DebugInformations-problem


von Benedikt (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
ich verwende einen MSP430-1232 mit MSP430-gcc und -ld,
ich implementiere einen eigenen Bootloader für den MSP und Teile mein 
Programm in unterschiedliche Sektionen ein wobei die .text section den 
Benutzercode enthält der überschreibbar ist.

Mein Problem ist nun das Variablen (zurzeit nur bei Globalen Variablen 
aufgefallen) in der von mir neu definierten section ein komisches 
verhalten an den Tag legen.

Beispielcode mit dem ich das Verhalten getestet habe:
1
static unsigned char state= 0;
2
3
void test()
4
{
5
  state++;
6
  if (state>=2) 
7
  {
8
    *do something*
9
  }
10
}
11
12
void main()
13
{
14
  while(1) test();
15
}

Das Verhalten ist Folgendes:
obwohl state immer erhöht wird, wird do something nicht aufgerufen, 
wenn ich state bei der deklaration auf 1 setze wird do something 
aufgerufen

daher denke ich wird state in der Funktion test wie eine lokale Variable 
verwendet und zu beginn immer mit dem Wert aus der deklaration 
initiiert.

dieses Verhalten tritt nur bei meinem geänderten Linker-File auf, was 
das Problem warscheinlich auf dieses einschränkt, nur weiß ich leider 
nicht wie ich das Linker-File umschreiben muss damit auch die Variablen 
richtig Verlinkt werden.

Ein weiteres Problem hatte ich mit den debug Informationen die meine 
Sektionen zum Überlaufen veranlassen, weshalb ich die 
Debug-Informationen vom MSP430-gcc nicht generieren lasse.

kann mir jemand beim Umschreiben des Linker Files helfen, wo die 
Variablen und Debug-Informationen wie in der .text Sektion 
berücksichtigt werden.

Mein geändertes Linker-File habe ich in den Anhang gegeben.

mfg Benedikt

von Christian R. (supachris)


Angehängte Dateien:

Lesenswert?

Variablen werden doch im .data und.bss abgelegt, die dürften sich nicht 
in die Quere kommen. AUch Debug-Infos kommen nicht in die .txt sections. 
Sehr komisch. Ich hab auch für meinen F1611 einen Funk-Bootloader 
geschrieben in einer eigenen Section, das klappt bestens. Allerdings 
benutze ich im Bootloader keine globalen Variablen aus dem "user 
programm".
Im Anhang mal das geänderte Linker-File.

von Benedikt (Gast)


Lesenswert?

Das Problem ist, dass ich die Sektion nicht in den Files stehen haben 
möchte sondern alles was in dem bootloader.c und bootloader.h File zu 
bootloader.o umgewandelt wird in meine eigene .bootloader section 
stelle, so wie es aussieht musst du bei deinen Funktionen davor noch 
überall den sektionsnamen angeben, dort wo er nicht steht werden bei dir 
die original sektionen verwendet. Deswegen wirst du auch keine Probleme 
mit den Varablen haben denk ich mir mal. Gibt es eine Möglichkeit, dass 
der Linker Variablen und Debug-Informationen automatisch wie er es im 
originalfile auch tut in die dafür vorgesehenen Sektionen ladet?

Mir fällt gerade ein weiteres Problem ein aber vielleicht is das ja eh 
keines, kenn mich bei dem msp430 Linker zu wenigaus:
Der Programmspeicher ist ja durch die Sektionen geschützt aber der 
Variablenspeicher ist bei der Verwendung wieder gemischt wie kann ich es 
schaffen das die Variablen immer an den gleichten Platz gebunden werden 
und nicht automatisch in den gemeinsamen Bereich verlinkt werden.
Denke mir das es da dann ein Problem geen könnte wenn die bereits von 
anderen Programmteilen verwendet werden nachdem der neue Code mittels 
eigenem Bootloader einspielt wird kann ja die Anordnung variieren 
wodurch die zugriffe auf die Variablen anders ausfallen oder kann das eh 
nicht passieren.

mfg Benedikt

von Christian R. (supachris)


Lesenswert?

Achso, hm, da kann ich dir leider nicht helfen. Ich hab die in einem 
"geschützen" Flash-Bereich stehen. Da müsstest du dich mal an die MSPGCC 
Profis in den Mailinglisten oder so wenden....Chris Lichti oder Steve 
Underwood.

von odic (Gast)


Lesenswert?

Ich habe leider im Moment keine Zeit mich durch dein Linker-file zu 
graben (kann aber gerne heute abend mal einen Blick rein werfen wenn das 
Problem dann immernoch besteht), hätte aber dennoch einen Tipp für dich:

Ich persönlich würde Bootloader und Anwendung immer als zwei getrennte 
Projekte übersetzen. Beide bekommen bezüglich RAM die selben (bzw. die 
jeweils passenden) Linkereinstellungen, allerdings getrennte Bereiche im 
Flash.

Nachteil:
- Du hast zweimal den Startup-Code enthalten. (Halte ich bei den paar 
Byte für unkritisch.)

Vorteile:
- Variablen werden garantiert richtig initialisiert bzw. getrennt 
verwendet.
- Du verschwendest in der eigentlichen Applikation keinen RAM für den 
Bootloader, weder auf dem Stack noch für globale Variable.


Grüße,
odic

von Benedikt (Gast)


Lesenswert?

Verstehe nicht ganz wie du das meinst, vielleicht kannst du mir das 
heute abend genauer erklären bzw vielleicht findest du ja den Fehler den 
ich im Linkerfile gemacht hab denk mir mal, dass da noch einige Einträge 
in den neuen Sektionen hinzugefügt werden müssen so wie es in der .text 
section gemacht wird nur wie die genau heißen oder wo das zu schreiben 
ist dazu kenn ich mich leider zu wenig in den Linker-File Syntax und in 
den Eintellungen aus. Weil wenn man das original Linker-File verwendet 
müssen ja auch keine eigenen Angaben zu den Variablen oder Sektionen im 
Code gemacht werden.

zum Besseren Verständnis habe ich mal einen kurzen Überblick über den 
Aufbau meines Programms, welches auf eigenen Speicherbereichen aufgebaut 
ist zusammengestellt:

(fixer Bereich nicht änderbar, Bootloader und Interne Funktionen)
*[ Bootloader Bereich ]*****************
Einstiegspunkt Main
Interrupt Routinen
Bootloader Routinen
Überprüfungs Routinen
Interne Routinen
...
****************************************

++++++++++++++++++++++++++++++++++++++++

(fixe Einsprungadressen, weiterspringen durch User änderbar)
*[ Eigene Funktionsvektoren ]***********
User Main Einsprungspunkt
User Interrupt Einsprungspunkte
User Main deaktivieren
...
****************************************

(eigener Bereich komplett durch User änderbar)
*[ User Bereich ]***********************
****************************************

++++++++++++++++++++++++++++++++++++++++

der gesammte Bereich der zwischen +++ gekennzeichnet ist soll danach 
mittels eigenem Bootloader umgeändert werden können.

Der Bereich mit den Eigenen Funktionsvektoren ist so aufgebaut das jede 
Funktion die im Bootlaoer aufgerufen wird in einer 0x10 Sektion abgelegt 
wird in der im Prinzip mittels extern auf die user funktionen verlinkt 
wird, nach dem Beispiel:

im Bootloader Bereich:
1
extern void user_main_vector();
2
void main()
3
{
4
  user_main_vector();
5
}

im eigene Funktionsvektoren Bereich:
1
extern void user_main();
2
void user_main_vector();
3
void user_main_vector()
4
{
5
  user_main();
6
}

im User Bereich:
1
void user_main();
2
void user_main()
3
{
4
  *code from the user executed as Main*
5
}

Hoffe es wird so ca. klar was ich machen will,
Danke schonmal im Voraus,
mfg Benedikt

von odic (Gast)


Lesenswert?

Ok, mein Post war vielleicht etwas knapp gehalten...

Also: ein Bootloader hat ja die Eigenschaft daß er im µC verbleibt, 
wohingegen die Anwendung die du damit laden möchtest, ausgewechselt 
wird. Wenn es sich bei deiner Anwendung nicht lediglich um 
Parametrierung handelt, hast du zum jetzigen Zeitpunkt ein Problem: du 
weißt nicht wieviel RAM deine Anwendung künftig brauchen wird und wo 
Compiler bzw. Linker dann versuchen werden, diesen zu allozieren. Daher 
hast du jetzt zwei Möglichkeiten:

1.) Entweder du reservierst Anwendung und Bootloader zwei getrennte 
Adressbereiche im RAM und linkst die jeweiligen Module entsprechend. 
Dann kannst du beide Softwareteile in einem einzigen Compiler- bzw. 
Linkerlauf in einem einzigen Projekt übersetzen. Somit ist aber der 
Adressbereich des Bootloaders für die Applikation gestorben, obwohl der 
Bootloader im Normalfall überhaupt nicht läuft.

2.) Bei der zweiten Variante übersetzt du Bootloader und Anwendung in 
zwei getrennten Projekten. Somit haben beide Softwareteile den vollen 
RAM zur Verfügung und du hast auch sonst keine Abhängigkeiten zwischen 
Bootloader und Anwendung. Zwar mußt du gewisse Softwareschichten doppelt 
vorhalten (Startup Code, ggf. Kommunikationsfunktionen, 
Transportprotokolle oder Flashfunktionen) was aber häufig insbesondere 
bei kleinen Prozessoren besser zu verschmerzen sein dürfte als wenn 
einem 100 Byte im RAM fehlen.

Da es bei dir ja um mehr geht als einen reinen Bootloader (es scheint 
keinen Zeitpunkt zu geben, zu dem du voll von einer Welt in die andere 
springst) hast du dich für Variante eins entschieden. Richtig?

Jetzt hast du allerdings ein anderes Problem: Du kannst problemlos 
text-segment, Konstanten und Initialisierungswerte für vorinitialisierte 
Variable in zwei unterschiedliche Flashbereiche legen, je nachdem ob sie 
aus Bootloader oder Anwendung stammen. Was du allerdings so einfach 
nicht hinbekommst, ist die Aufteilung im RAM. Selbst wenn du im 
Linkerfile getrennte Speicherbereiche einrichtest hast du ein Problem: 
der Startup-Code in deinem Bootloader weiß nicht, wieviele Daten der 
Anwendung er wo im Flash holen bzw. wohin ins RAM kopieren soll. D.h. 
hierfür müßtest du dir wieder selbst eine Routine schreiben. Was du da 
möchtest ist zwar machbar, aber nicht ganz trivial. Mit dem reinen 
Anpassen des Linkerfiles ist es jedenfalls nicht getan.

Ohne deine Anwendung jetzt im Detail zu kennen würde ich mir eine andere 
Frage stellen: Ist die momentan gewählte Aufteilung wirklich notwendig 
bzw. sinnvoll? Würde nicht auch ein einfacher und kleiner Bootloader 
nach Schema zwei deine Anforderungen ebenfalls abdecken? (Ok, waren zwei 
Fragen. ;-) )

Ich hoffe das war jetzt verständlicher....

Grüße,
odic

von Benedikt (Gast)


Lesenswert?

Ich habe vor das Programm wie bereits beschrieben im ROM zu trennen im 
RAM sollen später rein aus Platztechnischen gründen Überlappende 
Bereiche existieren. Ich habe mich deswegen für eine Mischung aus 
Variante eins und zwei entschieden damit sollte es mir möglich sein 
Informationen von einem Teil in den anderen zu bringen und 
nichtverwendete Bereiche des einen Teils im anderen Teil zu verwenden. 
Ich habe mich deswegen für diese umständliche Variante entschieden da 
ich später noch einen dritten Bereich einführen will der eine weiter 
Quelle für den Botloader bildet aber dann nicht geflashed werden darf so 
zu sagen:
Bootloaderbereich, Interner Sicherheitsbereich, Userbereich
Nur muss ich wie gesagt einige Informationen von einem in den anderen 
Bereich bekommen und das InfoMEM habe ich vor bereits für andere Dinge 
zu verwenden also das fällt leider auch flach.

Wie du bereits bemerkt hast ist zur Zeit alles noch auf Variante eins 
eingestellt, weil ich noch kein Speicherproblem habe, und noch am Testen 
bin, aber wenn das Variablenproblem gelöst ist werde ich da auch noch 
zum umstellen beginnen,

Ich denke das es sich bei den Problem wirklich um ein Linker Problem 
handelt dass die Variablen die ich in meiner Bootloader sektion verwende 
durch das Linker File irgendwie in diese Sektion geschrieben werden da 
dies aber nicht möglich ist können diese nicht erhöht werden und sind 
solange sie in verwendung sind in den registern und werden auch brav 
erhöht und am schluss wird versucht den wert des Registers wieder 
zurückzuschreiben aber das geht nicht da der speicherbereich nicht 
beschrieben werden kann und beim nächsten Aufruf werden die 
unveränderten Werte wieder aus dem Speicher ins Register geholt und das 
Spiel beginnt von vorne.

hoffe du verstehst, trotz meiner wirren Gedankengängen was ich denke was 
das Problem ist

mfg Benedikt

von odic (Gast)


Lesenswert?

Irgendwie reden wir aneinander vorbei:

Zu deinem aktuellen Problem:
Hast du ein MAP-file zu deinem Code?

Zu meinen Anmerkungen:
Hast du verstanden was dein Problem sein wird, wenn du versuchst, 
verschiedene Anwendungen mit deinem Bootloader zu laden?

Grüße,
odic

von Benedikt (Gast)


Angehängte Dateien:

Lesenswert?

Ich glaub ich versteh schon wie du das meinst,´
ich hoffe das es so zu lösen geht wie ich es vorhabe,
indem ich entweder ein globales Variablenfile erstelle und das mit 
Unions und Structs so aufteile das die Bereiche überschnitten werden und 
in den einzelnen files nur mit Variablen arbeite die als extern 
deklariert werden
oder
,und diese Möglichkeit hoffe ich umsetzen zu können,
in den jeweiligen Files Structs erzeugen die mit Linkeranweisungen an 
den bestimmten Speicherpunkt gerückt werden, da ich nicht gleichzeitig 
auf alle Bereiche zugreifen muss, Variablen auf die ich zugreifen muss 
die im anderen Bereich liegen würde ich über getter und setter 
Funktionen die im Funktionsvektorenbereich verlinkt werden zugreifen 
somit muss der eine Teil nicht wissen wo Variablen des anderen Teils 
wirklich liegen.

Hoffe das du das so gemeint hast wenn nicht hab ich noch immer was 
falsch verstanden und werd ein noch größeres Problem bekommen wenn mir 
der Speicher ausgehen sollte :/

Anbei das Map file von meinem Projekt, hoffe du siehst dich da raus, die 
sektionen werden brav aufgeteilt nur wie das genau mit den Variablen 
passiert ist mir ein rätsel :)

mfg Benedikt

von odic (Gast)


Lesenswert?

Naja, spätestens wenn mein bss auch im Flash liegt würde mich das schon 
stutzig machen.... ;-)

Zur Erklärung:
Du legst alle Segmente deines bootloader.o in eine einzige Section. Das 
dürfte nicht ganz das sein was du möchtest. Du willst lediglich das 
.text-Sement in diese Section legen. Probiers mal mit einem Attribut für 
deine Funktion ala __attribute__((section (".section_bootloader")))
Das müßte funktionieren. Kannst auch mal googeln wie sich das auf 
Dateiebene bewerkstelligen läßt. Geht mit Sicherheit auch, bin ich aus 
dem Kopf raus aber momentan überfragt. Nach dem gleichen Prinzip kannst 
du auch mit .bss bzw. .data vorgehen, wobei ich dir jetzt schon sagen 
kann daß dein Standard Startup-Code damit ziemlich sicher überfordert 
sein dürfte.... aber das Thema hatten wir schon mehrfach....

Grüße,
odic


PS: Ein Tipp noch: überleg dir mal eine durchgängige Nomenklatur für 
dein LinkerCommand-file. Teilweise heißen die Sections wie die Segmente, 
die darin abgelegt werden, teilweise heißen sie wie die 
Speicherbereiche, in denen sie liegen.... etwas unübersichtlich.

von Benedikt (Gast)


Lesenswert?

:) (ich habe angenommen das genau sowas der Fehler ist),

Das ist genau das worauf ich hinaus wollte, das alles in bootloader.o in 
eine section geschrieben wird genau das möchte ich ja ändern so wie es 
im original Linker-File umgesetzt wird wo die Variablen ohne direktiven 
in eine andere sektion als der programmcode kommen und die 
debug-informationen nochmals anders behandelt werden.

gibt es da eine Möglichkeit ohne direktiven im Sourcecode die Bereiche 
die normalerweise in .text verschoen werden, sobald sie aus einer 
gewissen *.o datei kommen in einen eigenen bereich zu setzen und die 
anderen sektionen aber zu übernehmen?

mfg Benedikt

von odic (Gast)


Lesenswert?

Änder mal dein Linkerfile:
1
  .section_bootloader :
2
  {
3
    bootloader.o 
4
  }  > section_bootloader

in
1
 .section_bootloader :
2
  {
3
    bootloader.o(.text)
4
  }  > section_bootloader

von Benedikt (Gast)


Lesenswert?

hallo, und danke,
ich hab das Linker File umgestellt und es wird nurnoch die text section 
dort eingetrage, ich kann jetzt auch wieder die debuginformation beim 
compilen aktivieren ohne den speicher zu überfüllen.

Weiters habe ich alle globalen Variablen in ein gemeinsames File 
gestellt,
das keine eigene behandlung im Linker erfährt und somit in .bss und 
.data gelinkt wird.

Habe noch 2 Funktionen (initvars_bootloader und initvars_user) 
eingeführt mit denen beim wechsel zwischen den bereichen die variablen 
initiiert werden.

trotz allem kämpfe ich mit dem compiler der teilweise einfache 
statements oder vergleiche unterschiedlich verarbeitet . . . ist 
warscheinlich tageszeit abhängig . . . :)
denke mir aber das da ein kleines stack problem auftritt . . .

wie gesagt danke nochmal für deine Hilfe
mfg Benedikt

von odic (Gast)


Lesenswert?

Keine Ursache....

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.