Forum: Mikrocontroller und Digitale Elektronik Wieso Wert nicht gleich auf 0 setzen?


von Hansi H. (Gast)


Lesenswert?

Nabend,

Wieso verundet man das Register mit 0? Was macht das für einen Sinn?
1
// a interrupt is only generated if a message was transmitted or received
2
    if (CANSTMOB & (1 << TXOK))
3
    {
4
      // clear MOb
5
      CANSTMOB &= 0;
6
      CANCDMOB = 0;
7
                }

von holger (Gast)


Lesenswert?

>Wieso verundet man das Register mit 0? Was macht das für einen Sinn?

Es macht keinen Sinn.

von Dussel (Gast)


Lesenswert?

Ich wüsste keinen allgemeinen Grund. Für welchen Controller und welchen 
Compiler ist das?

von Peter D. (peda)


Lesenswert?

Hansi  H. schrieb:
> Wieso verundet man das Register mit 0?

Das mußt Du den Autor des Schnipsels fragen.
Vielleicht steht auch was dazu im Datenblatt des unbekannten MCs.

von Hansi H. (Gast)


Lesenswert?

Es handelt sich um einen At90CAN128.
Hier der Code.
1
ISR(CANIT_vect)
2
{
3
  uint8_t canpage;
4
  uint8_t mob;
5
  
6
  if ((CANHPMOB & 0xF0) != 0xF0)
7
  {
8
    // save MOb page register
9
    canpage = CANPAGE;
10
    
11
    // select MOb page with the highest priority
12
    CANPAGE = CANHPMOB & 0xF0;
13
    mob = (CANHPMOB >> 4);
14
    
15
    // a interrupt is only generated if a message was transmitted or received
16
    if (CANSTMOB & (1 << TXOK))
17
    {
18
      // clear MOb
19
      CANSTMOB &= 0;
20
      CANCDMOB = 0;
21
      
22
23
      can_t *buf = CanBufferGetDequeuePtr(&CanTxBufferInfo);
24
      
25
      // check if there are any another messages waiting
26
      if (buf != NULL)
27
      {
28
        _CanCopyMessageToMob( buf );
29
        CanBufferDequeue(&CanTxBufferInfo);
30
        
31
        // enable transmission
32
        CANCDMOB |= (1<<CONMOB0);
33
      }
34
      else {
35
        // buffer underflow => no more messages to send
36
        _DisableMobInterrupt(mob);
37
        _transmission_in_progress = 0;
38
      }
39
    }
40
    else {
41
      // a message was received successfully
42
      can_t *buf = CanBufferGetEnqueuePtr(&CanRxBufferInfo);
43
      
44
      if (buf != NULL)
45
      {
46
        // read message
47
        _CanCopyMobToMessage( buf );
48
        
49
        // push it to the list
50
        CanBufferEnqueue(&CanRxBufferInfo);
51
      }
52
      else {
53
        // buffer overflow => reject message
54
        // FIXME inform the user
55
      }
56
      
57
      // clear flags
58
      CANSTMOB &= 0;
59
      CANCDMOB = (1 << CONMOB1) | (CANCDMOB & (1 << IDE));
60
    }
61
    
62
    // restore MOb page register
63
    CANPAGE = canpage;
64
  }
65
  else
66
  {
67
    // no MOb matches with the interrupt => general interrupt
68
    CANGIT |= 0;
69
  }
70
}

von Peter D. (peda)


Lesenswert?

Hansi  H. schrieb:
> Hier der Code.

Und woher ist der?
Ist das ein offizielles Beispiel von Microchip.

von Datenblatt (Gast)


Lesenswert?

Hallo

Laut Datenblatt des At90CAN128:
To acknowledge a MOb interrupt, the corresponding bits of CANSTMOB 
register (RXOK, TXOK,...) must be cleared by the software application. 
This operation needs a read-modify-write
software routine.

Hansi  H. schrieb:
> CANSTMOB &= 0;
entspricht ja
CANSTMOB = CANSTMOB & 0;

Das Register wird hier zuerst gelesen (read), danach mit & 0 auf 0 
gesetzt (modify) und abschließend wieder geschrieben (write).

von Hansi H. (Gast)


Lesenswert?


von Hansi H. (Gast)


Lesenswert?

Datenblatt schrieb im Beitrag #568134
> Hansi  H. schrieb:
> CANSTMOB &= 0;
>
> entspricht ja
> CANSTMOB = CANSTMOB & 0;
>
> Das Register wird hier zuerst gelesen (read), danach mit & 0 auf 0
> gesetzt (modify) und abschließend wieder geschrieben (write).
Das macht natürlich Sinn. Danke für die Erklärung.

von Jim M. (turboj)


Lesenswert?

Hansi  H. schrieb:
> Wieso verundet man das Register mit 0? Was macht das für einen Sinn?

Bugreport an den Author des Quellcodes. (Github: Issues).

Falls das wirklich so gedacht war (Zusätzlicher Lesezugriff auf das 
Register) dann muss da mindestens ein aussagekräftiger Kommentar sein.

von Walter (Gast)


Lesenswert?

Hansi  H. schrieb:
> CANGIT |= 0;

Register lesen und unverändert zurückschreiben ist mir bisher auch noch 
nicht untergekommen. Wenn das denn sein muss würde ich zumindest
CANGIT = CANGIT
schreiben

von Hansi H. (Gast)


Lesenswert?

Walter schrieb:
> Hansi  H. schrieb:
> CANGIT |= 0;
>
> Register lesen und unverändert zurückschreiben ist mir bisher auch noch
> nicht untergekommen. Wenn das denn sein muss würde ich zumindest
> CANGIT = CANGIT
> schreiben

Zumal ist das wahrscheinlich noch schneller.

von A. S. (Gast)


Lesenswert?

Jim M. schrieb:
> Falls das wirklich so gedacht war (Zusätzlicher Lesezugriff auf das
> Register) dann muss da mindestens ein aussagekräftiger Kommentar sein.

Bei uC, besonders bei serieller IO ist es üblich, das Register gelesen 
und beschrieben werden müssen.

Niemand würde, ohne das DB zu lesen, solch Registerzugriffe in der 
Reihenfolge vertauschen oder "optimieren".

Ein Kommentar? Didaktisch OK. Je nach skills der Zielgruppe. Am Ende 
will man aber weder das DB im Code haben, noch bei jeder RMW-operation 
dabeischreiben, dass es eine sein soll.

von Axel S. (a-za-z0-9)


Lesenswert?

Walter schrieb:
> Hansi  H. schrieb:
>> CANGIT |= 0;
>
> Register lesen und unverändert zurückschreiben ist mir bisher auch
> noch nicht untergekommen.

Der Grund dürfte der gleiche sein wie im Beispiel weiter oben: das Lesen 
des Registers hat einen hardwareseitigen Effekt, der benötigt wird.

Hansi  H. schrieb:
>> Wenn das denn sein muss würde ich zumindest
>> CANGIT = CANGIT schreiben

> Zumal ist das wahrscheinlich noch schneller.

Der Compiler wird die Veroderung mit 0 wegoptimieren.

von holger (Gast)


Lesenswert?

>Der Compiler wird die Veroderung mit 0 wegoptimieren.

Das darf er nicht weil CANGIT volatile ist.

von A. S. (Gast)


Lesenswert?

holger schrieb:
>>Der Compiler wird die Veroderung mit 0 wegoptimieren.
>
> Das darf er nicht weil CANGIT volatile ist.

Es geht ums oder. Das darf er wegoptumieren. Dann sind beide Zeilen 
gleichwertig.

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.