Forum: Compiler & IDEs Typenkonflikte in KeiluV5


von Fragender (Gast)


Lesenswert?

Hi

Ich verstehe gerade überhaupt nicht, warum da ein Fehler auftritt.
Es ist wie es aussieht ein Typenkonflikt, aber ich sehe den Fehler 
nicht.
Es handelt sich um STM32F0

Ich habe in einem h-file xxx definiert:
1
typedef struct pin{
2
GPIO_TypeDef* port;
3
uint16_t pin;
4
}pin_t;
5
6
7
typedef struct tscGroupPort{
8
GPIO_TypeDef* tscGroup1,
9
tscGroup2,
10
tscGroup3,
11
tscGroup4,
12
tscGroup5,
13
tscGroup6;
14
}tscGroupPorts_t;
15
16
#define TSC_GROUP_PORT       (tscGroupPorts_t)  {GPIOA, GPIOA, GPIOB, GPIOA, GPIOB, GPIOB}
17
#define TSC_SHIELD             (pin_t)           {TSC_GROUP_PORT.tscGroup5,GPIO_PIN_3}
18
#define TSC_SHIELD_SAMPLE      (pin_t)           {TSC_GROUP_PORT.tscGroup5,GPIO_PIN_4}
19
#define TSC_TOUCHKEY2          (pin_t)           {TSC_GROUP_PORT.tscGroup6,GPIO_PIN_12}
20
#define TSC_LS1               (pin_t)           {TSC_GROUP_PORT.tscGroup6,GPIO_PIN_14}
21
#define TSC_LS1_SAMPLE         (pin_t)           {TSC_GROUP_PORT.tscGroup6,GPIO_PIN_13}
22
#define TSC_TOUCHKEY1          (pin_t)           {TSC_GROUP_PORT.tscGroup1,GPIO_PIN_1}
23
#define TSC_LS2               (pin_t)           {TSC_GROUP_PORT.tscGroup1,GPIO_PIN_2}
24
#define TSC_LS2_SAMPLE         (pin_t)           {TSC_GROUP_PORT.tscGroup1,GPIO_PIN_3}
25
#define TSC_LS3               (pin_t)           {TSC_GROUP_PORT.tscGroup3,GPIO_PIN_0}
26
#define TSC_LS3_SAMPLE         (pin_t)           {TSC_GROUP_PORT.tscGroup3,GPIO_PIN_1}


Dann nutze ich eine Funktion:
1
void configureGPIO(uint32_t pin, GPIO_TypeDef* port,...)
und übergebe dieser:
1
configureGPIO(TSC_LS2_SAMPLE.pin, TSC_LS2_SAMPLE.port, ...)

Dann meldet er zB den Fehler:
1
SC_LS2_SAMPLE.pin, 
2
SC_LS2_SAMPLE.port, GPIO_MODE_AF_OD, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW, TSC_Alternate_FUNC);
3
..\Src\tsc.c(155): error:  #144: a value of type "GPIO_TypeDef *" cannot be used to initialize an entity of type "volatile uint32_t"
4
      configureGPIO(
5
SC_LS1_SAMPLE.pin, 
6
SC_LS1_SAMPLE.port, GPIO_MODE_AF_OD, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW, TSC_Alternate_FUNC);
7
..\Src\tsc.c(158): error:  #144: a value of type "GPIO_TypeDef" cannot be used to initialize an entity of type "GPIO_TypeDef *"
8
      configureGPIO(
9
SC_LS1_SAMPLE.pin, 
10
SC_LS1_SAMPLE.port, GPIO_MODE_AF_OD, GPIO_NOPULL, GPIO_SPEED_FREQ_LOW, TSC_Alternate_FUNC);
11
..\Src\tsc.c(161): error:  #144: a value of type "GPIO_TypeDef *" cannot be used to initialize an entity of type "volatile uint32_t"

: Verschoben durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Mach doch mal den Textersatz, den der Präprozessor macht:
1
configureGPIO(TSC_LS2_SAMPLE.pin, TSC_LS2_SAMPLE.port, ...)
2
3
4
// wird im ersten Schritt zu 
5
6
configureGPIO({TSC_GROUP_PORT.tscGroup1,GPIO_PIN_2}.pin, {TSC_GROUP_PORT.tscGroup1,GPIO_PIN_2}.port, ...)

Das schluckt kein C-Compiler.

