Why does this freeze?

Hello,

Well, I've got my first microcontroller project *almost* working :) So this should be some kind of burglar alarm. It is otherwise working well, but it tends to freeze when it's counting either arming or alarm delay. It doesn't freeze everytime, but often, say, averagely every other time.

The program code below might be pretty long and complicated to analyze, but if someone would bother to tell why does that freeze, I'd be extremely grateful =)

The freezing happens when in "arming" or "triggered" loop on the main program, the variables "armDelay and "alarmDelay" are decremented by Timer 1 overflow interrupt.

Btw, as I'm still a newbie on both programming and using microcontrollers, I know that the program might be _far_ from ideal/optimal design, but I'm currently mostly interested just about that why does it freeze.

Thanks in advance for everyone having any thought...

#include #include #include #include #include #include #asm .equ __lcd_port=0x15 ;PORTC #endasm #define BLINKERS PORTA.0 //Blinkers (turn signals) control relay #define HORN PORTA.1 //Horn control relay #define CALL PORTA.2 //Call -signal for attached cell phone #define IGNITION PORTA.3 //Ignition relay #define SENSOR PINB.7 //Sensor input #define POWER PINB.6 //Ignition lock state input (1-active)

// global variables char key='A'; //tells the number of pressed key int m=4; //keypad row multiplexer unsigned char intToChar[4]={'A'}; //integer to be displayed is converted to char in this variable eeprom int correctCode[4]={2,3,4,5}; //the correct code is stored in this table int code[4]={'A','A','A','A'}; //entered code is stored in this table int newCode[4]={'A','A','A','A'}; //fed new code is stored in this table before verification int p; //code input pointer int t; //code comparison pointer char c; //code[4] resetting pointer bit enterCode=0; //if 0, "enter code" displayed bit correct=0; //turns 1 when correct code entered int okKey=0; //tells what to do when # (OK-key) pressed: //if 0, code[4] will be compared to correctCode and correct=1 if matched //if 1, code[4] string will be converted to integer and stored in setAlarmDelay //if 2, code[4] string will be converted to integer and stored in setArmDelay //if 3, code[1] will be stored in autoArm //if 4, code[4] will be stored to newCode[4] and re- entering requested //if 5, code[4] will be compared to newCode and stored in correctCode if matched bit horn=0; //horn cycler int hornCycle=3; //horn on-off cycle interval, to be decremented by timer int callTime=0; //call-signal pulse timing eeprom int setArmDelay=20; //delay before arming int armDelay=0; //variable to be decremented by timer eeprom int setAlarmDelay=30; //Delay before activating alarm int alarmDelay=0; //variable to be decremented by timer eeprom int arming=0; //sets 1 when in "arming" -loop eeprom int armed=0; //sets 1 when in "armed" -loop eeprom int triggered=0; //sets 1 when in "triggered" -loop eeprom int alarm=0; //sets 1 when in "alarm" -loop bit settingsCodeQuery=0; //sets 1 when in "settings code query" -loop of settings entry bit cancel=0; //if 1, settings will be cancelled bit settingsEntry=0; //sets 1, when in settings mode bit settings=0; //sets 1, when correct code entered in settingsCodeQuery eeprom int autoArm=1; //sets 1, if "auto arming" -feature is enabled, 0 if disabled bit noAutoArm=1; //Turns 1 when disarming, reset to 0 when POWER==1. if 1, //auto arming temporarily disabled until reset //(in order to prevent auto arming right after disarming before ignition //has been turned on one time) int n; //number of digits fed in code[4] in delay settings long int r; //calculated (n-t)th power of 10 //(used when converting a string into an integer in delaysettings) int e=0; //the exponent of 10 of a digit being calculated (n-t) //(used when converting a string into an integer in delay settings)

void nollaus() //resets code[4], its display, and input pointer p { for(c=0;c

Reply to
Simoc
Loading thread data ...

Simoc skrev:

...

Hmmm, only 790 lines of code, i don't have anything to do this weekend, why not debug.... NOT

--
Hilsen Mikkel Lund
"Sund fornuft, har aldrig stoppet en tosse"
Jokeren i "Mænds ruin"
Reply to
Mikkel Lund

And you just HAD to leave the whole 700-something lines of code quoted, didn't you?

Geeze....

Bob M.

Reply to
Bob Myers

Are you using the WDT? try turning it off...

Reply to
scada

It does it because you coded it to do it. What else?

Reply to
Homer J Simpson

Of course. But I meant "how did I do that" :-)

See above.

I really don't expect you'd like to debug. Just if someone is having too much time and energy. Or if there's just some little thing that might be causing that.

I've spent myself a couple of months unsuccesfully trying to find the bug, and am still doing. So I thought to ask, if someone could help. Sorry if you found it offensive.

Reply to
Simoc

Thanks for the only proper reply in the thread =) But I'm not using WDT, at least not intentionally. And AFAIK, it should reset the chip if it times out, and not cause freezing. But I found that as I reduced the clock freq from 8MHz to 1MHz, it's now working better, but still freezes sometimes...

Reply to
Simoc

I'm a PIC person so I don't know the details of the processor you are using, but it smells like this to me. You're probably overflowing the stack somewhere or damaging the program context in an ISR. You have to sit down and figure out your worst case scenario of call stack depth. You have to take into consideration that the ISR can occur at any time and also pushes the stack at least one level and then further pushes it when it calls other functions. You are also spending vast amounts of time inside an interrupt handler. That's not necessarily bad, but it is a sign that maybe you should attack the problem a little bit differently. Also interrupts can occur at any time, anything the ISR does needs to be transparent to the main level code. Any registers changed must be restored before returning from the ISR. Usually, an ISR starts off by saving the program context and then ends by restoring it before returning from the ISR.

Reply to
Anthony Fremont

Reply to
Anthony Fremont

I didn't find it offensive. I just pointed out that the problem is in the code, barring some odd hardware problem.

Reply to
Homer J Simpson

I thought too that it might be something like that, but as I'm still not too familiar, with these things, I didn't know what that would practically mean...so thanks for your suggestion, that would confirm my thinking.

Yes, I've been doing so, but haven't got a real good idea yet..

Well, I'll try to examine that more...

The idea was to secure the completing of the ISR before starting another, actually in order to prevent the stack overflow :) But however, I based the idea just on my own logical thinking, which probably went wrong.

Thanks for the suggestion, I'll try removing the SREG settings.

Reply to
Simoc

Sorry, It just looked like a naive comment, and combined with Mikkel Lund's one and some things IRL, I was losing my mind...

Reply to
Simoc

Your question was unfocused. At this point you need some sort of debugger, hardware or simulator, IMO.

Reply to
Homer J Simpson

Nah, he doesn't really need any of that to fix this. A scope, some LEDs and a couple of spare i/o pins will do fine. Probably doesn't even need a scope. He just needs to figure out where it's locking up (one place or several) and go from there. By turning an LED on at the beginning and off at the end of sections of code, he should be able to establish where it's hanging up. Liberal use of LEDs is recommended to help trace what is happening. Scopes are great for determining how much time you spend doing things. I'm getting tired of figuring things out like this myself, so I'm getting a logic analyzer soon. ;-)

I really suspect that the manual manipulation of SREG and interrupt enabling is what is getting him by causing the ISR to be reentered recursively. The compiler should be taking care of enabling interrupts as part of the exit code for the ISR. Manually enabling interrupts while inside an ISR is usually dangerous at best. It's not necessarily wrong, but I suspect the OP can avoid it.

The big problem for me in this is that I don't know AVRs, I do PICs. I don't know how big his stack is, or how it works. On a PIC, he'd have a huge problem with what he is doing since it has only 8 levels of stack depth. I assume the AVR he is using is deeper than that?

Reply to
Anthony Fremont

Thanks for the idea, I might try that approach sometime..

Unfortunately, it seems that I was probably right in my thinking : ( ...I tried removing the SREG settings from the code, but it just made the thing working a lot worse.

Sorry my newbiness, I don't know it myself either... I tried to look for that on the datasheet, I did't find anything about "stack levels", but I found this kind of text:

"During interrupts and subroutine calls, the return address program counter (PC) is stored on the Stack. The Stack is effectively allocated in the general data SRAM, and consequently the stack size is only limited by the total SRAM size and the usage of the SRAM. All user programs must initialize the SP in the reset routine (before subroutines or interrupts are executed). The Stack Pointer SP is read/write accessible in the I/O space. The data SRAM can easily be accessed through the five different addressing modes supported in the AVR architecture."

So might the number of stack levels be somehow dynamic?

Reply to
Simoc

In a larger processor, i.e., not a PIC. But if you recurse any computer you can run out of stack.

Reply to
Homer J Simpson

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.