Autor: Peter II (Gast)
>verwende sie doch einfach, dann wird sie nicht wegoptimiert.
Das habe ich schon probiert.
Wenn ich in der "Main" folgendes hinzu füge:
1
uint16_tx=boot_reset;
wird sie nicht weg optimiert. Es ist allerdings nicht so richtig schön,
weil ich die Variable gar nicht brauche sondern den Boot-Vektor, den sie
an der Adresse 0 erzeugt ( memory section .bootreset=0 ).
>Autor: Benji (Gast)>volatile davor packen.
Das habe ich schon probiert. Bringt nichts, wird trotzdem weg optimiert.
>2. im Linkerscript schauen, was mit der section bootreset passiert
Das linker command, welches Atmel Studio 7 erzeugt, sieht so aus:
-Wl,-Map="$(OutputFileName).map" -Wl,--start-group -Wl,-lm
-Wl,--end-group -Wl,--gc-sections -Wl,-section-start=.text=0x1800
-Wl,-section-start=.bootreset=0 -mmcu=attiny85 -B "D:\Program Files
(x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.1.102\gcc\dev\attiny85"
.bootreset ist vorhanden, wie es aussieht. Da scheint also kein Fehler
zu sein.
ChrisMicro schrieb:>>Autor: Benji (Gast)>>volatile davor packen.> Das habe ich schon probiert. Bringt nichts, wird trotzdem weg optimiert.
volatile sorgt dafür, dass Zugriffe auf die Variable nicht
wegoptimiert, sondern so durchgeführt werden, wie sie im Code stehen. Es
gibt aber keine Zugriffe. Deshalb bringt volatile hier nichts.
ChrisMicro schrieb:> wird sie nicht weg optimiert. Es ist allerdings nicht so richtig schön,> weil ich die Variable gar nicht brauche sondern den Boot-Vektor, den sie> an der Adresse 0 erzeugt ( memory section .bootreset=0 ).
ich versteht immer noch nicht was du damit machst. Irgendwie musst du
sie doch mal verwenden, sonst macht das doch alles keinen sinn.
>ich versteht immer noch nicht was du damit machst. Irgendwie musst du>sie doch mal verwenden, sonst macht das doch alles keinen sinn.
Sie wird als Reset Vector für einen Bootloader verwendet, genau wie hier
im Abschnitt Speicherlayout beschrieben:
http://www.mikrocontroller.net/articles/Konzept_f%C3%BCr_einen_ATtiny-Bootloader_in_C
Man greift also nicht auf die Variable zu, sondern nur wenn der
Prozessor einen Reset bekommt wird der Variablenwert als Code
interpretiert ( RJMP ) und als Sprung zum eigentlichen Programm benutzt.
Scheinbar funktioniert es aber nicht mehr so wie in dem Artikel
beschrieben. Vielleicht hat sich in den neueren GCC Versionen etwas
verändert, so dass das Prinzip nicht mehr funktioniert.
ChrisMicro schrieb:> uint16_t boot_reset __attribute__((section(".bootreset")))= 0xCBFF;
Wie soll denn der Wert 0xCBFF überhaupt in deine Variable reinkommen?
Der normale .data-Loader im Startup-Code hat keine Ahnung, dass er
das mit tun sollte.
Hallo Jörg,
das ganze Prinzip habe ich aus dem Bootloader Artikel übernommen und
habe gehofft, dass es recht unproblematisch funktioniert:
http://www.mikrocontroller.net/articles/Konzept_f%C3%BCr_einen_ATtiny-Bootloader_in_C
In Atmel-Studio 7 habe ich folgendes gemacht
und in Atmeo Studio 7 => Toolchain/AVR_GNU_Linker/Memory
Settings/Flash-Segment
.bootreset=0
Ich nehme an, dass die von Atmel-Studio erstellten Linker Parameter hier
Beitrag "Re: AVR-GCC: Variable wir leider weg optimiert"
-Wl,-section-start=.bootreset=0
die Variable ins richtige Segment schieben.
Wenn ich in der Main den Code für den Variablenzugriff einfüge, steht
auch im Flash an der richtigen Stelle der gewünschte Wert.
Insofern löst der Variablenzugriff das Problem, aber es ist meiner
Ansicht nach ein wenig Murks.
Besser wäre, wenn man im C-Code gleich den RJMP an die richtige Stelle
assemblieren könnte, anstatt eine Variable zu missbrauchen.
ChrisMicro schrieb:> das ganze Prinzip habe ich aus dem Bootloader Artikel übernommen und> habe gehofft, dass es recht unproblematisch funktioniert
Bei denen sind es aber Flash-Daten. Ich habe den Eindruck, dass
du versuchst, das im RAM anzulegen (also wirklich als Variable).
Da musst du dir schon die Frage stellen, auf welche Weise die Werte
dann auch ins RAM gelangen.
ChrisMicro schrieb:>>ich versteht immer noch nicht was du damit machst. Irgendwie musst du>>sie doch mal verwenden, sonst macht das doch alles keinen sinn.>> Sie wird als Reset Vector für einen Bootloader verwendet, genau wie hier> im Abschnitt Speicherlayout beschrieben:
Das erscheint mir aber extrem hackish. Ich könnte mir vorstellen, dass
dieser Trick mit irgendeiner alten Toolchain-Version funktioniert hat,
aber nicht mehr mit der aktuellen.
Warum nutzt du dafür nicht den Inline-Assembler? Dann musst du auch
nicht den Hexcode für den RJMP-Befehl explizit in dein Programm
schreiben.
ChrisMicro schrieb:> Wie kann ich das ändern?
Ich habe gerade ein Ähnliches Problem bei einem nrf52 gelöst, in dem ich
den Wert einfach im linker script beschrieben habe:
>Bei denen sind es aber Flash-Daten. Ich habe den Eindruck, dass>du versuchst, das im RAM anzulegen (also wirklich als Variable).
Was mache ich im Vergleich zu denen falsch? Ich dachte, ich habe die
"section" für die Variable ins Flash gelegt.
Debug mit Debug-Wire zeigt, dass der Wert im Flash steht ( siehe Bild ).
>Das erscheint mir aber extrem hackish.
Das finde ich auch, es ist aber der Weg wie im Artikel beschrieben. Der
Artikel selbst ist sehr gut gemacht, finde ich. ( Ein Lob an denjenigen,
der sich die Arbeit gemacht hat )
>Warum nutzt du dafür nicht den Inline-Assembler?
Ich weiß leider nicht, wie es geht.
ChrisMicro schrieb:> Debug mit Debug-Wire zeigt, dass der Wert im Flash steht ( siehe Bild ).
Dann verstehe ich deine Aussage („wird wegoptimiert“) nicht. Wenn
der Wert im Flash liegt, dann ist er doch nicht „wegoptimiert“.
Aber ehrlich gesagt, ist mir auch das gesamte Anliegen nicht so recht
klar.
>Ich habe gerade ein Ähnliches Problem bei einem nrf52 gelöst, in dem ich>den Wert einfach im linker script beschrieben habe:
Danke für den Hinweis.
Es scheint also kein so einfaches Problem zu sein.
Tendenziell würde ich es lieber im Code haben und das Linker-Script eher
weniger verändern.
>Dann verstehe ich deine Aussage („wird wegoptimiert“) nicht. Wenn>der Wert im Flash liegt, dann ist er doch nicht „wegoptimiert“.
Er wird nur dann nicht "wegoptimiert" wenn in der "main" dieser nicht
benutzte Hilfszugriff steht:
ChrisMicro schrieb:> Er wird nur dann nicht "wegoptimiert" wenn in der "main" dieser nicht> benutzte Hilfszugriff steht:
Dann wurde dir aber schon genannt:
1
__attribute__((used))
Sag mal, benutzt du beim Linken sowas wie -Wl,--gc-sections? Dann
müsstest du dich nicht weiter wundern …
ChrisMicro schrieb:> Es scheint also kein so einfaches Problem zu sein.> Tendenziell würde ich es lieber im Code haben und das Linker-Script eher> weniger verändern.
Naja, jetzt hast Du die Definition dieser Konstanten im Flash im Code
und in den Linker-Parametern stehen. Wenn Du es im Linker-Script
definierst. Aber wir Jörg auch schon festgestellt hat: Die Konstante
wird nicht weg optimiert. Wenn irgend etwas nicht funktioniert, dann
scheint es ein anderes Problem zu sein.
>Dann wurde dir aber schon genannt:>__attribute__((used))
Ja, das habe ich hier schon so probiert:
Beitrag "Re: AVR-GCC: Variable wir leider weg optimiert"
Es hat aber nicht funktioniert. Ist es syntaktisch richtig? Es wurde
kein Warning geworfen.
ChrisMicro schrieb:>>Dann wurde dir aber schon genannt:>>__attribute__((used))> Ja, das habe ich hier schon so probiert:> Beitrag "Re: AVR-GCC: Variable wir leider weg optimiert"> Es hat aber nicht funktioniert. Ist es syntaktisch richtig? Es wurde> kein Warning geworfen.
Guck doch einfach mal ins Hex-File. Wenn es da drinnen steht, dann hat
"es" funktioniert.
>Guck doch einfach mal ins Hex-File. Wenn es da drinnen steht, dann hat>"es" funktioniert.
Hat es nicht.
Soweit ich es verstehe, ist kein Wert an der Stelle 0 sichtbar:
:101800000EC015C014C013C012C011C010C00FC04C
:101810000EC00DC00CC00BC00AC009C008C0112406
:101820001FBECFE5D2E0DEBFCDBF02D006C0E8CFFD
:0E183000CF93DF93CDB7DEB7FFCFF894FFCF95
:0400000300001800E1
:00000001FF
Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
>Sag mal, benutzt du beim Linken sowas wie -Wl,--gc-sections? Dann>müsstest du dich nicht weiter wundern …
Tja Jörg, das ist es. Danke. Ohne -Wl, --gc-sections wird es nicht mehr
weg optimiert.
Allerdings würde ich nicht sagen, dass ich "--gc-sections" benutzt habe,
sondern Atmel-Studio7.
Dort ist nämlich per default ein kleines, leicht zu übersehendes,
unschuldig aussehendes Häckchen bei
..Toolchain/AVR_GNU_C Compiler/Optimization/Garbage collect unuses
sections
macht man es weg, bleibt der Code.
Rein vom Verfahren gefällt mir das Ganze nicht so recht, weil eigentlich
eine Variable als Code missbraucht wird.
Kann mir jemand sagen, wie man den Inline-Assembler dazu bringt, Code in
eine bestimmte Section zu schreiben und danach den eigentlichen C-Code
an eine andere Stelle?
ChrisMicro schrieb:> Ohne -Wl, --gc-sections wird es nicht mehr weg optimiert.
Dann macht der Linker genau das, was du ihm gesagt hast.
Mich wundert allerdings, warum das "used"-Attribut nicht dagegen
helfen sollte.
> Allerdings würde ich nicht sagen, dass ich "--gc-sections" benutzt habe,> sondern Atmel-Studio7.
Kann gut sein. Diese Optionen (zusammen mit -ffunction-sections)
sind der Faulheit der Leute geschuldet, sauberen Code zu schreiben,
bei dem man nur solche Dinge auch tatsächlich in den Quellen hat,
die man am Ende benötigt.
ChrisMicro schrieb:> Aber leider wird die Variable "boot_reset" einfach weg optimiert.>> Wie kann ich das ändern?
Du brauchst dann ein passendes Linker Skript mit einem passenden KEEP()
Statement.
Deig mal dein aktuelles Linker Skript.
ChrisMicro schrieb:>>Warum nutzt du dafür nicht den Inline-Assembler?> Ich weiß leider nicht, wie es geht.
Ich habe den von dir velinkten Artikel nicht komplett gelesen, deswegen
weiß ich nicht im Detail, worauf es bei dem Sprung genau ankommt. Es
scheint aber so, dass er
1. an der Adresse 0 liegen muss (Reset-Vektor) und
2. an den Anfang der (in einen höheren Adressbereich verschobenen)
Vektortabelle springen soll, wo ein von der Toolchain generierter
Sprung zum eigentlich Programmstart steht.
Beides erreichts du mit folgender Funktion:
Mit -Wl,--gc-sections hast du auch hier das Problem, dass der Linker die
Section .bootreset wegoptimiert. Das used-Attribut wirkt sich nur auf
den Compiler, nicht aber auf den Linker aus, weswegen es hier nicht den
gewünschten Effekt hat. Du musst entweder die Option -Wl,--gc-sections
weglassen, oder ins Linkerscript eine entsprechende KEEP-Anweisung
einfügen.
Jörg W. schrieb:> ChrisMicro schrieb:>> Ohne -Wl, --gc-sections wird es nicht mehr weg optimiert.>> Dann macht der Linker genau das, was du ihm gesagt hast.>> Mich wundert allerdings, warum das "used"-Attribut nicht dagegen> helfen sollte.
Wirkt das used-Attribut nicht nur auf den Compiler und dessen
Optimierer?
Der Linker weiß doch davon garnichts. Oder?
Steffen R. schrieb:> Wirkt das used-Attribut nicht nur auf den Compiler und dessen> Optimierer?
Stimmt. Ich nahm an, dass er das auch dem Linker weiterreichen würde,
aber das ist nicht der Fall.
Damit ist klar, warum der Linker das bei --gc-sections rauskickt.
Dein Ansatz, auf diese Weise eine Referenz auf den Speicher zu bekommen
ist nur mit Vorsicht zu genießen.
Die spätere, tatsächliche Adresse kann sich ändern, wenn der Linker ein
paar Variablen (aus Bibliotheken) davor packt.
Jörg W. schrieb:> ChrisMicro schrieb:>> Ohne -Wl, --gc-sections wird es nicht mehr weg optimiert.>> Dann macht der Linker genau das, was du ihm gesagt hast.>> Mich wundert allerdings, warum das "used"-Attribut nicht dagegen> helfen sollte.
Weil "used" nur auf den Compiler wirkt: Das Objekt wird nicht verwendet,
wegen "used" aber dennoch angelegt — eine used-Direktive für gas gibt es
nicht. Da es nicht referenziert wird und nicht KEEP ist, wird es vom
Linker entsorgt.
Referenzieren bringt auch nur dann was, wenn es wirklich eine "Senke"
für die Verwendung gibt, die der Compiler nicht wegoptimieren kann.
Eine zu simple Verwendung kann durchaus ebenfalls vom Compiler als
solche erkannt und somit entsorgt werden.
Autor: Yalu X. (yalu) (Moderator)
>Beides erreichts du mit folgender Funktion: ..
Hallo Yalu, danke dafür. Das scheint mir sehr geeignet. Ich werde es mal
auf die Art probieren.
Autor: Amateur (Gast)
>Dein Ansatz, auf diese Weise eine Referenz auf den Speicher zu bekommen>ist nur mit Vorsicht zu genießen.
Der Bootloader sitzt mit
.text=0x1800
an einer fixen Adresse. Das einzige worauf man achten muss, ist dass der
Wert im Code und die Adresse der "section" Definition für den Linker
konsistent sind.
Die Zieladresse für den Programmstart muss sich der Bootloader irgendwo
merken, da immer zuerst der Bootloader angesprungen wird.
deklarier es als const (oder diese progmem Sache bei avr), sonst landet
es nicht im Flash sondern irgendwo im RAM.
Hier ist ein funktionierender Beispielschnipsel (aus nem ARM Startup
code), es gibt keinen Grund warum das nicht auch bei AVR funktionieren
sollte wenn man den Compiler davon überzeugen kann daß er die Konstante
in den Flash legen soll:
Bernd K. schrieb:> deklarier es als const (oder diese progmem Sache bei avr), sonst landet> es nicht im Flash sondern irgendwo im RAM.
"const" ist dafür völlig belanglos. Bei einem AVR landen auch
"const" deklarierte Variable keineswegs automatisch im Flash.
Aber das mit der Flash-Section hat er ja an sich hinbekommen, das
unterscheidet sich bei ihm nicht großartig von deinem Vorschlag. Der
Dreh- und Angelpunkt war halt die linker section garbage collection.