PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : GNU C-compiler, Atmega und Array kontrolle



Arexx-Henk
25.12.2005, 09:56
Hallo,

Frohes Weihnachten!

Ich benutze Programmers Notepad2 mit GNU gcc.exe compiler und Atmega8 (Asuro Roboter).

Jetzt mochte ich Messdaten realtime speichern und spater auslesen.

Die Atmega8 hat 1Kb static ram.

wenn ich programmiere:


unsigned char MeinArray[2000];

gibt es kein compiler meldung dass die speicher im Atmega8 zu klein ist und wird mein Program einfacht ausgefuht wobei andere variabelen uberschrieben werden.

Wie konnte ich dies kontrolieren?

Gruss,

Henk

PicNick
25.12.2005, 12:11
Wie konnte ich dies kontrolieren?

Einfach: 27-mal durchlesen und mitdenken.
Die erste und oberste Kontroll-Instanz bist du selber. Der Speicher wird ja auch dynamisch vom Stack verbraten, sodaß eine automatische Kontrolle sowieso nur teilweise hilfreich sein kann.
Ich nehme an, daß "2000" ein Schreibfehler ist, und das ist wenigstens einer der Sorte, die recht schnell auffällt. Da gibt's trickreichere Fehler, die sich besser verstecken.

Arexx-Henk
25.12.2005, 15:21
Hallo.

die '2000' ist kein schreibfehler sondern nur ein Beispiel wie man falsch programmieren kan ohne das die compiler ein fehlermeldung gibt.

ich denke vielleicht sollte mann 'allocmem()' oder sonstiges verwenden, nur weiss ich nicht ob dass functioniert oder dass ein 'false' zuruck gegeben wird wenn nicht genug speicher da is.

Gruss

Henk

PicNick
25.12.2005, 16:39
Ich hab gedacht, es ist ein Schreibfehler, denn ein Programmdesign mit 2000-Byte arrays für eine Mega8 ist doch recht bedenklich.
false/allocmem etc. könnten zur Laufzeit was dazu sagen, richtig.
aber:
char xy[2000] legst du ja dem kompiler vor die Nase. Du kannst bestenfalls mit dem Präprozessor mit RAMEND oder ähnlichem
vergleichen.

super_castle
25.12.2005, 16:51
"die '2000' ist kein schreibfehler sondern nur ein Beispiel wie man falsch programmieren kan ohne das die compiler ein fehlermeldung gibt."

Im Datenblatt des AVR steht drin, wieviel Speicher man nutzen kann....
Der Progger sollte dran denken.
Beim proggen sollte man mitdenken.

Der Gnu ist halt Freeware, was verlangst du davon...Perfektion umsonst.. nein.

Castle

Kaiser-F
21.04.2006, 06:59
Hi,

Ich habe auch ein Problem!

Ich programmiere gerade mein Grafik-LCD im ATMega8535.
Ich möchte das programmtechnisch so realisieren, dass die Pixel zunächst in einem Bildspeicher geschrieben werden.

Wenn eine Veränderung des Bildspeichers vorliegt, wird der gesamte Bildspeicher zum LCD übertragen.

Das LCD hat 128x64 Pixel. Also wollte ich dafür ein Array verwenden:

uint64_t LCD_BILD[128];

64 sind 8Byte,
8Byte * 128 ergibt 1024Byte, also 1KB.

Der Compiler bringt keine Fehlermeldung. Auch die größe des zu flashenden Programms ist bei rund 2-3 KB (von 8KB ).

Doch das Programm hängt dann bei: uint64_t LCD_BILD[128];

Ich habe auch ein anderes Array, welches eine Schriftart enthält.
( uint8_t FONT1[660]; ). Da gibds kein Problem.

Ich hoffe jemand kann mir da weiterhelfen... ](*,)

Kaiser-F
21.04.2006, 07:27
Hab schon umgeschrieben auf ein Mehrdimensionales Array:

uint8_t BILDSPEICHER[8][128];

Aber, gehd auch nicht. Sind ja auch 1KB

? WHY IS IT NOT FUNZING ?

