Hallo Gemeinde, ich habe ein kleines Problem mit dem GCC. Er spuckt mir die drei Warnungen aus. ../Hupe_GCC.c:2145: warning: passing arg 2 of `Seconds2BCD' discards qualifiers from pointer target type ../Hupe_GCC.c:2149: warning: passing arg 2 of `Int2BCD' discards qualifiers from pointer target type ../Hupe_GCC.c:2150: warning: passing arg 2 of `Int2BCD' discards qualifiers from pointer target type Als globale Variable ist volatile uint8_t tx_buffer[7]; // buffer for data paket to external display definiert. Die drei Warnungen werden bei diesen Funktionsaufrufen generiert. Seconds2BCD(display_time, tx_buffer); Int2BCD(goals_B, tx_buffer+2); Int2BCD(goals_W, tx_buffer+3); welche die folgenden Funktionen aufrufen. void Int2BCD(uint8_t data, uint8_t *buffer) { uint16_t tmp; tmp = data % 10; data = data / 10; *buffer=(data <<4) | tmp; } void Seconds2BCD(uint16_t data, uint8_t *buffer) { uint16_t tmp, tmp2; tmp = data % 600; data = data / 600; tmp2= data<< 4; // tens minutes data = tmp % 60; tmp = tmp / 60; *buffer= tmp2 | tmp; // ones minutes buffer++; tmp = data % 10; data = data / 10; *buffer= (data <<4) | tmp; // tens and ones seconds } Ideen? Ich arbeite mit AVR Studio 4.12, Service Pack 4 und WinAVR 20060421 MfG Falk
Du schmeißt bei der Übergabe des Zeigers an die Funktion das "volatile" weg ("volatile" ist ein "type qualifier", genauso wie "const" und in C99 jetzt neu "restricted"). Ich hatte schonmal hier erläutert, dass und warum volatile auf Arrays praktisch weder sinnvoll noch notwendig ist.
@Jörg Wunsch >Du schmeißt bei der Übergabe des Zeigers an die Funktion das "volatile" >weg ("volatile" ist ein "type qualifier", genauso wie "const" und in >C99 jetzt neu "restricted"). Aha. >Ich hatte schonmal hier erläutert, dass und warum volatile auf Arrays >praktisch weder sinnvoll noch notwendig ist. Link? Es geht darum, dass das Array als Sendepuffer dür RS232 arbeitet, sprich dass im Hauptprogramm der Puffer gefüllt wird und im ISR dann gelesen und gesendet. Ich nehme an dass Arrays sowieso nicht lokal gepuffert werden und immer direkt zurückgeschrieben werden, oder? MFG Falk
OK, ich hätte vielleicht den ersten Schritt vor dem zweiten machen sollen und das Forum nach volatile abgrasen. Hab ich nun gemacht und das Ergebnis ist, dass ich volatile auch in die Parameterdefinition der Funktionen bringen sollte? MFG Falk
Falk wrote: > ... das > Ergebnis ist, dass ich volatile auch in die Parameterdefinition der > Funktionen bringen sollte? Ich würde es lieber ganz weglassen. Wenn du die ISR mit dem Hauptprogramm synchronisieren musst, dann nimm eine einzelne volatile deklarierte (uint8_t-)Variable dafür.
@Jörg Wunsch (dl8dtl) > ... das > Ergebnis ist, dass ich volatile auch in die Parameterdefinition der > Funktionen bringen sollte? >Ich würde es lieber ganz weglassen. Wenn du die ISR mit dem Kann es komische Effekte verursachen? >Hauptprogramm synchronisieren musst, dann nimm eine einzelne >volatile deklarierte (uint8_t-)Variable dafür. Mach ich schon, aber hier ist es umgekehrt. Ich schreibe im Hauptprogamm Daten in den Puffer und schalte am Ende den UDRE Interrupt ein, welcher dann auch sofort angesprungen wird. D.h. in dem Moment muss garantiert der Inhalt von tx_buffer stimmen. MfG Falk
>D.h. in dem Moment muss garantiert der Inhalt von tx_buffer stimmen. Das passt schon... >Ich schreibe im Hauptprogamm Daten in den Puffer Mache ich auch meist so. Oder bastel mir ein "putchar(unsigned char c)", das sich um das Beschreiben des Puffers kümmert. Allerdings arbeite ich ohne Pointer, sondern mit Indizes.
> D.h. in dem Moment muss garantiert > der Inhalt von tx_buffer stimmen. Dann starte die Aussendung mit einem Funktionsaufruf. Eine andere Alternative wäre eine "memory barrier", aber die ist natürlich stark compilerabhängig: __asm __volatile(""::: "memory");
@Rahul, der Trollige >>D.h. in dem Moment muss garantiert der Inhalt von tx_buffer stimmen. >Das passt schon... Dein Wort in Gottes Gehörgang ;-) >Ich schreibe im Hauptprogamm Daten in den Puffer >Mache ich auch meist so. Oder bastel mir ein "putchar(unsigned char c)", Warum soll ich für ne simple Variablenzuweisung eine Funktion schreiben? >das sich um das Beschreiben des Puffers kümmert. Allerdings arbeite ich >ohne Pointer, sondern mit Indizes. Aber kaum als Parameter in ner Funktion. @Jörg Wunsch >> D.h. in dem Moment muss garantiert >> der Inhalt von tx_buffer stimmen. >Dann starte die Aussendung mit einem Funktionsaufruf. >Eine andere Alternative wäre eine "memory barrier", aber die ist >natürlich stark compilerabhängig: >__asm __volatile(""::: "memory"); Was spricht gegen volatile? Ich finde es arg Overkill wegen so einem Problemchen mit extra Funktionen oder gar kryptischen Compilertricks zu arbeiten. Aber das scheint der Fluch von C zu sein, die Hackersprache ist nie wirklich erwachsen geworden . . . MfG Falk
> Was spricht gegen volatile?
Dass du damit alle Optimierungen auf buffer verhinderst, auch die,
die man gar nicht verhindern muss. Gewissermaßen eine Pessimierung.
Die extra Funktion schafft einen sogenannten sequence point, und an
diesem müssen alle globalen Variablen rückgeschrieben sein (da sie
in der Funktion benutzt werden könnten). Das ist meiner Meinung
sogar dann der Fall, wenn die Funktion selbst so simpel ist, dass
sie der Compiler am Ende inline expandiert => du hast optimalen
Code, und den sogar garantiert.
Ganz davon abgesehen ist es im Sinne der Modularisierung guter
Programmierstil, wenn man das Handling der UART (und damit auch die
Freigabe des UDRE) dem UART-Modul codeseitig überlässt, auch wenn
es sich nur um ein einzelnes Register handelt, das es dafür zu
beschreiben gilt. Das fördert die Abstraktion, und der Code ließe
sich einfacher auf einen anderen Prozessor (mit anderer UART-Hardware)
portieren.
OK, das klingt einleuchtend und überzeugend. Ich werde einen Funktionsaufruf für die UART schreiben. Danke. MFG Falk
>Warum soll ich für ne simple Variablenzuweisung eine Funktion schreiben? >>das sich um das Beschreiben des Puffers kümmert. Allerdings arbeite ich >>ohne Pointer, sondern mit Indizes. >Aber kaum als Parameter in ner Funktion. Meine putchar sieht halt so aus: void putchar(unsigned char c) { sendbuffer[sendwritepointer++]=c; sendwritepointer %= Buflength; // Überlauf verhindern if (!(USR & (1<<UDRIE)) USR |= (1<<UDRIE); // Hies das Ding USR? } Da das USART wensentlich langsamer als das Hauptprogramm ist, wird alles schön in den Puffer geschrieben und per ISR abgearbeitet. In der ISR wird UDRIE gelöscht, sobald der sendwritepointer == sendreadpointer ist - beide Zeiger also an der gleichen Stelle stehen... Die Pointer sind global volatile, wie der Puffer auch, vereinbart.
>Die Pointer sind global volatile, wie der Puffer auch, vereinbart.
Sorry, aber den Puffer als flüchtig zu markieren versucht Jörg ihm doch
gerade auszureden...
>Sorry, aber den Puffer als flüchtig zu markieren versucht Jörg ihm doch >gerade auszureden... Dann halte ich mich lieber raus... (die "Pointer" sind auch nichts anderes als Indizes eines array, keine *...)
Um die Pointer geht's nicht, Du schriebst, dass Du den Puffer selbst 'volatile' machst...
>Um die Pointer geht's nicht, Du schriebst, dass Du den Puffer selbst >'volatile' machst... Ich sollte mir angewöhnen, die "Vorschau"-Funktion zu benutzen: Dann hätte ich Jörgs Post noch lesen können und mir meine Beiträge sparen können. Das "volatile" bei arrays werde ich jetzt einfach mal weglassen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.