AVRStudio6; Problem mit sei()

#2741088
Lesenswert?

Hallo,
ich möchte mich nun doch mal in die Programierung mit C einarbeiten.
Leider scheitere ich schon bei den ersten Zeilen... :-(.
Bei folgenden Code sollte ich im Simulator ( AVRStudio6) doch ein
gesetztes I-Flag im SREG erwarten; oder?

Werner

// ATMega 644P @ 20MHz

#include <avr/interrupt.h>

int Timer1Irq()
{
  //
  return (0);
}

ISR(TIMER1_COMPA_vect)
{
  Timer1Irq();
}

int main()
{
  sei();
  while(1)
  {
    //
  }
}
#2741114
Lesenswert?

Werner S. schrieb:
> Bei folgenden Code sollte ich im Simulator ( AVRStudio6) doch ein
> gesetztes I-Flag im SREG erwarten; oder?

Ja. Allerdings meine ich erst kürzlich auf AVFfreaks einen Thread 
gesehen zu haben, wo jemand ebenfalls das Problem hatte, dass der 
Simulator das I-Flag nicht korrekt angezeigt hatte. Also versteife dich 
nicht zu sehr darauf, das gesetzte Flag auch tatsächlich im Simulator zu 
sehen.
#2742274
Lesenswert?

Stefan Ernst:
> ....Also versteife dich nicht zu sehr darauf, das gesetzte Flag auch      > 
tatsächlich im Simulator zu sehen.

Hallo,
habe dann einfach mal weitergemacht und den folgenden Code geschrieben,
leider lande ich nicht auf dem Breakpoint??

@Stefan Ernst:
Vielen Dank für den Hinweis auf AVRfreaks!

Manfred

// ATMega 644P @ 20MHz
#include <avr/interrupt.h>

int Timer1Irq()
{
  //
  return (0);
}

ISR(TIMER1_COMPA_vect)
{
  Timer1Irq();    <------ BREAKPOINT
}

int main()
{
  OCR1A   = 1000;                   // compare value timer1 = 50µs
  TCCR1A  = 0;                      // switch to CTC-Mode..
  TCCR1B  = ((1<<WGM12)|(1<<CS10)); // ..top=CR1A; set prescaler to 1
  TIMSK1  = 1 << OCIE1A;            // interrupt by timer compareA match

  sei();

  while(1)
  {
   //
  }
}
#2742339
Lesenswert?

Werner S. schrieb:
> int Timer1Irq()
> {
>   //
>   return (0);
> }
>
> ISR(TIMER1_COMPA_vect)
> {
>   Timer1Irq();    <------ BREAKPOINT
> }

Das wird mit ziemlicher Sicherheit komplett wegoptimiert worden sein, 
weil der Code (aus Sicht des Compilers) kein Ergebnis hat, das den 
Aufruf der ISR überdauert ("toter Code").

Was du machen könntest wäre z.B.:
1
#include <stdint.h>
2
#include <avr/io.h>
3

4
volatile uint8_t t1count;
5

6
ISR(TIMER1_COMPA_vect)
7
  {
8
  t1count++;    // da sollte ein Breakpoint möglich sein
9
  }
10

11
void main(void)
12
  {
13
  uint8_t ctmp;
14

15
  OCR1A   = 1000;                   // compare value timer1 = 50µs
16
  TCCR1A  = 0;                      // switch to CTC-Mode..
17
  TCCR1B  = ((1<<WGM12)|(1<<CS10)); // ..top=CR1A; set prescaler to 1
18
  TIMSK1  = 1 << OCIE1A;            // interrupt by timer compareA match
19

20
  sei();
21

22
  while(1)
23
  {
24
  cli();
25
  ctmp = t1count;
26
  sei();
27
  if(ctmp == 0)
28
    {
29
    // hier irgendwas machen, z.B. ein Portbit toggeln...
30
    }
31
  }


Grüße

Stefan
#2743691
Lesenswert?

Hallo,
beim Ausprobieren von Stefans Code ist mir aufgefallen, daß
nach Benutzung von "Step Into" der Breakpoint nicht mehr angesprungen 
wurde.
Die Lösung war: Tools -> Options -> Debugger -> Mask interrupts while 
stepping = FALSE einzustellen.
Nun funktioniert auch mein ursprünglicher Code (incl. I_Flag).
Der Optimization Level ist übrigens egal, sofern man den Debug Level
> 2 stellt.
Nun mache ich erst mal weiter....

@Stefan
Danke für Deine Mühe

Werner
Gast #2774559
Lesenswert?

Peter II schrieb:
> bestimmt hast du eine ISR vergessen und der simualtor "bootet" neu. Gehe
> mal im ASM schrittweise durch.

Hey, danke für dir schnelle Antwort. Ich kann das Problem etwas 
eingrenzen, dazu folgender Quellcode-Ausschnitt:

void Timer1Init(void)
{
  TCCR1A =0x00;
  TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B);
  EIMSK  |= (1<<INT1);
  EICRA  |= (1<<ISC00) | (1<<ISC01);
  OCR1A = 20000;
  OCR1B = 20000;
  ICR1  = 0x4e20;
  TCCR1B |= (1<<CS11);
}
wenn ich die Register TIMSK1, EIMSK, EICRA und TCCR1B als hex-Zahlen 
ausschreibe, dann funktioniert das Programm einwandfrei, nur nicht, wenn 
ich die Register direkt zuweise. Hast du dafür eine Idee?
Gast #2774575
Lesenswert?

Hi Peter II;
hier zum Vergleich
void Timer1Init(void)
{
  TCCR1A =0x00;
  TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B);
  EIMSK  |= (1<<INT1);
  EICRA  |= (1<<ISC00) | (1<<ISC01);
  OCR1A = 20000;
  OCR1B = 20000;
  ICR1  = 0x4e20;
  TCCR1B |= (1<<CS11);
}
void Timer1Init(void)
{
  TCCR1A = 0x00;
  TIMSK1 = 0x07;

  EIMSK |= 0x01;
  EICRA |= 0x03;

  OCR1A= 20000;
  OCR1B= 20000;
  ICR1 = 0x4e20;

  TCCR1B = 0x02;
}
Wenn ich den oberen durch den unteren tausche, läuft es. Das mit der LSS 
file hab ich nicht verstanden, sry. Was meinst damit genau?
Gast #2774590
Lesenswert?

