Forum: Mikrocontroller und Digitale Elektronik Unverständliches Verhalten von struct-Variablen bei Interrupt


von Sascha (Gast)


Lesenswert?

Morgen zusammen!

Ich habe ein Problem mit einer Variablen meines structs.

Hier erstmal das struct:
1
struct  // Struct contains information used for communication with EEPROM
2
{
3
  uint16_t address;     // Address to be read or written
4
  uint8_t  byte [8];    // Byte 1 to 8 for complete page write
5
  uint8_t  bytecount;   // Number of bytes to read or written
6
  uint8_t  nextbyte;    // Next byte to be transmitted
7
  uint8_t  eeprom_nr;   // Selects between different EEPROMs
8
} eeprom;

Und hier die Interrupt-Routine:
1
#pragma vector = USCIAB0TX_VECTOR
2
__interrupt void usciab0vector (void)
3
{  
4
  if (IFG2 & UCB0TXIFG) // Byte successfully read from USCB0-TX-Buffer
5
  {
6
    
7
    if (eeprom.bytecount != 1) // More than one byte
8
    {
9
      eeprom.nextbyte += 1;
10
      if (eeprom.nextbyte < eeprom.bytecount)
11
      {
12
        UCB0TXBUF = eeprom.byte[eeprom.nextbyte];
13
      }
14
      else
15
      {
16
        eeprom.nextbyte = 0;
17
        EE1_WP;  // Write protect enabled
18
        EE1_DES; // Deselect EEPROM
19
      }
20
    }
21
    
22
  } // End if (IFG2 & UCB0TXIFG)  
23
}

Und zwar möchte ich damit mein EEPROM Interrupt-gesteuert beschreiben. 
In der Interrupt-Routine soll jedesmal automatisch das nächste Byte 
geladen werden. Insgesamt halt 8 Bytes für einen Page-Write.

Mein Problem: Jedesmal, wenn die ISR aufgerufen wird, also jedesmal, 
wenn der uC das Byte aus dem Sendepuffer entfernt hat und bereit für das 
nächste ist, ist meine Variable
1
eeprom.nextbyte

wieder 0! Somit wird natürlich jedesmal dasselbe Byte verschickt. 
Während die ISR abgearbeitet wird, wird die Variable erhöht, aber sie 
ist nächstes mal nciht mehr da.

Das struct ist global deklariert, wenn ich es zusätzlich als volatile 
deklariere, oder seine Kompnenten, dann gibts ne Warnung.


Hat jemand nen Tip?

von Mandrake (Gast)


Lesenswert?

Überleg nochmal, ob dein 2. if in deiner ISR wirklich die Bedingung 
prüft, die du willst. Das Kommentar dahinter sagt nämlich was 
anderes....

Dann müsste es heißen:
if (eeprom.bytecount > 1)

Gruß

Mandrake

von (prx) A. K. (prx)


Lesenswert?

Und wie so oft fehlt volatile.

von Sascha (Gast)


Lesenswert?

OK, dann noch der Code dazu:
1
void eeprom_write (void) // ONSemi CAT25256 256kB SPI
2
{
3
  EE1_WE; // Enable writing
4
  EE1_SEL; // Select EEPROM 1
5
  
6
  
7
  eeprom.bytecount = 5; 
8
  UCB0TXBUF = eeprom.byte[0];
9
}

in
1
byte.count
 lege ich hier fest, dass es 5 Bytes sind, die übertragen werden sollen.

Dann wird das erste in den TX-Buffer geschrieben und nach erfolgreichem 
Lesen aus dem TX-Buffer wird die ISR aufgeruen und das zweite Byte soll 
gesendet werden.
1
if (eeprom.bytecount != 1) // More than one byte
2
    {
3
      eeprom.nextbyte += 1;
4
      if (eeprom.nextbyte < eeprom.bytecount)
5
      {
6
        UCB0TXBUF = eeprom.byte[eeprom.nextbyte];
7
      }
8
      else
9
      {
10
        eeprom.nextbyte = 0;
11
        EE1_WP;  // Write protect enabled
12
        EE1_DES; // Deselect EEPROM
13
      }
14
    }

Die if-Anweisung stellt nur sicher, dass wenn nur ein Byte zum 
Übertragen war, kein neuer Wert in den Puffer geschrieben wird und somit 
auch kein neuer Interrupt vom USCI-Modul kommt.

Also ab zwei Bytes ght das Programm in die Anweisung rein und soll nun 
den
1
eeprom.nextbyte
 um 1 erhöhen, wodurch aus dem Array das Byte 1 (also das Zweite 
gesendet werden soll. Das funktioniert auch, Der TX-Buffer bekommt
1
byte[1]
.

Nächste if-Anweisung ist auch wahr, da 1 < 5 und der TX-Buffer wird 
neugeladen. So, bei der nächsten ISR ist
1
eeprom.nextbyte
 jedoch nicht mehr 1, sondern wieder 0 und ab da drehts sich natürlich 
rum und rum...

von Sascha (Gast)


Lesenswert?

Mandrake schrieb:
> Dann müsste es heißen:
> if (eeprom.bytecount > 1)

Ja, OK, das stimmt, hat den selben Effekt, schließt nur auch noch die 0 
mit ein, obgleich ich den Sendebefehl natürlich nicht aufrufe, wenn 
nichts zum Senden da ist.

A. K. schrieb:
> Und wie so oft fehlt volatile.

Nein, das fehlt nicht, habe es jetzt in verschiedenen Varianten 
ausprobiert, habe erst das gesamte struct als volatile deklariert, gibts 
ne Warnung mit undefined behaviour. Erstmal ignoriert -> selbes Ergebnis

Dann habe ich die einzelnen Komponenten im struct als volatile 
deklariert, selbe Warnung -> selbes Ergebnis

Dann mal nur die betroffene Variable als volatile -> keine Warnung, aber 
selbes Ergebnis

von Sascha (Gast)


Lesenswert?

Hat da niemand nen Tip für mich?

Ist ja nicht Controller bezogen, ist ja mehr generell irgendein Fehler 
in meinem C Quelltext.


Ich ste grad echt aufm Schlauch, probiere hier um, aber kriegs nicht 
hin.

von Frank S. (herrschrader)


Lesenswert?

Da hilft nur Reduktion.
Schmeiss mal alles aus dem Programm raus, was nicht unbedingt für das 
EEProm schreiben nötig ist und stell dann das komplette Teil mal hier 
rein.

Ich vermute mal, du überschreibst dir irgendwo ganz anders die Variable 
bytecount.

von Sascha (Gast)


Lesenswert?

In meinem Quelltext ist schon fast nichts mehr drin :)
1
#include "msp430x24x.h"
2
#include "stdint.h"
3
4
// #############################################################################
5
// # EEPROM Definitions #                                                      #
6
// ######################                                                      #
7
#define EE1_SEL (P3OUT &= ~0x01) // Chip selected EEPROM 1 °CS 'low'           #
8
#define EE1_DES (P3OUT |= 0x01)  // Chip deselected EEPROM 1 °CS 'high'        #
9
#define EE1_WP  (P2OUT &= ~0x80) // EEPROM 1 writing protected °WP 'low'       #
10
#define EE1_WE  (P2OUT |= 0x80)  // EEPROM 1 writing enabled °WP 'high'        #
11
#define EE1_HLD (P2OUT &= ~0x40) // EEPROM 1 holded °HOLD 'low'                #
12
#define EE1_ACT (P2OUT |= 0x40)  // EEPROM 1 not holded °HOLD 'high'           #
13
// #############################################################################
14
15
16
#define TRUE 1
17
#define FALSE 0
18
19
void eeprom_write (void);
20
21
22
struct  // Struct contains information used for communication with EEPROM
23
{
24
  uint16_t address;     // Address to be read or written
25
  uint8_t  byte [8];    // Byte 0 to 7 for complete page write
26
  uint8_t  bytecount;   // Number of bytes to be read or written
27
  uint8_t  nextbyte;    // Next byte to be transmitted
28
  uint8_t  eeprom_nr;   // Selects between different EEPROMs
29
}eeprom;
30
31
32
void  main (void)
33
{
34
  WDTCTL = WDTPW + WDTHOLD;
35
36
  // Initialisierung der Taktquelle - Quarz 1,8432 MHz
37
  
38
  // BCSCTL1: BASIC CLOCK SYSTEM CONTROL REGISTER 1
39
  // XT2OFF:  XT2 Oscillator (Bit geloescht: XT2 ist an)
40
  BCSCTL1 &= ~XT2OFF;
41
  
42
  // BCSCTL3: BASIC CLOCK SYSTEM CONTROL REGISTER 3
43
  // XT2Sx:   XT2 Range Select (hier SELM_1: 1-3 MHz)
44
  // XCAPx:   Oscillator Capacitor Selection (hier: ~12,5pF)
45
  BCSCTL3 = XT2S_1 + XCAP_3;
46
  
47
  do
48
  {
49
    IFG1 &= ~ OFIFG;                   // Oszillator-Fault IF loeschen
50
    for (unsigned int i = 0xFF; i > 0; i--)     // Zeit zum Einschwingen
51
    {}                                 // Schleife
52
  } while (IFG1 & OFIFG);              // Ausfuehren solange Oszillator-Fault da
53
  
54
  // BCSCTL2: BASIC CLOCK SYSTEM CONTROL REGISTER 2
55
  // SELMx:   Select MCLK (hier SELM_2: XT2CLK)
56
  // SELS:    Select SMCLK (Bit gesetzt: XT2CLK)
57
  BCSCTL2 = SELM_2 + SELS;
58
  
59
  
60
  // ******************** USCI B0 Konfiguration: SPI Modus ***********************
61
  
62
  // USCI B0 CONTROL REGISTER 0
63
  // UCCKPH   : Daten werden bei erster Flanke uebernommen, bei zweiter geaendert
64
  // UCMSB    : MSB wird als erstes gesendet
65
  // UCMST    : Mikrocontroller ist Master
66
  // UCSYNC   : Synchroner Modus
67
  UCB0CTL0 = UCCKPH + UCMSB + UCMST + UCSYNC;
68
  
69
  // USCI B0 CONTROL REGISTER 1
70
  // UCSSEL_2 : USCI Taktquelle ist SMCLK
71
  // UCSWRST  : USCI Modul ist im Reset-Modus
72
  UCB0CTL1 = UCSSEL_2 + UCSWRST;
73
  
74
  // USCI B0 BIT RATE CONTROL REGISTER
75
  // UCA1BR0  : Low-Byte vom Prescaler
76
  // UCA1BR1  : High-Byte vom Prescaler
77
  UCB0BR0 = 0x00;
78
  UCB0BR1 = 0x00;
79
  
80
  // USCI B0 STATUS REGISTER
81
  // UCBUSY   : Status-Bit zeigt an, ob momentan eine Uebertragung laeuft
82
  UCB0STAT = UCBUSY;
83
  
84
  UCB0CTL1 &= ~UCSWRST;                               // Software-Reset loeschen -> USCI B0 aktiv
85
  
86
  // USCI A0/B0 INTERRUPT ENABLE REGISTER
87
  // UCB0TXIE : Interrupt fuer erfolgreiches Laden aus dem Sendepuffer
88
  // UCB0RXIE : Interrupt fuer erfolgreich empfangenes Zeichen
89
  IE2 = UCB0TXIE + UCB0RXIE;
90
  
91
  IFG2 &= ~(UCB0TXIFG + UCB0RXIFG);
92
93
// ************************Ende Konfiguration USCI B0***************************
94
  
95
  
96
  P3SEL |= 0x0E; // P3.1,2,3 Special Function
97
  P3DIR |= 0x0F; // P3.0,1,2,3 Output Direction
98
  
99
  
100
  
101
  
102
  _BIS_SR (GIE);
103
  
104
  eeprom.byte[0] = 0xAA;
105
  eeprom.byte[1] = 0x5B;
106
  eeprom.byte[2] = 0x4C;
107
  eeprom.byte[3] = 0xCC;
108
  eeprom.byte[4] = 0xFB;
109
  
110
  eeprom_write ();
111
  
112
  while (1)
113
  {
114
    
115
  }
116
  
117
} // Ende main
118
119
120
void eeprom_write (void) // ONSemi CAT25256 256kB SPI
121
{
122
  EE1_WE; // Enable writing
123
  EE1_SEL; // Select EEPROM 1
124
  
125
  
126
  eeprom.bytecount = 5;
127
  eeprom.nextbyte = 0;
128
  UCB0TXBUF = eeprom.byte[0];
129
}
130
131
132
#pragma vector = USCIAB0TX_VECTOR
133
__interrupt void usciab0vector (void)
134
{  
135
  if (IFG2 & UCB0TXIFG) // Byte successfully read from USCB0-TX-Buffer
136
  {
137
    
138
    if (eeprom.bytecount > 1) // More than one byte
139
    {
140
      eeprom.nextbyte += 1;
141
      if (eeprom.nextbyte < eeprom.bytecount)
142
      {
143
        UCB0TXBUF = eeprom.byte[eeprom.nextbyte];
144
      }
145
      else
146
      {
147
        eeprom.nextbyte = 0;
148
        EE1_WP;
149
        EE1_DES;
150
      }
151
    }
152
    
153
  } // End if (IFG2 & UCB0TXIFG)  
154
}

