global jumps and stack

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
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



Re: global jumps and stack

[...]
Quoted text here. Click to load it

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 ( snipped-for-privacy@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.

Re: global jumps and stack
Quoted text here. Click to load it
'regular'

Using 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 /



Re: global jumps and stack
Quoted text here. Click to load it
a
'regular'

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



Site Timeline