Hallo zusammen!
Nachdem ich nun den ganzen Tag herum gesucht habe auf sämtlichen AVR
Seiten und Foren und leider keine explizite Antwort bekommen habe,
versuche ich nun doch mit meine Fragen an die Öffentlichkeit zu gehen.
Ich habe ein Programm mit vielen printf- Funktionen geschrieben.
Mein „Debugging“ mache ich über das HTerminal. Um den Programmablauf
nachvollziehen zu können benötige ich die printf Funktionen. Jedes
Zeichen im printf „klaut mir“ ein Byte im SRAM, soweit ist das klar.
Ich benutze einen ATMega 2561. Durch die bereits implementierten printfs
usw. ist mein Data: (.data + .bss + .noinit) schon bei 3206 bytes (39.1%
Full)
Mein Problem ist nun, dass ich einen Global Array von [6144] Werten
erzeugen muss, um eine Tabelle einlesen zu können. Die Tabelle wird im
SRAM abgespeichert. D.h. mein SRAM steigt auf ganze auf Data:9350 bytes
(114.1% Full) (.data + .bss + .noinit) an.
D.h. das Programm ist unbrauchbar und ich kann es nicht mehr verwenden.
Hardwaretechnisch ist schon alles gefixt, so dass ich auch keinen
externen SRAM mehr anbauen kann.
Wie kann ich denn nun schnell und effizient den SRAM nicht so auslasten
und den Speicher für die Tabelle garantieren??
Gibt es die Möglichkeit die uint8_t Tabelle[6144] über PROGMEM in den
RAM zu schreiben,
diese dann während der Programmlaufzeit mit Werten zu füllen und später
wieder auszulesen??
Wäre echt super wenn mir jemand einen Rat hätte!
Vielen Dank
------------------------------------------------------------------------
-------------------------------------------
Build started 20.8.2008 at 19:52:40
avr-gcc.exe -mmcu=atmega2561 -Wl,-Map=weiterleitung.map 2561.o Delay.o
RS232.o TWI216.o Main.o TWI_Master.o TMCadvanced.o TMCbasic.o USART.o
Interrupt.o -o weiterleitung.elf
avr-objcopy -O ihex -R .eeprom weiterleitung.elf weiterleitung.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load"
--change-section-lma .eeprom=0 --no-change-warnings -O ihex
weiterleitung.elf weiterleitung.eep || exit 0
avr-objdump -h -S weiterleitung.elf > weiterleitung.lss
AVR Memory Usage
----------------
Device: atmega2561
Program: 17984 bytes (6.9% Full)
(.text + .data + .bootloader)
Data: 9350 bytes (114.1% Full)
(.data + .bss + .noinit)
Build succeeded with 0 Warnings...
Build succeeded with 1 Warnings...
vielen Dank für die schnelle Antwort!
ich habe
#if DEBUG
#include <stdio.h>
#define PRINTF(s, ...) do{ static char __s[] PROGMEM = (s); \
printf_P(__s, ## _VA_ARGS_); }while(0)
#else
#define PRINTF(s, ...)
#endif
eingefügt und alle printf mit PRINTF ersetzt.
Das Resultat war deutlich spürbar:
Von Data: 9350 bytes (114.1% Full) bin ich wirklich auf Data: 6476 bytes
(79.1% Full) gekommen bei meinem 8K SRAM.
eine Frage habe ich noch:
Werte von Variablen werde ich wahrscheinlich mit der printf funktion
printf(" %d \n", UDR); auf den Bildschirm hohlen müssen ??
Wenn ich mehrere C-Files habe, muss ich dann #if DEBUG ... #endif in
jedes File einfügen? oder nur in mein Global.h oder in die Main.C ??
vielen Dank
Hans-Jakob
Häng diese Definition in ein zentrales Includefile. Also dein Global.h.
Das geht natürlich genauso:
PRINTF(" %d \n", UDR);
oder
PRINTF("-%S-", PSTR("irgendeintextimROM"));
Das Makro sorgt nur dafür, dass der erste Parameter automatisch im ROM
landet und die dazu passende printf-Version aufgerufen wird, ansonsten
ist das mit dem normalen printf identisch.
Ach ja: DEBUG muss natürlich irgendwie !=0 definiert sein. Ich habe
üblicherweise ein zentrales Config-Include, in dem dann
#define DEBUG 1
steht. Und wenn das Debugging nicht mehr gebraucht wurd, dann wird das
0.
Okay! Super! vielen Dank!
deinen letzten Beitrag kapiere ich leider nicht.
Wie ist das mit dem #define DEBUG 1
und dem "Und wenn das Debugging nicht mehr gebraucht wurd, dann wird das
0."
kannst du mir da evtl ein bsp Quellcode zeigen?
Danke
#define DEBUG 1
=> die PRINTF Statements werden übersetzt und ggf. ausgeführt.
#define DEBUG 0
=> die PRINTF Statements werden vom Compiler komplett ignoriert.
Wenn DEBUG nicht definiert ist, wirkt das als wäre es 0, so dass der
Code vom Compiler ignoriert wird. Das spart natürlich doppelt Platz. Nur
kriegst du so auch keine Ausgabe zu sehen.
Also folgende Funktionen funktionieren nicht:
PRINTF(" %d \n", UDR);
PRINTF("bitte mal UDR ausgeben %d \n", UDR);
PRINTF("-%S-", PSTR("irgendeintextimROM"));
Desweiteren bin ich echt zu doof dieses #define DEBUG 1 oder #define
DEBUG 0 einzubauen.
Da kommt immer eine Fehler Meldung, das DEBUG redefined wird.
ob ich es in Golobal.h oder Main.c einbaue.
Zusätzlich habe ich festgestellt, wenn ich eine der nicht
funktionierenden Funktionen einbaue, überhaupt keine Ausgabe auf dem
Terminal stattfindet und sobald ich versuche diese nicht
funktionierenden Funktionen wieder ausklammere mit // und es dann wieder
compile und builde das ganze trotzdem nicht funktioniert.
Erst wenn ich eine Kopie des ganzen Programmes mache und dies wieder
zusammen builde läuft die Kopie des Programmes, bis ich wieder eine
nicht funktionierende Funktion einbaue.
------------------------------------------------------------------------
---
AVR Studio 4.14.589
GUI Version 4, 14, 0, 589
AVR Simulator 1, 0, 2, 1
ATmega2561 167
Operating System
Major 5
Minor 1
PlatformID 2
Build 2600
Service Pack 3
Plugins:
AvrPluginAvrAsmObject 1, 0, 0, 46
AvrPluginavrgccplugin 1, 0, 0, 9
Stk500Dll 1, 0, 1, 10
Zudem verwende ich die RS232.c und RS232.h Versionen aus
Beitrag "AVR TWI Master und Slave Funtionen in C"
und WinAVR-20080512
Hans Jakob wrote:
> Also folgende Funktionen funktionieren nicht:>> PRINTF(" %d \n", UDR);>> PRINTF("bitte mal UDR ausgeben %d \n", UDR);>> PRINTF("-%S-", PSTR("irgendeintextimROM"));
"funktionieren nicht"? Was heißt das im Klartext?
Und wenn du DEBUG nochmal definierst, obwohl es schon definiert war,
dann kommt der von dir genannte Fehler. Hast du schon irgendwo DEBUG im
Code definiert? u.U. in deinen RS232 Quellen?
> "funktionieren nicht"? Was heißt das im Klartext?
Der Compiler baut alles schön zusammen und alles ist bereit zum Flashen.
Nach korrektem Anschließen und Verbindungsaufbau an das Terminal müsste
die Bildschirmausgabe kommen. Diese kommt nicht.
>Hast du schon irgendwo DEBUG im Code definiert? u.U. in deinen RS232 >Quellen?
Das einzige was ich gemacht habe ist das Macro von oben miteingebaut
(#if DEBUG...#endif) und dann den Rat befolgt:
>>#define DEBUG 1>> => die PRINTF Statements werden übersetzt und ggf. ausgeführt.>>#define DEBUG 0>> => die PRINTF Statements werden vom Compiler komplett ignoriert.
schreibe ich nun #define DEBUG 1 hinzu kommt folgende Fehlermeldung:
GlobalTest.c:24: undefined reference to `PRINTF_P'
@ Andreas Kaiser: das war der interessanteste Beitrag seit 2 Monaten,
den ich hier gelesen habe :) Hatte auch Tabellen mit Pointern auf
Funktionen, die nun im ROM gelandet sind. Danke!
Hans Jakob wrote:
> schreibe ich nun #define DEBUG 1 hinzu kommt folgende Fehlermeldung:> GlobalTest.c:24: undefined reference to `PRINTF_P'
Dann hast du irgendwo im Makro PRINTF_P statt printf_P stehen.
Artur F***** wrote:
> den ich hier gelesen habe :) Hatte auch Tabellen mit Pointern auf> Funktionen, die nun im ROM gelandet sind. Danke!
Das ist schon ein bischen um die Ecke gedacht, denn während das mit
printf ziemlich transparent abläuft musst du dir die Pointer mit
pgm_read_word zu Fuss aus dem ROM fischen.
> fp FCTN = pgm_read_word(CMD_f) [CMD_BYTE];
Ich glaube kaum, dass diese Zeile vom Compiler überhaupt geschluckt
wird.
fp FCTN = (fp)pgm_read_word(&CMD_f[CMD_BYTE]);
>Ich glaube kaum, dass diese Zeile vom Compiler überhaupt geschluckt>wird.
Hast recht, war eigentlich: fp FCTN = pgm_read_word(CMD_f [CMD_BYTE]);
gemeint.
>fp FCTN = (fp)pgm_read_word(&CMD_f[CMD_BYTE]);
&CDM_f leuchtet mir ein, aber warum muss vor pgm_read.. noch (fp) vor?
Dein Vorschlag geht übrigens! Danke für die Hilfe.
Artur F***** wrote:
>>fp FCTN = (fp)pgm_read_word(&CMD_f[CMD_BYTE]);> &CDM_f leuchtet mir ein, aber warum muss vor pgm_read.. noch (fp) vor?
pgm_read_word liefert ein uint16_t zurück. Der Cast macht daraus wieder
den gewünschten Typ.
Was du auch noch beachten solltest:
Keine Seiteneffekte in den PRINTF - Parametern auslösen, sonst läuft das
Programm später mit ausgeschaltetem Debugging nicht mehr.
Beispiel:
PRINTF("UDR=%d\n",UDR);
liest das UDR-Register, und setzt damit ggfs das RXC-Bit zurück oder
holt das nächste Byte aus dem FIFO.
mit
#define DEBUG 0
wird das UDR-Register nicht mehr gelesen, und das Programm verhängt sich
evtl. in endlosen Interrupt-Aufrufen usw.