Forum: Mikrocontroller und Digitale Elektronik malloc hard fault KEIL


von Colombo010 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo, ich versuche einen Ringbuffer auf einem Cortex M0 (kl25z board) 
zu implementieren, wie er in der angehängten Datei nachzulesen ist.

Bei der Ausführung von malloc, springt der Prozessor aber in den 
HardFault_Handler. Woran kann das liegen. Habe im Startup File versucht 
die Heapsize einzustellen, hat aber nix gebracht.

1
; <h> Stack Configuration
2
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
3
; </h>
4
5
Stack_Size      EQU     0x00000800
6
7
                AREA    STACK, NOINIT, READWRITE, ALIGN=3
8
Stack_Mem       SPACE   Stack_Size
9
__initial_sp    EQU     0x20002ff8
10
11
12
; <h> Heap Configuration
13
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
14
; </h>
15
16
Heap_Size       EQU      0x00000400
17
18
19
                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
20
__heap_base
21
Heap_Mem        SPACE   Heap_Size
22
__heap_limit



Und wie muss man sich das mit

extern uint32_t HEAP$$Base;
extern uint32_t HEAP$$Limit;
uint32_t __HEAP_START = (uint32_t)&HEAP$$Base;
uint32_t __HEAP_END = (uint32_t)&HEAP$$Limit;

vorstellen, irgendwo muss ja in einem anderen File HEAP$$Base und 
HEAP$$Limit definiert sein. Mir fehlt einfach das Verständnis, was da 
wirklich vorgeht und was gemacht werden muss damit es richtig ist. 
Vielleicht kann man es ja auch ohne malloc lösen.Hoffe auf Anregungen 
und Tipps,Danke.

von Dr. Sommer (Gast)


Lesenswert?

Bei 16kB RAM ist malloc so eine Sache. Versuche es ganz zu vermeiden. 
Musst du unbedingt während das Programm läuft verschiedene Ringbuffer 
zuvor unbekannter Größe anlegen und wieder löschen? Wenn nicht, legst du 
alle Ringbuffer fix mit bekannter Größe an (zB als globale Variablen) 
und sparst dir das malloc-Zeug komplett. zB so:
1
struct RingBuffer [
2
  char* data;
3
  size_t size;
4
};
5
6
char rb1Data [1024];
7
char rb2Data [64];
8
RingBuffer buffer1 = { rb1Data, 1024 };
9
RingBuffer buffer2 = { rb2Data, 64 };
10
11
void ringBufferInit (RingBuffer* b);
12
void ringBufferWrite (RingBuffer* b, char* data, size_t size);
13
void ringBufferRead (RingBuffer* b, char* data, size_t size);
In C++ mit Templates ginge das auch noch eleganter.

von Avr A. (colombo010)


Lesenswert?

Hallo, danke für die schnelle Antwort, also ich will per UART senden und 
empfangen also reichen zwei Ringbuffer. Die Größe ist auch bekannt. ich 
möchte auch alle Daten in Strukturen ablegen, um diese einfacher zu 
verarbeiten.

zb soll

struct nam {
   int size;
   char nname[20];

} data;

in den TX_buffer geschrieben werden. dann soll das ganze rausgeschickt 
werden.

von Dr. Sommer (Gast)


Lesenswert?

Dann funktioniert das ja mit meinem Vorschlag, musst diesen struct halt 
umcasten oder unions verwenden.

von Udo S. (urschmitt)


Lesenswert?

Wie willst du nur mit einer Variable size wissen wo das erste Byte zum 
Lesen ist und wo das erste freie Byte zum Schreiben?

Wie soll diese Funktion
void ringBufferWrite (RingBuffer* b, char* data, size_t size);
funktionieren?

von Dr. Sommer (Gast)


Lesenswert?

Jo die Implementation braucht natürlich noch Schreibpointer+Füllstand 
oder so im struct. Ich hatte nur die für die Fragestellung relevanten 
Dinge, nämlich Array-Pointer+Größe, hineingeschrieben.

Udo Schmitt schrieb:
> Wie soll diese Funktion funktionieren
Sie schreibt "size" bytes  aus "data" in den Ringbuffer.

von Avr A. (colombo010)


Lesenswert?

Ja, habs jetzt sowie im folgenden Link gemacht,

http://www.tschallener.net/AVR/intr_usart.pdf

was mir noch unklar ist, wie ich ein Struct in den Buffer 
reingeschaufelt bekomme, wahrscheinlich ist es nix wildes, habe halt 
noch keine Jahrelange Programmiererfahrung

von Dr. Sommer (Gast)


Lesenswert?

Mit casten:
1
struct nam;
2
nam.size = 5;
3
memcpy (nam.nname, "blubb");
4
ringBufferWrite (&buffer1, (char*) (&nam), sizeof (nam));

von Avr A. (colombo010)


Lesenswert?

ok, kannst du viell die Funktion definieren komplett, wenns keine Mühe 
macht natürlich :)

von Dr. Sommer (Gast)


Lesenswert?

Nä, die Mühe darfst dir selber machen :-P

von W.S. (Gast)


Lesenswert?

avr avr schrieb:
> zb soll
>
> struct nam {
>    int size;
>    char nname[20];
>
> } data;
>
> in den TX_buffer geschrieben werden.