Kaiser-F
21.04.2006, 07:38
Tut mir leid wegen dem Massenposting 8-[

Also, innerhalb der main-Funktion kann ich es Deklarieren.

Ausserhalb nicht!!!

WARUM? das versteh ich nun wirklich nicht...

uint8_t BILDSPEICHER[8][128];

SprinterSB
22.04.2006, 09:26
Vieliel RAM hat denn der 8535? AFAIK het er 1kByte, und das ist zu wenig für ein Array von 1k, weil noch andere Sachen im RAM stehem müssen (Stack, globale Variablen, etc).

Übrigens: GCC ist zwar freie Software, aber deshalb nicht automatisch kostenlos. Und auch von freier Software kann man verlangen oder erwarten, daß sie fehlerfrei ist bzw. Fehler abfängt oder anmeckert.

Allerdings kann ein Compiler solche Sachen nicht melden, das kann bestenfalls ein Linker oder Locator. Ein C-Compiler weiß ja nicht, für welchen Controller übersetzt wird (z.B., wenn man Module in eine Lib tut, und zum Linken wieder entnehmen will).

Daß der Linker nicht meckert ist zumindest ein Schnatzer. Es bietet sich dann an, mit avr-size die Großen zu kontrollieren. Ggf kann man das auch automatisieren im Makefile, die Größen berechnen lassen und nen Fehler werfen, wenn .data+.bss+.noinit zu groß sind.

Kaiser-F
22.04.2006, 11:34
Hm...
Aber das Komische ist folgendes:

Programm:

So gehts nicht:



// AVR-Includes
#include <avr/io.h>

uint8_t BILDSPEICHER[8][128];

int main (void)
{

while(1){
}
}


Und so geht es:



// AVR-Includes
#include <avr/io.h>

int main (void)
{

uint8_t BILDSPEICHER[8][128];

while(1){
}
}

ogni42
22.04.2006, 12:32
Das sind zwei unterschiedliche Speicherarten, die Du verwendest:
Im ersten Fall wird statisch - also zur Compilezeit - Speicherplatz reserviert. In Deinem Fall müsste das .bss Block Storage Segment, d.h. uninitialisierter Speicher im RAM sein.
Im zweiten Fall wird der Speicher erst bei Aufruf der Funktion auf dem Stack reserviert. Das kann der Linker nur dann prüfen, wenn man ihm vorher sagt, wie groß der Stack maximal ist. Da die Variable ebenfalls nicht initialisert ist reicht es, in Assembler den Stackpointer entsprechend zu verschieben und sich nur die Anfangsadresse des Bereiches auf dem Stack zu merken. Dass das auf der Zielhardware nicht passt, kann der Compiler in dem Fall nicht wissen - und dem Linker sagt's ja niemand.

SprinterSB
22.04.2006, 13:08
Egal wie du es drehst: Die 64*128 Bit bekommst du keinesfalls im RAM unter, auch wenn der Compiler nicht meckert! Wenn du 1kByte auf dem Stack allokierst un dein RAM ist 1k groß, dann läuft der SP einfach 1 mal rum. Mehr Platz hat dein RAM deshalb noch lange nicht...

Wie gesagt, manchmal hilft einem Brain 1.0 schneller und effektiver als Compiler x.y ;-)

SprinterSB
22.04.2006, 13:49
Zumindest gibt's die Möglichkeit, zur Laufzeit zu reagieren. Wünschenswert wäre aber ein Fehler zur Linkzeit :-(

#include <avr/io.h> // RAMEND
extern char __heap_start; // from linker script

int main ()
{
if ((uint16_t) & __heap_start > RAMEND)
panic();
...
}
Nich das Gelbe vom Ei, aber immerhin...

Das gehl allerdings nur modulo 65535. Wenn du ein
char[65600] machst, landest du nicht in panic().

Kaiser-F
22.04.2006, 14:26
ÄÄÄHMMM

<-- NIX FRRRRSTÄÄÄN :-)

Kaiser-F
22.04.2006, 14:26
Aber wenn ichs einfach in der Mainfunktion Initialisiere gehds ja...

SprinterSB
22.04.2006, 14:34
Was geht? Es wird compilert oder es läuft wie es soll?

Es wird vielleicht compilert. Aber es sollte nicht lauffähig sein...

Die Größe kann man auch aus dem Mapfile rauslesen lassen:

grep 'PROVIDE.*__heap_start' <MapFile>, wobei für <MapFile> der Name des MapFiles einzutragen ist.

Das sollte dann so aussehen:
0x0080814d PROVIDE (__heap_start, .)

Die maximale Adresse darf
0x800060+RAMEND sein. Für einen ATmega8 also 0x80045f

Evtl. noch durch sed oder gawk pipen zum Automatisieren.

Kaiser-F
22.04.2006, 14:37
Er compiliert, und es gehd dann auch...

Aber nur, wenn es innerhalb der main-Funktion steht.

uint8_t BILDSPEICHER[8][128];


Andernseits sind ja FONTS auch als ARRAY speicherbar... das sind auch sehr sehr viele bytes. Die gehen ja auch...


EDIT: ich verwende ATMEGA8535 später dann ATMEGA32 !

SprinterSB
22.04.2006, 14:41
Der ATmega8535 hat aber doch nicht mehr als 1k RAM, oder irre ich mich da.. Verrats doch einfach, bevor man sich das wo zusammensuchen muss in Netz oder in PDFs die man nicht hat!

Fonts sollte man nicht in's RAM legen; zumindest nicht, wenn sie nicht verändert werden.

Manno, oben das war ein Beispiel. Das auf deine Umgebung zu übertragen wirst du noch schaffen, oder?

izaseba
22.04.2006, 15:09
Hier (http://www.atmel.com/dyn/resources/prod_documents/doc2502.pdf)
ist ein Dattenblatt zu Mega 8535, er hat 512 Bytes RAM

Gruß Sebastian

izaseba
22.04.2006, 15:31
grep 'PROVIDE.*__heap_start' <MapFile>

Evtl. noch durch sed oder gawk pipen

Sprinter, eine Frage,
Klappt das jetzt unter Dos ?
Ich dachte immer, daß so mächtige Werkzeuge nur in der Unixwelt existieren
:-k
Klär mich bitte auf :-)

Gruß Sebastian

SprinterSB
22.04.2006, 17:54
Ich dachte immer, daß so mächtige Werkzeuge nur in der Unixwelt existieren :-k

Mit WinAVR hat man einen Happen der Macht auch unter WinDos *g*.

Schau mal unter
<WinAVR-HOME>/utils/bin

Da gibt es feine Sachen wie make, gawk, sed, grep, egrep, bc, wc, uuencode/decode, basename, diff, md5sum, m4, sh, etc

izaseba
22.04.2006, 18:07
Happen der Macht

Mit mächtig meinte ich eher "klein aber fein", aber danke für die Erklärung :-)

Gruß Sebastian

Kaiser-F
22.04.2006, 18:58
Danke für die Antworten.


Der ATmega8535 hat aber doch nicht mehr als 1k RAM, oder irre ich mich da.. Verrats doch einfach, bevor man sich das wo zusammensuchen muss in Netz oder in PDFs die man nicht hat!


Sorry... Aber ich hatte oben erwähnt dass ich den ATMEGA8535 verwende. Hab aber leider vergessen auf deine Frage, wieviel RAM der hat, zu antworten.



Hi,

Ich habe auch ein Problem!

Ich programmiere gerade mein Grafik-LCD im ATMega8535....


Das mit dem RAM leuchtet mir jetzt ein. Der hat tatsächlich nur 512Byte.
Ich war irgendwie schon so auf Mega32... der hat 2KB... aber das wäre trotzdem zu viel Belastung, der soll ja auch noch mehr machen.

Das über die Speicherarten möchte ich mir noch genauer erarbeiten.
Das mit STAK usw... Ich Programmier ja nun doch erst seit nem knappen Jahr.... :oops:

habt ihr da nen Link, wo das erklärt wird?

SprinterSB
22.04.2006, 19:24
Vielleicht bei Onkel Wicki?
http://de.wikipedia.org/wiki/Stapelspeicher

ogni42
23.04.2006, 13:34
Schau mal in einem C-Tutorial nach den Speicherarten (z.B. "auto"). Da steht dann alles erklärt.