Forum: Mikrocontroller und Digitale Elektronik Arduino Mega2560 mit externem RAM: linker flag für .data section geht nicht


von Noob A. (strippenzieher)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe einem Arduino Mega2560 32k externes RAM gegönnt und versuche 
das jetzt möglichst flexibel einzurichten.
Die Methode die auf 
https://hackaday.io/project/21561-arduino-mega-2560-32kb-ram-shield 
erwähnt wird, lässt ja nur zu dynamische Variablen in den XRAM zu 
schieben.

Laut https://www.nongnu.org/avr-libc/user-manual/malloc.html kann man 
auch .data und .bss in den externen Speicher schieben, aber das 
funktioniert nicht :/

Ich habe mir in der Arduino-Umgebung ein eigenes board erstellt.
Dazu reicht es im sketch-folder einen Ordner mit einer boards.txt 
anzulegen.
Um die Linker flags übergeben zu können braucht es dann noch eine 
platforms.txt mit dem Eintrag
1
compiler.ldflags=-Wl,--section-start,.data=0x802200,--defsym=__heap_end=0x80A1FF

leider klappt das nicht - ich habe es nicht weiter untersucht, aber an 
der seriellen kommt keine Ausgabe

Wenn ich jedoch nur den heap in den externen RAM verweise
1
compiler.ldflags=-Wl,--defsym=__heap_start=0x802200,--defsym=__heap_end=0x80A1FF
dann funktionniert das wunderbar.
Allerdings habe ich dann wieder die Einschränkung dass nur dynamisch 
erstellte Variablen dahin verwiesen werden.

Leider ist mein Verständnis von Compiler und Linker recht gering und ich 
weiss nicht wie ich hier weitersuchen soll, bzw. was da überhaupt 
passiert.

Bin für jeden Hinweis dankbar!

von fair zweifel tear (Gast)


Lesenswert?

Bob A. schrieb:
> Die Methode die auf
> https://hackaday.io/project/21561-arduino-mega-2560-32kb-ram-shield
> erwähnt wird

Nachdem ich eine zeitlang bei den hackadays gesucht habe und
dort nichts gefunden habe erlaube ich mir dir die Frage zu stellen
ob du jemals den Begriff "Abblock-Kondensator" gehört hast.

Klar, ich weiss, das ist reine Esoterik, Abblock-Kondensatoren
sind rein für die Ästhetik und zeugen davon dass der geneigte
Arduino-Besitzer genug Geld hat um seine Werke zu verschönern.
Ansonsten machen die Kondensatoren ja keinen Sinn, ausser
Beschäftigungstherapie.

Aber ich frag halt mal ..... ich weiss, das macht dein Speicher-
Problem nicht besser ....

von Noob A. (strippenzieher)


Lesenswert?

Ich schrub doch: "bin für jeden Hinweis dankbar" :)

also Danke dafür!
Habe das im Eifer  und in der Freude dass der Drahtverhau tatsächlich 
funzt grad mal vergessen.
Wird nachgerüstet und kommt auch ganz sicher ins fertige Layout.
Und ja, leider hilfts bei der eigentlichen Fragestellung nicht weiter... 
auch wenns womöglich später die Suche nach dem Ursprung von obskurem, 
sporadischen Fehlverhalten unnötig macht :)

Ob der Abblock-C bei all den schönen Antennen aber das größte Problem 
ist...

von fair zweifel tear (Gast)


Lesenswert?

Bob A. schrieb:
> Ob der Abblock-C bei all den schönen Antennen aber das größte Problem
> ist...

Nicht der_ sondern _die! Für jeden Baustein einen und für die
Board-zu-Board-Verbindung noch einen Elko 10-47uF.

Du fällst aus der Rolle der Arduino-Maker! Du meinst wirklich
man könnte Kondensatoren vorsichtshalber einbauen? Ich kenne
nur die Betonköpfe die sagen es geht auch ohne.

Selbst hackadays turnt dir vor dass es keine Abblock-
Kondensatoren braucht!

von Noob A. (strippenzieher)


Lesenswert?

das war ein generisches Singular, da ist der Plural mitgemeint...

von Noob A. (strippenzieher)


Lesenswert?

