268Byte verbraucht nur durch while(1)-Schleife?! Was macht der MPLAB wirklich?
Dienstag, 22. Mai 2012
 
 

PIC Mikrocontroller Forum  |  PIC Mikrocontroller  |  Entwicklungswerkzeuge  |  MPLAB  |  268Byte verbraucht nur durch while(1)-Schleife?! Was macht der MPLAB wirklich? « vorheriges nächstes »
Seiten: [1] Nach unten Drucken
Autor Thema: 268Byte verbraucht nur durch while(1)-Schleife?! Was macht der MPLAB wirklich?  (Gelesen 1232 mal)
 
Schoasch
Sr. Member
****
Offline Offline

Beiträge: 343



Profil anzeigen
« am: November 04, 2009, 21:47:14 »

Hi,

Ich hab da ein kleines Problem mit dem MPLAB.

Wenn ich folgenden Code compilieren will und mir dann den speicherverbrauch ansehe, wird mir gesagt, dass ich 268 Byte des "data memories" verbraucht habe.

Wie kann das sein? Und was kann ich dagegen tun?
Wenn ich mir das ASM-Listing ansehe, so macht der Chip irgendwas am Anfang, was ich ihm eigentlich nicht sage(zumindest nicht wissentlich ;-)

Könnt ihr mich bitte aufkläre, dass da los ist?

Code:
#include<p18f4320.h>
#pragma config WDT = OFF
#pragma config OSC = HSPLL
#pragma config MCLRE = ON
#pragma config LVP = OFF

void main(void)
{
unsigned char i=0;
while(1)
{
}
}

mfg Schoasch
Gespeichert
Stampede
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 969



Profil anzeigen WWW
« Antworten #1 am: November 04, 2009, 22:33:30 »

Hallo,

schau dir mal das Assembler Listing an, der effektiv für Code erzeugt.
Beachten musst du aber auch, dass Sachen wie Stack etc. für Variablenübergaben initialisiert werden. Im dem C18 Compilerhandbuch steht nochmal explizit drin, was das genau ist.

Gruß
Stefan
Gespeichert

Bernd
Globaler Moderator
Hero Member
*****
Offline Offline

Beiträge: 3815



Profil anzeigen
« Antworten #2 am: November 04, 2009, 23:40:07 »

Zitat
Wie kann das sein?

Zuerst sei gesagt, daß es nicht an MPLAB liegt, sondern am C18. Für lokale Variablen und die Parameter-Übergabe an Funktionen reserviert der C18 einen Software-Stack von 256 Bytes (eine Bank), sofern der Debugger nicht aktiviert ist. Aus dem Linkerscript:

Code:
// File: 18f4320_g.lkr
// Generic linker script for the PIC18F4320 processor

#IFDEF _CRUNTIME
    SECTION    NAME=CONFIG     ROM=config
    #IFDEF _DEBUGDATASTART
        STACK SIZE=0x80 RAM=gpr0
    #ELSE
        STACK SIZE=0x100 RAM=gpr1     // Bank1 mit 0x100 = 256 Bytes wird
                                      // für den Stack reserviert
    #FI
#FI

Die restlichen 12 Bytes sind vom Compiler für interne Zwecke reserviert, die in Deinem Beispielprogramm eventuell noch nicht benötigt werden,  aber in jeder „real world“ Anwendung verwendet werden.

Zitat
Wenn ich mir das ASM-Listing ansehe, so macht der Chip irgendwas am Anfang, was ich ihm eigentlich nicht sage(zumindest nicht wissentlich ;-)

Das ist der Startup-Code, den Du im Installationsverzeichnis des C18 unter \src\traditional\startup\ findest (bzw. \src\extendend\startup\, wenn Du den Extended-Mode des PICs verwendest).

Welche Datei konkret verwendet wird, hängt von den Einstellungen des Compilers ab. Wenn er Variablen beim Start initialisieren soll (müßte die Standardeinstellung des C18 sein), wird „c018i*“ verwendet. Ohne Intitialisierung jeglicher globalen Variablen (nicht wirklich sinnvoll in C) wird „c018*“ verwendet. Bei standardkonformer Einstellung des C18 findet „c018iz*“ Anwendung.

Zur Erklärung von „standardkonform“: Der ANSI-C Standard fordert, daß alle globalen Variablen (definiert außerhalb jeder Funktion) und alle statischen Variablen ohne explizite Wertzuweisung mit „0“ initialisiert werden.

Code:
unsigned char foo;            // globale Variable
static unsigned char bar;     // statische Variable

Gemäß ANSI-C hätten die beiden obigen Variablen den Wert „0“. Beim C18 in dessen Standardeinstellung ist deren Wert hingegen undefiniert. Um einen definierten Wert in der Standardeinstellung des C18 zu erhalten, muß die „0“ explizit angegeben werden:

Code:
unsigned char foo = 0;   
static unsigned char bar = 0;

Zitat
Und was kann ich dagegen tun?

Die einfachste Maßnahme wäre, im Linkerscript den für den Stack reservierten RAM-Bereich zu verkleinern (dazu das Linkerscript in das Projektverzeichnis kopieren, dem Projekt hinzufügen und STACK SIZE entsprechend anpassen).

Dabei mußt Du sicherstellen, daß selbst für den ungünstigsten „call path“ der Stack nicht überläuft (d.h. das mehr Bytes für die Übergabe von Parametern und lokale Variablen benötigt werden, als im reservierten Bereich aufgenommen werden können). Eine große Anzahl von lokalen Variablen oder eine Funktion, welche sehr viele andere Funktionen mit mehreren Funktionsargumenten aufruft, sind dabei natürlich zu vermeiden.

Eine weitere Möglichkeit wäre die Verwendung der Compiler-Option „-sco“. Dann sind die Funktionsparameter automatisch vom Typ „overlay“ und die lokalen Variablen „static“ und der Stack wird nicht mehr benötigt. Daraus resultierende Nachteile/Probleme siehe hier.

Generell kann man den Stack-Bedarf dadurch minimieren, daß Funktionsparameter als overlay und lokale Variablen als „static“ definiert werden.  Durch „overlay“ entstehen überhaupt keine Nachteile, da der für die Funktionsparameter reservierte Speicher mehrfach verwendet werden kann (der Speicherbedarf wird nur vom Stack in das „normale“ RAM verschoben). „static“ hingegen reserviert die lokalen Variablen einer Funktion für die Laufzeit des gesamten Programms, d.h.  dieser Bereich des RAMs kann von keiner anderen Funktion genutzt werden.

Der Ansatz mit „overlay“ allein (bei vielen Funktionsargumenten oder großer Aufruftiefe) ist am vielversprechendsten in Bezug auf den RAM-Bedarf und der Compiler-Einstellung „-sco“ i.A. vorzuziehen.

Viele Grüße

Bernd
Gespeichert

Seiten: [1] Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  

Powered by MySQL Powered by PHP Made for Mozilla (Firefox) Made for Internet Explorer
Seite erstellt in 0.04 Sekunden mit 19 Zugriffen.
 
Top! Top!