von Fragender (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Mach doch mal den Textersatz, den der Präprozessor macht:
>
> configureGPIO(TSC_LS2_SAMPLE.pin, TSC_LS2_SAMPLE.port, ...)
>
> // wird im ersten Schritt zu
>
> configureGPIO({TSC_GROUP_PORT.tscGroup1,GPIO_PIN_2}.pin,
> {TSC_GROUP_PORT.tscGroup1,GPIO_PIN_2}.port, ...)
>
> Das schluckt kein C-Compiler.

Ok, und weshalb funktioniert Folgendes? :
1
#define TOUCHKEY2_LED        (pin_t)             {GPIOB, GPIO_PIN_2}
2
configureGPIO(TOUCHKEY2_LED.pin, TOUCHKEY2_LED.port,

von Nico W. (nico_w)


Lesenswert?

Das ist normales C.

Sieht irgendwie aus als ob da irgendwas verschoben ist.

Ein Minimalbeispiel würde da sicher besser helfen.

von NichtWichtig (Gast)


Lesenswert?

Steht da doch:
a value of type "GPIO_TypeDef *" cannot be used to initialize an entity 
of type "volatile uint32_t"

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Fragender schrieb:
> typedef struct tscGroupPort{
> GPIO_TypeDef* tscGroup1,
> tscGroup2,
> tscGroup3,
> tscGroup4,
> tscGroup5,
> tscGroup6;
> }tscGroupPorts_t;

Du hast 2 Möglichkeiten, das zu fixen:

A) Du schreibst vor jeden Struct Member explizit den Typ hin und 
schließt die Zeilen mit Semikolon statt Komma ab.

B) Du wiederholst den Stern in jeder Zeile, damit tscGroup2 usw. auch 
wirklich Pointer sind - so wie Du es auch für tscGroup1 vorgesehen hast.

Ein oft gemachter Fehler, wie z.B.
1
int main ()
2
{
3
   int * a, b, c;
4
}

a ist dann ein Pointer, b und c sind aber keine.

So etwas passiert, wenn man alles möglichst knapp formulieren will. Das 
rächt sich dann.

P.S.

Ich vermeide prinzipiell, das Sternchen an den Typ zu kleben, sondern 
umgebe ihn immer mit Leerzeichen links und rechts. Denn es gehört nicht 
direkt zum Typ. Zum anderen habe ich mir angewöhnt, den Typ explizit vor 
jeden Identifier wie z.B. einer Variablen zu schreiben. Ist zwar mehr 
Schreibarbeit, ist aber lesbarer. Aus diesem Grund ist der Fehler in der 
obigen Definition auch extrem schlecht zu erkennen.

Ein Compiler sieht
1
   int* a, b, c;

als Kurzform von:
1
   int * a;
2
   int b;
3
   int c;

Ein Mensch sieht das auf den ersten Blick unter Umständen anders.

: Bearbeitet durch Moderator
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Ich vermeide prinzipiell, das Sternchen an den Typ zu kleben, sondern
> umgebe ihn immer mit Leerzeichen links und rechts.

Man könnte das Sternchen an den Variablennamen kleben, das ist IMHO 
eindeutiger.

von Fragender (Gast)


Lesenswert?

Frank M. schrieb:
> Fragender schrieb:
>> typedef struct tscGroupPort{
>> GPIO_TypeDef* tscGroup1,
>> tscGroup2,
>> tscGroup3,
>> tscGroup4,
>> tscGroup5,
>> tscGroup6;
>> }tscGroupPorts_t;
>
> Du hast 2 Möglichkeiten, das zu fixen:
>
> A) Du schreibst vor jeden Struct Member explizit den Typ hin und
> schließt die Zeilen mit Semikolon statt Komma ab.
>
> B) Du wiederholst den Stern in jeder Zeile, damit tscGroup2 usw. auch
> wirklich Pointer sind - so wie Du es auch für tscGroup1 vorgesehen hast.
>
> Ein oft gemachter Fehler, wie z.B.int main ()
> {
>    int * a, b, c;
> }
>
> a ist dann ein Pointer, b und c sind aber keine.
>
> So etwas passiert, wenn man alles möglichst knapp formulieren will. Das
> rächt sich dann.
>
> P.S.
>
> Ich vermeide prinzipiell, das Sternchen an den Typ zu kleben, sondern
> umgebe ihn immer mit Leerzeichen links und rechts. Denn es gehört nicht
> direkt zum Typ. Zum anderen habe ich mir angewöhnt, den Typ explizit vor
> jeden Identifier wie z.B. einer Variablen zu schreiben. Ist zwar mehr
> Schreibarbeit, ist aber lesbarer. Aus diesem Grund ist der Fehler in der
> obigen Definition auch extrem schlecht zu erkennen.
>
> Ein Compiler sieht
>    int* a, b, c;
>
> als Kurzform von:
>    int * a;
>    int b;
>    int c;
>
> Ein Mensch sieht das auf den ersten Blick unter Umständen anders.