Hi,
entschuldige das missverständnis, entweder verwende ich den oberen oder 
den unteren Quellcode; es wird nichts überschrieben.
Dieser Tipp von dir war der entscheidende

"bestimmt hast du eine ISR vergessen und der simualtor "bootet" neu. 
Gehe
mal im ASM schrittweise durch."

-->EIMSK  |= (1<<INT1);
es muss heißten
-->EIMSK  |= (1<<INT0);
Ich hab das durcheinander gebracht, jetzt laufen beide!
Danke für deine Mühe, hat mir Zeit erspart :-)
#2774591
Lesenswert?

Bernd schrieb:
> Hi Peter II;
> hier zum Vergleich
> void Timer1Init(void)
> {
>   TCCR1A =0x00;
>   TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B);
>   EIMSK  |= (1<<INT1);
>   EICRA  |= (1<<ISC00) | (1<<ISC01);
>   OCR1A = 20000;
>   OCR1B = 20000;
>   ICR1  = 0x4e20;
>   TCCR1B |= (1<<CS11);
> }
> void Timer1Init(void)
> {
>   TCCR1A = 0x00;
>   TIMSK1 = 0x07;
>
>   EIMSK |= 0x01;
>   EICRA |= 0x03;
>
>   OCR1A= 20000;
>   OCR1B= 20000;
>   ICR1 = 0x4e20;
>
>   TCCR1B = 0x02;
> }
> Wenn ich den oberen durch den unteren tausche, läuft es.

Dann hast du höchst wahrscheinlich im Projekt den falschen Prozessor 
eingestellt. Denn der Compiler macht ja auch nichts anderes, als aus den 
Bitnamen die Hex-Werte ausrechnen. Dazu benutzt er vordefinierte 
Konstanten, die auf den jeweiligen Prozessortyp abgestimmt sind und in 
aus den Include-Files kommen.
Im Include File steht zb

#define  TOIE1   0
#define  OCIE1A  1
#defien  OCIE1B  2

Um zb
>   TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B);
zu übersetzen, rechnet der Compiler den Ausdruck rechts aus und kommt 
zum Ergebnis, dass da 0x07 rauskommt.
Endgültig compiliert wird daher dann

   TIMSK1 |= 0x07;

Also, bis auf die Verorderung, dasselbe was du auch mit

   TIMSK1 = 0x07;

hinschreibst.

Aber: Bei einem anderen Prozessor mag zb OCIE1B nicht mehr das Bit 2 
sondern das Bit 4 sein. Als C Programmierer brauchst du dann bei

     TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B);

überhaupt nichts machen. Durch das andere #define im Include-File

#define OCIE1B   4

rechnet der COmpiler die geänderte Konstante aus und compiliert

   TIMSK1 |= 0x13;

Schreibst du selbst aber im Original

   TIMSK1 = 0x07;

dann darfst du nicht vergessen, bei einem anderne µC diese Konstante 
anzupassen. Und daher ist die Variante mit den Bitnamen zu bevorzugen - 
wenn dir der COmpiler Arbeit abnehmen kann, dann lass ihn das machen.

Die Kehrseite der Medaille: Wenn das Include File für einen falschen 
Prozessor benutzt wird, dann sind die #define für die Bitnamen falsch. 
Stimmen also die Ergebnisse für Bitnamen nicht mit dem überein, was du 
selbst als Hex-Zahlen ermittelt hast, dann gibt es 3 Möglichkeiten
* entweder sind die Include Files falsch
  (ist unwahrscheinlich, das wäre schon vor dir jemandem aufgefallen)
* Du hast dich bei der Ermittlung der Bits vertan
* oder du hast den falschen µC (und damit die falschen Include
  Files) eingestellt.

Letzterer Fall ist der Häufigere.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren