PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : &-operator Problem, constante im Programmspeicher, sizeo



chientech
09.08.2009, 11:20
Hi,

ich versuch mich gerade an einem Problem mit der Adressübergabe an einen Pointer im .progmem.data -Bereich.

folgendes:




#ifndef __ATTR_PROGMEM__
#define __ATTR_PROGMEM__ __attribute__((__progmem__))
#endif

#ifndef PROGMEM
#define PROGMEM __ATTR_PROGMEM__
#endif

struct PROGMEM Norm
{
prog_U8 faktor;
prog_U8 decimal;

const prog_S8 sNormUnit[NORM_UNIT_MAXLEN];
const prog_S8 sNormName[NORM_NAME_MAXLEN];
};

/*** ---- Normalization ------------- Faktor Decimal Unit Name ------ ***/
struct Norm PROGMEM Norm_Voltage1 = { 1, 0, {"V"}, {"VOLTAGE 1"} };
struct Norm PROGMEM Norm_Voltage2 = { 1, 3, {"mV"}, {"VOLTAGE 2"} };

struct PROGMEM Norm* PROGMEM NormArray[NORM_AMOUNT] = { &Norm_Voltage1,
&Norm_Voltage2
};



gibt bei mir immer folgende Warnung:

../para.c:58: warning: initialization discards qualifiers from pointer target type


Was mach ich falsch? Gibt es einen Ersatzoperanten für & für den .progmem.data -Bereich?

