Forum: Compiler & IDEs Warnung bei globaler PROGMEM-Deklaration: Uninitialized variable


von xfr (Gast)


Lesenswert?

Ich habe in meinem Programm ein globales Array mit Funktionspointern, 
das im Flashspeicher liegen soll. Das Programm funktioniert wie es soll, 
allerdings bekomme ich beim Compilieren eine Warnung (siehe unten). Hier 
erstmal die relevanten Codeteile:

Damit ich von verschiedenen Programmteilen auf das Array zugreifen kann, 
habe ich es in einem Headerfile als extern deklariert:
1
// vtimer_config.h
2
3
#define VTIMER_CLIENT_NUM 2
1
// vtimer.h
2
3
#include "vtimer_config.h"
4
5
// Callback function prototype
6
typedef void (*vtimer_callback_t)(void);
7
8
// Callback function array (must be defined by user)
9
extern const PROGMEM vtimer_callback_t vtimer_callback[VTIMER_CLIENT_NUM];

Die Definition des Arrays erfolgt im Hauptprogramm:
1
// main.c
2
3
#include "vtimer.h"
4
5
void client_callback_1(void)
6
{
7
    leds_toggle(LED_GREEN);
8
}
9
10
void client_callback_2(void)
11
{
12
    leds_toggle(LED_RED);
13
}
14
15
const PROGMEM vtimer_callback_t vtimer_callback[VTIMER_CLIENT_NUM] = {
16
    client_callback_1,
17
    client_callback_2,
18
};

In vtimer.c wird in einer ISR auf das globale Array zugegriffen, um die 
Callback-Funktion aufzurufen:
1
// vtimer.c
2
3
#include "vtimer.h"
4
5
ISR(RTC_COMP_vect)
6
{
7
    // [...]
8
    ((vtimer_callback_t) pgm_read_word(&vtimer_callback[i]))();
9
    // [...]
10
}

Es funktioniert auch alles so weit. Allerdings bekomme ich beim 
Compilieren von vtimer.c folgende Compilerwarnung:
1
In function '__vector_11':
2
[Pfad]\vtimer.h(20,40): uninitialized variable 'vtimer_callback' put into program memory area [-Wuninitialized]

Hat das etwas zu bedeuten? Wird das Array wirklich nochmal in vtimer.c 
angelegt? Das Programm funktioniert wie gesagt, verwendet wird also 
offensichtlich schon das Array aus main.c. Soll ich die Warnung 
ignorieren? Bzw. gibt es eine Möglichkeit, sie loszuwerden?

Ich benutzte AVR-Studio 6.0 mit dem AVR-GCC 4.6.2, der standardmäßig 
dabei ist.

Danke schonmal!

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

xfr schrieb:
> uninitialized variable 'vtimer_callback' put into
> program memory area [-Wuninitialized]
>
> Hat das etwas zu bedeuten?

Es bedeutet, daß du folgende Optionen hast:

• Mit der Warnung leben

• -Wno-uninitialized (oder eine Obermenge davon) deaktivieren.

• Auf eine avr-gcc Version oder Distribution umsteigen, die einen
  Fix für PR51756 hat, z.B. 4.6.3 oder neuer.

von xfr (Gast)


Lesenswert?

Alles klar, vielen Dank!

Dann war ja tatsächlich mal der Compiler Schuld ... :)

Die Warnung verschwindet übrigens auch, wenn man in der Deklaration das 
"PROGMEM" weglässt. Allerdings ist das ja eine essentielle Information 
für denjenigen, der das Array definieren soll, also keine Lösung.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

xfr schrieb:

> Dann war ja tatsächlich mal der Compiler Schuld ... :)

Nein, der Compiler ist unschuldig. Ich war Schuld.

> Die Warnung verschwindet übrigens auch, wenn man in der Deklaration das
> "PROGMEM" weglässt. Allerdings ist das ja eine essentielle Information
> für denjenigen, der das Array definieren soll, also keine Lösung.

Es genügt wenn das progmem Attribut an der Definition steht.

von xfr (Gast)


Lesenswert?

Johann L. schrieb:
> Es genügt wenn das progmem Attribut an der Definition steht.

