Forum: Mikrocontroller und Digitale Elektronik C Programmierung: switch Anweisung mit zwei Argumenten?


von Bastler0815 (Gast)


Lesenswert?

Hallo,
bei einem Beispielprogramm von TI bin ich über eine switch - Anweisung 
gestolpert, der 2 Argumente übergeben werden. Kann mir das jemand 
erklären?
Es steht dabei, dass es eine effiziente Implementierung wäre, aber ich 
werde nicht so ganz schlau daraus.



// Timer_A3 Interrupt Vector (TAIV) handler
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A(void)
{
  switch (TAIV, 10)        // Efficient switch-implementation
  {
    case  2:                                // TACCR1
      P1OUT ^= 0x01;                        // Toggle P1.0
      TACCR1 += 50000;                      // Add Offset to TACCR1
      break;
    case  4: break;                         // TACCR2 not used
    case 10: break;                         // Overflow not used
  }
}

von lucem (Gast)


Lesenswert?

Garantiert kein ANSI-C konformes Verhalten.
Kann es sein, dass das eine Spracherweiterung von TI auf dem hauseigenen 
Compiler ist?

von Bastler0815 (Gast)


Lesenswert?

Es sollte lt. Beschreibung auch mit IAR laufen:
//  Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 
3.41A

von yalu (Gast)


Lesenswert?

Doch, das ist Standard-C. Der Ausdruck a,b evaluiert sowohl a als auch
b und liefert als Ergebnis b. In diesem Fall wird (vielleicht zu
Debug-Zwecken) immer in case 10 verzweigt.

von Stefan (Gast)


Lesenswert?

Ob das ganze ANSI-(oder wie auch immer)konform ist, weiß ich nicht.
Es ist jedenfalls eine Spezialität des IAR-Compilers, der unter 
bestimmten Voraussetzungen aus der switch-Anweisung einen optimierten 
Code generiert.

In neueren Versionen müsste es eigentlich heißen:
1
// Timer_A3 Interrupt Vector (TAIV) handler
2
#pragma vector=TIMERA1_VECTOR
3
__interrupt void Timer_A(void)
4
5
switch (__even_in_range(TAIV, 10))          // Efficient switch-implementation
6
  {
7
    case  2:                                // TACCR1
8
      P1OUT ^= 0x01;                        // Toggle P1.0
9
      TACCR1 += 50000;                      // Add Offset to TACCR1
10
      break;
11
    case  4: break;                         // TACCR2 not used
12
    case 10: break;                         // Overflow not used
13
  }

Der TIMERA1_VECTOR hat mehrere Quellen, wobei in TAIV vermerkt ist, 
welche Quelle gerade in der ISR bearbeitet wird. Es ist hierbei bekannt, 
dass der Wert in TAIV maximal 10 sein kann (->...(TAIV,10)...) und 
geradzahlig ist (__even_in_range).
Dann kann eine Sprungtabelle angelegt werden, auf die einfach 
zugegriffen werden kann, indem der aktuelle TAIV-Wert auf den Program 
Counter addiert wird. Die Sprungtabelle verzweig dann in die 
unzterschiedlichen cases.
Das ist alles ;-)

von Bastler0815 (Gast)


Lesenswert?

Viele Dank,
das hilft mir weiter!

Funktioniert das dann auch so mit dem CCE - Compiler?

von Stefan (Gast)


Lesenswert?

Den CCE kenne ich nicht.
Ich denke aber, dass das (zumindest in dieser Notation) nur im IAR 
funktioniert. Vielleicht hat der CCE aber einen ähnlichen "Mechanismus". 
Da sollte aber dessen User-Guide weiterhelfen...

von I_ H. (i_h)


Lesenswert?

Das scheint schon Ansi-C zu sein, der gcc mäkelt jedenfalls auch net. 
Ist übrigens teils schon witzig was der C Standard hergibt, der 
Klassiker:
1
        n = (anzahl + 3) / 4;
2
 
3
        switch(anzahl % 4) {
4
        case 0:        do { ziel[stelle] = quelle[stelle]; stelle++;
5
        case 3:             ziel[stelle] = quelle[stelle]; stelle++;
6
        case 2:             ziel[stelle] = quelle[stelle]; stelle++;
7
        case 1:             ziel[stelle] = quelle[stelle]; stelle++;
8
                       } while(--n > 0);
9
        }

von routy (Gast)


Lesenswert?

weia. ich werde wohl alt... werde mir mal dr. kawasakis gehirndauerlauf 
holen... ;-)

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


Lesenswert?

I_ H. wrote:

> Das scheint schon Ansi-C zu sein, der gcc mäkelt jedenfalls auch net.

Er wird aber dabei etwas völlig anderes tun. ;-)  Wie yalu schon
geschrieben hat, wird er zwar das Register TAIV auswerten, aber
anschließend fest zum Wert 10 in der switch-Anweisung verzweigen.

In der aktuellen IAR-Doku findet man darüber auch nichts mehr, sondern
nur die weiter oben beschriebene (Pseudo-)Funktion __even_in_range(),
die ganz offensichtlich eigens für diese Eigenheit der MSP430s
gezimmert worden ist (und die es dann auch nur bei der MSP430-Version
gibt).

von Jorge (Gast)


Lesenswert?

Es handelt sich um den Komma Operator und den gibts eigentlich nur bei 
C++ (nicht überladbar) oder beim normalen C mit Herstellerspezifischen 
Erweiterungen ist glaube ich nicht ANSI konform.

von Andreas K. (a-k)


Lesenswert?

Jorge wrote:

> Es handelt sich um den Komma Operator und den gibts eigentlich nur bei
> C++ (nicht überladbar)

Ist normales C seit K&R.

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


Lesenswert?

Andreas Kaiser wrote:

>> Es handelt sich um den Komma Operator und den gibts eigentlich nur bei
>> C++ (nicht überladbar)
>
> Ist normales C seit K&R.

Nur halt nicht in dieser etwas eigenwilligen semantischen Ausdeutung
da ganz oben. ;-)  Aber daher haben sie's ja offenbar auch korrigiert
und stattdessen den korrekten Weg mit __even_in_range() gewählt.

von Peter (Gast)


Lesenswert?

> Es handelt sich um den Komma Operator und den gibts eigentlich nur bei
> C++ (nicht überladbar)

type& operator , ( type )
{
}

Der MS-compiler kann das, ob es sinn macht ist eine andere Frage.

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.