- Akku Tests und Balkonkraftwerk Speicher         
Ergebnis 1 bis 1 von 1

Thema: Bitdefinition mit fatalen Folgen

  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076

    Bitdefinition mit fatalen Folgen

    Anzeige

    Praxistest und DIY Projekte
    Hallo zusammen,
    ich habe nach einem etwas merkwürdigem Fehler in meiner Software gesucht und bin dann fündig geworden.
    Das Problem wollte ich Euch mal eben offen legen und vielleicht gibts da ja auch eine andere Lösung:

    Meine gesamten headerfiles für die Prozessorregister schreibe ich generell selbst

    Definition des LPC1768 Timer Interrupt Registers
    Schön ordentlich mit den Bits definiert

    Code:
    typedef volatile union
    {
      struct {
      U32 MR0INT   : 1;  /* Interrupt flag for match channel 0 */
      U32 MR1INT   : 1;  /* Interrupt flag for match channel 1 */
      U32 MR2INT   : 1;  /* Interrupt flag for match channel 2 */
      U32 MR3INT   : 1;  /* Interrupt flag for match channel 3 */
      U32 CR0INT   : 1;  /* Interrupt flag for capture channel 0 event */
      U32 CR1INT   : 1;  /* Interrupt flag for capture channel 0 event */
      U32 reserved : 26; /* unused bits */
      } bits;
      U32 value;
    } TIMER_IR_TypeDef;
    
    #define LPC_T0IR (* (TIMER_IR_TypeDef *)(0x40004000))
    #define LPC_T1IR (* (TIMER_IR_TypeDef *)(0x40008000))
    #define LPC_T2IR (* (TIMER_IR_TypeDef *)(0x40090000))
    #define LPC_T3IR (* (TIMER_IR_TypeDef *)(0x40094000))
    
    
    /*---- die Interrupt Funktion (nur zum Verständis, ohne jegliche Funktion) ---*/
    void TIMER0_IRQHandler(void)
    {
      if (LPC_T0IR.bits.CR0INT)  /* if Capture 0 interrupt occurred */
      {
        LPC_T0IR.bits.CR0INT = 1;  /* clear the correspond interrupt flag */
      }
    
      if (LPC_T0IR.bits.CR1INT)    /* if Capture 1 interrupt occurred */
      {
        LPC_T0IR.bits.CR1INT = 1;    /* clear the correspond interrupt flag */
      }
    
    }
    sieht doch eigentlich okay aus, A B E R :
    Der Compiler erzeugt bei Bitdefinitionen (bei meinem GNU Compiler) IMMER eine Read Modify Write Sequenz
    Read : Register "komplett" lesen
    Modify : entsprechendes Bit maskieren
    Write : "komplettes" Register zurück schreiben

    Die Funktionsweise des Interruptregisters ist aber wie folgt definiert:
    Eine 1 signalisiert einen Interrupt.
    Um dieses Interrupt Bit zu löschen, muss es per Software auf 1 gesetzt werden.
    Klingt nicht nur merkwürdig funktioniert auch NICHT richtig, WEIL:

    Wenn sich zusätzliche eine "1" beim Lesen im Register befindet, dann wird unweigerlich
    auch dieses Interrupt Bit zurückgesetzt, obwahl man durch die Maskierung es ja eigentlich verhindern wollte.
    Der Compiler liest das Register mit z.B. 2 Einsen, setzt das gewünschte Bit auf 1 und schreibt den kompletten Wert zurück ins Register.
    Alle anderen Bits bleiben also erhalten. Durch das Zurückschreiben von vorher gesetzten Einsen werden nun diese Interruptflags auch gelöscht.

    Fazit: Bei deisem Register darf auf keinen Fall eine Bitdefinition erfolgen.
    Wir müssen im Interrrupt nur einen Wert schreiben (WRITE)
    also wenn wir nur das CR0INT Bit löschen wollen, müssen wir das mit
    Register = (1 << 4); tun.
    Schade eigentlich, ich fand die Bitdefinition viel übersichtlicher....
    Aber vielleicht geht das ja auch noch anders.
    Siro


    So sieht es ja auch noch vernünftig aus:

    Code:
    #define CPU_REG_32 *(volatile unsigned int*)   /* points to an 32 Bit register */
    
    #define TIMER0_IR CPU_REG_32 0x40004000
    
    #define IR_MR0 (1 << 0)
    #define IR_MR1 (1 << 1)
    #define IR_MR2 (1 << 2)
    #define IR_MR3 (1 << 3)
    #define IR_CR0 (1 << 4)
    #define IR_CR1 (1 << 5)
    
    
    void TIMER0_IRQHandler(void)
    {
      if (TIMER0_IR & IR_CR0)  /* Capture 0 interrupt occured */
      {
        TIMER0_IR = IR_CR0;  /* clear the corresponing interrupt flag */
      }
    
      if (TIMER0_IR & IR_CR1)  /* Capture 1 interrupt occured */
      {
        TIMER0_IR = IR_CR1;  /* clear the corresponing interrupt flag */
      }
    Geändert von Siro (25.01.2016 um 14:08 Uhr)

Ähnliche Themen

  1. Akku kurzgeschlossen - Folgen?
    Von Virtuelx im Forum Elektronik
    Antworten: 8
    Letzter Beitrag: 26.06.2012, 21:23
  2. Linie folgen
    Von Martinius11 im Forum Asuro
    Antworten: 2
    Letzter Beitrag: 29.10.2009, 18:03
  3. Linie Folgen
    Von BlackDevil im Forum C - Programmierung (GCC u.a.)
    Antworten: 47
    Letzter Beitrag: 17.08.2008, 12:44
  4. Bewegung folgen
    Von Bartolomero im Forum Sensoren / Sensorik
    Antworten: 10
    Letzter Beitrag: 10.09.2007, 14:28
  5. Linie folgen
    Von tornado im Forum Sensoren / Sensorik
    Antworten: 13
    Letzter Beitrag: 18.05.2006, 18:14

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests