Forum: Mikrocontroller und Digitale Elektronik volatile Funktionspointer in ISR


von Alexander H. (ill_son)


Lesenswert?

Hallo,

ich arbeite gerade an einem Projekt mit einem ATXMEGA128A1 un Atmel 
Studio und habe folgende Frage:

Ich möchte in einer ISR eine kleine Funktion aufrufen und zwar abhängig 
von einer Bedingung entweder Funktion1 oder Funktion2. Beide Funktionen 
haben die gleiche Signatur.

Ich habe mit dazu einen Funtionspointer definiert
1
uint16_t ( *volatile readSensor )( void )

dem weise ich abhängig von der Bedingung am Anfang der main die Funktion 
zu:
1
if(read1 == 1)
2
   readSensor = readSensor1;
3
else
4
   readSensor = readSensor2;

Ist das so korrekt? AtmelStudio markiert mir die Pointerdefinition rot, 
weil dort volatile steht und sagt Symbol undefiniert. Ist das ein "Bug" 
im AS oder habe ich da noch einen Fehler gemacht? Compilieren kann ich 
es.

Grüße, Alex

:
von Falk B. (falk)


Lesenswert?

http://www.embedded.com/electronics-blogs/beginner-s-corner/4023801/Introduction-to-the-Volatile-Keyword

Stellt sich die Frage, ob der volatile Funktionszeiger wirklich nötig 
und sinnvoll ist. Man kann ebenso die Steuervariable in der ISR 
auswerten und passend die Funktion aufrufen. Die paar Takte, die das 
kostet werden deine ISR nicht unbrauchbar machen.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Auch ganz ohne volatile wird das funktionieren.

von Falk B. (falk)


Lesenswert?

Jörg W. schrieb:
> Auch ganz ohne volatile wird das funktionieren.

Warum? Was unterscheidet einen Funktionszeiger von einer Variablen? 
Werden Funktionszeiger prinzipiell nicht optimiert und lokal gepuffert?

von Falk B. (falk)


Lesenswert?

Alexander H. schrieb:
> dem weise ich abhängig von der Bedingung am Anfang der main die Funktion
> zu:
> 1if(read1 == 1)
> 2   readSensor = readSensor1;
> 3else
> 4   readSensor = readSensor2;

Aber auch hier muss man aufpassen! Die Zuweisung muss ATOMAR erfolgen!

https://www.mikrocontroller.net/articles/Interrupt#Atomarer_Datenzugriff

von Alexander H. (ill_son)


Lesenswert?

Falk B. schrieb:
> Jörg W. schrieb:
>> Auch ganz ohne volatile wird das funktionieren.
>
> Warum? Was unterscheidet einen Funktionszeiger von einer Variablen?
> Werden Funktionszeiger prinzipiell nicht optimiert und lokal gepuffert?

Die Frage stelle ich mir auch gerade.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Falk B. schrieb:
>> Auch ganz ohne volatile wird das funktionieren.
>
> Warum?

Weil der Compiler in einer ISR gar keine Chance hat, da irgendwie 
irgendwas unpassendes zu cachen. Der kann nur auf den globalen 
Funktionszeiger zugreifen, um die entsprechende Funktion aufzurufen.

Anders wäre die Situation, wenn sich noch während der Laufzeit der ISR 
dieser Zeiger ("von außen") ändern könnte. Aber das wird ja wohl eher 
nicht der Fall sein.

von Alexander H. (ill_son)


Lesenswert?

https://stackoverflow.com/questions/40108010/how-to-use-function-pointer-inside-arduino-interrupt-service-routine-to-modify-t

In dem Post steht was anderes, allerdings geht aus den Kommentaren 
hervor, dass er auch noch eine anderes Problem mit seinem Code haben 
könnte.

von Peter D. (peda)


Lesenswert?

Jörg W. schrieb:
> Auch ganz ohne volatile wird das funktionieren.

Eher nicht.
Der Compiler sieht im Mainkontext keinerlei Verwendung und schenkt sich 
die Zuweisung in die Variable.

Den Interrupt interessiert das volatile nicht. Er kennt keine vorherige 
Instanz, d.h. muß die Variable in jedem Fall neu einlesen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Der Compiler sieht im Mainkontext keinerlei Verwendung und schenkt sich
> die Zuweisung in die Variable.

