PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wieviel SRAM ist noch frei?



SprinterSB
31.10.2005, 13:19
Werkzeuge wie avr-size können keine Informationen über den Laufzeit-Verbrauch an SRAM liefern. Das liegt in der Natur der Sache, weil der Verbrauch nicht statisch bestimmt werden kann. Zumindest nicht von avr-size, und nicht für ein allgemeines Programm.

Falls es interessiert, wie viel SRAM man noch zur Verfügung hat, geht das mit folgendem Code. Dabei wird vorausgesetzt, daß keine dynamische Speicherverwaltung mit malloc() und Konsorten verwendet wird und das SRAM maximal 64k groß ist. __builtin_alloca() stellt kein Problem dar.

In der init-Sequenz wird ein Muster ins SRAM geschrieben. Zur Laufzeit kann mit der Funktion
unsigned short get_mem_unused(void)
getestet werden, wie viel von diesem Muster noch intakt ist und nicht von Stackframes der Funktionen/Interruptroutinen überpinselt wurde. Damit hat man einen Anhaltspunkt, wie weit der Stack bislang maximal nach unten gewachsen ist. Kann man dann ins EEPROM merken und auslesen oder aufs Display/PC weiterschicken. Das vom Benutzer verwendete SRAM, wo Variablen etc liegen (Sections .data, .bss und .noinit), ist schon berücksichtigt und muss nicht mehr abgezogen werden.

Das Modul mit -O1, -O2 oder -Os übersetzen.

mem-check.h:

#ifndef _MEM_CHECK_H_
#define _MEM_CHECK_H_

extern unsigned short get_mem_unused (void);

#endif /* _MEM_CHECK_H_ */

mem-check.c:

#include <avr/io.h> // RAMEND
#include "mem-check.h"

#if !defined (__OPTIMIZE__)
#warning mem-check funzt nur mit Optimierung

unsigned short
get_mem_unused (void)
{
return 0;
}

#else /* __OPTIMIZE__ */

// Mask to init SRAM and check against
#define MASK 0xaa

// From linker script
extern void* __heap_start;

unsigned short
get_mem_unused (void)
{
unsigned short unused = 0;
const unsigned char *ramend = (unsigned char*) RAMEND;
unsigned char *p = (unsigned char*) &__heap_start;

do
{
if (*p++ != MASK)
break;

unused++;
} while (p < ramend);

return unused;
}

// Init SRAM to MASK
// !!! Do never call this function !!!
void __attribute__ ((naked, section (".init2")))
__init_mem (void)
{
unsigned char *p = (unsigned char*) &__heap_start;
const unsigned char *ramend = (unsigned char*) RAMEND;

do
{
*p++ = MASK;
} while (p < ramend);
}

#endif /* __OPTIMIZE__ */

PicNick
31.10.2005, 13:39
Gute Idee.
Ich frag' mich grad', ob ein Pattern notwendig ist ? Return addr. = 0 gibt's doch eigentlich genausowenig ?

SprinterSB
31.10.2005, 14:11
Ich denk schon, daß man ein Muster braucht.

Auf dem Stapel wird ja auch der Frame angelegt, der dient ja nicht nur für Rücksprung mit rets/reti. Zudem werden auch Register dort gesichert im Funktions/ISR-Prolog. Und Registerinhalte können durchaus 0 sein.

Der Hauptgrund ist aber, daß das SRAM der AVRs nach PORST (power on/down reset) keinen definierten Zustand hat. Was als Saat für Pseudo-Zufall praktisch ist, würd hier dazu führen, daß man schnell einen Wert findet, der != Pattern ist, und man wäre fehlinformiert.

PicNick
31.10.2005, 14:20
Ja sicher, hast eh' recht, außerdem was soll's, frißt ja kein Brot.

0tes-Gesetz
06.07.2006, 14:55
Ich stell mich etwas blöd an, aber wie nutze ich die obigen Codeschnipsel bitte?

Bisheriges erfolgloses Vorgehen:

Ich hab eine "mem-check.h" in "/utils" abgelegt und binde sie wie die twi.h in mein Programm ein, also..

#include <util/mem-check.h>

mem-check.h:

#ifndef _MEM_CHECK_H_
#define _MEM_CHECK_H_

extern unsigned short get_mem_unused (void);

#endif /* _MEM_CHECK_H_ */

und dann hab ich den anderen 'mem-check.c'-CODE in mein Programm kopiert vor die ganzen ISR's und nach den globalen Variablendeklarationen.

Das Programm wird schon immer mit -Os compiliert, also sollte ich die "Forderung" nach optimierter Übersetzung erfüllen, oder?

Das Problem ist nun eine Fehlermeldung während des compilierens, bei dem es die Art, wie ich die get-mem-unused aufrufe moniert.
Ich rufe die Funktion folgendermassen auf:

volatile uint8_t test=0;

..

test = get-mem-unused;

Fehlermeldung:
error: invalid arguments to binary

Was mach ich falsch?

Danke & Grüße
0tes_Gesetz

PicNick
06.07.2006, 14:58
Die function ist vom typ "short", test ist aber nur n'byte ?

0tes-Gesetz
06.07.2006, 15:32
Thx für die Antwort, aber das Verstellen des Variablentyps der Variable 'test' von "uint8_t" auf "unsigned short" oder "uint16_t" brachte keinen Erfolg.

Fehlermeldung nach wie vor:
error: invalid arguments to binary

Wenn ich die Funktion über ..

test = get-mem-unused;

..aufrufe.

Grüße
0tes_Gesetz

PS: was bedeutet "invalid arguments to binary" ... "ungültige Argumente in/für Binary"? - welche Binary?
Die Funktion get-mem-unused braucht doch keine Übergabeparameter, oder? - ist doch (void)...

PicNick
06.07.2006, 15:35
test = get-mem-unused;

Du machst das aber schon mit Klammer ?
test = get-mem-unused();

0tes-Gesetz
06.07.2006, 15:38
Jetzt ja!!

:D

Ganz großes Dankeschön.

Grüße
0tes_Gesetz

PicNick
06.07.2006, 15:39
Na, sehen sie, Herr Kollege, kaum macht man's richtig, geht's. :mrgreen:

SprinterSB
06.07.2006, 15:45
Ich hab eine "mem-check.h" in "/utils" abgelegt und binde sie wie die twi.h in mein Programm ein, also..

#include <util/mem-check.h>

:-k das ist nicht so sehr geschickt. Falls du sowas machen willst dann leg die header in ein eigened Verzeichnis, etwa nach c:\eigene\include\util

und fütterst den Compiler mit der Option (Win32)

-I/c/eigene/include
Dadurch sucht gcc auch in den I-Pfaden nach System-Includes die in <> stehen, und du musst nicht die gcc-Datei-Struktur aufbohren!

geronet
06.04.2007, 11:37
Kann das sein dass der Code mit dem neustem WinAVR nicht funktioniert?

Ich hab jetzt mal einen Bugreport geschrieben:
http://sourceforge.net/tracker/index.php?func=detail&aid=1695514&group_id=68108&atid=520074

Grüsse, Stefan

geronet
06.04.2007, 13:10
Fehler gefunden:
Falsch:


void __attribute__ ((naked, section (".init8")))
__init8_mem (void)
{...
Richtig:

void __init8_mem (void) __attribute__ ((naked, section (".init8")));
void __init8_mem (void)
{...


Könnte das einer mal im Wiki ändern?
Link: https://www.roboternetz.de/wissen/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc

SprinterSB
07.04.2007, 00:14
Ja, du kannst es ändern.

Solle aber beides gehen (wenn dein gcc keinen bug hat ;-)).