Forum: Mikrocontroller und Digitale Elektronik c: gcc/avr gleiche/ungleiche varianten of string declarartion


von Apollo M. (Firma: @home) (majortom)


Lesenswert?

hi,
variante 1 und variante 2 sollten eigentlich gleichen code erzeugen ... 
tun sie aber nicht bzgl. ram allocation, bei variante 2 liegt die string 
copy im ram, wie kann ich das vermeiden?

mt
1
variante 1:
2
PROGMEM const char unit0[] = "uSv/h";
3
PROGMEM const char unit1[] = "uR/h";
4
PROGMEM const char unit2[] = "mR/h";
5
PROGMEM PGM_P const unitTable[] = {unit0, unit1, unit2};
6
7
variante 2:
8
enum {UNIT_uSv, UNIT_uR, UNIT_mR};
9
PROGMEM PGM_P const unitTable[] = {
10
  [UNIT_uSv] = "uSv/h",
11
  [UNIT_uR] = "uR/h",
12
  [UNIT_mR] = "mR/h",
13
};

von Walter T. (nicolas)


Lesenswert?

Die Strings müssen mit PSTR auch ins Flash. So liegen nur die Zeiger auf 
die Strings dort.

von Thomas W. (goaty)


Lesenswert?

Das ist ein Array von Pointern?
Vielleicht vor jedes Element noch progmem schreiben oder in etwas 
anderes als Array von Pointen ändern.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

... so weiter rumgesucht

laut https://ewiki.e-dschungel.de/software/avr-gcc
geht nur variante1?!

das PSTR macro kann hier nicht verwendet werden.

... ich will aber die blonde variant2 und bekomm sie nicht, gemein!


mt

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Variante 2 ist mit progmem nicht darstellbar.

PSTR ist an der Stelle syntaktisch nicht möglich.

Was geht:

Variante A
1
#include <avr/pgmspace.h>
2
3
const char unitTable[][6] PROGMEM =
4
{
5
  "uSv/h", "uR/h", "mR/h"
6
};
Allerdings ist das dann kein Array von const char*.  Für ein Array von 
const char* braucht man Strings in progmem wie in deiner Variante 1 oder 
man verwendet __flash mit Compound Literals:

Variante B
1
#define FSTR(X) (const __flash char[]) { X }
2
3
const __flash char* const __flash unitTable[] =
4
{
5
  FSTR ("uSv/h"), FSTR ("uR/h"), FSTR ("mR/h")
6
};
progmem ist ein Attribut und bezieht sich immer auf das definierte 
Objekt.  __flash ist ein Qualifier (wie z.B. const oder volatile) und 
kann sich auch auf ein Pointer-Target beziehen.  Mit __flash geht 
natürlich auch das Analogon von Variante A:

Variante C
1
const __flash char unitTable[][6] =
2
{
3
  "uSv/h", "uR/h", "mR/h"
4
};

Nachteil der Varianten A und C ist, dass man die Maximallänge der 
beteiligten Strings kennen muss, und dass man Verschnitt hat, wenn viele 
Strings unterschiedlicher Längen auftreten.  Außerdem muss mit der 
Stringlänge multipliziert werden, was teuer ist, wenn der µC keine MUL 
Instruktion kennt.

Bei Variante B hat man hingegen Verschnitt durch die zusätzlich zu 
speichernden String-Adressen, und man hat eine Indirektion mehr.  Dafür 
braucht es nur eine einfache Multiplikation mit 2:
1
char get_first_B (const __flash char* const __flash strings[], uint8_t index)
2
{
3
    return strings[index][0];
4
}
5
6
char get_first_C (const __flash char strings[][6], uint8_t index)
7
{
8
    return strings[index][0];
9
}
compiliert zu:
1
get_first_B:
2
  mov r30,r22
3
  ldi r31,0
4
  lsl r30
5
  rol r31
6
  add r30,r24
7
  adc r31,r25
8
  lpm r0,Z+
9
  lpm r31,Z
10
  mov r30,r0
11
  lpm r24,Z
12
  ret
13
14
get_first_C:
15
  ldi r18,lo8(6)
16
  mul r22,r18
17
  add r24,r0
18
  adc r25,r1
19
  clr __zero_reg__
20
  movw r30,r24
21
  lpm r24,Z
22
  ret

Vorteil von __flash ist, dass man die hässlichen pgm_read_xxx nicht mehr 
braucht und dass es einfacher ist, an Situationen anzupassen, in denen 
__flash nicht verfügbar oder ungünstig ist:
1
#if !defined(__FLASH) || defined (__AVR_PM_BASE_ADDRESS__)
2
#define __flash // empty
3
#endif
Nachteil ist, dass es nicht in C++ verfügbar ist (kann man wahlweise 
auch als Nachteil von C++ ansehen ;-))

von mh (Gast)


Lesenswert?

Johann L. schrieb:
> Nachteil ist, dass es nicht in C++ verfügbar ist (kann man wahlweise
> auch als Nachteil von C++ ansehen ;-))

Braucht man es in C++ außer wenn man C Code direkt übernehmen will?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.