Hallo,
könnte mir jemand das angehängte Linkerscript (Code im Flash) für den
STM32F07 so umbauen, dass die nachfolgenden Sections einzeln ansprechbar
sind durch Schlüsselworte in der __attribute_sections Anweisung. Ich
brauche die Sections einzeln. Alles ohne SSchlüsselwort soll im SRAM1
landen, Stack und Heap genauso.
CCM
SRAM1
SRAM2
SRAM3
BURAM
mit den Grenzen:
Backup RAM 0x4002.4FFF - 0x4002.4000
SRAM3 0x2002.FFFF- 0x2002.0000
SRAM2 0x2001.FFFF - 0x2001.C000
SRAM1 0x2001.BFFF - 0x2000.0000
CCM Core RAM 0x1000.0000 - 0x1000.FFFF
und das Ganze wieder hier posten? :-)
Gruss
C.J.
Steffen R. schrieb:> Du willst es doch sicherlich lernen.
Es soll nur funktionieren. Ich kann nicht jedes Fass aufmachen, was mir
auf dem Weg zum Ziel begegnet.
Ist einfach nur sinngemaess kopiert, ohne zu wissen was da genau
passiert
und warum >BKRAM AT> ROM da stehen muss. Jedenfalls legt er es nicht da
hin, sondern es erzeugt einen Fehler wegen *Überlappung mit dem ROM.
.bkram :
{
. = ALIGN(4);
_sbkram = .; /* create a global symbol at bkram start */
*(.bkram)
*(.bkram*)
. = ALIGN(4);
_ebkram = .; /* create a global symbol at bkram end */
} >BKRAM AT> ROM
PS: Ok, nimmt man das AT > ROM weg erzeugt er folgendes, was zu passen
scheint:
*(.bkram)
.bkram 0x40024000 0x4 obj\release\src\main.o
0x40024000 testvar
*(.bkram*)
und
*(.ccram)
.ccram 0x10000000 0x4 obj\release\src\main.o
0x10000000 ccramvar
*(.ccram*)
Da ich keinen ARM Assembler kann ist die Intialisierung vorbelegter
static Variablen leider noch ein Wunschtraum.
Vom Gefühl her müsste das hier aber nur kopiert werden meine ich:
1
/* Loop to copy data from read only memory to RAM. The ranges
2
* of copy from/to are specified by following symbols evaluated in
3
* linker script.
4
* __etext: End of code section, i.e., begin of data sections to copy from.
5
* __data_start__/__data_end__: RAM address range that data should be
6
* copied to. Both must be aligned to 4 bytes boundary. */
7
8
ldr r1, =__etext
9
ldr r2, =__data_start__
10
ldr r3, =__data_end__
11
/* Here are two copies of loop implemenations. First one favors code size
12
* and the second one favors performance. Default uses the first one.
Am Beispiel des STM32F407VG. Anpassung der Adressen/Größen ist ggf.
erforderlich:
Die Spezifikation von Speicherbereichen der Hardware geht so:
1
MEMORY
2
{
3
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
4
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
5
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
6
}
Dann muss per Output-Sections definiert werden, was in welche Region
soll. Der folgende Code nimmt alle "normalen" Variablen (ohne
section-Attribut) und packt sie in den angebenen Speicher, also hier
"RAM". Die im C(++)-Code angegebenen Initialwerte werden in den Speicher
"FLASH" geschrieben:
1
.ram_data :
2
{
3
. = ALIGN(4);
4
_sdata1 = .;
5
*(.data)
6
*(.data*)
7
8
. = ALIGN(4);
9
_edata1 = .;
10
} >RAM AT> FLASH
11
_sidata1 = LOADADDR(.ram_data);
In den Symbolen _sdata1, _edata1, und _sidata1 werden die Start-Adresse
dieser Daten im RAM, Endadresse sowie Anfangsadresse der Initial-Werte
im Flash abgelegt. Die Symbole werden im Folgenden der Einfachheit wegen
durchnummeriert, die genauen Namen sind aber prinzipiell egal.
Ähnliche Output Sections kann man dann z.B. für den CCM oder den
Backup-RAM anlegen:
1
.ccm :
2
{
3
. = ALIGN(4);
4
_sdata2 = .;
5
*(.ccm)
6
*(.ccm*)
7
. = ALIGN(4);
8
_edata2 = .;
9
} >CCMRAM AT> FLASH
10
_sidata2 = LOADADDR(.ccm);
Auch hier werden die Initialwerte im Flash abgelegt.
Da man für die mit 0 oder gar nicht initialisierten Variablen nicht jede
Menge 0en im Flash ablegen möchte, fügt man eine BSS-Section hinzu:
1
.bss :
2
{
3
. = ALIGN(4);
4
_sbss1 = .;
5
*(.bss)
6
*(.bss*)
7
*(COMMON)
8
. = ALIGN(4);
9
_ebss1 = .;
10
} >RAM
Standardmäßig schreibt der Compiler alle 0-Variablen in diese Section,
die hier im RAM landet. Über _sbss1 und _ebss1 geben wir Anfang & Ende
dieser Daten im RAM an. Man kann auch weitere bss-Sections definieren,
falls man 0-Variablen in verschiedenen Speicherbereichen hat (dann muss
man diese aber explizit per section-Attribut zuweisen).
Um eine spezifische Variable im Code in den CCM zu Packen, muss man sie
in die Section ".ccm" schieben:
1
intmyCCMVar__attribute__((section(".ccm")))=42;
Was jetzt noch fehlt, ist die Initialisierung der Werte über den
Startupcode. Zunächst schreiben wir eine einfache Assembler-Funktion die
Word-aligned Daten kopiert:
1
/*
2
r0 = Destination begin
3
r1 = Destination end
4
r2 = Source begin
5
6
Clobber: r3
7
*/
8
.section .text.Reset_InitCopy
9
.type Reset_InitCopy, %function
10
Reset_InitCopy:
11
cmp r0, r1
12
bhs CopyDataEnd
13
14
CopyDataLoop:
15
ldr r3, [r2], #4
16
str r3, [r0], #4
17
18
cmp r0, r1
19
blo CopyDataLoop
20
21
CopyDataEnd:
22
bx lr
Und eine Funktion die einen Bereich auf 0 setzt:
1
/*
2
r0 = Destination begin
3
r1 = Destination end
4
5
Clobber: r2
6
*/
7
.section .text.Reset_InitZeri
8
.type Reset_InitZero, %function
9
Reset_InitZero:
10
mov r2, #0
11
12
cmp r0, r1
13
bhs ZeroEnd
14
15
ZeroLoop:
16
str r2, [r0], #4
17
18
cmp r0, r1
19
blo ZeroLoop
20
21
ZeroEnd:
22
bx lr
Jetzt müssen diese Funktionen lediglich noch mit den richtigen
Parametern, die aus den Symbolen des Linkerscripts stammen, aufgerufen
werden. Der Startupcode sieht dann so aus:
1
.word _sidata1
2
.word _sdata1
3
.word _edata1
4
.word _sbss1
5
.word _ebss1
6
7
.word _sidata2
8
.word _sdata2
9
.word _edata2
10
11
.section .text.Reset_Handler
12
.weak Reset_Handler
13
.type Reset_Handler, %function
14
Reset_Handler:
15
16
ldr sp, =_estack
17
18
// Enable CCM & Backup SRAM
19
ldr r0, =0x40023830
20
mov r1, 0x00140000
21
str r1, [r0]
22
23
// Copy first data section from flash to RAM
24
25
ldr r0, =_sdata1 // Begin in RAM
26
ldr r1, =_edata1 // End in RAM
27
ldr r2, =_sidata1 // Start in Flash
28
bl Reset_InitCopy
29
30
// Copy second data section from flash to CCM
31
32
ldr r0, =_sdata2 // Begin in CCM
33
ldr r1, =_edata2 // End in CCM
34
ldr r2, =_sidata2 // Start in Flash
35
bl Reset_InitCopy
36
37
// Zero-Initialize first bss section
38
39
ldr r0, =_sbss1 // Begin BSS
40
ldr r1, =_ebss1 // End ESS
41
bl Reset_InitZero
42
43
// Globale Konstruktoren aufrufen
44
bl __libc_init_array
45
46
// main()-Funktion aufrufen
47
bl main
48
.size Reset_Handler, .-Reset_Handler
Wie zu sehen ist werden CCM und Backup-SRAM zuvor aktiviert indem im
RCC_AHB1ENR-Register die Bits CCMDATARAMEN und BKPSRAMEN gesetzt werden,
denn sonst funktionieren die Zugriffe nicht.
Gegebenenfalls macht es Sinn alle normalen Variablen in den CCM zu
legen, und nur explizit markierte im "RAM" (nämlich die, auf die per DMA
zugegriffen werden soll, denn das geht im CCM nicht). Gleichermaßen
könnte man den im CCM ablegen:
1
_estack = 0x10010000;
Und wo wir gerade dabei sind:
Möchtest du den Code per JTAG/SWD im RAM ausführen, musst du lediglich
das >FLASH durch >RAM austauschen. Die Variablen müssen dann aber nicht
mehr durch den Startupcode initialisiert werden, denn das macht der
Debugger von selbst. Daher lassen sich die entsprechenden Sections
vereinfachen:
1
.ram_data :
2
{
3
. = ALIGN(4);
4
*(.data)
5
*(.data*)
6
7
. = ALIGN(4);
8
} >RAM AT> FLASH
Das _sidata1 wird hier nicht mehr gebraucht. Die Initialisierung im
startupcode kann ersatzlos gestrichen werden. Lediglich das 0-Setzen vom
.bss würde ich vielleicht beibehalten. Damit Interrupts funktionieren,
kannst du noch das VTOR im Startupcode beschreiben:
1
ldr r0, =0xE000ED08
2
ldr r1, =g_pfnVectors
3
str r1, [r0]
Hierbei wird angenommen, dass g_pfnVectors im Startupcode den Anfang des
ISR-Vektors anzeigt. Dies funktioniert dann auch korrekt, wenn normal im
Flash ausgeführt wird. Somit muss nur das Linkerscript angepasst werden
um zwischen Ausführung im RAM / Flash umzuschalten. Das funktioniert
aber so leider nur bei Cortex-M3/4.
Hallo Niklas,
vielen Dank, gleich ausgedruckt !!!!!!! Probiere ich heute abend direkt
aus. Weisst Du auch wieso bei mir Zuweisungen nicht im BKRAM landen? Die
Variablen bleiben Null, wenn ich sie beschreibe. Bei allen anderen
Sections geht es aber.
Ist das die Begründung?
>Wie zu sehen ist werden CCM und Backup-SRAM zuvor aktiviert indem im>RCC_AHB1ENR-Register die Bits CCMDATARAMEN und BKPSRAMEN gesetzt >werden, denn
sonst funktionieren die Zugriffe nicht.
Kann ich sinngemaess
.ccm :
{
. = ALIGN(4);
_sdata2 = .;
*(.ccm)
*(.ccm*)
. = ALIGN(4);
_edata2 = .;
} >CCMRAM AT> FLASH
_sidata2 = LOADADDR(.ccm);
auch für BKRAM umschreiben, was müsste dann anstelle von .ccm da stehen?
.buram :
{
. = ALIGN(4);
_sdata3 = .;
*(.buram)
*(.buram*)
. = ALIGN(4);
_edata3 = .;
} >BKRAM AT> FLASH
_sidata3 = LOADADDR(.buram);
???
Gruss,
Christian
Niklas hat ja sehr ausführlich erläutert. Meine Antworten hier nur der
Vollständigkeit halber. Meine folgenden Angaben dienen nur dem
Verständnis und sind nicht angepasst an Niklas seine gute Beschreibung!
Nicht mischen!
Christian J. schrieb:> Steffen R. schrieb:>> Du willst es doch sicherlich lernen.>> Es soll nur funktionieren. Ich kann nicht jedes Fass aufmachen, was mir> auf dem Weg zum Ziel begegnet.
Ja, aber genau deswegen kannst Du auch dein Problem nicht lösen, warum
die Daten nicht dort landen. Ich hatte auch schon verschiedenste
Varianten und muss gestehen, dass ich das Linkerfile an die *.map File
Ausgabe angepasst habe.
Christian J. schrieb:> warum >BKRAM AT> ROM da stehen muss.
Das war von Dir nicht gefordert und in deinem Linkerfile auch nicht
enthalten. Warum machst Du es dann? Dies schreibst Du erst in deinen
späteren Posts. Du willst die Initialisierungsdaten dort ablegen. Nimmst
Du diese weg, fehlen die Initialisierungsdaten für das spätere
Umkopieren.
Diese Zeile entspricht der .data Section. D.h. du legst die Daten in den
Bereich ROM. Ausführen möchtest du sie aber später im Bereich BKRAM.
Mit solchen Konstrukten habe ich auch so meine Probleme. Ich nutzen dann
die Lösung für .data in abgewandelter Form:
1
__etext=.;
2
.data:AT(__etext)
3
{
4
}>RAM
Und die Sektion hinter den ganzen ROM Sections legen.
Christian J. schrieb:> Da ich keinen ARM Assembler kann ist die Intialisierung vorbelegter> static Variablen leider noch ein Wunschtraum.
Die static Variablen werden normalerweise in .data gelegt. Da klappt
auch die Initialisierung ohne zusätzlichen Code (ist im startup bereits
enthalten - wie du selbst zeigst).
Nebenbei: Coocox macht diesen Schritt in C. Es muss also nicht alles
Assembler sein.
Christian J. schrieb:> Map File:>> *(.bkram)> .bkram 0x40024000 0x4 obj\debug\src\graphik.o> 0x40024000 testvar
Das zeigt ja, dass testvar im bkram liegt. Die Lage ist nicht dein
Problem.
Hallo,
ich denke, dass ich mit diesen Infos was zuwege bekomme. Und die
Geschichte mit der Initialierung beschränke ich auf den "normalen" SRAM,
das ist ja auch schon fertig im mitgelieferten Startup Code. Eine
Initialisierung im Backup RAM kann ja nicht stattfinden, da dieses erst
freigeschaltet werden muss. Klar kann man das auch im Startup machen
aber ich habe es lieber "bewusst" in meiner Anwendung.
/* Enable Backup Register */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
Und den Startup in C habe ich mir von CooCox geklaut, ist mir
sympathischer als der in Asm und leichter anzupassen.
Christian J. schrieb:> Und den Startup in C habe ich mir von CooCox geklaut, ist mir> sympathischer als der in Asm und leichter anzupassen.
Nimm ihn nur zur Ansicht und nur für deine zusätzlichen Bereiche.
startup und linkerfile müssen zusammenpassen. Da du ein "normales" gcc
Linkerfile nutzt, solltest du für den Hochlauf auch das "normale" gcc
startup nutzen! Niklas hat Dir ja schon alles für genau deine Umgebung
aufgeschrieben.
Mische nicht die Lösungen von unterschiedlichen Umgebungen!
Ich wollte damit eigentlich nur ausdrücken, dass Du auch per C die
Initialisierungsdaten vom Flash in deine Backup Daten kopieren kannst.
Steffen R. schrieb:> Ich wollte damit eigentlich nur ausdrücken, dass Du auch per C die> Initialisierungsdaten vom Flash in deine Backup Daten kopieren kannst.
Ich überlege grad, nachdem ich diverse Lösungen im Netz studiert habe,
ob das Einmappen des Backup Ram überhaupt sinnig ist. Die meisten
schreiben 2-3 Routinen und übergeben ihre Daten als Struct zum
wegschreiben. Danach wird Schreibschutz wieder aktiviert. Aber Variablen
da rein zu mappen macht keiner.
Klar muss Startup zum .ld passen! Aber die habe ich schon angepasst, der
C Code läuft genauso wie der Asm Code auf dem gleichen Linker File.
Ich frickel grad etwas in der Firma (Freitag....) ohne eine
Entwicklungsumgebung zu haben, nur aus dem Kopf.
Mich irritiert grad etwas das __etext, welches im Linkerfile bei
__etext = .;
.data : AT (__etext)
{
_data_start_ = .;
*(vtable)
*(.data*)
[....]
auftaucht. Was muesste da beim CCM stehen?
Aus einem anderen Projekt habe ich funktionierenden CCRAM Linker Script
Code eben geladen. (schön, wenn der eigene Rechner daheim per ssh
erreichbar ist :-)
1
// CCM-RAM section
2
3
_siccram = LOADADDR(.ccram);
4
.ccram :
5
{
6
. = ALIGN(4);
7
_sccram = .; /* create a global symbol at ccmram start */
8
*(.ccram)
9
*(.ccram*)
10
11
. = ALIGN(4);
12
_eccram = .; /* create a global symbol at ccmram end */
13
} >ccram AT> flash
Der dazu passende Startup Code müsste dann ja wie folgt lauten:
// CCM initialisieren
ldr r1, =_siccram // Quelle der Initialdaten im Flash
ldr r2, =_sccram // Ziel Startadresse im CCRAM
ldr r3, =_eccram // Ziel Endadresse im CCRAM
.flash_to_ccm_loop: // ... und kopieren!
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .flash_to_ccm_loop
Ist
ldr r1, =_siccram
richtig als Quelle der Initialdaten?
Christian J. schrieb:> Weisst Du auch wieso bei mir Zuweisungen nicht im BKRAM landen? Die> Variablen bleiben Null, wenn ich sie beschreibe. Bei allen anderen> Sections geht es aber.
Vermutlich weil du den BK-RAM nicht aktiviert hast im RCC_AHB1ENR
Register?
Christian J. schrieb:> auch für BKRAM umschreiben, was müsste dann anstelle von .ccm da stehen?
Das erste .ccm hat praktisch keine Bedeutung, da kannst du auch
.hanswurst hinschreiben. Es muss nur gleich zu dem sein, was in LOADADDR
steht. Schlau ist natürlich es so zu nennen, dass du es wieder erkennst,
also z.B. ".bkram". Das zweite .ccm in meinem Code entspricht der
Input-Section, also dem was du im Section-Attribut im C(++)-Code
schreibst.
Dein Beispiel mit ".buram." sollte passen. Im C(++)-Code dann
section(".buram") verwenden.
Steffen R. schrieb:> Ich nutzen dann> die Lösung für .data in abgewandelter Form:__etext = .;> .data : AT (__etext)> {> } > RAM> Und die Sektion hinter den ganzen ROM Sections legen.
Ist mehr oder weniger gleich zur Variante mit LOADADDR, aber du solltest
unbedingt ein .=ALIGN(4) vor dieses Konstrukt packen...
Steffen R. schrieb:> Da du ein "normales" gcc> Linkerfile nutzt, solltest du für den Hochlauf auch das "normale" gcc> startup nutzen!
Nur woher gibts ein "normales" gcc File für STM32?? Die klaut man doch
bei ST oder schreibst sie sich selber...
Steffen R. schrieb:> Mische nicht die Lösungen von unterschiedlichen Umgebungen!
!!!
Christian J. schrieb:> auftaucht. Was muesste da beim CCM stehen?
Nimm doch meine Lösung aus meinem ersten Post...
Christian J. schrieb:> Aus einem anderen Projekt habe ich funktionierenden CCRAM Linker Script> Code eben geladen.
Meins funktioniert auch...
Christian J. schrieb:> Ich überlege grad, nachdem ich diverse Lösungen im Netz studiert habe,> ob das Einmappen des Backup Ram überhaupt sinnig ist.
Klar, so kannst du bequem den Linker prüfen lassen ob die Daten
überhaupt reinpassen, und du brauchst keine Adressfrickelei im
C(++)-Code. So kannst du auch einfach mehrere BKRAM-Variablen im ganzen
Projekt in verschiedenen .c Dateien unterbringen, indem du denen das
section-Attribut verpasst. Es gibt keinen Zwang die alle in einen struct
zu packen:
> Die meisten> schreiben 2-3 Routinen und übergeben ihre Daten als Struct zum> wegschreiben. Danach wird Schreibschutz wieder aktiviert. Aber Variablen> da rein zu mappen macht keiner.
Die können wahrscheinlich einfach nur keine Linkerscripte schreiben :]
Supi!
Warte scon sehnsüchtig auf Dienstschluss um das alles auszuprobieren.
Ist mein letzter Code denn so sinnig? Ich habe mir meine Files
geschnappt. Zu Hause werde ich dann noch alles schön kommentieren (in
Deutsch!) und dann sauber ablegen als Muster.
>>Die können wahrscheinlich einfach nur keine Linkerscripte schreiben :]
Das dürften viele nicht können, da das nunmal echtes Kauderwelsch ist.
Man nimmt das was passt, frickelt sich was dazu, bzw schreibt es
irgendwo ab... so ist die Welt :-)
Christian J. schrieb:> Ist mein letzter Code denn so sinnig? Ich habe mir meine Files> geschnappt.
Ich vermute meiner ist minimal schneller. Wenn viele Daten kopiert
werden und die Startzeit des Controllers kritisch ist, kann das evtl.
einen Unterschied machen.
Christian J. schrieb:> Das dürften viele nicht können, da das nunmal echtes Kauderwelsch ist.
Das ist C aber auch. Aber es ist ja dokumentiert:
https://sourceware.org/binutils/docs/ld/index.html
Christian J. schrieb:> Mich irritiert grad etwas das __etext, welches im Linkerfile bei
Niklas verwendet hierfür _sidata2. Da du aber am Anfang auch das Problem
mit dem überlappenden Flash Bereichen hattest wäre hier meine Veriante
die Alternative.
1
__etext=.;
2
3
.data:AT(__etext)
"berechnet" die aktuelle Adresse, bei der der Linker steht und beginnt
dort die nächste Adresse (alles im Flash gerechnet).
Bei Niklas klappt dies automatisch korrekt.
Niklas holt sich die Anfangsadresse hinterher.
1
_sidata2=LOADADDR(.ccm);
Warum die Automatik manchmal nicht funktioniert, weiß ich nicht. Dies
äußert sich dann dadurch, dass für mehrere Sektionen am Anfang der
Memory Bereiche angefangen wird.
Niklas G. schrieb:> Ist mehr oder weniger gleich zur Variante mit LOADADDR, aber du solltest> unbedingt ein .=ALIGN(4) vor dieses Konstrukt packen...
Danke. Hatte bisher noch keine "krummen" Adressen bekommen. Aber sicher
ist sicher.
Niklas G. schrieb:> Steffen R. schrieb:>> Da du ein "normales" gcc>> Linkerfile nutzt, solltest du für den Hochlauf auch das "normale" gcc>> startup nutzen!> Nur woher gibts ein "normales" gcc File für STM32?? Die klaut man doch> bei ST oder schreibst sie sich selber...
Wußte auch nicht, wie ich es anders schreiben sollte. Ich denke 90% der
gcc Anwender nutzen linker und startup files, ähnlich wie sie auch ST
mit dem CMSIS liefert. Ich wollte darauf hinaus, dass Coocox hier sehr
weit weg davon ist mit Ihrem eigenen Definitionen. Da sie aber genauso
den Standard gcc nutzen, konnte ich dies sprachlich nicht richtig
auflösen.
Christian J. schrieb:>>>Die können wahrscheinlich einfach nur keine Linkerscripte schreiben :]> Das dürften viele nicht können, da das nunmal echtes Kauderwelsch ist.> Man nimmt das was passt, frickelt sich was dazu, bzw schreibt es> irgendwo ab... so ist die Welt :-)
Genau das Ansehen solcher Frickelei hat mich am Anfang total verwirrt.
Genau dort kommst du an das Grübeln, warum etwas gemacht wird, obwohl es
nach Handbuch unsinnig ist.
Niklas, ich hänge mich mal in einer speziellen Frage hier rein.
z.B. hat ein int ein Alignment von 4.
Wird die nächst passende Adresse mit der RUN Adresse oder als Offset zum
Sectionsanfang gerechnet?
Ich beziehe mich hier auf deinen Hinweis, die Section immer aligned(4)
beginnen zu lassen.
1
.ccm:
2
{
3
.=ALIGN(4);
4
_sdata2=.;
Das braucht das startup, weil die Kopierroutine 32bit-weise kopiert,
richtig?
Christian, für dich die Anmerkung von Niklas eigebaut:
Frage völlig am Thema vorbei:
Ich finde die Doku der StdPeriph Libs für den 32F4xxx ums Verrecken
nicht im Netz bei ST. Wo haben die die als pdf versteckt ???
Klappt alles nicht :-( Bin zu blöd dafür.
>RAM AT> FLASH
führt zu einem Crash des Programs in den Exception Handler. Nehme ich es
weg sind die RAM Variablen nicht initialiert, nicht mal die normalen.
Mir ist das ehrlich gesagt zu hoch.
../arm-none-eabi/bin/ld.exe: section .ccram loaded at
[08009908,0800990b] overlaps section .data loaded at [08009908,08009a53]
:-(
PS:
Ok, auf jeden Fal kann ich erstmal Werte manuell auf die Variablen
zuweisen, die in den verschiedenen Regionen liegen und der Debugger
zeigt mir auch, dass sie die richtigen Adressen haben. Backup RAM muss
manuell eingeschaltet werden, dann sind da auch die Zahlen drin, die ich
reinschreiben. Initialierung ist noch nicht fertig, eines nach dem
anderen.
Mein Linkerscript sieht erstmal so aus und wird auch nicht angemeckert,
alles liegt dann da wo es soll, nur ramvar ist richtig initialisiert,
der Rest muss noch...
Christian J. schrieb:> Mir ist das ehrlich gesagt zu hoch.>> ../arm-none-eabi/bin/ld.exe: section .ccram loaded at> [08009908,0800990b] overlaps section .data loaded at [08009908,08009a53]
Genau wegen diesem Problems gehe ich immer den Weg, den du in deinem
Skript für .data gewählt hast. Das Warum kann ich aber auch nicht
beantworten.
Christian J. schrieb:> PS: 2 Tassen Kaffee und ne Ziggi später: Läuft :-)
Hast Du auch dieses Problem gelöst?
_sccram = .; /* create a global symbol at ccmram start */
7
*(.ccram)
8
*(.ccram*)
9
10
. = ALIGN(4);
11
_eccram = .; /* create a global symbol at ccmram end */
12
} >CCRAM
mit dem
1
/* Kopiere CCRAM Inhalte vom Flash ins CCRAM */
2
3
ldr r1, =_siccram
4
ldr r2, =_sccram
5
ldr r3, =_eccram
6
7
.flash_to_ccram_loop:
8
cmp r2, r3
9
ittt lt
10
ldrlt r0, [r1], #4
11
strlt r0, [r2], #4
12
blt .flash_to_ccram_loop
sorgt genau dafür, dass
a) CCRAM wird auch wirklich verwendet
b) Initialisierte globale Variablen stehen dann auch initialisiert drin.
c) Lokale, dynamische Variablen lasse sich nicht auf CCRAM zuweisen, das
meckert der Compiler an. Ich vermute, dass die auf dem Stack liegen.
Beim Flashen mit dem Stlink Tool wird ein 2.ter Fortschritts-Streifen
eingeblendet, was der bedeutet weiss ich aber nicht, das geht zu schnell
wieder zu das Fenster.
Die Initialisierung des Backup Ram macht keinen Sinn.
Christian J. schrieb:> Steffen R. schrieb:>> Hast Du auch dieses Problem gelöst?>> Welches?
Das overlap Problem, auf welches ich darüber eingegangen bin.
Christian J. schrieb:> Die Initialisierung des Backup Ram macht keinen Sinn.
Oder so.
Steffen R. schrieb:> Das overlap Problem, auf welches ich darüber eingegangen bin.
Nein, ich habe durch die Verwendung von LOADADDR und Vermeidung von RAM
> AT FLASH dieses Problem umgangen. Ich vermute, dass die beiden
irgendwie das Gleiche ausdrücken sollen.
Ich gestehe, dass ich da auch mehr probiert und gefrickelt habe bis
irgendwann das rauskam was ich haben wollte.
Obwohl oben steht:
ccm :
{
. = ALIGN(4);
_sdata2 = .;
*(.ccm)
*(.ccm*)
. = ALIGN(4);
_edata2 = .;
} >CCMRAM AT> FLASH
_sidata2 = LOADADDR(.ccm);
also beides. Das läuft aber nicht durch, dann wird gemeckert, dass da
was doppelt verwendet wird.
Und das hat ja auch was zu bedeuten:
.data : AT (__etext)
{
dieses AT dahinter.
Was mir fehlt wäre so ein Buch "Linkerscript für Dummies", von Adam und
Eva angefangen.
Christian J. schrieb:> Was mir fehlt wäre so ein Buch "Linkerscript für Dummies", von Adam und> Eva angefangen.
Mir hat das hier geholfen:
http://www.delorie.com/gnu/docs/binutils/ld_6.html
Damit habe ich die Linkerskripte des STM32F4 verstanden und konnte sie
für meine Zwecke anpassen.
Mir hat das hier geholfen:
http://www.delorie.com/gnu/docs/binutils/ld_6.html
Damit habe ich die Linkerskripte des STM32F4 verstanden und konnte sie
für meine Zwecke anpassen.
Mich nervt, dass es für ARM und GCC nur englische Literatur gibt. Klar
kann ich Englisch lesen aber brauche die 1,5-fache Zeit dafür als wenn
ich ein deutsches Buch vor mir hätte. Selbst bei Amazon gibt es nicht
ein einziges Buch in deutsch über diese Themen.
Hallo,
ich wollte nicht extra einen neuen Thread dafür aufmachen.
Problem: Speicherinitialisierung im Code (nicht im Startup!)
Speicherbereich BackupRam: 0x40024000 - .... 4kb
definiert als
MEMORY
{
ROM (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
CCRAM (rwx) : ORIGIN = 0x10000000, LENGTH = 64K
BKRAM (rw) : ORIGIN = 0x40024000, LENGTH = 4K
}
und
/* Backup RAM section */
.bkram (NOLOAD):
{
. = ALIGN(4);
*(.bkram)
*(.bkram*)
. = ALIGN(4);
} >BKRAM
für globale Variablenzweisungen bekannt unter
#define BKRAM __attribute__((section(".bkram")))
Frage:
Wie kann ich durch einen einfachen Befehl oder Schleife
zb mit memset die gesamten 4k ausnullen?