Cause of resetting discovered, reason unknown

Go To Last Post
25 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello all,

So I decided to make a simple LED candle as an exercise to learn ADC, USART, and random number generation in one shot. Everything was going fine till a strange reset issue arose.

As I am using CV I disabled interrupts during my delay as recommenced by CV for an accurate delay using their function. I've done this on several other programs with no problems however this part of the code in this program causes a reset. I'm guessing this is due to using this code in conjunction with the surrounding code in the manner I am but have no idea why.

Can anyone explain this to me? I'm at a loss :?

When the 2 #asm lines are removed no rest occurs.

Code below, Thanks

Self proclaimed Captain Link

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well,

I don't know C or use CV, but I'm guessing that those that do will actually want to see the code... :)

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I’m trying to submit the code however for whatever reason each time I do I get a web page cannot be found error so please hang in there I’m working on it. Can’t submit as code, quote, or even as is.

Self proclaimed Captain Link

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

WOW, ok so the reason I couldn't post the code was the "%"d in the printf statmen so I changed it to "-d".

   
while (1) {

ADCSRA = ADCSRA | 0x40;

adc_val = ADCW;
seed = adc_val;
srand(seed);
rand_num = (rand()%(max-min+1))+min;
rand_num2 = (rand()%(max2-min2+1))+min2;
OCR0B = rand_num;
#asm("cli"); 
delay_ms(rand_num2);
#asm("sei");
printf ("-d, ", rand_num);
printf ("-d| ", rand_num2);   

    }

}

Self proclaimed Captain Link

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since I don't have the datasheet handy and you do, what does the 0x40 in ADCSRA do (that is, which bit are you setting)?

(hint: 6 is the wrong answer)

I'll go ahead and venture my guess - you're getting an interrupt without a handler. The sei is the culprit, since it enables the interrupts.

I assume there's more code, since your braces are unbalanced.

Chuck Baird

"I wish I were dumber so I could be more certain about my opinions. It looks fun." -- Scott Adams

http://www.cbaird.org

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
(hint: 6 is the wrong answer)

:lol:

ADSC (ADC Start Conversion) per the data sheet "In Single Conversion mode, write this bit to one to start each conversion." and I am using single conversion mode.

Not sure what interrupt I would be getting so I'll have to look a little deeper into that.

Here is the full code, I was trying to keep the first post short.

#include 
#include 
#include 
#include 

#define xtal 1000000L


void main(void) {

int max = 255;
int min = 100;
int adc_val;
int max2 = 150;
int min2 = 100;
int rand_num;
int rand_num2;
int seed;

// timmer/counter0 pwm
TCCR0A = 0x21;
TCCR0B = 0x02;

// usart transmit only
UCSR0A=0x00;
UCSR0B=0x08;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x0C;

// ADC
ADMUX = 0x45;
ADCSRA = 0xCB;

DDRD.5 = 1;

printf ("\n\rHello World");
        
while (1) {

ADCSRA = ADCSRA | 0x40;

adc_val = ADCW;
seed = adc_val;
srand(seed);
rand_num = (rand()%(max-min+1))+min;
rand_num2 = (rand()%(max2-min2+1))+min2;
OCR0B = rand_num;
#asm("cli"); 
delay_ms(rand_num2); 
#asm("sei"); 
printf ("-d, ", rand_num);
printf ("-d| ", rand_num2);   

    }

}

EDIT: I forgot to put the cli/sei back in but now it's back in.

Self proclaimed Captain Link

Last Edited: Mon. Dec 14, 2009 - 08:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
ADCSRA = 0xCB;

You shouldn't set ADIE (Bit 3). If the global interrupt bit is set it could cause problems like what your seeing. Is the the real and actual code you're running? Or does your code have sei set like in your first post of src code?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

On the second post I forgot to put cli/sei back in after removing it to avoid the resetting but I just went back and edited it and yes the second post is the full and actual code with the exception of the - in the printf statement is really a % but for whatever reason the forum wouldn't let me post without changing it . Ran as is it resets after the delay, removing the two asm lines = no resets.

I'll make that change, thanks for the heads up. I don't remember off the top of my head why I thought I needed to set that bit so it's time to reread that part of the data sheet :)

Thanks to everyone for their help in understanding this issue.

Self proclaimed Captain Link

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not to hijack the post, but it's nice to see that you are an Xfiles fan too, atomicdog..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
write this bit to one to start each conversion

Note the emphasis that I added. You have to wait for the conversion to complete before reading the answer.

There is no reason to clear and enable the global interrupt flag if you are not using interrupts. And the proper way of disabling interrupts for a short period like this is to read old value of the interrupt flag before clearing it, then setting it back to the original value rather than just setting it to 1.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just because a program starts running over again from the beginning may not be a reset at all. A software crash may do this all by itself. You are actually better off with a real reset because all the AVR I/O registers are reset to initial default values and not left in some random state like after a crash.