Wie gesagt, sämtliche volatile-Varianten habe ich schon durchprobiert. 
Immer dasselbe

von (prx) A. K. (prx)


Lesenswert?

Und wie äussert sich darin der Fehler?

von Sascha (Gast)


Lesenswert?

A. K. schrieb:
> eeprom.nextbyte += 1;

Der Fehler liegt darin, dass
1
eeprom.nextbyte += 1;

nicht übernommen wird, sondern beim nächsten Aufruf von der ISR, es 
wieder "0" ist und sich ab da eine nicht endende Schleife bildet.

von (prx) A. K. (prx)


Lesenswert?

Woran siehst du das? Weil immer das gleiche Byte versendet wird? Das 
könnte auch ein permanenter Restart bewirken.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Sascha schrieb:
> UCB0CTL0 = UCCKPH + UCMSB + UCMST + UCSYNC;

Ich habe in diesem Fall keine Ahnung, aber das sieht für mich komisch 
aus (repräsentativ für ähnliche Konstrukte).

Das soll doch hoffentlich kein Zusammensetzen eines Steuerbytes sein.
Ich kenne das eher als
1
UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCSYNC

Es kann natürlich in diesem Fall anders sein.
Wenn ja, bitte erklären. Ich lerne gerne neues dazu.

von Sascha (Gast)


