Building solution adds code in Atmel Studio

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

Hello everyone, I'm having some issues with Atmel Studio adding code to my C program in some tests I'm doing since I'm pretty new to AVR programming outside Arduino IDE.

I'm trying to use the PWM function in the timers in an ATmega2560. This is my program in C:


#include <avr/io.h>
#include <avr/interrupt.h>

#define F 16000000UL			// clk freq
#define TOP1 19999				// Top timer TC1
#define DC10 1999				// min duty cycle
#define DC90 17999				// max duty cycle

int flag = 1;
void configTC1();
ISR(TIMER1_OVF_vect){
	flag = 1;
}



int main(void){
	DDRB = 0xFF;
	configTC1();
	OCR1B = 0;
	sei(); 
    while (1){
		if(flag){
			OCR1B += 10;
			if(OCR1B > DC90){
				OCR1B = DC10;
			}
			flag = 0;
		}	
    }
}

void configTC1(){
	TCCR1A = (1<<COM1B1)|(1<<WGM11)|(1<<WGM10); 
	TCCR1B = (1<<CS11)|(1<<WGM13)|(1<<WGM12); // Prescaler 8
	TCCR1C = 0;
	OCR1A = TOP1; // TOP
	TIFR1 = 0xFF;
	TIMSK1 = (1<<TOIE1)|(1<<OCIE1B);
}

I'm just trying to increase the duty cycle of the 100 Hz PWM from 10 % to 90 % and then reset the value to 10 % again (I'm just using the flag variable because I though changing OCR1B inside the ISR was the problem). But when I try simulating the code it doesn't work neither in Atmel Studio simulator nor Proteus (with and Arduino Library).

The problem is that, after the ISR, the code above "while(1)" executes again, when in theory it shouldn't, or at least that is what I understand, that the uC executes that section of the code only once before entering the while forever. So, after every ISR, instead of increasing OCR1B, it reset its value to 0 because of the "OCR1B = 0;" line.

In the *.lss file I found this (I'm just copying a section of it):

int flag = 1;
void configTC1();
ISR(TIMER1_OVF_vect){
 114:	1f 92       	push	r1
 116:	0f 92       	push	r0
 118:	0f b6       	in	r0, 0x3f	; 63
 11a:	0f 92       	push	r0
 11c:	11 24       	eor	r1, r1
 11e:	8f 93       	push	r24
 120:	9f 93       	push	r25
	flag = 1;
 122:	81 e0       	ldi	r24, 0x01	; 1
 124:	90 e0       	ldi	r25, 0x00	; 0
 126:	90 93 01 02 	sts	0x0201, r25	; 0x800201 <__data_start+0x1>
 12a:	80 93 00 02 	sts	0x0200, r24	; 0x800200 <__data_start>
}
 12e:	9f 91       	pop	r25
 130:	8f 91       	pop	r24
 132:	0f 90       	pop	r0
 134:	0f be       	out	0x3f, r0	; 63
 136:	0f 90       	pop	r0
 138:	1f 90       	pop	r1
 13a:	18 95       	reti

0000013c <configTC1>:
		}	
    }
}

void configTC1(){
	TCCR1A = (1<<COM1B1)|(1<<WGM11)|(1<<WGM10); // 
 13c:	83 e2       	ldi	r24, 0x23	; 35
 13e:	80 93 80 00 	sts	0x0080, r24	; 0x800080 <__TEXT_REGION_LENGTH__+0x700080>
	TCCR1B = (1<<CS11)|(1<<WGM13)|(1<<WGM12); // Prescaler 8
 142:	8a e1       	ldi	r24, 0x1A	; 26
 144:	80 93 81 00 	sts	0x0081, r24	; 0x800081 <__TEXT_REGION_LENGTH__+0x700081>
	TCCR1C = 0;
 148:	10 92 82 00 	sts	0x0082, r1	; 0x800082 <__TEXT_REGION_LENGTH__+0x700082>
	OCR1A = TOP1; //TOP
 14c:	8f e1       	ldi	r24, 0x1F	; 31
 14e:	9e e4       	ldi	r25, 0x4E	; 78
 150:	90 93 89 00 	sts	0x0089, r25	; 0x800089 <__TEXT_REGION_LENGTH__+0x700089>
 154:	80 93 88 00 	sts	0x0088, r24	; 0x800088 <__TEXT_REGION_LENGTH__+0x700088>
	TIFR1 = 0xFF;
 158:	8f ef       	ldi	r24, 0xFF	; 255
 15a:	86 bb       	out	0x16, r24	; 22
	TIMSK1 = (1<<TOIE1)|(1<<OCIE1B);
 15c:	85 e0       	ldi	r24, 0x05	; 5
 15e:	80 93 6f 00 	sts	0x006F, r24	; 0x80006f <__TEXT_REGION_LENGTH__+0x70006f>
 162:	08 95       	ret

00000164 <main>:
}