To identify a real AVR reset, see your data sheet MCUSR description. Without MCUSR confirmation, reset is the wrong term to use in describing your problem.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@ Koshchi

Quote:
You have to wait for the conversion to complete before reading the answer.

The space in my code between setting the start bit and writing the value to the adc_val variable had a for loop to waste 25 clock cycles, the conversion time for the first conversion per the data sheet, if I'm understanding it correctly :).

for (i=0; i<25; i++) {
}

This was removed while changing some code around but I intend to put it back in. Is this a good method to pass that time?

@ Mike B
I'll have to verify which is actually occurring.

Thanks again to all, I'm picking up some good info here.

Even a thanks to JC who gave me a good laugh. As I was trying to figure out why I couldn't originally post my code the main thing going through my mind was "I'd beter figure this out quick before someone looks at my post and thinks this moron didn't post his code" :lol:

Self proclaimed Captain Link

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

to waste 25 clock cycles, the conversion time for the first conversion per the data sheet, if I'm understanding it correctly

Not exactly. The first conversion takes 25 >>ADC<< clock cycles. At rated speeds that is 100us give-or-take a factor.

To investigate further, please post "real" code that is causing the symptom(s). And do trap and report the MCUSR as suggested.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are going to sit and wait, then why not just wait for the ADC to tell you that it is done. Guessing whether or not a delay loop will be long enough is not a very good way to code. And since the loop does nothing productive, there is a chance that the compiler will simply optimize it out completely.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After a few busy days I finally got back to my project.

So it was not a reset issue as some suspected. Thanks for the tip on how to determine that.

@atomicdog
I no longer have ADIE set and that seams to have done the trick.

@Koshchi

Quote:
If you are going to sit and wait, then why not just wait for the ADC to tell you that it is done

So I tried to put my main loop in an IF statment that read

if (ADIF == 0) {
code here
    }

However the code simply did not run. ADIF is defined in the MEGA168 header for CV, am I going about this completely wrong?

My most up to date code is as follows

#include 
#include 
#include 
#include 

#define xtal 1000000L


void main(void) {

int mcu_stat_reg;
int max = 255;
int min = 100;
int adc_val;
int max2 = 150;
int min2 = 100;
int rand_num;
int rand_num2;
int seed;

// timmer/counter0 pwm
TCCR0A = 0x21;
TCCR0B = 0x02;

// usart transmit only
UCSR0A=0x00;
UCSR0B=0x08;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x0C;

// ADC
ADCSRA = 0xC7;
ADMUX = 0x45;

DDRD.5 = 1;
mcu_stat_reg = MCUSR;
printf ("\n\r-d, ", mcu_stat_reg);
MCUSR = 0x00;
mcu_stat_reg = MCUSR;
printf ("\n\r-d, ", mcu_stat_reg);
printf ("\n\rHello World");
       
while (1) {

adc_val = ADCW;
seed = adc_val;
srand(seed);
rand_num = (rand()%(max-min+1))+min;
rand_num2 = (rand()%(max2-min2+1))+min2;
OCR0B = rand_num;
#asm("cli");
delay_ms(rand_num2);
#asm("sei");
printf ("\n\r-d, ", adc_val);
printf ("-d, ", rand_num);
printf ("-d, ", rand_num2);   
ADCSRA = 0xC7;  
  };
 }

Thanks again and sorry for the delayed response

Self proclaimed Captain Link

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
Last Edited: Mon. Dec 21, 2009 - 04:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Given that ADIF is defined in mosts AVRs as:


iom16.h:#define ADIF    4
iom163.h:#define ADIF   4
iom165.h:#define ADIF    4
iom165p.h:#define ADIF    4
iom168p.h:#define ADIF 4
iom169.h:#define ADIF   4
iom169p.h:#define ADIF   4
iom16m1.h:#define ADIF 4
iom16u4.h:#define ADIF 4
iom32.h:#define ADIF    4
iom323.h:#define ADIF   4
iom325.h:#define ADIF    4
iom3250.h:#define ADIF    4
iom328p.h:#define ADIF 4
iom329.h:#define ADIF    4
iom3290.h:#define ADIF    4
iom32c1.h:#define ADIF 4
iom32m1.h:#define ADIF 4
iom32u4.h:#define ADIF 4
iom32u6.h:#define ADIF 4
iom48p.h:#define ADIF 4

then why would either:

if (4 == 0) { 
code here 
    }

or:

while (!4) 
{ 
 //empty loop. waiting for conversion... 
}

do what was intended. Personally I'd use ADSC not ADIF as the marker (as it's self clearing) and do something like:

while (ADCSRA & (1<<ADSC)); // wait for completion

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see. Now I'm understand the header file. In the past I would have gone with 0x10 as opposed to (1<<ADSC) but this reads better and explains why ADSC would be defined as just 4.

The hamster is back on the wheal :)

Again I'd like to thank everyone for their time.

Self proclaimed Captain Link

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

In the past I would have gone with 0x10 as opposed to (1<<ADSC) but this reads better and explains why ADSC would be defined as just 4.

