Forum: Mikrocontroller und Digitale Elektronik STM32x kein malloc mehr möglich


von wolfhunters (Gast)


Lesenswert?

Hallo zusammen

ich habe seid kurzm folgendes Problem.
Ich habe eine Entwicklungskit von Olimex mit einem STM32F103 Controller.
Wenn ich versuche Speicher per malloc zu allozieren, dann beendet sich 
das Programm und gibt mir eine BusFaultException raus. Ich habe keine 
Ahnung, wie man dem Problem auf den Grund geht, oder wo ich den Fehler 
suchen soll.
Vielleicht hat ja einer einen Idee.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ist denn die Heapverwaltung überhaupt initialisiert?

von wolfhunters (Gast)


Lesenswert?

Wo wird das denn verwaltet? Im Linkerskript wird der Stack festgelegt, 
aber ob und wo man den Heap verwaltet, weiß ich leider nicht. 
Entschuldige bitte, aber ich bin Anfänger. Vielleicht kannst du mir da 
auf die Sprünge helfen. Ich muss dazu sagen, dass es schon einmal 
funktioniert hat. Aber jetzt irgendwie nicht mehr.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Hi,

arbeitest du mit den Keil Tools?

Da kann man im startup-file sehr einfach den heap einstellen.
Übrigends ist die Demo bis 32k frei (20k Code + 12k konstanten). Damit 
kann man schon mal so einiges anstellen.

Auf jeden Fall erst mal etwas Heap "freigeben".


VG,
/r.

von wolfhunters (Gast)


Lesenswert?

Hallo

Ich arbeite nicht mit Keil. 32k sind mir leider zu wenig (hab jetzt 
schon 85k). Ich arbeite mit Eclipse, dem GCC von der sarm-toolchain von 
ST und OpenOCD per JTag von Olimex. Ich habe gelesen, dass man das bei 
Keil einstellen kann. Aber es muss doch auch so irgendwo einstellbar 
sein oder festgelegt werden können.

von TT (Gast)


Lesenswert?

Suche dir doch irgendwo ein C++ Beispiel für den ARM-GCC,
da wird auf jedenfall der Heap benötigt und reserviert.

von Bolo (Gast)


Lesenswert?

Abgesehen davon würde ich bei uC-Anwendungen niemals mit dynamischer 
Speicherreservierung arbeiten.

von TT (Gast)


Lesenswert?

@Bolo

Arbeitest du aber schon immer, Stackbedarf ist auch dynamische
Speicherreservierung, wenn man es genau betrachtet.

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Zum Ursprungsproblem: Man zeige das verwendete linker-script.

von wolfhunters (Gast)


Angehängte Dateien:

Lesenswert?

anbei das verwendete Linkerskript (habe es im Internet gefunden und es 
funktionierte). beim Testen und rumspielen habe ich jetzt festgestellt, 
dass das Allozieren von speicher bis zu einer bestimmten Größe möglich 
ist, aber darüber hinaus nicht. ich kann maximal 492 Bytes allozieren, 
mehr nicht. Ist echt ein komischer Wert.

DANKE für eure Mithilfe

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Memory-Layout lässt eine Stack-Heap-Kollision zu. Ist etwas kniffig zu 
debuggen. Wäre einfacher mit Stack hinter bss und Heap nach Stack, dann 
kann der Heap nur gegen das RAM-ende "krachen", Core-Exception dürfte 
aber die Gleiche sein.  Wird in der Anwendung schon ordentlich RAM durch 
globale/statische Variablen oder zeitweise durch große/viele 
automatische Variablen verbraucht?

Evlt. enthält "." ganz am Ende und ausserhalb der sections irgend einen 
unsinnigen Wert. Testweise die Zeile mit provide end ganz am Ende 
löschen und weiter oben hinter
1
end = .;
und vor } noch
1
 __end__ = . ;
2
 _end = .; 
3
 PROVIDE (end = .);

Vorher und nachher anhand von map- und symbol-File prüfen, ob end auf 
eine sinnvolle Adresse gesetzt wird (vgl. _bss_end_). Ansonsten: 
Minimalprojekt mit allen erforderlichen Dateien erzeugen (source, 
startup, linkerscript, makefile), um das Problem nachzuvollziehen und 
hier einstellen. Evtl. auch an Spencer Oliver senden, er düfte in Sachen 
STM32 und GNU-Tools einer der kompetentesten Ansprechpartner sein 
(e-mail Adresse an vielen Stellen in SARM Dateien)

von wolfhunters (Gast)


Lesenswert?

@Martin Thomas
Habe das mal ausprobiert, aber ohne Erfolg. Leider kenne ich mich mit 
den Linkerfiles überhaupt nicht aus. Wie kann ich denn den Stack und 
Heap hinter bss bringen? Entschuldige, aber ich habe wirklich keinen 
Plan davon.
Eigentlich verwende ich nicht sehr viel an globalen Variablen, einige 
kleinere char-Arrays (2x90byte + ein paar kleinere)

von Daniel W. (wolfhunters)


Lesenswert?

Ich bin jetzt mal etwas tiefer eingestiegen.
Es sieht so aus, als ob malloc hier nicht den richtigen Heappointer 
benutzt. die Funktion malloc hat eine Variable names __malloc_sbrk_base. 
Dies ist die Base-Adresse des Heaps. Die wird hier falsch übergeben. Die 
hier angezeigte Adresse liegt mitten im bss-Segment.
Das ganze noch mal rein formal:

Adresse end. am Ende des Linkerscripts liegt bei bspw. 0x2000091f, die 
in __malloc_sbrk_base angezeigte Adresse ist aber 200003f8, also mitten 
im bss-Segment. Dann ist klar, dass malloc schief gehen muss. Aber wo 
wird malloc die Adresse für __malloc_sbrk_base übergeben. habe nirgens 
in der Newlib eine zuweisung oder Adressierung gefunden.

Mein Problem ist, dass ich einen SPI SD-Kartentreiber gefunden habe, der 
funktioniert. Habe ein fertiges Programm kompiliert und getestet. Wenn 
ich das bei mir integriere, dann bekomme ich dieses Problem. Aber der 
Treiber greift auf keine Malloc-funktion zu, habe ich getestet. Mit 
einem anderen Treiber, der aber nicht so schön, nicht vollständig und 
leider noch fehlerbehaftet und unkomfortabel ist, habe ich nicht das 
Problem nicht. Das passt der Pointer genau. Ich habe da jetzt hin und 
hergesucht, finde aber keine Erklärung dafür. Kann mir dazu jemande 
einen Tipp geben?

von Werner B. (Gast)


Lesenswert?

Das ist eines der "ARM-Probleme". Das Runtime-Startup-File und das 
Linkerscript müssen zusammenpassen. Jede Umgebung die ich bisher gesehen 
habe verwendet andere Bezeichner (z.B. für Heap-Anfang/Ende, Stack 
Anfang/Ende usw.) und Reihenfolgen der Speicherbereiche. Somit ist es 
ohne (z.T. erheblichen) Zusatzaufwand kaum möglich diese Files zwischen 
verschiedenen Paketen zu mischen (z.B. WinARM mit Yagarto).

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Daniel Wolf wrote:
> Ich bin jetzt mal etwas tiefer eingestiegen.
> Es sieht so aus, als ob malloc hier nicht den richtigen Heappointer
> benutzt. die Funktion malloc hat eine Variable names __malloc_sbrk_base.

Hmm, woher kommt die Information? Quellcode - zumindest von sbrk? 
Üblicherweise (bei newlib) greift malloc auf sbrk zurück und sbrk 
braucht beim ersten Aufruf die Information darüber, wo es dann mit dem 
Heap loslegen darf. Standardbezeichnung ist end (siehe auch 
Standard-Linkerscripts der binutils). Kann aber gut sein, dass sbrk so 
implementiert wurde, dass es statt end wohl __malloc_sbrk_base erwartet. 
Habe auf dem Rechner grade sarm/Idealist nicht installiert, sonst kann 
man in den Beispielen nachschauen. Zur Not ein eigenes sbrk 
implementieren. Wenn richtig erinnert ist das in syscalls der newlib in 
sarm "weak".

> Dies ist die Base-Adresse des Heaps. Die wird hier falsch übergeben. Die
> hier angezeigte Adresse liegt mitten im bss-Segment.
> Das ganze noch mal rein formal:
>
> Adresse end. am Ende des Linkerscripts liegt bei bspw. 0x2000091f, die
> in __malloc_sbrk_base angezeigte Adresse ist aber 200003f8, also mitten
> im bss-Segment. Dann ist klar, dass malloc schief gehen muss. Aber wo
> wird malloc die Adresse für __malloc_sbrk_base übergeben. habe nirgens
> in der Newlib eine zuweisung oder Adressierung gefunden.

Man versuche im Linker-Script direkt hinter PROVIDE (end = .); die Zeile 
PROVIDE (__malloc_sbrk_base = .); und prüfe, ob dann die Zuweisung 
passt.

> Mein Problem ist, dass ich einen SPI SD-Kartentreiber gefunden habe, der
> funktioniert. Habe ein fertiges Programm kompiliert und getestet. Wenn
> ich das bei mir integriere, dann bekomme ich dieses Problem. Aber der
> Treiber greift auf keine Malloc-funktion zu, habe ich getestet. Mit
> einem anderen Treiber, der aber nicht so schön, nicht vollständig und
> leider noch fehlerbehaftet und unkomfortabel ist, habe ich nicht das
> Problem nicht. Das passt der Pointer genau. Ich habe da jetzt hin und
> hergesucht, finde aber keine Erklärung dafür. Kann mir dazu jemande
> einen Tipp geben?

Etwas zu wenig Information. Das angefrage Minimalbespiel um das Problem 
zu reproduzieren steht ja noch aus.

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Werner B. wrote:
> Das ist eines der "ARM-Probleme". Das Runtime-Startup-File und das
> Linkerscript müssen zusammenpassen. Jede Umgebung die ich bisher gesehen
> habe verwendet andere Bezeichner (z.B. für Heap-Anfang/Ende, Stack
> Anfang/Ende usw.) und Reihenfolgen der Speicherbereiche.
Soweit "kopfnick".

> Somit ist es
> ohne (z.T. erheblichen) Zusatzaufwand kaum möglich diese Files zwischen
> verschiedenen Paketen zu mischen (z.B. WinARM mit Yagarto).
Was haben Linker-Scripte und Startup-Code mit dem Packet der toolchain 
zu tun? Worum erheblicher Zeitaufwand? Wofür? Der einzig wirklichen 
Unterschied zwischen WinARM (20060606) und Yagarto(letzte ausprobierte 
Version, länger her) war/ist die konfiguration der newlib bezgl. 
syscalls. Falls man diese nicht braucht sehe ich keinen Grund für 
"erheblichen" Zusatzaufwand.

von Daniel W. (wolfhunters)


Angehängte Dateien:

Lesenswert?

> Hmm, woher kommt die Information? Quellcode - zumindest von sbrk?

ich stelle mal die aktuell von mir verwendeten Linkerscripte und Vector 
in den Anhang. diese habe ich modifiziert und angepasst so weit ich 
konnte. Habe sie in den Anhang gestellt. sie sind ursprünglich auf einem 
anderen Projekt (Donwloadlink: 
http://www.st.com/mcu/modules.php?mop=modload&name=Splatt_Forums&file=attachment&AtchOp=get&postid=20160&AtchName=cs-stm32-0.91.zip&AtchNum=0) 
Syscalls habe ich auch begefügt, diese habe ich aus einem 
STM32-Framework. (zu finden unter 
http://www.munts.com/MCU/ARM/stm32f103/) In den Syscalls wird mit end[] 
der Heappointer initialisiert, wenn ich mich nicht irre. Dessen Adresse 
kann ich nach dem Start auslesen.


> Man versuche im Linker-Script direkt hinter PROVIDE (end = .); die Zeile
> PROVIDE (__malloc_sbrk_base = .); und prüfe, ob dann die Zuweisung
> passt.

bring leider auch keinen Erfolg

> Etwas zu wenig Information. Das angefrage Minimalbespiel um das Problem
> zu reproduzieren steht ja noch aus.

also den ersten, meiner Meinung nach nicht so guten Code für SPI -> 
SD/MMC ist der, den ich bei meinem Entwicklungsboard mit dabei hatte 
(Download: http://www.olimex.com/dev/soft/arm/STR/STM32F103-STK-TST.rar, 
mmc.c +.h). Der zweite, meiner Meinung nach besser ist von IAR auch in 
einem Demoprojekt für das Entwicklungsboard (Download: 
http://www.olimex.com/dev/soft/arm/ST/STM32-103STK/EW-ARM511%20STM32-103STK-.zip 
, zu finden im Ordner STM32-103STK-MassStorage/app die Dateien mmc.c +.h 
und mmc_ll_SPI2.c). Den habe ich modifiziert und erstmal alles was die 
DMA betrifft, entfernt. Das ist meine Grundlage, mit der ich versuche 
was auf die Beine zu stellen.

von Daniel W. (wolfhunters)


Lesenswert?

So, habe es jetzt endlich zum laufen bekommen. Ich habe mir den SARM 
Idealist heruntergeladen und mir mal die Bsp. angeschaut. Habe darauf 
hin dann alle notwendigen Dateien, wie Linkerscript, Vectortabelle und 
Startup in mein Porjekt integriert, passende Bib aus der SARM-Toolchain 
dazugelinkt, und siehe da, es funktioniert.

Also vielen Dank, vor allem an Martin Thomas. Dank seiner Tipps habe ich 
es zu laufen gebracht.

von Werner B. (Gast)


Lesenswert?

@Martin Thomas

Der "erhebliche Zeitaufwand" ist bei denen vorhanden die sich erst
A) in die Syntax der Linkerscripte einarbeiten müssen
B) rauszufinden welchen Zweck die einzelnen (jeweils anders genannten) 
Symbole erfüllen (sollen).

Um auch zu "wissen was man tut"  (-;|=

Das das für dich kein Problem ist steht ausser Frage. Einer hat eben 
schon das spezelle Fachwissen und Fragesteller (und ich ;) idR nicht.

Werner

von Martin Thomas (Gast)


Lesenswert?

Ich hatte nach dem "erheblichen Zeitaufwand" im Hinblick auf das 
"Mischen"
zwischen verschiedenen Binärpacketen der GNU toolchain gefragt.

von Denis S. (h44656e)


Lesenswert?

Hallo,
ich verzweifele an gleichem Problem mit STM32F4...
...kannst du mir vielleicht paar tipps geben?
ich verwende eclipse mit Sourcery uns GDB - Server von Atollic.

gruß
Denis

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.