Hello! I'm programming two ATmega162s which should do some communication via their USART-interfaces. I'm using the C-programming language with the CodeVision AVR Compiler. I preferred C, because I do not have too much experience in programming in assembly language and to this point everything worked pretty good. But sadly a serious problem occured: My Programm runs in an endless loop ("main-loop"), getting chars from the usart0 and putting them to usart1. This procedure is regulary (each 200ms) interrupted by Timer-Interrupt1 (CTC-mode), which puts a certain ping-signal ('*****') to usart1 and then starts Timer2(CTC-mode aswell), which Interrupts after 2ms. Within these two milliseconds 5 respond-chars should be received on usart1 in the main-loop. If not a certain PIN gets pulled down for some short time. So far so good this seems to me to be a good idea. The Problem is, that TimerInterrupt1 would return to the main-loop, waiting for characters on usart0. In the case that at that time no char would arrive at usart0, the programm woulf be blocked by the corresponding getchar()-routine. So I put a longjump into the interrupt-routine1 to get to another place in the main-loop, where the ATmega then should wait for the ping-response at usart1. This all works, but it only works for 230 times receiving 'regular' characters on usart0 and putting them to usart1. I suspect the stack of growing and growing, because the jump-operations, and I tested this. The Stack grows from somewhere 1275 to 837 and then the program hangs itself up. It would be nice, if someone could help me with that jump things.... Bye Arnim Here are the corresponding code excerpts: .... #include <mega162.h> #include <delay.h> #include <setjmp.h> // Alphanumeric LCD Module functions #asm .equ __lcd_port=0x1B #endasm #include <lcd.h> #include <stdlib.h> .... //global vars char trans; char pingsent; char pongreceived = 0; char mode; //debugging-vars int i = 0; int j = 0; int count_t1 = 0; int count_t2 = 0; char a[6], b[6], c[6]; int count_reset = 0; //Processor-states according sot setjmp.h jmp_buf cpu_state; //Functions char sendping(void); char receivepong(void); .... interrupt [TIM1_COMPA] void timer1_compa_isr(void) { count_t1+=1; LED0_AN; mode=PING; pingsent = sendping(); TCCR2=0x0F; //start timer 2 LED0_AUS; //Longjump back to the main-loop longjmp(cpu_state, 1); } // Timer 2 output compare interrupt service routine //2ms interrupt [TIM2_COMP] void timer2_comp_isr(void) { count_t2+=1; TCCR2=0x00; //stop itself TCNT2=0x00; //block next ctc-match if(pongreceived){ pongreceived = 0; } else { LED1_AN; //self-defined LED-ON delay_ms(10); LED1_AUS; //self-defined LED-OFF } }//Interrupt Timer2 char sendping(){ int i; for(i=0;i<5;i++)putchar1('*'); return 1; }//send char receivepong(){ char c; int i; for(i=0; i<5; i++){ c = getchar1(); }//rof return 1; }//receivepong ..... void main(void) { ... //endless-loop / main-loop while (1) { if (setjmp(cpu_state)==0) { /* //Some debugging-output to display i+=1; lcd_gotoxy(0,0); itoa(i,a); lcd_puts(a); */ lcd_gotoxy(5,0); lcd_putsf("TIM2:"); itoa(count_t2,b); lcd_puts(b); lcd_gotoxy(5,1); lcd_putsf("TIM1:"); itoa(count_t1,a); lcd_puts(a); trans = getchar(); putchar1(trans); } else { /* //Some debugging-output to display j+=1; lcd_gotoxy(0,1); itoa(j,b); lcd_puts(b); */ lcd_gotoxy(5,1); lcd_putsf("TIM1:"); itoa(count_t1,a); lcd_puts(a); lcd_gotoxy(5,0); lcd_putsf("TIM2:"); itoa(count_t2,b); lcd_puts(b); pongreceived = receivepong(); } };//while1 }//main
global jumps and stack
Started by ●February 10, 2004
Reply by ●February 10, 20042004-02-10
Arnim Zichner <zichner@tuhh.de> wrote: [...]> So far so good this seems to me to be a good idea. The Problem is, that > TimerInterrupt1 would return to the main-loop, waiting for characters on > usart0. In the case that at that time no char would arrive at usart0, the > programm woulf be blocked by the corresponding getchar()-routine.You can't use exclusive busy-waiting in a multi-input situation like that. You'll have to put non-blocking versions of getchar() to *both* serial ports into the waiting loop. I.e. instead of the main loop being while (1) { c = getchar(usart0); /* do something with it */ } it'll have to become something like this: while (1) { if (peekchar(usart0)) { c = getchar(usart0); /* do something with it */ } if (status_waiting_for_int2 && peekchar(usart1)) { c = getchar(usart1); /* do something with it */ } } -- Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de) Even if all the snow were burnt, ashes would remain.
Reply by ●February 10, 20042004-02-10
"Arnim Zichner" <zichner@tuhh.de> wrote in message news:c0b0br$15f5ej$1@uni-berlin.de...> Hello! > >So I put a > longjump into the interrupt-routine1 to get to another place in the > main-loop, where the ATmega then should wait for the ping-response at > usart1. This all works, but it only works for 230 times receiving'regular'> characters on usart0 and putting them to usart1. > > I suspect the stack of growing and growing, because the jump-operations, > and I tested this. The Stack grows from somewhere 1275 to 837 and then the > program hangs itself up. It would be nice, if someone could help me with > that jump things.... > > > Bye > > ArnimUsing setjmp and longjmp is asking for trouble. Putting the longjmp in an interrupt routine is asking for even more trouble (like you've got). The pair are designed to work together only when the function with the longjmp has been called (directly or indirectly) from the one with the setjmp. Although you could regard the interrupt as a "function call", the stack frame is likely to be somewhat different (all those extra pushes and pops) - hence the problem. My only advice would be *never* to use these things. Redesign your program as if you'd never heard of them. -- Peter Bushell http://www.software-integrity.com/
Reply by ●February 10, 20042004-02-10
"Arnim Zichner" <zichner@tuhh.de> wrote in message news:c0b0br$15f5ej$1@uni-berlin.de...> > So far so good this seems to me to be a good idea. The Problem is, that > TimerInterrupt1 would return to the main-loop, waiting for characters on > usart0. In the case that at that time no char would arrive at usart0, the > programm woulf be blocked by the corresponding getchar()-routine. So I puta> longjump into the interrupt-routine1 to get to another place in the > main-loop, where the ATmega then should wait for the ping-response at > usart1. This all works, but it only works for 230 times receiving'regular'> characters on usart0 and putting them to usart1.I strongly suggest you revise your code such that the interrupts only communicate with the main loop via data. Set a request flag in the interrupt, and act on it and clear it in the main loop. Steve http://www.fivetrees.com http://www.sfdesign.co.uk