Danke schon mal im voraus 8-[ 8-[

sast
10.08.2009, 11:22
Also als erstes einmal sind da ganz schön viele PROGMEMs in deinem Code. Dazu kann ich leider nicht allzuviel sagen, da ich bisher nur mal ein Stringarray in den Flash umgeschichtet habe.

Ich würde aus dem ganzen Wust ein typedef machen. Dann hast du zum Schluß nur noch so was wie norm_t übrig.

Die Warnung könnte daher rühren, dass du dem Kompiler den Typecast explizit mitteilen musst. zB

...
typedef struct Norm{
...
} norm_t;

...
norm_t PROGMEM NormVoltage1 = ...
...

...NormArray[...] = { (norm_t*)&Norm_Voltage1,
...

Ich hoffe, das hilft dir weiter

sast

chientech
11.08.2009, 22:27
Danke.

Jetzt hab ich aber noch ne Frage. Mit dem typedef hab ich so meine Schwirigkeiten.

Bei deinem Beispiel:

typedef struct Norm{
...
} norm_t;

...
norm_t PROGMEM NormVoltage1 = ...

>Heißt das nun das, das norm_t soviel wie struct Norm bedeutet? Funzt auf jedenfall.

Danke nochmal

chientech
11.08.2009, 22:55
Hi,
ich hab das jetzt ein Wenig anders gelöst und steh vor einem neuen Problem:

sizeof (NormArray[1]) geht (bzw. Compiler hat nichts dagegen) und müsste mir die größe des Array-elements in Byte geben.

Jetzt hätte ich gerne die Größe des gesamten Arrays in Byte



#ifndef PROGMEM
#define PROGMEM __attribute__((__progmem__))

typedef char PROGMEM prog_S8;

typedef unsigned char PROGMEM prog_U8;

#endif

typedef struct Norm
{
prog_U8 factor;
prog_U8 decimal;

const prog_S8 sNormUnit[NORM_UNIT_MAXLEN];
const prog_S8 sNormName[NORM_NAME_MAXLEN];
}norm_t;

norm_t PROGMEM NormArray[] = {

// Faktor Decimal Unit Name *
{ 1, 0, { "V"}, { "VOLTAGE 1"} }, // 0
{ 1, 3, { "mV"}, { "VOLTAGE 2"} }, // 1
{ 1, 0, { "A"}, { "CURRENT 1"} }, // 2
};

unsigned char normAmound;
normAmound = sizeof (NormArray);


normAmound = sizeof (NormArray);

gibt bei mir immer folgenden Fehler:

../xxxxxxx.c:523: error: invalid application of `sizeof' to incomplete type `({anonymous})'

Warum ist der type hier anonymous?
Ich dachte erst das liegt an dem PROGMEM aber es geht auch ohne nicht.

sast
12.08.2009, 08:02
Also bei mir "E:\WinAVR-20090306rc1\utils\bin\make.exe" all
tuts compilieren ohne warnings und errors

.c Ausschnitt


#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <avr/pgmspace.h>

#include "main.h"

void initio(void);
void delay_ms(unsigned int ms);

norm_t NormArray[] PROGMEM =
{ // Faktor Decimal Unit Name
{1, 0, { "V"}, {"VOLTAGE 1"}}, // 0
{1, 3, { "mV"}, {"VOLTAGE 2"}}, // 1
{1, 0, { "A"}, {"CURRENT 1"}}, // 2
};

int main( void )
{
int i;

unsigned char normAmound;

normAmound = sizeof (NormArray);

initio();
...


und die .h


...
#define NORM_UNIT_MAXLEN 4
#define NORM_NAME_MAXLEN 12



typedef char PROGMEM prog_S8;

typedef unsigned char PROGMEM prog_U8;

typedef struct Norm
{
prog_U8 factor;
prog_U8 decimal;

const prog_S8 sNormUnit[NORM_UNIT_MAXLEN];
const prog_S8 sNormName[NORM_NAME_MAXLEN];
}norm_t;


Um das normAmound vom ersten Post zu bekommen, müsstest du aber dein sizeof(NormArray) noch durch die Größe des Structs teilen

normAmount = sizeof(NormArray)/sizeof(norm_t);

sast

Edit:

Nur mal so als Hinweis. Jörg Wunsch hat mal in einem anderen Forum zu PROGMEM geschrieben:
"It's not required to be global variables, but they ought to
be variables with static storage duration. All global
variables do have that, but it can also be applied to local ones."

chientech
12.08.2009, 22:17
Hi,

tausend Dank. =D>

Das geht schon mal.

Aber ich weiß auch warum es nicht ging. Ich weiß nicht wie man eine Array in einem anderen c-File bekannt macht.

das h-File



#ifndef __ATTR_PROGMEM__
#define __ATTR_PROGMEM__ __attribute__((__progmem__))
#endif

#ifndef PROGMEM
#define PROGMEM __ATTR_PROGMEM__
#endif

typedef struct PROGMEM Norm
{
prog_U8 faktor;
prog_U8 decimal;

const prog_S8 sNormUnit[NORM_UNIT_MAXLEN];
const prog_S8 sNormName[NORM_NAME_MAXLEN];
}norm_t;


das 1. c-File


#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <avr/pgmspace.h>
include h-file
/*** ---- Normalization ------------- Faktor Decimal Unit Name ------ ***/
norm_t Norm_Voltage1 = { 1, 0, {"V"}, {"VOLTAGE 1"} };
norm_t Norm_Voltage2 = { 1, 3, {"mV"}, {"VOLTAGE 2"} };

norm_t* PROGMEM NormArray[] =
{ (norm_t*)&Norm_Voltage1, (norm_t*)&Norm_Voltage2 };


das 2. c-File


#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <avr/pgmspace.h>
include h-file
extern norm_t* PROGMEM NormArray[];

void foo(void)
{
U8 normAmound = sizeof(NormArray);
...
...
}


ich hab schon so ziemlich alle varianten versucht:
norm_t* PROGMEM NormArray[];
extern norm_t* PROGMEM NormArray;
extern norm_t* NormArray[];

leider ist probieren nicht immer von Erfolg gekröhnt.

sast
12.08.2009, 23:00
Die Variante im Code Teil sieht doch ganz gut aus, was gibt es denn für eine Fehlermeldung?

Versuch doch mal wieder den obligatorischen typecast in der sizeof Funktion.

sizeof((norm_t **)NormArray);

sast

chientech
13.08.2009, 19:16
Hi,

zum Glück gibt es Menschen die mich an ihrem Wissen teilhaben lassen.
Danke jetzt meckert der Compiler nicht mehr und die Funktion teste ich bald und geb ein Feedback.

mfg
Christoph

sast
13.08.2009, 21:33
Schön zu hören, das es jetzt soweit funktioniert.

Dafür ist das Forum da und außerdem macht helfen auch Spass und man muss sich selbst mal mit Dingen beschäftigen, die man sonst nie selbst gemacht hätte.

sast

chientech
16.08.2009, 13:19
Hi,
das PROGMEM bringt mich noch um, alles was früher mal geklappt hat macht jetzt Schwirigkeiten.



#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "uart.h" // Peter Fleury

#ifndef __ATTR_PROGMEM__
#define __ATTR_PROGMEM__ __attribute__((__progmem__))
#endif

#ifndef PROGMEM
#define PROGMEM __ATTR_PROGMEM__
#endif

S8 sTx[16];

typedef struct PROGMEM Norm
{
prog_U8 faktor;
prog_U8 decimal;

const prog_S8 sNormUnit[NORM_UNIT_MAXLEN];
const prog_S8 sNormName[NORM_NAME_MAXLEN];
}norm_t;

/*** ---- Normalization ------------- Faktor Decimal Unit Name ------ ***/
norm_t Norm_Voltage1 = { 1, 0, {"V"}, {"VOLTAGE 1"} };
norm_t Norm_Voltage2 = { 1, 3, {"mV"}, {"VOLTAGE 2"} };

norm_t* PROGMEM NormArray[] =
{ (norm_t*)&Norm_Voltage1, (norm_t*)&Norm_Voltage2 };


void foo(void)
{
norm_t* p_norm;

p_norm = (norm_t*) NormArray[0];

uart_puts( (S8*) p_norm->sNormName ); // Da kommt nur mist raus


uart_puts( (S8*) ((norm_t*)NormArray[0])->sNormName ); // Da auch



}




Offensichtlich habe ich Probleme mit Pointern in den Progmem Bereich.
Und das nicht nur bei Strings sondern auch Werte kommen falsch raus.



void foo(void)
{
uart_puts( itoa( NormArray[i]->factor, sTx, 10) );
}


mit den Pointern tu ich mir einfach schwer.
Weiß hier jemand weiter?

Oder kennt einer ein Beispiel für Constanten und deren Benutzung im PROGMEM bereich?

gruß christoph

markusj
16.08.2009, 13:34
Das Problem ist, dass du den Kram erst einmal aus dem Flash rauslesen musst ... dafür gibt es in in "pgmspace.h" entsprechende Methoden.

mfG
Markus

sast
17.08.2009, 08:22
Du solltest dir mal ein Tutorial zu Progmem durchlesen. Ich glaube unter mikrokontroller.net oder avrfreaks gibts da was ganz brauchbares.

sast

chientech
17.08.2009, 21:26
ich schau mal, besser wär en link, aber trotzdem Danke.

chientech
25.08.2009, 18:20
Hi,

hab es nun endlich hinbekommen.

die #include <avr/pgmspace.h>
hält alle Lösungen parat.

Da ich meine Informationen in einer Strukturen im PROGMEM Speicher abgelegt hab, kopiere ich mir beim Zugriff darauf die Struktur in eine lokale Struktur im .data Bereich.



norm_t Norm_tmp; // local Norm structure element
PGM_VOID_P p_Norm_tmp; // local pointer to PROGMEM Norm structure

p_Norm_tmp = (U32*) pgm_read_word_far( (U16) &NormArray[i] );
memcpy_P(&Norm_tmp, p_Norm_tmp, sizeof(norm_t));

// einfacher Zugriff
... = (S8*) Norm_tmp.normName;
... = (S8*) Norm_tmp.normUnit;



Bin froh, dass es jetzt endlich hingehauen hat.
\:D/
Danke, für die Hilfe und Beschleunigung in die richtige Richtung.

chientech
26.08.2009, 18:55
Hi,
so jetzt hab ich noch ein Problem von früher.

.c Ausschnitt




#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <avr/pgmspace.h>

#include "main.h"

void initio(void);
void delay_ms(unsigned int ms);

norm_t NormArray[] PROGMEM =
{ // Faktor Decimal Unit Name
{1, 0, { "V"}, {"VOLTAGE 1"}}, // 0
{1, 3, { "mV"}, {"VOLTAGE 2"}}, // 1
{1, 0, { "A"}, {"CURRENT 1"}}, // 2
};

int main( void )
{
int i;

unsigned char normAmound;

normAmound = sizeof (NormArray);

initio();
...


und die .h




...
#define NORM_UNIT_MAXLEN 4
#define NORM_NAME_MAXLEN 12



typedef char PROGMEM prog_S8;

typedef unsigned char PROGMEM prog_U8;

typedef struct Norm
{
prog_U8 factor;
prog_U8 decimal;

const prog_S8 sNormUnit[NORM_UNIT_MAXLEN];
const prog_S8 sNormName[NORM_NAME_MAXLEN];
}norm_t;



der Compiler frisst das Zwar aber das ist leider nur die halbe Miete.

das sizeof() ergibt immer entweder die größe eines Elements oder die Pointergröße 2.

egal in welcher Konstellation:
normAmound = sizeof (NormArray);
normAmound = sizeof ( (norm_t*) NormArray);
normAmound = sizeof ( (norm_t**) NormArray);
normAmound = sizeof ( (PGM_P) NormArray);
normAmound = sizeof ( (PGM_P*) NormArray);
normAmound = sizeof ( (PGM_VOID_P) NormArray);
normAmound = sizeof ( (PGM_VOID_P*) NormArray);

gibt es eine Möglichkeit die größe des Arrays zu ermitteln?

chientech
26.08.2009, 19:20
Sorry,

hab da was verwechselt das

normAmound = sizeof (NormArray);

passt.

sast
26.08.2009, 21:19
:)
Manchmal hilft es, wenn man einfach mal mit jemandem darüber gesprochen hat. Dann kommt man bereits alleine auf die Lösung.

Geht mir auch oft so.

sast

chientech
27.08.2009, 22:03
Hi,

mal ne andere Frage:

wird das sizeof (NormArray); eigendlich zur laufzeit gebildet oder macht das der Preprozessor?

mit anderen Worten geht das auch (ich habs nicht hinbekommen :-k ) ?

#define NORMAMOUND (sizeof (NormArray))

sternst
27.08.2009, 22:43
wird das sizeof (NormArray); eigendlich zur laufzeit gebildet oder macht das der Preprozessor?Weder noch. Das macht der Compiler.


mit anderen Worten geht das auch (ich habs nicht hinbekommen :-k ) ?

#define NORMAMOUND (sizeof (NormArray))Preprozessor Defines sind immer nur reine Textersetzungen. Wenn du irgendwo im Source "NORMAMOUND" schreibst, ersetzt er das stumpf durch "(sizeof (NormArray))". Das Ganze funktioniert also nur dort, wo NormArray für den Compiler vollständig bekannt ist.