ich hab mir jetzt mal das .elf angeschaut mit dem netten online viewer 
von Bastian Molkenthin 
(http://www.sunshine2k.de/coding/javascript/onlineelfviewer/onlineelfviewer.html)

Nur schade dass ich nicht so ganz kapiere was ich da sehe...
Mir scheint dass es in dem Bereich "Program Header Table" sich die 
Addressen für .data und .bss wiederfinden. Und zwar unterteilt in 
virtuelle und physische Addressen.

im XMEM: (Einträge eingekürzt damit es keinen Zeilenumbruch gibt)
1
Program header tables
2
=====================
3
4
Type                Offset              VAddr               PAddr               
5
PT_LOAD             0x00000094          0x00000000          0x00000000       
6
PT_LOAD             0x00000D94          0x00802200          0x00000D00        
7
PT_LOAD             0x00000E5E          0x008022CA          0x008022CA

Im section header sieht es dann so aus (auch gekürzt)
1
0                                  SHT_NULL       0x00000000
2
1              .data               SHT_PROGBITS   0x00802200
3
2              .text               SHT_PROGBITS   0x00000000
4
3              .bss                SHT_NOBITS     0x008022CA

Da oben die gleichen Addressen auftauchen und auch Offset und Size 
passen gehe ich davon aus dass es sich auch bei den obigen Einträgen um 
.data und .bss handelt.

im normalen Speicher (auch gekürzt)
1
Program header tables
2
=====================
3
4
Type                Offset              VAddr               PAddr          
5
PT_LOAD             0x00000094          0x00000000          0x00000000       
6
PT_LOAD             0x00000D94          0x00800200          0x00000D00         
7
PT_LOAD             0x00000E5E          0x008002CA          0x008002CA

Interessant finde ich, dass sich die Physiche Adresse von .data nicht 
ändert, die von .bss aber sehr wohl.
Ob das was zu bedeuten hat - dafür reicht mein Wissensstand nicht. 
Leider!

Weiterhin ist mir aufgefallen dass bei der XMEM-Variante für 
DATA_REGION_ORIGIN (doppelte underscores vorn und hinten entfernt um 
Formatierung zu verhindern) der Wert 0x0800200 erhalten bleibt, 
__data_start
 aber den Wert 0x0802200 zugewiesen bekommt.

Auch hier fehlt mir das nötige Wissen um das beurteilen zu können...

Würd mich freuen wenn jemand mich aufschlauen kann, bzw. mich in die 
richtige Richtung weist wo man sich selber aufschlauen kann...

von EAF (Gast)


Lesenswert?

Bob A. schrieb:
> leider klappt das nicht - ich habe es nicht weiter untersucht, aber an
> der seriellen kommt keine Ausgabe

Das Problem wird sein, dass in XMCRA das SRE Bit gesetzt sein muss 
bevor die Variablen (z.B. Serial) initialisiert werden.
Das kann man in einer frühen .init Section tun.

von Noob A. (strippenzieher)


Lesenswert?

EAF schrieb:

> Das kann man in einer frühen .init Section tun.

Hallo EAF,

auch wenn ich wenig Ahnung habe klingt das einleuchtend.
nur - wie kann ich das bewerkstelligen?
Hast du Doku zu den ganzen .init Sachen, evtl. Beispiele? Würde mich 
gerne einlesen, weiss aber nicht wo anfangen

von Noob A. (strippenzieher)


Lesenswert?

Hab jetzt das hier gefunden:

https://rn-wissen.de/wiki/index.php/Avr-gcc/Interna

Da steht zumindest für mich einiges Neues drin.
vielleicht hilfts ja dem Einen oder Anderen auch weiter...

von foobar (Gast)


Lesenswert?

> Das kann man in einer frühen .init Section tun.

Das muss bereits im Startup-Code, der ja die Data-Sektion ins RAM 
kopiert, drin sein.

Aber mal ehrlich: was soll der Krampf, die vermurksten 2560er noch mit 
externem RAM zu erweitern - die werden dadurch nicht besser.  Mehr als 
64kB Kode+Daten wird mit 8-Bit-CPUs immer ein häßliches Gewurschtel - da 
sollte man doch mal den Schritt zu 32-Bit-CPUs wagen.  Ist ja nicht so, 
dass die schwieriger zu kommen oder teurer sind ...

von Noob A. (strippenzieher)


Lesenswert?

foobar schrieb:
> Ist ja nicht so, dass die schwieriger zu kommen oder teurer sind ...

sehr witzig angesichts der aktuellen Lage...

von Noob A. (strippenzieher)


Lesenswert?

foobar schrieb:
> die vermurksten 2560er

Würdest du das einem Unbedarften bitte weiter erläutern? Dankeschön.

von Noob A. (strippenzieher)


Lesenswert?

foobar schrieb:
> Das muss bereits im Startup-Code, der ja die Data-Sektion ins RAM
> kopiert, drin sein.

Danke sehr!
Ich versuche mal herauszufinden wie ich das bewerkstelligen kann

von EAF (Gast)


Lesenswert?

Bob A. schrieb:
> Hallo EAF,
>
> auch wenn ich wenig Ahnung habe klingt das einleuchtend.
> nur - wie kann ich das bewerkstelligen?
> Hast du Doku zu den ganzen .init Sachen, evtl. Beispiele? Würde mich
> gerne einlesen, weiss aber nicht wo anfangen
1
void enableExternalMemory() __attribute__((naked,used)) __attribute__((section (".init1"))); 
2
void enableExternalMemory()
3
{
4
  XMCRA = (1<<SRE);
5
  //XMCRA |= (1<<SRE);
6
}
7
8
void setup() 
9
{
10
}
11
12
void loop() 
13
{
14
}

Die Doku der Gcc Toolchain ist hier wohl maßgeblich.

von Noob A. (strippenzieher)


Lesenswert?

Da ändert sich leider genau nix wenn ich das Beispiel mit .init1 
verwende

Addressen ohne .init1
1
08:27:29.020 -> Dynamic buffer 1 of 4096 bytes created, address: 0x11F9
2
08:27:29.020 -> Dynamic buffer 2 of 4096 bytes created, address: 0x1F9
3
08:27:29.068 -> Dynamic buffer 3 of 4096 bytes created, address: 0xF1F9
4
08:27:29.068 -> Dynamic buffer 4 of 4096 bytes created, address: 0xE1F9
5
08:27:29.068 -> Dynamic buffer 5 of 4096 bytes created, address: 0xD1F9
6
08:27:29.068 -> Dynamic buffer 6 of 4096 bytes created, address: 0x2376
7
08:27:29.068 -> Dynamic buffer 7 of 4096 bytes
buffer 6 und 7 werden dynamisch erzeugt und korrekt irgendwo hinter 
0x2200 und vor 0xA1FF geschoben

hier habe ich die Fkt. enableExternalMemory() wie oben beschrieben 
eingefügt
1
08:29:43.135 -> Dynamic buffer 1 of 4096 bytes created, address: 0x11F9
2
08:29:43.135 -> Dynamic buffer 2 of 4096 bytes created, address: 0x1F9
3
08:29:43.135 -> Dynamic buffer 3 of 4096 bytes created, address: 0xF1F9
4
08:29:43.135 -> Dynamic buffer 4 of 4096 bytes created, address: 0xE1F9
5
08:29:43.182 -> Dynamic buffer 5 of 4096 bytes created, address: 0xD1F9
6
08:29:43.182 -> Dynamic buffer 6 of 4096 bytes created, address: 0x2376
7
08:29:43.182 -> Dynamic buffer 7 of 4096 bytes

Alles wie gehabt :(

Wie kann ich den startup-code modifizieren, und das dann auch noch so 
dass es abhängig von der board-Auswahl in der Arduino IDE gemacht wird?

von foobar (Gast)


Lesenswert?

Hast du mit deinem Drahtverhau überhaupt schon einmal einen Memorytest 
laufen lassen?

Btw, 4k at 0xF1F9 sieht ziemlich merkwürdig aus ...

von Noob A. (strippenzieher)


Lesenswert?

Ich habe den Test von
https://hackaday.io/project/21561-arduino-mega-2560-32kb-ram-shield
laufen lassen
Sagt: alles in Ordnung selbst mit 0 waitstate
Hast du da eine bessere Möglichkeit das zu testen?

Ja ich weiss, die Addressen sind total wirr. Keine Ahnung wie das 
zustande kommt...
Eigentlich dürfte ja auch nix hinter 0xA1FF addressiert werden da das 
als heap_end gefiniert wurde.
Zumindest soweit ich das verstanden habe...

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

EAF schrieb:
> Die Doku der Gcc Toolchain ist hier wohl maßgeblich.

Eigentlich die der avrlibc.

https://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_ext_ram

Bob A. schrieb:
> ich hab mir jetzt mal das .elf angeschaut mit dem netten online viewer
> von Bastian Molkenthin
> 
(http://www.sunshine2k.de/coding/javascript/onlineelfviewer/onlineelfviewer.html)
>
> Nur schade dass ich nicht so ganz kapiere was ich da sehe...

Ich sach mal, in Anbetracht der völlig wirren Adressen, die das tool 
ausspuckt, vergiß das halt einfach.

Oliver

von Programmierer (Gast)


Lesenswert?

foobar schrieb:
> Mehr als
> 64kB Kode+Daten wird mit 8-Bit-CPUs immer ein häßliches Gewurschtel - da
> sollte man doch mal den Schritt zu 32-Bit-CPUs wagen.  Ist ja nicht so,
> dass die schwieriger zu kommen oder teurer sind ...

Genau, Arduino Due hat 96 KM SRAM direkt im uC. Kann genau wie gewohnt 
mit der Arduino IDE programmiert werden. Warum sich mit den antiken 
8-Bit-Controllern und ihrer schmalen Ausstattung rumplagen, während 
längst wesentlich besser ausgestattete Controller Standard sind...

von Noob A. (strippenzieher)


Lesenswert?

Oliver S. schrieb:
> Ich sach mal, in Anbetracht der völlig wirren Adressen, die das tool
> ausspuckt, vergiß das halt einfach.

Wieso wirr?

die wirren Adressen kommen nicht vom Tool sondern von "meinem" 
Test-sketch
1
void setup()
2
{
3
  uint32_t arraysize = 1024;
4
  Serial.begin(9600);
5
  
6
  XMCRA |= 1ul<<7; // Switch ext mem iface on
7
  XMCRB = 0;
8
9
/*------------------------------------
10
  __malloc_heap_start = (char*)0x8000;
11
  __malloc_heap_end   = (char*)0xFFFF;
12
//-------------------------------------*/
13
//*
14
  uint32_t dataBuffer1[arraysize];
15
  uint32_t dataBuffer2[arraysize];
16
  uint32_t dataBuffer3[arraysize];
17
  uint32_t dataBuffer4[arraysize];
18
  uint32_t dataBuffer5[arraysize];
19
  uint32_t* dataBuffer6 = new uint32_t[arraysize];
20
  uint32_t* dataBuffer7 = new uint32_t[arraysize];
21
//------------------------------------------------*/  
22
/*
23
  uint32_t dataBuffer1[arraysize];
24
  uint32_t dataBuffer2[arraysize];
25
  uint32_t dataBuffer3[arraysize];
26
  uint32_t dataBuffer4[arraysize];
27
  uint32_t dataBuffer5[arraysize];
28
  uint32_t dataBuffer6[arraysize];
29
  uint32_t dataBuffer7[arraysize];
30
//--------------------------------*/
31
  
32
  Serial.println();
33
  Serial.print("Dynamic buffer 1 of ");
34
  Serial.print(arraysize * sizeof(uint32_t));
35
  Serial.print(" bytes created, address: 0x");
36
  Serial.println((uintptr_t)dataBuffer1, HEX);
37
  Serial.print("Dynamic buffer 2 of ");
38
  Serial.print(arraysize * sizeof(uint32_t));
39
  Serial.print(" bytes created, address: 0x");
40
  Serial.println((uintptr_t)dataBuffer2, HEX);
41
  Serial.print("Dynamic buffer 3 of ");
42
  Serial.print(arraysize * sizeof(uint32_t));
43
  Serial.print(" bytes created, address: 0x");
44
  Serial.println((uintptr_t)dataBuffer3, HEX);
45
  Serial.print("Dynamic buffer 4 of ");
46
  Serial.print(arraysize * sizeof(uint32_t));
47
  Serial.print(" bytes created, address: 0x");
48
  Serial.println((uintptr_t)dataBuffer4, HEX);
49
  Serial.print("Dynamic buffer 5 of ");
50
  Serial.print(arraysize * sizeof(uint32_t));
51
  Serial.print(" bytes created, address: 0x");
52
  Serial.println((uintptr_t)dataBuffer5, HEX);
53
  Serial.print("Dynamic buffer 6 of ");
54
  Serial.print(arraysize * sizeof(uint32_t));
55
  Serial.print(" bytes created, address: 0x");
56
  Serial.println((uintptr_t)dataBuffer6, HEX);
57
  Serial.print("Dynamic buffer 7 of ");
58
  Serial.print(arraysize * sizeof(uint32_t));
59
  Serial.print(" bytes created, address: 0x");
60
  Serial.println((uintptr_t)dataBuffer7, HEX);
61
62
  
63
  for (size_t i=0; i<arraysize; ++i)
64
  {
65
    dataBuffer1[i] = i*2;
66
    dataBuffer2[i] = i*2;
67
    dataBuffer3[i] = i*2;
68
    dataBuffer4[i] = i*2;
69
    dataBuffer5[i] = i*2;
70
    dataBuffer6[i] = i*2;
71
    dataBuffer7[i] = i*2;
72
  }
73
  Serial.println();
74
  Serial.println();
75
/*
76
  Serial.println("Data Buffer 1");
77
  for (size_t i=0; i<arraysize; i+=4)
78
  {
79
    Serial.println();
80
    Serial.print(i, DEC);
81
    Serial.print('\t');
82
    Serial.print(dataBuffer1[i], DEC);
83
    Serial.print('\t');
84
    Serial.print(dataBuffer1[i+1], DEC);
85
    Serial.print('\t');
86
    Serial.print(dataBuffer1[i+2], DEC);
87
    Serial.print('\t');
88
    Serial.print(dataBuffer1[i+3], DEC);
89
  }
90
91
//----------------------------------------*/
92
}
93
94
void loop()
95
{
96
}

edit: hab das ein wenig eingekürzt, alle buffer werden testweise 
ausgegeben, hier aber nur der code für einen

: Bearbeitet durch User
von Noob A. (strippenzieher)


Lesenswert?

Programmierer schrieb:
> Genau, Arduino Due hat 96 KM SRAM direkt im uC. Kann genau wie gewohnt
> mit der Arduino IDE programmiert werden. Warum sich mit den antiken
> 8-Bit-Controllern und ihrer schmalen Ausstattung rumplagen, während
> längst wesentlich besser ausgestattete Controller Standard sind...

Das wäre ja einfach...

Mal davon abgesehen dass man mit dem arbeitet was man hat, habe ich 
bisher schon Einiges lernen können.
Erkenntnisgewinn kann auch eine Motivation sein!

von foobar (Gast)


Lesenswert?

Ehem, deine dataBuffer1-5 sind auf dem Stack!

von Noob A. (strippenzieher)


Lesenswert?

foobar schrieb:
> Ehem, deine dataBuffer1-5 sind auf dem Stack!

Öhm... dann habe ich da wohl etwas grundlegend nicht verstanden.
Ich habe es so verstanden, dass Variablen die mit
1
int buffer[128]
 (ich glaube man sagt dazu statisch) definiert werden kommen in die 
.data-section

https://www.nongnu.org/avr-libc/user-manual/mem_sections.html#sec_dot_data

und die versuche ich ja per Linker-Anweisung in den externen Speicher zu 
schieben

von EAF (Gast)


Lesenswert?

Bob A. schrieb:
> Da ändert sich leider genau nix wenn ich das Beispiel mit .init1
> verwende
Das sich damit irgendwelche Adressen ändern, hätte ich auch nicht 
erwartet.
Wie auch?

Bob A. schrieb:
> Wie kann ich den startup-code modifizieren,
Das habe ich dir gezeigt!
.ini1 ist schon ein passender Zeitpunkt.

Bob A. schrieb:
>  und das dann auch noch so
> dass es abhängig von der board-Auswahl in der Arduino IDE gemacht wird?
Arduino kennt Boards und Varianten.
Die kannst du selber erstellen und auch die vorhandenen modifizieren.
Hier finden sich die Regeln:
https://arduino.github.io/arduino-cli/0.20/platform-specification/

von Oliver S. (oliverso)


Lesenswert?

Bob A. schrieb:
> Ich habe es so verstanden, dass Variablen die mit1int buffer[128]
>  (ich glaube man sagt dazu statisch) definiert werden kommen in die
> .data-section

Wenn du das Zauberwort schon nennst, dann schreib das auch in den Code.
Dann klappt das auch mit .data

Oliver

von EAF (Gast)


Lesenswert?

Oder so:
(ungetestet, habe keine Erweiterung)
1
  constexpr size_t arraysize = 1024;
2
  
3
  uint32_t dataBuffer1[arraysize];
4
  uint32_t dataBuffer2[arraysize];
5
  uint32_t dataBuffer3[arraysize];
6
  uint32_t dataBuffer4[arraysize];
7
  uint32_t dataBuffer5[arraysize];
8
9
10
11
void setup()
12
{
13
14
  Serial.begin(9600);
15
  
16
  XMCRA |= 1ul<<7; // Switch ext mem iface on
17
  XMCRB = 0;
18
/*------------------------------------
19
  __malloc_heap_start = (char*)0x8000;
20
  __malloc_heap_end   = (char*)0xFFFF;
21
//-------------------------------------*/
22
//*
23
  uint32_t* dataBuffer6 = new uint32_t[arraysize];
24
  uint32_t* dataBuffer7 = new uint32_t[arraysize];
25
//------------------------------------------------*/  
26
/*
27
  uint32_t dataBuffer1[arraysize];
28
  uint32_t dataBuffer2[arraysize];
29
  uint32_t dataBuffer3[arraysize];
30
  uint32_t dataBuffer4[arraysize];
31
  uint32_t dataBuffer5[arraysize];
32
  uint32_t dataBuffer6[arraysize];
33
  uint32_t dataBuffer7[arraysize];
34
//--------------------------------*/
35
  
36
  Serial.println();
37
  Serial.print("Dynamic buffer 1 of ");
38
  Serial.print(arraysize * sizeof(uint32_t));
39
  Serial.print(" bytes created, address: 0x");
40
  Serial.println((uintptr_t)dataBuffer1, HEX);
41
  Serial.print("Dynamic buffer 2 of ");
42
  Serial.print(arraysize * sizeof(uint32_t));
43
  Serial.print(" bytes created, address: 0x");
44
  Serial.println((uintptr_t)dataBuffer2, HEX);
45
  Serial.print("Dynamic buffer 3 of ");
46
  Serial.print(arraysize * sizeof(uint32_t));
47
  Serial.print(" bytes created, address: 0x");
48
  Serial.println((uintptr_t)dataBuffer3, HEX);
49
  Serial.print("Dynamic buffer 4 of ");
50
  Serial.print(arraysize * sizeof(uint32_t));
51
  Serial.print(" bytes created, address: 0x");
52
  Serial.println((uintptr_t)dataBuffer4, HEX);
53
  Serial.print("Dynamic buffer 5 of ");
54
  Serial.print(arraysize * sizeof(uint32_t));
55
  Serial.print(" bytes created, address: 0x");
56
  Serial.println((uintptr_t)dataBuffer5, HEX);
57
  Serial.print("Dynamic buffer 6 of ");
58
  Serial.print(arraysize * sizeof(uint32_t));
59
  Serial.print(" bytes created, address: 0x");
60
  Serial.println((uintptr_t)dataBuffer6, HEX);
61
  Serial.print("Dynamic buffer 7 of ");
62
  Serial.print(arraysize * sizeof(uint32_t));
63
  Serial.print(" bytes created, address: 0x");
64
  Serial.println((uintptr_t)dataBuffer7, HEX);
65
  
66
  for (size_t i=0; i<arraysize; ++i)
67
  {
68
    dataBuffer1[i] = i*2;
69
    dataBuffer2[i] = i*2;
70
    dataBuffer3[i] = i*2;
71
    dataBuffer4[i] = i*2;
72
    dataBuffer5[i] = i*2;
73
    dataBuffer6[i] = i*2;
74
    dataBuffer7[i] = i*2;
75
  }
76
  Serial.println();
77
  Serial.println();
78
/*
79
  Serial.println("Data Buffer 1");
80
  for (size_t i=0; i<arraysize; i+=4)
81
  {
82
    Serial.println();
83
    Serial.print(i, DEC);
84
    Serial.print('\t');
85
    Serial.print(dataBuffer1[i], DEC);
86
    Serial.print('\t');
87
    Serial.print(dataBuffer1[i+1], DEC);
88
    Serial.print('\t');
89
    Serial.print(dataBuffer1[i+2], DEC);
90
    Serial.print('\t');
91
    Serial.print(dataBuffer1[i+3], DEC);
92
  }
93
//----------------------------------------*/
94
}
95
void loop()
96
{
97
}
98
99
void enableExternalMemory() __attribute__((naked,used)) __attribute__((section (".init1"))); 
100
void enableExternalMemory()
101
{
102
  XMCRA = (1<<SRE);
103
  //XMCRA |= (1<<SRE);
104
}

von Noob A. (strippenzieher)


Lesenswert?

Oliver S. schrieb:
> Wenn du das Zauberwort schon nennst, dann schreib das auch in den Code.
> Dann klappt das auch mit .data

ich habe das mal so interpretiert dass nur mit "static" deklarierte 
Variablen in .data landen - richtig?
Das hat jetzt genau einmal funktioniert (array-Größe darf dann 
allerdings nicht per Variable zugewiesen werden), alle Versuche das zu 
wiederholen scheitern und es erscheint genau nix im Terminal... Da ist 
doch zum Mäuse melken...

von Oliver S. (oliverso)


Lesenswert?

Bob A. schrieb:
> Das hat jetzt genau einmal funktioniert

Was hat wie jetzt genau einmal funktioniert?
Zeig den Code, Compileraufruf, linkeraufruf, etc.
Und alles bitte als ANHANG.

Oliver

: Bearbeitet durch User
von EAF (Gast)


Lesenswert?

EAF schrieb:
> XMCRA |= 1ul<<7; // Switch ext mem iface on
>   XMCRB = 0;
Das ist natürlich in meiner setup()  Überflüssig, schadet aber auch 
nicht.

von Noob A. (strippenzieher)


Lesenswert?

EAF schrieb:
> Das sich damit irgendwelche Adressen ändern, hätte ich auch nicht
> erwartet.
> Wie auch?

Ich hatte das so verstanden, dass Variablen die so deklariert werden in 
.data landen. Scheinbar ein Trugschluss

> Das habe ich dir gezeigt!
> .ini1 ist schon ein passender Zeitpunkt.

Mir war nicht klar dass ich damit den startup-code ändere. Von den STM32 
kenne ich das eher so, dass es eine separate Datei gibt in der der 
startup-code enthalten ist. So einen Mechanismus wie hier, ich dachte 
das ist was Anderes.
Wieder was gelernt ;)


> Arduino kennt Boards und Varianten.
> Die kannst du selber erstellen und auch die vorhandenen modifizieren.
> Hier finden sich die Regeln:
> https://arduino.github.io/arduino-cli/0.20/platform-specification/

Soweit bin ich auch gekommen, ich habe im sketch-folder ein board 
angelegt und die baords.txt so modifiziert dass es einen Atmega2560 mit 
40k Speicher gibt und in der platform.txt die zusätzlichen Linker-Flags 
hinterlegt.
Das klappt auch so weit.
Ich weiss aber nicht wie ich es anstelle dass der Code zum Einschalten 
der XMEM-Schnittstelle auch automatisch mit der board-Auswahl übernommen 
wird.

von Noob A. (strippenzieher)


Angehängte Dateien:

Lesenswert?

EAF schrieb:
> EAF schrieb:
>> XMCRA |= 1ul<<7; // Switch ext mem iface on
>>   XMCRB = 0;
> Das ist natürlich in meiner setup()  Überflüssig, schadet aber auch
> nicht.

Oliver S. schrieb:
> Was hat wie jetzt genau einmal funktioniert?


ich hatte die buffer als static und fest mit 1024 deklariert. 
Runtergeladen und die buffer hatten andere Adressen.

Dann die beiden Zeilen oben aus setup() entfernt und nix geht mehr.
Mal 'ne Minute von der Versorgungsspannung getrennt und es scheint 
wieder wie gehabt zu funktioniern. fingerscrossed



> Zeig den Code, Compileraufruf, linkeraufruf, etc.
> Und alles bitte als ANHANG.

da ich nicht weiss was genau mit Compileraufruf gemeint ist (wird ja 
öfter aufgerufen), mal der komplette output der Arduino-IDE.
Was genau möchtest du sehen und wie komme ich da ran?

Linker dürfte das hier sein:
1
Linking everything together...
2
"C:\\Users\\xxXXxxXXxx\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-gcc" -Wall -Wextra -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega2560 -Wl,--section-start,.data=0x802200,--defsym=__heap_end=0x80A1FF -o "C:\\Users\\xxXXxxXXxx\\AppData\\Local\\Temp\\arduino_build_504005/xmem-test-2.ino.elf" "C:\\Users\\xxXXxxXXxx\\AppData\\Local\\Temp\\arduino_build_504005\\sketch\\xmem-test-2.ino.cpp.o" "C:\\Users\\xxXXxxXXxx\\AppData\\Local\\Temp\\arduino_build_504005/core\\core.a" "-LC:\\Users\\xxXXxxXXxx\\AppData\\Local\\Temp\\arduino_build_504005" -lm

von EAF (Gast)


Lesenswert?

Bob A. schrieb:
> Ich weiss aber nicht wie ich es anstelle dass der Code zum Einschalten
> der XMEM-Schnittstelle auch automatisch mit der board-Auswahl übernommen
> wird.

In dem du eine eigene variant erstellst.
Dafür gibts ja schließlich den zugehörigen Eintrag in der boards.txt
*.c und *.cpp (evtl auch *.S) Dateien im variants Order werden 
automatisch mit kompiliert.

von Noob A. (strippenzieher)


Lesenswert?

EAF schrieb:
> Bob A. schrieb:
>> Ich weiss aber nicht wie ich es anstelle dass der Code zum Einschalten
>> der XMEM-Schnittstelle auch automatisch mit der board-Auswahl übernommen
>> wird.
>
> In dem du eine eigene variant erstellst.
> Dafür gibts ja schließlich den zugehörigen Eintrag in der boards.txt
> *.c und *.cpp (evtl auch *.S) Dateien im variants Order werden
> automatisch mit kompiliert.

Super, Dankeschön!

von EAF (Gast)


Lesenswert?

Bob A. schrieb:
> Dann die beiden Zeilen oben aus setup() entfernt und nix geht mehr.
Ich hoffe dass du die enableExternalMemory() dabe die nicht vergessen 
hast.

von Oliver S. (oliverso)


Lesenswert?

1
void setup()
2
{
3
  uint32_t arraysize = 1024;
4
  Serial.begin(57600);
5
  
6
  XMCRA |= 1ul<<7; // Switch ext mem iface on
7
  XMCRB = 0;
8
...

Die XMCRA/B-Zeilen sollten da noch weg. Das Interface wird ja in der 
init1-Section schon initialisiert, und das muß es auch.

Oliver

von Noob A. (strippenzieher)


Lesenswert?

EAF schrieb:
> Bob A. schrieb:
>> Dann die beiden Zeilen oben aus setup() entfernt und nix geht mehr.
> Ich hoffe dass du die enableExternalMemory() dabe die nicht vergessen
> hast.

Nee, die war schon noch drin, bzw. eine etwas andere Variante die aber 
auch funktioniert hat.

Aktuell sieht es so aus als ob es funktioniert - evtl sogar schon immer 
funktioniert hat. Nur habe ich falsche Annahmen wegen zu geringem 
Wissensstand gemacht und so wie gedacht hätte es nie funktionieren 
können.

Ich resümiere und bitte um Korrektur wenn ich wieder was nicht kapiert 
habe:

- startup-code kann durch Verwendung von __attribute__(section) 
verändert werden

- selbst wenn .data und .bss im externen Speicher liegen, dann werden 
"normale" Variablen (int foo;) in den Stack lokalisiert

- in .data landen nur Variablen die entweder als static deklariert 
werden oder wie im Beispiel von EAF, arrays die als Größe eine constexpr 
haben

- so wie ich mir das vorgestellt habe, dass einfach alles im externen 
Speicher landet, das geht gar nicht

von Noob A. (strippenzieher)


Lesenswert?

Oliver S. schrieb:
> Die XMCRA/B-Zeilen sollten da noch weg. Das Interface wird ja in der
> init1-Section schon initialisiert, und das muß es auch.

Ist jetzt so, hatte vorher auch schon das Interface in .init3 und diese 
Zeilen. Hat wie es scheint nichts ausgemacht.
Jetzt aber nur an einer Stelle (immer noch .init3, nicht .init1)

von Noob A. (strippenzieher)


Lesenswert?

Bob A. schrieb:
> - in .data landen nur Variablen die entweder als static deklariert
> werden oder wie im Beispiel von EAF, arrays die als Größe eine constexpr
> haben

Hmm, nee scheint nicht zu stimmen
1
uint32_t someInt;
2
uint32_t someOtherInt = 213;
landen im internen Speicher
1
char err_str[] = "Your program has died a horrible death!";
auch nicht, obschon das das Beispiel von
https://www.nongnu.org/avr-libc/user-manual/mem_sections.html#sec_dot_data 
ist

ich kapiers immer noch nicht was warum wo landet...

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Bob A. schrieb:
> ich kapiers immer noch nicht was warum wo landet...

Tja, nicht immer hilft trail-and-error, machmal muß man lesen und 
lernen.
Dein char[] landet zudem auch noch im Flash ;)

https://www.nongnu.org/avr-libc/user-manual/mem_sections.html

Bob A. schrieb:
> - so wie ich mir das vorgestellt habe, dass einfach alles im externen
> Speicher landet, das geht gar nicht

Für ungenutztes internes SRAm gibts eh kein Geld zurück, also kannst du 
das auch verwenden. Den Stack sollte (oder muß) man da lassen, alles 
andere kann ins externe Ram.

Oliver

: Bearbeitet durch User
von Noob A. (strippenzieher)


Lesenswert?

Oliver S. schrieb:
> Tja, nicht immer hilft trail-and-error, machmal muß man lesen und
> lernen.

Aber ich bin doch durch Lesen zu der Annahme gekommen dass diese Art 
Variablen in .data landet.
Steht ja in der avr-libc Doku so drin und ich habe genau das Beispiel 
von da verwendet...

Ich raffs einfach nicht :(

von Oliver S. (oliverso)


Lesenswert?

Ok, dann wäre das nächste Vorschlag, ein C-Buch zu lesen. Stichworte 
sind "globale", "statische", "lokale", "automatische" Variable.

Auf der einen Seite machst du da erfolgreich Experimente für 
Fortgeschrittene, auf der anderen Seite fehlen dir die einfachsten 
Grundlagen. Das ist schon eine seltene Mischung ;)

Oliver

von Oliver S. (oliverso)


Lesenswert?

Ach so, noch vergessen:

Wenn du das mit C-Buch durch hast, informier dich mal über AVR und 
Strings im Flash. Es könnte sein, daß du danach dein externes Ram gar 
nicht mehr brauchst.

Oliver

von Noob A. (strippenzieher)


Lesenswert?

quasi reverse knowledge aquisition lach

ich hab noch irgendwo ein Kerneggie-Ritchie (oder so ähnlich) rumstehen 
- sollte ich mal wieder bemühen :)

von EAF (Gast)


Lesenswert?

Bob A. schrieb:
> quasi reverse knowledge aquisition lach

Evtl. solltest du anfangen im Schritttempo zu denken und nicht 5 Stufen 
auf einmal nehmen.
Das kannst du erst tun, wenn du sattelfest bist.

von Noob A. (strippenzieher)


Lesenswert?

Mjoah.... ich hab den Wink mit dem Scheunentor verstanden :)

Nichtsdestotrotz funzt es jetzt - auch die Integration in die 
Arduino-Welt!

Dank allen Helfern hier!

Ich habe wieder mal viel gelernt - auch wo die eigenen Wissenslücken 
sind. Eigentlich auch ganz wertvoll!

PS:
Damit der automagisch mitkompiliert Code aus dem variants-folder funzt, 
muss man noch
1
#include <avr/io.h>
2
#include <avr/iomxx0_1.h>
einbinden.

Ob das so händisch-hardcoded als eine gute Idee ist?
Aber eigentlich ist es ja fest mit der Variante Atmega2560 verbandelt, 
daher sollte es keine Bedarf geben dass das geändert werden muss.

PPS:
Jetzt muss ich "nur" noch besser verstehen wieso es klappt und warum es 
nicht so geht wie ich anfänglich angenommen hatte.

Danke auch für den Tipp mit dem C-Buch. Werde ich beherzigen!

von Noob A. (strippenzieher)


Angehängte Dateien:

Lesenswert?

Hier noch der Vollständigket halber eine .zip die man unter
"arduino-sketch-.folder"/hardware extraheiren kann um die Variante mit 
extra-Speicher zu bekommen.
Es wird NICHT abgefragt ob der Speicher überhaupt vorhanden ist, da muss 
ich mir noch was überlegen ob und wie das möglich ist.

von EAF (Gast)


Lesenswert?

Bob A. schrieb:
> Damit der automagisch mitkompiliert Code aus dem variants-folder funzt,
> muss man noch#include <avr/io.h>
> #include <avr/iomxx0_1.h>
> einbinden.

Oder einfach:
#include <Arduino.h>

von Noob A. (strippenzieher)


Lesenswert?

EAF schrieb:
> Oder einfach:
> #include <Arduino.h>


Danke!

war wohl zu naheliegend...

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.