global jumps and stack

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 #include #include

// Alphanumeric LCD Module functions #asm .equ __lcd_port=0x1B #endasm #include #include

....

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

Reply to
Arnim Zichner
Loading thread data ...
[...]

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 to
Hans-Bernhard Broeker

'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

formatting link

Reply to
Peter Bushell

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

formatting link
formatting link

Reply to
Steve at fivetrees

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.