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-[
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.
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.
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
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
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
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.
:)
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))
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.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.