Progmem zuweisungen

Gast #3434290
Lesenswert?

Guten Tag,

eine Frage meinerseits zum Einsparen von RAM.  Ich arbeite mit dem 
ATmega32.

Gibt es noch andere Möglichkeiten ausser:

1)
PrintString(PSTR("Hallo"));

oder

2)
#define PrintString(__pstr,x)   PrintString_P((PSTR(__pstr)),x)

PrintString("Hallo");




Danke für alle Hilfe. :)
#3434300
Lesenswert?

mem schrieb:
> Guten Tag,
>
> eine Frage meinerseits zum Einsparen von RAM.  Ich arbeite mit dem
> ATmega32.
>
> Gibt es noch andere Möglichkeiten ausser:

Was gefällt dir an den beiden Möglichkeiten nicht?
Sind doch perfekt!

Das einzige was man bekritteln könnte ist, dass aus dem Funktionsnamen 
'PrintString' nicht unmittelbar ersichtlich ist, dass es sich dabei um 
eine Spezialversion handelt, die den String im Flash erwartet (das ist 
doch so programmiert, oder nicht?). Aus dem Grund gibt es eine 
Konvention, dass derartige Funktionen hinten im Funktionsnamen ein _p 
oder ein _P haben. Aber das ist nur eine Konvention.
Gast #3434308
Lesenswert?

Karl Heinz schrieb:
> Was gefällt dir an den beiden Möglichkeiten nicht?
> Sind doch perfekt!


Bei der ersten Möglichkeit muss man ständig das "PSTR()" mitschleifen, 
was unschön ist. Bei der zweiten Möglichkeit gefällt mir nicht, dass ich 
dem user ein Makro nach außen liefere anstatt einer Funktion.

Hinweis:  Ich schreibe eine Bibliothek, welche dann vom user in seine 
Projekte einfefügt werden soll. Da würde ich ihm gerne im Header-File 
als Schnittstelle liefern: void PrintString (uint8_t *String);
anstatt: #define PrintString(__pstr,x)   PrintString_P((PSTR(__pstr)),x)

Ist das irgendwie hinzubekommen? :)
#3434319
Lesenswert?

mem schrieb:

> Bei der ersten Möglichkeit muss man ständig das "PSTR()" mitschleifen,
> was unschön ist. Bei der zweiten Möglichkeit gefällt mir nicht, dass ich
> dem user ein Makro nach außen liefere anstatt einer Funktion.

So schlimm ist das auch wieder nicht.

flash Pointer, wie von Marc angeführt, vereinfachen zwar einiges, lösen 
aber nicht das Problem, dass im Aufruf
1
  PrintString_P( PSTR("Hallo") )
für den Compiler klar gemacht werden muss, dass dieser String im Flash 
residieren soll. Um den Teil kommt man meines Wissens nicht herum. Auch 
nicht durch flash Pointer. Dann muss man eben, unter Zuhilfe nahme des 
im Tutorial angebenen Makros FSTR schreiben
1
  PrintString_F( FSTR("Hallo") );
ok. Einen Vorteil hat letztere Lösung. Da das "flash_" Teil des 
Datentyps ist, ist es für den Compiler prüfbar, ob man hier einen Fehler 
gemacht hat. Ein
1
  PrintSring_F( "Hallo" );
müsste zu einem Fehler führen, was in der alten Systematik nicht so ist.
Gast #3434340
Lesenswert?

mem schrieb:
> Hinweis:  Ich schreibe eine Bibliothek, welche dann vom user in seine
> Projekte einfefügt werden soll. Da würde ich ihm gerne im Header-File
> als Schnittstelle liefern: void PrintString (uint8_t *String);

Das kannst auch einfach so machen. Der gcc unterscheidet keinen Ram- und 
Flash-Pointer, für den ist das alles das gleiche. Damit muß die Funktion 
selber wissen, wo sie das Arguemnt herholen muß.
Deshalb gibt es z.B. in der avrlibc die Stringfunktionen doppelt, einmal 
normal mir Argument im RAM, und einemal mit _p hintendrann, die erwartet 
das Argument im Flash.

Das Makro in PSTR("Hallo") braucht es ja nicht für den Aufruf der 
Funktion, sondern um die Konstante "Hallo" in den Flash zu befördern. 
Das geht halt bei der Verwednung einer Konstaneten als Argument nicht 
anders.

Oliver
Persönliche Seite #3434362
Lesenswert?

@Karl Heinz
Ebnend ist für den Abruf nichts besonders nötig, nur zum Ablegen ist
das __flash nötig. Zu lesen dann nicht mehr.
1
static const __flash uint8 TEMP = 0x44;

und schon ist Temp eine Flash Konstante, und kann so verwendet werden 
ohne
nochmal explizit auf einen anderen Speicherort hinweisen zu müssen.
(gilt analog für natürlich auch für Pointer oder andere Strukturen).

dazu ggf.
http://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html

Bei der Verwendung der Krücke PROGMEN ist das so das man den Compiler
jedes mal sagen musste das das benötigte DATUM im Flash residiert.

Kennen sollte man beides, ich bin persönlich weg von PROGMEN bei neuen 
Code.
Gast #3434373
Lesenswert?

Marc D. schrieb:
> Wenn dein C Compiler GCC und >= 4.7 ist dann darfst du dir das leben
> auch
> ein ganz klein wenig einfacher machen.

Ich benutze Atmel Studio 6. Da hab ich grad folgendes rausgelesen:
Installed Packages: AVRGCC - 3.4.1.95
AVR Toolchain 32Bit (3.4.1.348 - GCC 4.4.3)
Kann ich in Atmel Studio den Compiler auf einfache Weise erneuern?