HÄ?
Was soll denn das? Wenn du irgendwas per UART senden willst, dann gewiß 
Chars und keine Structs, gelle?

Also, mal ganz von vorne:
Ein Ringpuffer ist ein Speicherbereich, der von zwei unterschiedliche 
Instanzen benutzt wird: die eine schreibt hinein und die andere liest 
heraus (ok, Computerdeutsch..). Dazu gibt's 2 Zeiger. Die Zeiger lesen 
dürfen beide Instanzen, schreiben darf aber nur jede Instanz ihren 
eigenen Zeiger.

Beispiel:
1
#define buffersize 128
2
char Buffer[buffersize]; // das ist der Ringpuffer
3
int rdz, wrz;            // das sind die Zeiger
4
5
void InitBuffer (void)
6
{ wrz = rdz = 0; }
7
8
bool IsBufferFull (void)
9
{ int i;
10
  i = (wrz+1) % buffersize;
11
  return (i == rdz);
12
}
13
14
void PutIntoBuffer (char c)
15
{ int i;
16
  i = (wrz+1) % buffersize;
17
  if (i==rdz)
18
  { tja, Puffer ist voll, also was angemessenes hier tun }
19
  Buffer[wrz] = c;
20
  wrz = i;
21
}
Das aufrufende Programm braucht nur die Funktionen zu kennen, nicht aber 
den eigentlichen Puffer und die Zeiger. Modulintern muß es natürlich 
noch ne Funktion geben, die den Krempel dann auch wieder aus dem Puffer 
abholt und verarbeitet. Ins Headerfile gehören also nur
1
 
2
extern void InitBuffer (void); 
3
extern bool IsBufferFull (void);
4
extern void PutIntoBuffer (char c);
Beide Instanzen müssen dabei logischerweise mit dem gleichen Datentyp 
arbeiten, also wenn du nen char Buffer[..] kreierst, dann passen da nur 
Char's rein, wenn du nen verrückten struct Buffer[..] hernimmst, dann 
passen da eben nur verrückte struct's rein. (Deine Idee mit dem struct 
ist Mist)


Dr. Sommer schrieb:
> Wenn nicht, legst du
> alle Ringbuffer fix mit bekannter Größe an (zB als globale Variablen)
> und sparst dir das malloc-Zeug komplett. zB so:
> struct RingBuffer [
>   char* data;
>   size_t size;
> };

Den Sinn deines "RingPuffer"s sehe ich überhaupt nicht ein, wozu diesen 
unnützen struct, der nicht mal ein wirklicher Ringpuffer ist? Und den 
auch noch in globale Variablen? Zum Aufblähen des Codes? Zum Züchten von 
Bugs? Zum Verwirren von Anfängern?

Gute Programme erkennt man daran, daß sie Funktionalität sinnvoll 
kapseln.
Das hier ist das Gegenteil davon:
> char rb1Data [1024];
> char rb2Data [64];
> RingBuffer buffer1 = { rb1Data, 1024 };
> RingBuffer buffer2 = { rb2Data, 64 };
>
> void ringBufferInit (RingBuffer* b);
> void ringBufferWrite (RingBuffer* b, char* data, size_t size);
> void ringBufferRead (RingBuffer* b, char* data, size_t size);
.. mal abgesehen davon, daß dir immer noch die wichtigsten Teile das 
Ringpuffers fehlen.

W.S.

: Bearbeitet durch User
von Avr A. (colombo010)


Lesenswert?

Structs können Structs beinhalten gelle.
ließ mal den Code im Link, da ists mit lese und schreibzeiger, der 
Ringpuffer soll auch kein Struct sein, im Programm wird mit Structs 
gearbeitet und somit sollen die Bytes der Struktur in ein Ringpuffer, 
damit man man die Daten raussenden kann. Ich möchte also eine Funktion 
die den Buffer mit Inhalten aus dem Struct füllt.

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:

>> struct RingBuffer [
>>   char* data;
>>   size_t size;
>> };
>
> Den Sinn deines "RingPuffer"s sehe ich überhaupt nicht ein, wozu diesen
> unnützen struct, der nicht mal ein wirklicher Ringpuffer ist? Und den
> auch noch in globale Variablen? Zum Aufblähen des Codes? Zum Züchten von
> Bugs? Zum Verwirren von Anfängern?
>
> Gute Programme erkennt man daran, daß sie Funktionalität sinnvoll
> kapseln.
> Das hier ist das Gegenteil davon:
>> char rb1Data [1024];
>> char rb2Data [64];
>> RingBuffer buffer1 = { rb1Data, 1024 };
>> RingBuffer buffer2 = { rb2Data, 64 };
>>
>> void ringBufferInit (RingBuffer* b);
>> void ringBufferWrite (RingBuffer* b, char* data, size_t size);
>> void ringBufferRead (RingBuffer* b, char* data, size_t size);
> .. mal abgesehen davon, daß dir immer noch die wichtigsten Teile das
> Ringpuffers fehlen.
>

Die Idee (wenn auch nicht komplett durchgezogen, die Schreib- Lesezeiger 
fehlen), dürfte gewesen sein, mehrere Ringbuffer mit unterschiedlichen 
Größen instatiieren zu können. Daher die struct für den Ringbuffer 
selbst, daher die Übergabe einer derartigen Struktur an die Funktionen.

> W.S.

: Bearbeitet durch User
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.