Aus Sicht des Compilers ja, zur Selbstdokumentation allerdings nicht. 
Wenn sich jemand nur die Header-Datei ansieht, kann er ja nicht ahnen, 
dass das Array im Flash abgelegt werden soll (bzw. ist, wenn man es 
andersrum verwenden würde). Man könnte es natürlich entsprechend 
kommentieren, bleibt aber unsauber.

Naja, habe noch mal grundsätzlich drüber nachgedacht und es jetzt anders 
gelöst: Das Array kommt mit static-Attribut in die vtimer_config.h und 
wird nur in vtimer.c eingebunden. Dann stehen auch die Anzahl der 
Einträge und die Einträge selbst an einer Stelle.

Nachteil ist, dass ich in vtimer_config.h jetzt die Header zu allen 
Funktionen einbinden muss, auf die ich verweise. Die wären in main.c 
halt schon da. Außerdem kann ich in in main.c nicht mehr Funktionen ohne 
Header-Datei definieren und als Callbacks benutzten. Aber gut, man kann 
nicht alles haben ...

Danke nochmal für den Hinweis. :)

von Karl H. (kbuchegg)


Lesenswert?

xfr schrieb:
> Johann L. schrieb:
>> Es genügt wenn das progmem Attribut an der Definition steht.
>
> Aus Sicht des Compilers ja, zur Selbstdokumentation allerdings nicht.
> Wenn sich jemand nur die Header-Datei ansieht, kann er ja nicht ahnen,
> dass das Array im Flash abgelegt werden soll (bzw. ist, wenn man es
> andersrum verwenden würde). Man könnte es natürlich entsprechend
> kommentieren, bleibt aber unsauber.

Die Krise an dieser Stelle ist, dass das PROGMEM hier beim extern im 
Grunde auch nichts anderes als eine Dokumentation ist.

Ob es da ist oder nicht, spielt keinen Walzer. Weder wirst du vom 
Compiler gezwungen, da irgendwas spezielles damit zu machen und du wirst 
auch nicht vom Compiler gezwungen hier

((vtimer_callback_t) pgm_read_word(&vtimer_callback[i]))();

einen pgm_read_word anzuwenden, anstatt den Funktionsaufruf direkt über 
das Array zu machen.

So gesehen: ob du einen Kommentar machst, oder ob du da PROGMEM 
hinschreibst, ist Jacke wie Hose. OK, PROGMEM sieht ein wenig 
offizieller aus.

von xfr (Gast)


Lesenswert?

Stimmt schon, mehr als ein Hinweis ist es nicht. Wenn das PROGMEM in der 
Deklaration steht, könnte man sie halt einfach kopieren und zu einer 
Definition machen, ohne das PROGMEM zu vergessen. Das beste ist aber 
wahrscheinlich, die ganzen PROGMEM-Geschichten möglichst lokal zu halten 
und nicht nach außen zu zeigen.

Falls es jemanden interessiert, hab es jetzt so gemacht:
1
// vtimer_config.h
2
3
// Callback function type
4
typedef void (*vtimer_callback_t)(void);
5
6
// Number of callback functions
7
#define VTIMER_CALLBACK_NUM 2
8
9
// Callback functions array initializer
10
#define VTIMER_CALLBACK_ARRAY { \
11
  client_callback_1, \
12
  client_callback_2, \
13
}
1
// vtimer.h
2
3
#include "vtimer_config.h"
1
// vtimer.c
2
3
#include "vtimer.h"
4
5
// Callback functions array
6
static const PROGMEM vtimer_callback_t vtimer_callback[VTIMER_CALLBACK_NUM] = VTIMER_CALLBACK_ARRAY;

Gewinnt sicher auch keinen Schönheitspreis. Aber damit befindet sich 
immerhin alles, was mit PROGMEM zu tun hat, nur noch in vtimer.c und 
kann bei Bedarf auch geändert werden, ohne die Konfigurations-Dateien 
der Anwendungen anfassen zu müssen.

von Karl H. (kbuchegg)


Lesenswert?

xfr schrieb:

> Gewinnt sicher auch keinen Schönheitspreis.

Find ich jetzt ehrlich gesagt gar nicht soooo wild. Man muss halt im 
Hinterkopf halten, dass es da ein potentielles Problem gibt, welches du 
so 'entschärfst'. Von daher finde ich das sogar gar keine schlechte 
Lösung.

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.