Karl Heinz schrieb:
> Einen Vorteil hat letztere Lösung. Da das "flash_" Teil des
> Datentyps ist, ist es für den Compiler prüfbar, ob man hier einen Fehler
> gemacht hat.

Danke für den Tipp! Stimmt.

Karl Heinz schrieb:
> Um den Teil kommt man meines Wissens nicht herum.

Hmm Ok.

Oliver schrieb:
> Deshalb gibt es z.B. in der avrlibc die Stringfunktionen doppelt, einmal
> normal mir Argument im RAM, und einemal mit _p hintendrann, die erwartet
> das Argument im Flash.

Hmm, ja so mache ich das wahrscheinlich auch. Gebe dem user dann als 
Schnittstelle vor:
void PrintString (uint8_t *String);
void PrintString_P (uint8_t *String);
oder
void PrintString_F (....);  <-- Welche Übergabeparameter hier?
#3434421
Lesenswert?

mem schrieb:
> Hmm, ja so mache ich das wahrscheinlich auch. Gebe dem user dann als
> Schnittstelle vor:
> void PrintString (uint8_t *String);
> void PrintString_P (uint8_t *String);
> oder
> void PrintString_F (....);  <-- Welche Übergabeparameter hier?

An deiner Stelle würde ich dann ja gleich __memx nehmen:
1
void PrintString (uint8_t __memx *String);
Dann kann der Benutzer mit der selben Funktion sowohl Strings aus dem 
Flash, als auch welche aus dem RAM ausgeben.
#3434445
Lesenswert?

>Installed Packages: AVRGCC - 3.4.1.95

Ich denke mal die 3.4.1 bezieht sich nicht auf die gcc version
sondern auf die Atmel Build Nummer. da muesste sich ein gcc 4.7.2
dahinter verstecken. Juengst kam eine Version mit dem gcc 4.8.1
heraus.

Man kann die Atmel Toolchain auch seperat installieren.

Wenn man die neue TTC dem AS unterschieben will, dann muss  man
sicher nur das entsprechende Verzeichnis innerhalb des AS Baumes finden
und umbenennen und die neue TC dort hin kopieren.
Gast #3442572
Lesenswert?

Hallo, ich bin wieder da.

Also mein compiler kennt kein __flash:

static const __flash uint8 x = 0x44;

Error  1 : unknown type name '__flash'


Muss ich noch irgendeine Bibliothek miteinbinden?


Das "__memx"  kennt er auch nicht.
Gast #3442585
Lesenswert?

Wie und wo komme ich an einen aktuellen compiler? Einfach das neuste 
Atmel studio 6 installieren?

Karl Heinz schrieb:
> Den Teil aus dem TutorialDaher müssen C-Module, die Address-Spaces
> verwenden, mit -std=gnu99 compiliert werden.
> hast du beachtet?

Ich habe unter Toolchain > AVR/GNU C Compiler > Other flags: -std=gnu99

per Hand eingefügt. Sehe auch das flag im output Fenster beim erstellen.
Gast #3442590
Lesenswert?

Wobei... stop!

Unter Help > About Atmel Studio > AVRGCC  lese ich:

AVR Toolchain 32 Bit
Version: 3.4.1.348 - GCC 4.4.3



Ich arbeite mit dem ATmega32 und brauche also eine AVR Toolchain.
GCC 4.4.3 ist veraltet oder?  Wie bekomme ich eine neue her?
Gast #3443479
Lesenswert?

Guten Tag!

Also meine Toolchain habe ich nun endlich erneuert bekommen und alles 
funktioniert jetzt.

Hier die Zusammenfassung meiner Erkenntnisse:

1. String wird im RAM abgelegt
1
Func("Hallo");
2
void Func (uint8_t *pstring)
3
{}

2. String wird im FLASH abgelegt
1
Func_P(PSTR("Hallo"));
2
void Func_P ()
3
{}

3. String wird im FLASH abgelegt
1
static const __flash uint8_t FLASH[10] = {'B'};
2
Func_F(FLASH);
3
void Func_F (const __flash char* pstring)
4
{}


Folgende Fragen sind noch offen:

1. Oben wurde gepostet, dass das funktionieren sollte:
1
Func_M("Hallo");
2
void Func_M (const __memx char* pstring)
3
{
Das funktioniert aber nicht. Oder mach ich was falsch?

2. Weiter wurde gesagt, dass der Compiler einen Fehler meldet bei:
1
static uint8_t RAM[10] = {'B'};
2
Func_F(RAM);
3
void Func_F (const __flash char* pstring)
4
{}
Tut er aber nicht.

Bin für alle weiteren Tipps dankbar! :)
Gast #3443694
Lesenswert?

Noch eine weitere Frage ist aufgetaucht:

Wieso funktioniert das nicht?:

1
#define FSTR(X) ((const __flash char[]) { X } )
2

3
Func_F(FSTR("Hallo"));
4
Func_F(const __flash char *String)
5
{}


Wie schreibt man das richtig?
Gast #3443881
Lesenswert?

Hier nochmals der gesamte Code. Ich habe den Fehler nicht finden können.
1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3

4

5
#define FSTR(X) ((const __flash char[]) { X } )
6

7

8
Func_F(const __flash char *String);
9

10
 
11
int main(void)
12
{
13
    
14
    Func_F(FSTR("Hallo"));
15
    
16
    while(1)
17
    {
18
        //TODO:: Please write your application code 
19
    }
20
}
21

22

23
Func_F (const __flash char *String)
24
{
25
    
26
}

Fehlermeldung: compound literal qualified by address-space qualifier

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren