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 } }
Garantiert kein ANSI-C konformes Verhalten. Kann es sein, dass das eine Spracherweiterung von TI auf dem hauseigenen Compiler ist?
Es sollte lt. Beschreibung auch mit IAR laufen: // Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.41A
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.
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 ;-)
Viele Dank, das hilft mir weiter! Funktioniert das dann auch so mit dem CCE - Compiler?
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...
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 | }
|
weia. ich werde wohl alt... werde mir mal dr. kawasakis gehirndauerlauf holen... ;-)
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).
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.
Jorge wrote: > Es handelt sich um den Komma Operator und den gibts eigentlich nur bei > C++ (nicht überladbar) Ist normales C seit K&R.
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.
> 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.