This kind of comes from Atmel. For their assembler, because of instructions like SBI, CBI, etc., their device header files define bit positions rather than bit masks - so ADSC=4 rather than 0x10 and so to use it as a mask a 1 must be shifted to that position. This has a knock-on effect to the C compilers (because the core of all bit definitions are the XML files supplied with Studio+asembler)

Interestingly, for the Xmega, they seem to have headed off if the bit mask direction and the header files are littered with *_bm where _bm denotes a bit mask.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

ADIF is defined in the MEGA168 header for CV,

Finally we find out which AVR model is being used.

If using CV, why not let the Wizard create ADC polled and/or interrupt-driven ADC work? At least to start, for a working example.

Quote:

would have gone with 0x10 as opposed to (1<<ADSC) but this reads better and explains why ADSC would be defined as just 4.


Well, no and neither. ADIF would be 4; ADSC would be 6.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Well, no and neither. ADIF would be 4; ADSC would be 6.

Good eye, I guess I had bit 4 on the brain when I responded :).

Quote:
If using CV, why not let the Wizard create

Not using the wizard as I learn forces me to read the data sheets. I have to understand what I'm doing to do it, with help at times obviously & thanks. I plan on using the wizard later when I already know what's going on and want to be lazy, though sometimes I do use it as a reference against my final code.

Self proclaimed Captain Link

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Not using the wizard as I learn forces me to read the data sheets. I have to understand what I'm doing to do it, with help at times obviously & thanks. I plan on using the wizard later when I already know what's going on and want to be lazy, though sometimes I do use it as a reference against my final code.


Then I'm out. I've railed on about this before. If you aren't going to stand on anyone's shoulders, then why not make your own compiler or other source processing tool? Why use an AVR in the first place--you will learn so much more by using only NAND gates.

I never said "don't read the datasheet". You ask for examples and to "correct" your code. Study the Wizard-generated patterns, with the datasheet at your side. Then improve on them all you want.

I guess I'm just too lazy to help, then.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@theusch

I'm sorry to hear that. Your response sounds somewhat on the angry tone, I hope nothing I wrote was taken offensively. I think their is a big difference between wanting to understand the functionality of the peripherals and backing down to NAND gates. I'm glad these tools are available, for instance you can see I haven't written my own delay function yet. I'm not saying using the wizard is lazy but more making light of the fact that once well enough versed I plan to use them to do that work for me.

And yes, I do ask for code reviews, a point in the right direction, and on occasion just what I should be doing. After reading the data sheets, google, and my books thing still don't always click. Learning electronics and programing on my own leaves me with me and the student can't exactly grade his own work ;) One of the great things about this forum is the level of exp. a lot of the members have. Even if I get something working I'm never sure at this point if I'm achieving it in the proper/best manner, unless I have seen it done that specific way. I'm also glad to have poor practices pointed out to me so I don't get stuck in bad habits that may cause problems late down the line. Something that requires an experienced set of eyes.

If this is it for you then thanks for the help till now I have appreciated it, but I hope it's not.

In closing, sorry for the lengthly response but I just feel this method of learning suits me. I very much appreciate this forum and hope this is not the common sentiment.

Self proclaimed Captain Link

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I'm not saying using the wizard is lazy

Yes, you did.
Quote:

wanting to understand the functionality of the peripherals

There is no contradiction between using the Wizard and understanding the peripherals.

I just feel like there was a lot of time spent leading you from step to step, that indeed could have been avoided by study of the Wizard code.

Is that study "lazy"? Isn't that why we have books and profs--"Here is a way it is done. You can also..." Is it lazy, or bad, to go to class with a prof and a textbook?

If there is a particular question, or a query "Couldn't this be done faster/smaller/differently?" then we are all ears.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll reword my comment, It was not my intention to imply using the wizard is lazy. Rather I was facetiously saying I have full intentions of using this tool so I would not have to spend time on that code. Like using a calculator after learning math.

Saying I was led step by step is arguable. Through the last portion of the debugging stage perhaps. Prior to this project I had no USART, ADC, or random number generation experience. I take credit for the time I spent learning and give credit for the help provided on this forum to guide me across the finish line and give me pointers along the way. I didn't just come on the forum and say tell me how to do this. I worked on it & studied for some time till I got stuck and could not figure it out on my own.

In addition to "Couldn't this be done faster/smaller/differently?" I think "What am I doing wrong, as far as I can tell this should be working" is valid question during the learning proses.

FYI I'm not angry, nor do I have any hurt feelings. Text only conversation can often lead to misunderstanding and again I don't mean to offend or come off as ungrateful.

Quote:
There is no contradiction between using the Wizard and understanding the peripherals.

When I first looked at the wizard I had no idea what selection to make to get the desired result, this was in relation to PWM. Thats when I decided to stick to this method till I understood. Though I do see your point.

Hope I'm not coming off as augmentative, I just wanted to explain myself.

Self proclaimed Captain Link