int main(void){
	DDRB = 0xFF;
 164:	8f ef       	ldi	r24, 0xFF	; 255
 166:	84 b9       	out	0x04, r24	; 4
	configTC1();
 168:	e9 df       	rcall	.-46     	; 0x13c <configTC1>
	OCR1B = 0;
 16a:	10 92 8b 00 	sts	0x008B, r1	; 0x80008b <__TEXT_REGION_LENGTH__+0x70008b>
 16e:	10 92 8a 00 	sts	0x008A, r1	; 0x80008a <__TEXT_REGION_LENGTH__+0x70008a>
	sei(); 
 172:	78 94       	sei
    while (1)
 178:	2f ec       	ldi	r18, 0xCF	; 207
 17a:	37 e0       	ldi	r19, 0x07	; 7
	DDRB = 0xFF;
	configTC1();
	OCR1B = 0;
	sei(); 
    while (1){
		if(flag){
 17c:	80 91 00 02 	lds	r24, 0x0200	; 0x800200 <__data_start>
 180:	90 91 01 02 	lds	r25, 0x0201	; 0x800201 <__data_start+0x1>
 184:	00 97       	sbiw	r24, 0x00	; 0
 186:	f1 f3       	breq	.-4      	; 0x184 <main+0x20>
			OCR1B += 10;
 188:	80 81       	ld	r24, Z
 18a:	91 81       	ldd	r25, Z+1	; 0x01
 18c:	0a 96       	adiw	r24, 0x0a	; 10
 18e:	91 83       	std	Z+1, r25	; 0x01
 190:	80 83       	st	Z, r24
			if(OCR1B > DC90){
 192:	80 81       	ld	r24, Z
 194:	91 81       	ldd	r25, Z+1	; 0x01
 196:	80 35       	cpi	r24, 0x50	; 80
 198:	96 44       	sbci	r25, 0x46	; 70
 19a:	10 f0       	brcs	.+4      	; 0x1a0 <main+0x3c>
				OCR1B = DC10;
 19c:	31 83       	std	Z+1, r19	; 0x01
 19e:	20 83       	st	Z, r18
			}
			flag = 0;
 1a0:	10 92 01 02 	sts	0x0201, r1	; 0x800201 <__data_start+0x1>
 1a4:	10 92 00 02 	sts	0x0200, r1	; 0x800200 <__data_start>
 1a8:	e9 cf       	rjmp	.-46     	; 0x17c <main+0x18>

000001aa <_exit>:
 1aa:	f8 94       	cli

000001ac <__stop_program>:
 1ac:	ff cf       	rjmp	.-2      	; 0x1ac <__stop_program>

So, as you can see, inside the "main()" section, there are two "while" loops, and two of other lines as well, including "OCR1B = 0;". Is this a normal behavior? Or is there something wrong with my code or, possibly, my Atmel Studio configuration?

 

Maybe this is pretty basic, so if there is some documentation I can read about it a link would be appreciated.

This topic has a solution.
Last Edited: Sun. Oct 13, 2019 - 04:51 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgrojas wrote:
Or is there something wrong with my code

Unrelated to your direct question, but "stuf" isn't going to work correctly unless your "flag" variable, shared between ISR and mainline, is made volatile.

https://www.microchip.com/webdoc...

 

[even more unrelated:  why a 16-bit 'int' for the aforementioned flag?  now atomicity issues come into play.]

 

jgrojas wrote:
Is this a normal behavior?

Probably normal for your toolchain, giving a code dump.  Do you see two actual settings of OCR1B to 0?  Two loops?  I did not at a quick pass.

 

Tell your optimization and other build settings.  The gurus of the infinite-value toolchain can chime in on the "best" way to get a code dump.

 

Oh, gee.  I.e. explore the use of -Og

https://gcc.gnu.org/onlinedocs/g...

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.

Last Edited: Sat. Oct 12, 2019 - 01:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, thanks for replying! Yes I know atomicity is an issue, and that I don't need 16 bit for the flag, this was just a quick sketch to test the pwm.
I'm just using the toolchain of Atmel Studio, I tried with WinAVR but it does the same thing.
I don't have my computer now, but in an hour I'm going to reply again with my settings.

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

Read the assembler code closely. I think you'll find it does what you wanted.  You can try to second guess the compiler, but you'll most likely be wrong.

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

The "two while loops" thing is simply an error in the source annotation. It's clear from the assembler there is only one while(1). It starts at 17C and loops back at 1A8. The issue, as others have said, is that you broke rule 1 and did not make 'flag' volatile. You can see the consequence of that at 17C to 186. It does the LDS to read flag but the actual loop repeating the test is the SBIW and BREQ at 184/186. Because it's not volatile it is not repeatedly re-read, just re-tested over and  over again with no chance for a change to be noticed.

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

Changed the flag to volatile uint8_t so I won't have problems with it not being volatile nor it not being read atomically. The problem started before using the flag anyway that's why I didn't bother with all that, so that's not the problem.

 

Since all the answers are focus on those two things I'm just going to keep trying to fix it myself. Thank you all anyway.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Fixed it. The OCR1B comparation interruption flag was set, but I forgot to define at least an empty ISR for it, so the program would reset itself after every comparation, thus executing all the code again.

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

jgrojas wrote:
Since all the answers are focus on those two things I'm just going to keep trying to fix it myself.

Maybe because your thread title and the first part of the original post had to do with "building solution adds code".

 

If your query was really buried in between the two code postings, then perhaps you could have worded it differently such that our attention would be directed to the proper area.

 

And though "solved" I'll bet it won't work as you expect without the pooh-poohed 'volatile'.

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.