Darf er nicht. Die ist global, da muss er immer mit Seiteneffekten 
rechnen.

von Walter T. (nicolas)


Lesenswert?

DAS ist doch mal eine Freitagsdiskussion, die nicht auf Anhieb nervt.

von Falk B. (falk)


Lesenswert?

Jörg W. schrieb:
>> Der Compiler sieht im Mainkontext keinerlei Verwendung und schenkt sich
>> die Zuweisung in die Variable.
>
> Darf er nicht. Die ist global, da muss er immer mit Seiteneffekten
> rechnen.

Wenn das so ist, warum müssen dann Variablen volatile deklariert werden?

von Cyblord -. (cyblord)


Lesenswert?

Falk B. schrieb:
> Jörg W. schrieb:
>>> Der Compiler sieht im Mainkontext keinerlei Verwendung und schenkt sich
>>> die Zuweisung in die Variable.
>>
>> Darf er nicht. Die ist global, da muss er immer mit Seiteneffekten
>> rechnen.
>
> Wenn das so ist, warum müssen dann Variablen volatile deklariert werden?

Hab ich mich auch gerade gefragt.
1
uint8_t myVar=0;
2
3
int main() {
4
while(1) {
5
if (myVar==24) doSomething();
6
}
7
}
8
9
ISR() {
10
myVar=24;
11
}

klappt nicht ohne volatile weil der compiler myVar nicht mehr aus dem 
speicher liest. es wird im prinzip der ganze schleifeninhalt 
wegrationalisiert.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Cyblord -. schrieb:
> klappt nicht ohne volatile weil der compiler myVar nicht mehr aus dem
> speicher liest. es wird im prinzip der ganze schleifeninhalt
> wegrationalisiert.

Das ist allerdings auch der gegenteilige Fall.

In der ISR gibt es keine Schleife, also muss der Wert aus dem globalen 
Kontext stammen.

von Nop (Gast)


Lesenswert?

Falk B. schrieb:

> Aber auch hier muss man aufpassen! Die Zuweisung muss ATOMAR erfolgen!

Quatsch. Am Anfang der main() erfolgt die Zuweisung, also bevor die 
Interrupts aufgesetzt werden. Da muß überhaupt nichts atomar sein.

von Cyblord -. (cyblord)


Lesenswert?

Walter T. schrieb:
> Cyblord -. schrieb:
>> klappt nicht ohne volatile weil der compiler myVar nicht mehr aus dem
>> speicher liest. es wird im prinzip der ganze schleifeninhalt
>> wegrationalisiert.
>
> Das ist allerdings auch der gegenteilige Fall.

Bitte was?
Es geht nicht um den Fall, sondern um die Aussage globale Variablen 
bräuchten kein volatile.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Analog wäre:
1
uint8_t myVar=0;
2
3
int main() {
4
myVar = 0;
5
while(1) {
6
    myVar = !myVar;
7
}
8
9
}
10
11
ISR() {
12
   if (myVar) doSomething();
13
}

Cyblord -. schrieb:
> Es geht nicht um den Fall, sondern um die Aussage globale Variablen
> bräuchten kein volatile.

Die Aussage gab es nie. Es gab die Aussage, dass in diesem Fall eine 
globale Variable kein volatile benötigte.

: Bearbeitet durch User
von Cyblord -. (cyblord)


Lesenswert?

Walter T. schrieb:
> Analog wäre:
>
1
> uint8_t myVar=0;
2
> 
3
> int main() {
4
> myVar = 0;
5
> while(1) {
6
>     myVar = !myVar;
7
> }
8
> 
9
> }
10
> 
11
> ISR() {
12
>    if (myVar) doSomething();
13
> }
14
>

Ja richtig. So rum gehts weil er beim Eintritt in die ISR myVar aus dem 
Speicher lesen muss.
Nur die Aussage von Jörg war an diese Stelle etwas zu allgemein.
Bezogen auf diesen Fall aber korrekt.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Walter T. schrieb:
> In der ISR gibt es keine Schleife, also muss der Wert aus dem globalen
> Kontext stammen.

s/Schleife/wiederholte Verwendung/

Nur in dem Zusammenhang ist das so relevant. Aber ja, in der Regel 
erfolgt diese wiederholte Verwendung natürlich innerhalb einer Schleife, 
insbesondere, wenn man dabei auf irgendeine Veränderung pollt, die durch 
einen Interrupt verursacht wird.

Einfaches Beispiel:
1
#include <avr/interrupt.h>
2
#include <avr/io.h>
3
#define F_CPU 1E6
4
#include <util/delay.h>
5
6
void (*fptr)(void);
7
8
ISR(USART_RX_vect)
9
{
10
        if (fptr)
11
                fptr();
12
}
13
14
void
15
set_led(void)
16
{
17
        PORTB &= ~_BV(1);
18
}
19
20
void
21
clear_led(void)
22
{
23
        PORTB |= _BV(1);
24
}
25
26
int
27
main(void)
28
{
29
        DDRB |= _BV(1);
30
31
        for (;;)
32
        {
33
                fptr = set_led;
34
                _delay_ms(100);
35
                fptr = clear_led;
36
                _delay_ms(100);
37
        }
38
}

Auch mit maximaler Optimierung wirft der Compiler die Zuweisung an 
"fptr" nicht weg, und die ISR holt sich selbstverfreilich den Wert von 
da. Was sollte sie auch sonst tun?
1
        .file   "example.c"
2
__SP_H__ = 0x3e
3
__SP_L__ = 0x3d
4
__SREG__ = 0x3f
5
__tmp_reg__ = 0
6
__zero_reg__ = 1
7
        .text
8
.global set_led
9
        .type   set_led, @function
10
set_led:
11
/* prologue: function */
12
/* frame size = 0 */
13
/* stack size = 0 */
14
.L__stack_usage = 0
15
        cbi 0x5,1
16
/* epilogue start */
17
        ret
18
        .size   set_led, .-set_led
19
.global clear_led
20
        .type   clear_led, @function
21
clear_led:
22
/* prologue: function */
23
/* frame size = 0 */
24
/* stack size = 0 */
25
.L__stack_usage = 0
26
        sbi 0x5,1
27
/* epilogue start */
28
        ret
29
        .size   clear_led, .-clear_led
30
.global __vector_18
31
        .type   __vector_18, @function
32
__vector_18:
33
        push r1
34
        push r0
35
        in r0,__SREG__
36
        push r0
37
        clr __zero_reg__
38
        push r18
39
        push r19
40
        push r20
41
        push r21
42
        push r22
43
        push r23
44
        push r24
45
        push r25
46
        push r26
47
        push r27
48
        push r30
49
        push r31
50
/* prologue: Signal */
51
/* frame size = 0 */
52
/* stack size = 15 */
53
.L__stack_usage = 15
54
        lds r30,fptr
55
        lds r31,fptr+1
56
        sbiw r30,0
57
        breq .L4
58
        icall
59
.L4:
60
/* epilogue start */
61
        pop r31
62
        pop r30
63
        pop r27
64
        pop r26
65
        pop r25
66
        pop r24
67
        pop r23
68
        pop r22
69
        pop r21
70
        pop r20
71
        pop r19
72
        pop r18
73
        pop r0
74
        out __SREG__,r0
75
        pop r0
76
        pop r1
77
        reti
78
        .size   __vector_18, .-__vector_18
79
        .section        .text.startup,"ax",@progbits
80
.global main
81
        .type   main, @function
82
main:
83
/* prologue: function */
84
/* frame size = 0 */
85
/* stack size = 0 */
86
.L__stack_usage = 0
87
        sbi 0x4,1
88
        ldi r18,lo8(gs(set_led))
89
        ldi r19,hi8(gs(set_led))
90
        ldi r24,lo8(gs(clear_led))
91
        ldi r25,hi8(gs(clear_led))
92
.L10:
93
        sts fptr+1,r19
94
        sts fptr,r18
95
        ldi r30,lo8(24999)
96
        ldi r31,hi8(24999)
97
1:      sbiw r30,1
98
        brne 1b
99
        rjmp .
100
        nop
101
        sts fptr+1,r25
102
        sts fptr,r24
103
        ldi r30,lo8(24999)
104
        ldi r31,hi8(24999)
105
1:      sbiw r30,1
106
        brne 1b
107
        rjmp .
108
        nop
109
        rjmp .L10
110
        .size   main, .-main
111
.global fptr
112
        .section .bss
113
        .type   fptr, @object
114
        .size   fptr, 2
115
fptr:
116
        .zero   2
117
        .ident  "GCC: (GNU) 10.2.0"
118
.global __do_clear_bss

(Dass Funktionszeiger in ISRs auf dem AVR keine sonderlich gute Idee 
sind, weil sie eine push/pop-Orgie nach sich ziehen, steht auf einem 
anderen Blatt.)

von A. S. (Gast)


Lesenswert?

Peter D. schrieb:
> Der Compiler sieht im Mainkontext keinerlei Verwendung und schenkt sich
> die Zuweisung in die Variable.

Das reicht allein nicht.

Main muss nach der Zuweisung noch eine weitere Zuweisung haben, 
dazwischen keinen Funktionsaufruf aber eine loop (mit volatile var als 
Bedingung).

Also kann prinzipiell Probleme bereiten, aber praktisch selten. Quasi 
nur wenn alles im Interrupt läuft.

von Falk B. (falk)


Lesenswert?

Nop schrieb:
> uatsch. Am Anfang der main() erfolgt die Zuweisung,

Sagt der OP.

> also bevor die
> Interrupts aufgesetzt werden.

Das weißt du nicht.

von Alexander H. (ill_son)


Lesenswert?

Jörg W. schrieb:
> (Dass Funktionszeiger in ISRs auf dem AVR keine sonderlich gute Idee
> sind, weil sie eine push/pop-Orgie nach sich ziehen, steht auf einem
> anderen Blatt.)

Die Aussage reicht mir schon, um die Bedingung in der ISR zu machen und 
auf den Pointer zu verzichten.

Danke für die hilfreichen Beiträge.

Grüße, Alex

von Cyblord -. (cyblord)


Lesenswert?

Alexander H. schrieb:
> Die Aussage reicht mir schon, um die Bedingung in der ISR zu machen und
> auf den Pointer zu verzichten.

Naja wenn man in einer Hochsprache schreibt, sollte der Fokus erst mal 
auf gutem Code in dieser Hochsprache liegen. Erst wenn es sein muss 
sollte man diesen Code auf besseren ASM Code hin optimieren. z.B. wenn 
man wirklich Zeitkritische Dinge macht, welche den Controller sowieso 
schon an den Rand der Leistungsfähigkeit bringen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. S. schrieb:

> Main muss nach der Zuweisung noch eine weitere Zuweisung haben,
> dazwischen keinen Funktionsaufruf aber eine loop (mit volatile var als
> Bedingung).

Ja, korrekt, man muss natürlich irgendwas haben, was potenziell in der 
Lage sein könnte, den Wert zu verwenden. Wenn ich in meinem Beispiel die 
_delay_ms()-Aufrufe rausnehme, werden die wiederholten Zuweisungen an 
die Variable weg optimiert.

Aber wie du schon schriebst: in der Praxis normalerweise kein Problem.

von Falk B. (falk)


Lesenswert?

Alexander H. schrieb:
>> (Dass Funktionszeiger in ISRs auf dem AVR keine sonderlich gute Idee
>> sind, weil sie eine push/pop-Orgie nach sich ziehen, steht auf einem
>> anderen Blatt.)
>
> Die Aussage reicht mir schon, um die Bedingung in der ISR zu machen und
> auf den Pointer zu verzichten.

Hast du das auch richtig verstanden? Es geht bei dem Problem nicht nur 
um Funktionszeiger, sondern auch um normale Funktionsaufrufe in einer 
ISR. Die sind beim avr gcc relativ "teuer" in bezug auf die push/pop 
Liste der Register.

Beitrag "Atmega ISR Prolog dauert zu lange - verschieben möglich?"

von Alexander H. (ill_son)


Lesenswert?

Ich dachte, Jörgs Aussage bezog sich jetzt konkret auf mein Problem mit 
dem Funktionszeiger. Mir ist bekannt, dass Funktionsaufrufe push/pop 
verursachen.
Bei mir ist es im wesentlichen das lesen einer uint16_t Variable über 
SPI. Die Lesefunktion ist in einer (eigenen) Bibliothek für den 
Sensor-Baustein, die ich mir geschrieben habe. Ich könnte das noch als 
inline deklarieren, wenn das was bringt. Es sind aber nicht viele 
ineinander verschachtelte Funktionen, nur Lesen und darin noch eine 
Funktion, die die Pins setzt und eine, die die SPI bedient. Das ist 
nicht ewig tief.

von Falk B. (falk)


Lesenswert?

Alexander H. schrieb:
> Ich dachte, Jörgs Aussage bezog sich jetzt konkret auf mein Problem mit
> dem Funktionszeiger. Mir ist bekannt, dass Funktionsaufrufe push/pop
> verursachen.

Sie verursachen in einer ISR aber noch mehr push/pop.

> Ich könnte das noch als
> inline deklarieren, wenn das was bringt.

Das funktioniert nicht immer. Probier's aus.

> Es sind aber nicht viele
> ineinander verschachtelte Funktionen, nur Lesen und darin noch eine
> Funktion, die die Pins setzt und eine, die die SPI bedient. Das ist
> nicht ewig tief.

Klingt trotzdem nach einer arg akademischen Implementierung eines 
schnöden SPI-Zugriffs.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Falk B. schrieb:
> Klingt trotzdem nach einer arg akademischen Implementierung eines
> schnöden SPI-Zugriffs.

Falls ein SPI-Zugriff timergesteuert sehr exakt erfolgen soll, mag sowas 
Sinn haben.

von Falk B. (falk)


Lesenswert?

Jörg W. schrieb:
>> Klingt trotzdem nach einer arg akademischen Implementierung eines
>> schnöden SPI-Zugriffs.
>
> Falls ein SPI-Zugriff timergesteuert sehr exakt erfolgen soll, mag sowas
> Sinn haben.

Das meinte ich nicht. Sondern die Verschachtelung von 2-3 Funktionen für 
bissel SPI, was mit einem Dutzend Zeilen in einer Funktion erledigen 
kann.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

OSI layering? ;-)

Wir kennen seine Aufgabe nicht.

von Alexander H. (ill_son)


Lesenswert?

Jörg W. schrieb:
> Falls ein SPI-Zugriff timergesteuert sehr exakt erfolgen soll, mag sowas
> Sinn haben.

Das ist bei mir der Fall. Ich habe eine genaue Uhr auf dem Board und der 
Messwert muss zum Takt der Uhr (1kHz) genommen werden.

In der ISR passiert im Wesentlichen das:
1
uint16_t adis16003ReadValueY( void )
2
{
3
  int16_t tmp;
4
  adis16003SetCS(0);              
5
  tmp = adis16003SendReceiveByte(ADIS_Y_DIRECTION);
6
  tmp = (tmp << 8) | adis16003SendReceiveByte(ADIS_Y_DIRECTION);
7
  adis16003SetCS(1);
8
  return tmp;
9
}

Das ist während der Messung außer einem 100ms Timer, der noch paar LED 
setzt, auch das Einzige was an Interrupts passiert.

: Bearbeitet durch User
von vonweiterweg (Gast)


Lesenswert?

Alexander H. schrieb:
> tmp = adis16003SendReceiveByte(ADIS_Y_DIRECTION);
> tmp = (tmp << 8) | adis16003SendReceiveByte(ADIS_Y_DIRECTION);

Das kann man in eine Funktionsaufruf zusammenfassen.
Spart Zeit / Overhead.

Alexander H. schrieb:
> adis16003SetCS(0);
> adis16003SetCS(1);

Das kann man auch ohne Funktionsaufruf machen, nämlich als Makro.
Spart Zeit / Overhead.

von Oliver S. (oliverso)


Lesenswert?

vonweiterweg schrieb:
> Das kann man in eine Funktionsaufruf zusammenfassen.
> Spart Zeit / Overhead.

Klar. Eine Eine Zeile Sourcecode statt zwei spart 50%. Wenn du dann noch 
die Funktionsnamen auf die halbe Länge kürzt, spart das nochmal 50%. 
Macht zusammen dann 100%.

Oliver

von mh (Gast)


Lesenswert?

Jörg W. schrieb:
> Einfaches Beispiel:
Die Zuweisung von fptr müsste noch atomisiert werden oder?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

mh schrieb:
> Die Zuweisung von fptr müsste noch atomisiert werden oder?

Ja, im Prinzip schon, korrekt.

von Falk B. (falk)


Lesenswert?

mh schrieb:
> Die Zuweisung von fptr müsste noch atomisiert werden oder?

Naja, du meinst eine atomare Zuweisung. Atomisieren bedeutet im 
Allgemeinen eher das Gegenteil ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

:-)

von vonweiterweg (Gast)


Lesenswert?

Hier meine Version wie ich das direkt in der ISR implementieren
würde ohne Zeit mit Funktionsaufrufen und entsprechendem push/pull
Overhead zu verschwenden.
1
#define  WAITSPI_RDY  do { /* wait */ } while ( (SPIF_STATUS & 0x80) == 0);
2
3
#define  SPI_LCD_CS_BIT  (1<<PIN0)
4
#define  CS_High         PORTF_OUTSET = SPI_LCD_CS_BIT
5
#define  CS_Low          PORTF_OUTCLR = SPI_LCD_CS_BIT
6
7
uint16_t XMega_SPI_ReadWord (void) // das ganze in die ISR
8
{
9
  uint8_t  byte0, byte1;
10
11
  // Hier muss man ggf noch etwas Sinnvolles senden
12
  SPIF_DATA = 0;  // Transfer starten (adis16003SendReceiveByte)
13
  WAITSPI_RDY  ;
14
  byte0 = SPIF_DATA;  // SPI lesen
15
16
  // Hier muss man ggf noch etwas Sinnvolles senden
17
  SPIF_DATA = 0;  // Transfer starten (adis16003SendReceiveByte)
18
  WAITSPI_RDY  ;
19
  byte1 = SPIF_DATA;  // SPI lesen
20
21
  return ( (uint16_t)(byte0<<8) | byte1 );
22
23
} /* --- XMega_SPI_ReadWord --- */

von vonweiterweg (Gast)


Lesenswert?

Mir ist schon klar dass die ISR nichts zurückgeben kann
á la
1
  return ( (uint16_t)(byte0<<8) | byte1 );

Soviel Abstraktionsfähigkeit des Lesers setze ich voraus ....

von Falk B. (falk)


Lesenswert?

vonweiterweg schrieb:
> return ( (uint16_t)(byte0<<8) | byte1 );

Das funktioniert nur deshalb, weil die Integer Promotion vom Compiler 
sowieso VOR dem Schieben gemacht wird. Bei 32 Bit Zielgröße würde es 
NICHT funktionieren. Richtig ist es so. Erst der cast, dann schieben! 
Die Klammer um byte0 ist eine Angstmaßnahme, braucht man eigentlich 
nicht.

return ( (((uint16_t)byte0)<<8) | byte1 );

von Falk B. (falk)


Lesenswert?

vonweiterweg schrieb:
> Soviel Abstraktionsfähigkeit des Lesers setze ich voraus ....

CS fehlt . . . naja

von vonweiterweg (Gast)


Lesenswert?

Ok danke.

An geeigneter Stelle ist CS_Low, CS_High einzufügen.

von vonweiterweg (Gast)


Lesenswert?

Falk B. schrieb:
> Richtig ist es so. Erst der cast, dann schieben!

Ok, danke. Im Eifer die Klammer falsch gesetzt.

von MaWin (Gast)


Lesenswert?

Alexander H. schrieb:
> Ich habe mit dazu einen Funtionspointer definiert
> uint16_t ( *volatile readSensor )( void )
>
> dem weise ich abhängig von der Bedingung am Anfang der main die Funktion
> zu:
> if(read1 == 1)
>    readSensor = readSensor1;
> else
>    readSensor = readSensor2;
>
> Ist das so korrekt?

Natürlich nicht. Du hast ein Fu..poi.. deklariert. Und da ist das 
volatile blödsinn. :-<<<

Wenn volatile, gehört zur Definition der Variablen readSensor.

Und den atomaren Zuweisungskrams erwarte ich vom Compiler. Wenn er das 
nicht kann, ist er Schrott. :-<<<

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

MaWin schrieb:

> Natürlich nicht. Du hast ein Fu..poi.. deklariert. Und da ist das
> volatile blödsinn. :-<<<

Blödsinn ist hier die Hälfte von dem, was du schreibst.

> Wenn volatile, gehört zur Definition der Variablen readSensor.

Genau da stand/steht es.

> Und den atomaren Zuweisungskrams erwarte ich vom Compiler. Wenn er das
> nicht kann, ist er Schrott. :-<<<

Schrott ist, was du da schreibst. Nur, weil du dir "MaWin" als Nick 
klaust, hilft das noch lange nichts.

Mittlerweile gibt es sogar ein <stdatomic.h>, welches in den nächsten 
C-Standard mit reinkommen wird, um sowas abzuhandeln. Das werden sie 
sich nicht aus Spaß so augedacht haben.

von mh (Gast)


Lesenswert?

MaWin schrieb:
> Du hast ein Fu..poi.. deklariert. Und da ist das
> volatile blödsinn. :-<<<
>
> Wenn volatile, gehört zur Definition der Variablen readSensor.
Bist du dir da sicher?

von MaWin (Gast)


Lesenswert?

mh schrieb:
> Bist du dir da sicher?

Ja.

von MaWin (Gast)


Lesenswert?

Jörg W. schrieb:
> Nur, weil du dir "MaWin" als Nick
> klaust

Wie soll das gehen? Wenn der Nick vergeben ist, kann ich doch nicht 
nutzen, oder?

von MaWin (Gast)


Lesenswert?

Jörg W. schrieb:
> Genau da stand/steht es.

Zeig mal.

von mh (Gast)


Lesenswert?

MaWin schrieb:
> mh schrieb:
>> Bist du dir da sicher?
>
> Ja.
Dann wissen wir jetzt ja, dass du keine Ahnung von C hast, wer auch 
immer du bist.

von MaWin (Gast)


Lesenswert?

mh schrieb:
> wer auch
> immer du bist.

MaWin

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

MaWin schrieb:
> mh schrieb:
>> wer auch
>> immer du bist.
>
> MaWin

Naja, jedenfalls nicht der MaWin. Der, den die, die ihn kennen, schon 
aus dem Usenet kennen.

Ist aber auch egal, deine Ahnungslosigkeit hinsichtlich C hast du uns ja 
nun ausreichend demonstriert.

von MaWin (Gast)


Lesenswert?

Jörg W. schrieb:
> der MaWin

Doch ich bin MaWin, der MaWin.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

MaWin schrieb:
> Jörg W. schrieb:
>> der MaWin
>
> Doch ich bin MaWin, der MaWin.

Du brauchst nicht zu lügen. Der MaWin bist du nicht, sondern 
irgendeiner. Wir kennen unsere Pappenheimer hier …

Beitrag #6684619 wurde von einem Moderator gelöscht.
Beitrag #6684625 wurde von einem Moderator gelöscht.
Beitrag #6684629 wurde von einem Moderator gelöscht.
Beitrag #6684633 wurde von einem Moderator gelöscht.
Beitrag #6684634 wurde von einem Moderator gelöscht.
von Mucky F. (Gast)


Lesenswert?

Alexander H. schrieb:
> dem weise ich abhängig von der Bedingung am Anfang der main die Funktion
> zu:
> if(read1 == 1)
>    readSensor = readSensor1;
> else
>    readSensor = readSensor2;

Da sind dann mehrere Abhängigkeiten über den Sourcecode verstreut.

Warum machst du das nicht ohne Funktionspointer und fragst read1 in der 
ISR ab? So ist es eine Operation mehr (das Laden der Sprungadresse) 
während die sonst "fest verdrahtet" im Opcode steht.

Das ist leichter zu lesen (auch im Assembler) und auch in 10 Jahren noch 
nachvollziehbar. Wenn die read1 Variable der Bitbreite des Prozessors 
entspricht muss das auch nicht atomar sein. Der Prozessor schreibt die 
Variable dann ja in einem Befehlszyklus, der ist imo auch bei Atmel uCs 
atomar.

Beitrag #6685044 wurde von einem Moderator gelöscht.
Beitrag #6685048 wurde von einem Moderator gelöscht.
Beitrag #6685700 wurde von einem Moderator gelöscht.
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.