Lesenswert?

Moment, ich hab jetzt erstmal Feierabend, melde mich gleich von zuhause 
zurück.

von Karl H. (kbuchegg)


Lesenswert?

Was genau wird wiederholt?
Nur ein Zeichen oder die ganze Sequenz?


Ich würde mir auf jeden Fall hier
1
    if (eeprom.bytecount > 0) // More than one byte
2
    {
3
      eeprom.nextbyte += 1;
4
      if (eeprom.nextbyte < eeprom.bytecount)
5
      {
6
        UCB0TXBUF = eeprom.byte[eeprom.nextbyte];
7
      }
8
      else
9
      {
10
        eeprom.nextbyte = 0;
11
        eeprom.bytecount = 0;
12
        EE1_WP;
13
        EE1_DES;
14
      }

den Bytecount auch noch auf 0 setzen (und auch auf größer 0 testen). 
Denn genau das ist ja passiert: Es sind keine Daten mehr zu versenden.
So wie du das hast, darf die UART keine Zeichen für sich puffern. Sobald 
die UART selbt noch ein Zeichen zwischenspeichert, geht dein Mechanismus 
schief, weil du nach dem Erkennen des Endes (und nicht mehr Einstellen 
eines Bytes) noch einen Interrupt kriegst.

Mit deinem Meschanismus, so wie er jetzt ist, hast du keine Möglichkeit 
anhand der Variableninhalte festzustellen, ob du überhaupt noch etwas zu 
versenden hast. nextbyte auf 0 zu setzen reicht nicht. Du kannst dann 
die Fälle "Senden hat gerade erst begonnen" nicht vom Fall "Senden ist 
beendet" unterscheiden.

von Sascha (Gast)


Lesenswert?

Ich habe im Debugger einen Break hinter
1
eeprom.nextbyte += 1;
...also jede Runde, wo die ISR aufgerufen wird, komme ich da an. Und da 
ist jedesmal halt die Variable wieder auf 0. Die ersten zwei Bytes 
werden gesendet, danach nurnoch das zweite immer wieder in Folge, weil 
diese Variable immer wieder "0" ist.

Byte eins wird ja noch aus der main() gesendet, bzw. aus der 
eeprom_write() und ab da wird das nächste Byte ja in jeder ISR 
verschickt, sollte zumindest, beim zweiten klappt das ja auch noch, weil 
da dann byte[1] verschickt wird, ab da dann halt immer byte[1]

von Sascha (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Sobald
> die UART selbt noch ein Zeichen zwischenspeichert, geht dein Mechanismus
> schief, weil du nach dem Erkennen des Endes (und nicht mehr Einstellen
> eines Bytes) noch einen Interrupt kriegst.

Ich bekomme noch einen Interrupt, klar, aber der geht ja mit
1
if (eeprom.bytecount > 1)
 ins leere, weil ich den ja nach dem letzten Byte auf "0" gesetzt habe.

Der USART speichert ein Byte zwischen klar, aber er ruft die ISR ja auf, 
wenn er bereit für ein neues Zeichen ist, das bekommt er dann, bzw. soll 
es sich selber nehmen.

von Karl H. (kbuchegg)


Lesenswert?

Sascha schrieb:

> Ich bekomme noch einen Interrupt, klar, aber der geht ja mit
>
1
if (eeprom.bytecount > 1)
> ins leere, weil ich den ja nach dem letzten
> Byte auf "0" gesetzt habe.

Wo genau hast du das in deinem Code gemacht?

von Sascha (Gast)


Lesenswert?

Der UART generiert ja immer ein Interrupt, wenn er seinen Puffer frei, 
das vorige Byte jetzt versenden wird und für einen nahtlosen Datenstrom 
schonmal das nächste im Puffer haben will.

von Karl H. (kbuchegg)


Lesenswert?

Sascha schrieb:
> Ich habe im Debugger einen Break hinter
>
1
eeprom.nextbyte += 1;
> ...also jede Runde, wo die ISR aufgerufen wird, komme ich da an.

Ist dein Optimizer eingeschaltet?
Wenn ja, dann kannst du der Anzeige des Debuggers nicht unbedingt 
trauen.

Hats du die Variante
1
struct  // Struct contains information used for communication with EEPROM
2
{
3
  volatile uint16_t address;     // Address to be read or written
4
  volatile uint8_t  byte [8];    // Byte 0 to 7 for complete page write
5
  volatile uint8_t  bytecount;   // Number of bytes to be read or written
6
  volatile uint8_t  nextbyte;    // Next byte to be transmitted
7
  volatile uint8_t  eeprom_nr;   // Selects between different EEPROMs
8
}eeprom;

schon probiert?

von Sascha (Gast)


Lesenswert?

Ja, ich habe alles durch! Habe auch schon die Variable aus dem struct 
genommen und sie einzeln deklariert - keine Änderung. Aber ich sehe es 
auf dem Oszi ja auch, die beiden ersten Bytes gehen, danach nurnoch das 
Zweite fortlaufend. Wenn er in den Reset gehen würde, dann müsste ja 
erstmal wieder das Erste kommen.

von Sascha (Gast)


Lesenswert?

Christian H. schrieb:
> Das soll doch hoffentlich kein Zusammensetzen eines Steuerbytes sein.
> Ich kenne das eher als UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCSYNC

Doch genau das ist es und auch völlig OK.

Das wird in den Code-Examples auch so gemacht.

von Karl H. (kbuchegg)


Lesenswert?

Sascha schrieb:
> Christian H. schrieb:
>> Das soll doch hoffentlich kein Zusammensetzen eines Steuerbytes sein.
>> Ich kenne das eher als UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCSYNC
>
> Doch genau das ist es und auch völlig OK.

UCCKPH und Konsorten sind offenbar irgendwelche Konstante, in denen die 
richtigen Bits gesetzt sind. Solange es keine Bitüberschneidungen bei 
einzelnen Konstanten gibt, ist das ok

  0x01 + 0x02  -> 0x03
  0x01 | 0x02  -> 0x03

Aber
  0x01 | 0x03  -> 0x03
  0x01 + 0x03  -> 0x04

> Das wird in den Code-Examples auch so gemacht.

Das ist kein guter Grund.

von Sascha (Gast)


Lesenswert?

Ich weiß schon, was du meinst, aber ich kann auch:

P1OUT &= ~(LED1 + LED2);

von Sascha (Gast)


Lesenswert?

Aber das hab ich mich auch schon gefragt, jedoch ist es in jedem 
Code-Example von TI so gehalten. Weiß nicht, ob es speziell im Header 
des uCs  definiert ist, oder im IAR.

von Sascha (Gast)


Lesenswert?

Hier mal ein Ausschnitt:
1
//******************************************************************************
2
//  MSP430x26x Demo - USCI_B0 to USCI_B1 I2C RX and TX single bytes
3
//
4
//  Description: This demo connects both USCI_B channels on one MSP430 via the 
5
//  I2C bus. The master (B0) reads from the slave(B1), then the slave (B1) reads
6
//  from the master (B0). 
7
//  ACLK = n/a, MCLK = SMCLK = BRCLK = default DCO = ~1.045MHz
8
//
9
//                                /|\              /|\
10
//               MSP430F261x      10k              10k     
11
//             -----------------   |                |
12
//           -|XIN  P5.1/UCB0SDA|<-|---+----|       |
13
//            |                 |           |       |
14
//           -|XOUT             |           |       |
15
//            |     P5.2/UCB0SCL|<-+------- | ------|
16
//            |                 |           |       |
17
//            |     P3.1/UCB0SDA|<----------|       |
18
//            |                 |                   |
19
//            |                 |                   |
20
//            |     P3.2/UCB0SCL|<------------------|
21
//            |                 |        
22
//
23
//  R. B. Elliott / H. Grewal
24
//  Texas Instruments Inc.
25
//  January 2008
26
//  Built with IAR Embedded Workbench Version: 3.42A
27
//******************************************************************************
28
#include "msp430x26x.h"
29
30
....
31
....
32
void SlaveUSCIB1TX (void){
33
  
34
  UC1IE &= ~UCB1RXIE;                       // Disable RX interrupt
35
  UCB1CTL1 |= UCSWRST;                      // Enable SW reset 
36
  UCB1CTL0 = UCMODE_3 + UCSYNC;             // I2C Slave, synchronous mode
37
  UCB1I2COA = 0x48;                         // Own Address is 048h
38
  UCB1CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
39
  Slave_RX = 0;
40
  UCB1I2CIE  |= UCSTPIE + UCSTTIE;          // Enable STT and STP interrupt
41
  UC1IE |= UCB1TXIE;                        // Enable TX interrupt
42
}

von Karl H. (kbuchegg)


Lesenswert?

Sascha schrieb:
> Ich weiß schon, was du meinst,

Offenbar nicht.

Das das in den TI Beispielen auch so gemacht wird, ist kein guter Grund.

Ein guter Grund wäre, dass man in den Header Files die entsprechenden 
#define rausgesucht hat und verifiziert hat, dass es zu keinen 
Überschneidungen kommt.

Nur weil andere etwas so machen, ist das noch lange kein Grund es auch 
so zu machen. Vor allen Dingen, wenn es bei

    FLAG1 + FLAG2

eine Fehlermöglichkeit existiert, die bei

    FLAG1 | FLAG2

nicht existiert.
Wenn beide Versionen im Nicht-Fehler Fall das gleiche Ergebnis liefern, 
im Fehlerfall die eine aber immer noch ein richtiges Ergebnis liefert 
und die andere nicht, dann nehm ich zumindest lieber die Version, die 
auch dann noch funktioniert.

von Karl H. (kbuchegg)


Lesenswert?

Sascha schrieb:
> Ich weiß schon, was du meinst, aber ich kann auch:
>
> P1OUT &= ~(LED1 + LED2);

Und wenn du dich vertust und schreibst
1
P1OUT &= ~(LED1 + LED2 + LED1);
dann liefert diese Version etwas nicht Beabsichtigtes, während

1
P1OUT &= ~(LED1 | LED2 | LED1);

immer noch das Beabsichtigte macht. LED1 wird halt quasi '2 mal 
abgeschaltet'. Macht aber nichts. Abgeschaltet ist abgeschaltet und mehr 
als abgeschaltet kann die LED nicht sein.

Nennt sich 'defensives programmieren'. Man rechnet als Programmierer 
damit, dass man selbst Fehler macht und gestaltet seinen Code so, dass 
der Code einige der Programmierfehler von alleine abfangen kann und sie 
sich nicht auswirken.


Aber das ist jetzt nicht unbedingt der springende Punkt.
Deine Interrupt Steuerung ist das Problem.

von Sascha (Gast)


Lesenswert?

OK, sehe ich vollkommen ein, es funktioniert auch mit OR. Dann werde ich 
das ab jetzt benutzen, Wir haben in der Fachhochschule das Thema 
Mikrocontroller nur sehr kurz angeschnitten und mussten uns eigentlich 
alles anhand der Examples von TI beibringen. Da hat sich das irgendwie 
so festgesetzt.

Aber Recht hast du natürlich!

Trotzdem haben alles diese Einstellungen leider keinen Bezug auf die ISR 
:) Der Hund liegt woanders begraben. Nur kann ich ihn nicht 
ausbuddeln...

von Karl H. (kbuchegg)


Lesenswert?

Das hier
Beitrag "Re: Unverständliches Verhalten von struct-Variablen bei Interrupt"
ist dein kompletter Code?

Dann deaktiviere mal den Interrupt für 'Zeichen empfangen'. Du hast 
keinen Handler dafür. Wer weiß was passiert, wenn dieser Interrupt 
anspricht.

von Sascha (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> ist dein kompletter Code?

Ja ist er. Mit dem IR-Handler für RXIFG ist vielleicht ein Punkt mit dem 
du Recht haben könntest. Das werde ich mal ausprobieren. Leider erst 
morgen, hab das nebenbei bei der Arbeit geschrieben (in der Pause 
natürlich :))

Ich werde das Ergebnis berichten!

Danke schonmal!

von Frank S. (herrschrader)


Lesenswert?

Wenn soviele Leute den Code ankucken und keine Fehler finden, gibt es 
noch die Möglichkeit eines Compiler-Fehlers, d.h. der Compiler generiert 
falschen Code. Ist zwar sehr selten, kommt aber vor.

Wenn möglich schau dir mal in einem Listing den generierten 
Assembler-Code an, ob der Sinn macht.

von Peter D. (peda)


Lesenswert?

Ich kenne mich mit Deiner CPU nicht aus.

Aber wenn Du was mit nem Interrupt machst, dann solltest Du erst den 
Interrupt sperren, die Struct mit gültigen Daten füllen und als letztes 
den Interrupt wieder freigeben.

D.h. der Interupt darf nicht mit ner halb vollen Struct schon irgendnen 
Mumpitz machen dürfen.



Wenn Du denkst, daß der Interrupt die Struct zerstört, dann gib mal die 
komplette Struct vor und nach dem Interrupt aus:

- Interrupts global sperren
- warten bis Interruptflag gesetzt
- Struct ausgeben
- Interrupts global freigeben
- NOP (Interrupt ausführen)
- Interrupts global sperren
- Struct ausgeben
usw.


Peter

von Sascha (Gast)


Lesenswert?

Guten morgen zusammen,

so, neues Spiel, neues Glück - ES LÄUFT!

Karl-Heinz hat den ehler gefunden. Es lag tatsächlich daran, dass mein 
RXIFG freigeschlatet war und ich keinen Handler dafür definiert hatte. 
Jetzt wird alles wie gwünscht hochgezählt.

Vielen Dank an alle!

Eine letzte Frage noch: Wie schon erwähnt, gibt der Compiler mir bei 
einer kompletten volatile-Deklaration des structs eine Warnung mit 
"undefined behaviour" aus - soweit ich das verstehe, liegt es daran, 
dass er zwei volatile-Variablen miteinander vergleicht, und zwar in der 
Zeile
1
if (eeprom.nextbyte < eeprom.bytecount)

Ist das schlimm, bzw. wie werde ich diese Warnung noch los?

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Sascha schrieb:
> Ist das schlimm, bzw. wie werde ich diese Warnung noch los?
Leg die beiden Werte vor dem Vergleich in eine lokale Variable.

Das ist sowieso anzuraten da der Compiler bei jedem Zugriff alles neu 
aus derm Speicher holen muß.
DU könntest also erstmal eeprom.nextbyte und eeprom.bytecount am Anfang 
lokal holen, und am ende in den Strukt zurückschreiben.

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.