SprinterSB
31.10.2005, 14: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__ */
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__ */