Hi Frank

So funktionierts.

Rufus Τ. F. schrieb:
> Mach doch mal den Textersatz, den der Präprozessor macht:
>
> configureGPIO(TSC_LS2_SAMPLE.pin, TSC_LS2_SAMPLE.port, ...)
>
> // wird im ersten Schritt zu
>
> configureGPIO({TSC_GROUP_PORT.tscGroup1,GPIO_PIN_2}.pin,
> {TSC_GROUP_PORT.tscGroup1,GPIO_PIN_2}.port, ...)
>
> Das schluckt kein C-Compiler.

Vonwegen es schluckt kein Compiler...

Wirklich top von dir Frank, danke für deine Hilfe.
Ich hatte gemeint, wenn der Stern am Typ hängt, gälte das für alle 
members. Wieder etwas neues gelernt.

Ich habe mich für deine Variante entschieden.
1
typedef struct tscGroupPort{
2
GPIO_TypeDef *tscGroup1;
3
GPIO_TypeDef *tscGroup2;
4
GPIO_TypeDef *tscGroup3;
5
GPIO_TypeDef *tscGroup4;
6
GPIO_TypeDef *tscGroup5;
7
GPIO_TypeDef *tscGroup6;
8
}tscGroupPorts_t;

von Fragender (Gast)


Lesenswert?

NichtWichtig schrieb:
> Steht da doch:
> a value of type "GPIO_TypeDef *" cannot be used to initialize an entity
> of type "volatile uint32_t"

Woww! Suppper Tipp.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Rufus Τ. F. schrieb:
> Man könnte das Sternchen an den Variablennamen kleben, das ist IMHO
> eindeutiger.

Ja, könnte man, dagegen sträubt sich bei mir aber das ästhetische 
Empfinden. Daher habe ich für mich Leerzeichen links und rechts vom 
Sternchen als Kompromiss gewählt ;-)

Zudem ziehe ich die Variablennamen auf dieselbe Spalte. Dann sieht es 
bei mir so aus:
1
int main ()
2
{
3
    unsigned char * bytearray;
4
    int *           intarray;
5
    int             counter;
6
    int             noch_ein_counter;
7
    unsigned int    errorcode;
8
}

Das wäre für mich noch eine Alternative:
1
int main ()
2
{
3
    unsigned char * bytearray;
4
    int           * intarray;    // beachte Lage des Sternchens
5
    int             counter;
6
    int             noch_ein_counter;
7
    unsigned int    errorcode;
8
}

Die Kurzform
1
    int* intarray, counter, noch_ein_counter;
vermeide ich jedoch grundsätzlich. Da braucht man viel zu lange, es mit 
den Augen korrekt zu erfassen. Siehe oben: Das eigentliche Problem, dass 
der TO hat, hat keiner der Leser auf Anhieb gesehen. Ich musste da auch 
erst dreimal draufschauen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Fragender schrieb:
> So funktionierts.

Freut mich.

> Ich habe mich für deine Variante entschieden.

Finde ich soweit okay. ;-)

von W.S. (Gast)


Lesenswert?

Fragender schrieb:
> error:  #144: a value of type "GPIO_TypeDef *" cannot be used to
> initialize an entity of type "volatile uint32_t"

Warum verstehst du die Fehlermeldung eigentlich nicht?

du hast eine Variable
1
volatile unsigned long blabla;
und willst selbige mit einem Zeiger, nämlich GPIO_TypeDef* belegen. 
Jetzt müßtest du bloß mal nachschauen, wie dein Typ "GPIO_TypeDef" denn 
überhaupt definiert ist. Ich vermute mal, daß sich dahinter ein dicker 
fetter struct befindet, der sämtliche Register eines der GPIO's enthält. 
Aber das kannst du ja selber herauskriegen.

Warum mußt du eigentlich alles so unsäglich verkomplizieren, bis keiner 
mehr durchsieht, was du da eigentlich gemacht hast (im Gegensatz zu 
gemeint hast)

W.S.

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.