I noticed that the Delay.h wasn't working well in a project when used with an ATtiny45, so I've made a small piece of code to test where I went wrong with my coding. I've just made a blinky-LED program on PB3 which goes on for 200 ms and off for 500 ms.
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB |= (1 << PB3);
while (1)
{
PORTB |= (1 << PB3);
_delay_ms(200);
PORTB &= ~(1 << PB3);
_delay_ms(500);
}
}
What I've noticed is that the LED goes on for 200 ms and then the LED goes off for a very, very short time. After a lot of testing, searching, and failing I've figured out that the problem could be that the linking to delay.h isn't working well.
The problem is you are creating an object file, but not linking it. Without linking, branch instructions in the machine code are not filled with the required destination addresses, so the code simply executes linearly until it 'falls off the end' into unallocated memory. Eventually it reaches the end of memory and wraps around to zero to execute your code again. The end result is the LED flashes with a very low duty cycle.
(Source: Delay doesn't work (avr attiny 26, delay.h))
(Another post with same issues: Using avr-gcc _delay_ms causes chip to freeze)
Now I've been using (Atmel &) Microchip Studio for 5 or 6 years to make all kind of small ATtiny projects. There are some features I don't know a lot about, but everything always worked without any problems.
I've started a few new projects to be sure I didn't change any settings or stuff like that, but it always failed with an ATtiny45.
Now the strange part is, when I started a new project with an ATtiny461 (and used an ATtiny461 ofcourse), and used this code to try it on, it worked without any problems. After that, I tried to change the device to an ATtiny45 and it failed again, and reverting back to a 461 made it work again.
- Can anyone explain why it's not working on one device and does work on the other?
- Is my assumption correct that this Delay.h doesn't work on an ATtiny45??
- The links above are talking about a linker-file, but as said before, these are the features I'm not familiar with. If this is the problem, where or how should I change this? And how come there's a difference between the two devices?
Also, in the project-properties>ToolChain>AVR/GNU C Compiler: The compile-string is the same (with the exception of Attiny45<->Attiny461)
Extra info:
I'm using Microchip Studio to write (in C) and compile the whole thing and I'm using AVRDUDESS to write the .hex via USBasp to the Attiny.
Edit:
As @Martin said/asked, the MCU restarts (I didn't put that clear in the question). I had done some tests with different times and an input to trigger different scenarios, but it clearly restarted every time.
Below you can find the assembler code (well the .lss, but I hope it's what you asked for). I've put them also in a compare-file and the differences don't seem too big (as far as I understand everything).
The only thing I see what could be something is the fact that with the ATtiny45 the 5th last line says:
60: ea cf rjmp .-44 ; 0x36 <main+0x6>
which could mean to restart the MCU? (assumptions, assumptions.)
Attiny45:
JustANotherTestProject.elf: file format elf32-avr
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000066 00000000 00000000 00000054 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00800060 00800060 000000ba 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .comment 00000030 00000000 00000000 000000ba 2**0
CONTENTS, READONLY
3 .note.gnu.avr.deviceinfo 0000003c 00000000 00000000 000000ec 2**2
CONTENTS, READONLY
4 .debug_aranges 00000020 00000000 00000000 00000128 2**0
CONTENTS, READONLY, DEBUGGING
5 .debug_info 0000056c 00000000 00000000 00000148 2**0
CONTENTS, READONLY, DEBUGGING
6 .debug_abbrev 000004dc 00000000 00000000 000006b4 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_line 0000022c 00000000 00000000 00000b90 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_frame 00000024 00000000 00000000 00000dbc 2**2
CONTENTS, READONLY, DEBUGGING
9 .debug_str 00000336 00000000 00000000 00000de0 2**0
CONTENTS, READONLY, DEBUGGING
10 .debug_loc 00000048 00000000 00000000 00001116 2**0
CONTENTS, READONLY, DEBUGGING
11 .debug_ranges 00000010 00000000 00000000 0000115e 2**0
CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:
00000000 <__vectors>:
0: 0e c0 rjmp .+28 ; 0x1e <__ctors_end>
2: 15 c0 rjmp .+42 ; 0x2e <__bad_interrupt>
4: 14 c0 rjmp .+40 ; 0x2e <__bad_interrupt>
6: 13 c0 rjmp .+38 ; 0x2e <__bad_interrupt>
8: 12 c0 rjmp .+36 ; 0x2e <__bad_interrupt>
a: 11 c0 rjmp .+34 ; 0x2e <__bad_interrupt>
c: 10 c0 rjmp .+32 ; 0x2e <__bad_interrupt>
e: 0f c0 rjmp .+30 ; 0x2e <__bad_interrupt>
10: 0e c0 rjmp .+28 ; 0x2e <__bad_interrupt>
12: 0d c0 rjmp .+26 ; 0x2e <__bad_interrupt>
14: 0c c0 rjmp .+24 ; 0x2e <__bad_interrupt>
16: 0b c0 rjmp .+22 ; 0x2e <__bad_interrupt>
18: 0a c0 rjmp .+20 ; 0x2e <__bad_interrupt>
1a: 09 c0 rjmp .+18 ; 0x2e <__bad_interrupt>
1c: 08 c0 rjmp .+16 ; 0x2e <__bad_interrupt>
0000001e <__ctors_end>:
1e: 11 24 eor r1, r1
20: 1f be out 0x3f, r1 ; 63
22: cf e5 ldi r28, 0x5F ; 95
24: d1 e0 ldi r29, 0x01 ; 1
26: de bf out 0x3e, r29 ; 62
28: cd bf out 0x3d, r28 ; 61
2a: 02 d0 rcall .+4 ; 0x30 <main>
2c: 1a c0 rjmp .+52 ; 0x62 <_exit>
0000002e <__bad_interrupt>:
2e: e8 cf rjmp .-48 ; 0x0 <__vectors>
00000030 <main>:
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB |= (1 << PB3);
30: 87 b3 in r24, 0x17 ; 23
32: 88 60 ori r24, 0x08 ; 8
34: 87 bb out 0x17, r24 ; 23
while (1)
{
PORTB |= (1 << PB3);
36: 88 b3 in r24, 0x18 ; 24
38: 88 60 ori r24, 0x08 ; 8
3a: 88 bb out 0x18, r24 ; 24
#else
//round up by default
__ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
#endif
__builtin_avr_delay_cycles(__ticks_dc);
3c: 8f e4 ldi r24, 0x4F ; 79
3e: 93 ec ldi r25, 0xC3 ; 195
40: 01 97 sbiw r24, 0x01 ; 1
42: f1 f7 brne .-4 ; 0x40 <__SREG__+0x1>
44: 00 c0 rjmp .+0 ; 0x46 <__SREG__+0x7>
46: 00 00 nop
_delay_ms(200);
PORTB &= ~(1 << PB3);
48: 88 b3 in r24, 0x18 ; 24
4a: 87 7f andi r24, 0xF7 ; 247
4c: 88 bb out 0x18, r24 ; 24
4e: 9f e9 ldi r25, 0x9F ; 159
50: 26 e8 ldi r18, 0x86 ; 134
52: 81 e0 ldi r24, 0x01 ; 1
54: 91 50 subi r25, 0x01 ; 1
56: 20 40 sbci r18, 0x00 ; 0
58: 80 40 sbci r24, 0x00 ; 0
5a: e1 f7 brne .-8 ; 0x54 <__SREG__+0x15>
5c: 00 c0 rjmp .+0 ; 0x5e <__SREG__+0x1f>
5e: 00 00 nop
60: ea cf rjmp .-44 ; 0x36 <main+0x6>
00000062 <_exit>:
62: f8 94 cli
00000064 <__stop_program>:
64: ff cf rjmp .-2 ; 0x64 <__stop_program>
Attiny461:
YetANotherTest.elf: file format elf32-avr
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000006e 00000000 00000000 00000054 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000000 00800060 00800060 000000c2 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .comment 00000030 00000000 00000000 000000c2 2**0
CONTENTS, READONLY
3 .note.gnu.avr.deviceinfo 0000003c 00000000 00000000 000000f4 2**2
CONTENTS, READONLY
4 .debug_aranges 00000020 00000000 00000000 00000130 2**0
CONTENTS, READONLY, DEBUGGING
5 .debug_info 000005fc 00000000 00000000 00000150 2**0
CONTENTS, READONLY, DEBUGGING
6 .debug_abbrev 00000564 00000000 00000000 0000074c 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_line 00000244 00000000 00000000 00000cb0 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_frame 00000024 00000000 00000000 00000ef4 2**2
CONTENTS, READONLY, DEBUGGING
9 .debug_str 0000035e 00000000 00000000 00000f18 2**0
CONTENTS, READONLY, DEBUGGING
10 .debug_loc 00000048 00000000 00000000 00001276 2**0
CONTENTS, READONLY, DEBUGGING
11 .debug_ranges 00000010 00000000 00000000 000012be 2**0
CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:
00000000 <__vectors>:
0: 12 c0 rjmp .+36 ; 0x26 <__ctors_end>
2: 19 c0 rjmp .+50 ; 0x36 <__bad_interrupt>
4: 18 c0 rjmp .+48 ; 0x36 <__bad_interrupt>
6: 17 c0 rjmp .+46 ; 0x36 <__bad_interrupt>
8: 16 c0 rjmp .+44 ; 0x36 <__bad_interrupt>
a: 15 c0 rjmp .+42 ; 0x36 <__bad_interrupt>
c: 14 c0 rjmp .+40 ; 0x36 <__bad_interrupt>
e: 13 c0 rjmp .+38 ; 0x36 <__bad_interrupt>
10: 12 c0 rjmp .+36 ; 0x36 <__bad_interrupt>
12: 11 c0 rjmp .+34 ; 0x36 <__bad_interrupt>
14: 10 c0 rjmp .+32 ; 0x36 <__bad_interrupt>
16: 0f c0 rjmp .+30 ; 0x36 <__bad_interrupt>
18: 0e c0 rjmp .+28 ; 0x36 <__bad_interrupt>
1a: 0d c0 rjmp .+26 ; 0x36 <__bad_interrupt>
1c: 0c c0 rjmp .+24 ; 0x36 <__bad_interrupt>
1e: 0b c0 rjmp .+22 ; 0x36 <__bad_interrupt>
20: 0a c0 rjmp .+20 ; 0x36 <__bad_interrupt>
22: 09 c0 rjmp .+18 ; 0x36 <__bad_interrupt>
24: 08 c0 rjmp .+16 ; 0x36 <__bad_interrupt>
00000026 <__ctors_end>:
26: 11 24 eor r1, r1
28: 1f be out 0x3f, r1 ; 63
2a: cf e5 ldi r28, 0x5F ; 95
2c: d1 e0 ldi r29, 0x01 ; 1
2e: de bf out 0x3e, r29 ; 62
30: cd bf out 0x3d, r28 ; 61
32: 02 d0 rcall .+4 ; 0x38 <main>
34: 1a c0 rjmp .+52 ; 0x6a <_exit>
00000036 <__bad_interrupt>:
36: e4 cf rjmp .-56 ; 0x0 <__vectors>
00000038 <main>:
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB |= (1 << PB3);
38: 87 b3 in r24, 0x17 ; 23
3a: 88 60 ori r24, 0x08 ; 8
3c: 87 bb out 0x17, r24 ; 23
while (1)
{
PORTB |= (1 << PB3);
3e: 88 b3 in r24, 0x18 ; 24
40: 88 60 ori r24, 0x08 ; 8
42: 88 bb out 0x18, r24 ; 24
#else
//round up by default
__ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
#endif
__builtin_avr_delay_cycles(__ticks_dc);
44: 8f e4 ldi r24, 0x4F ; 79
46: 93 ec ldi r25, 0xC3 ; 195
48: 01 97 sbiw r24, 0x01 ; 1
4a: f1 f7 brne .-4 ; 0x48 <__SREG__+0x9>
4c: 00 c0 rjmp .+0 ; 0x4e <__SREG__+0xf>
4e: 00 00 nop
_delay_ms(200);
PORTB &= ~(1 << PB3);
50: 88 b3 in r24, 0x18 ; 24
52: 87 7f andi r24, 0xF7 ; 247
54: 88 bb out 0x18, r24 ; 24
56: 9f e9 ldi r25, 0x9F ; 159
58: 26 e8 ldi r18, 0x86 ; 134
5a: 81 e0 ldi r24, 0x01 ; 1
5c: 91 50 subi r25, 0x01 ; 1
5e: 20 40 sbci r18, 0x00 ; 0
60: 80 40 sbci r24, 0x00 ; 0
62: e1 f7 brne .-8 ; 0x5c <__SREG__+0x1d>
64: 00 c0 rjmp .+0 ; 0x66 <__SREG__+0x27>
66: 00 00 nop
68: ea cf rjmp .-44 ; 0x3e <__SP_H__>
0000006a <_exit>:
6a: f8 94 cli
0000006c <__stop_program>:
6c: ff cf rjmp .-2 ; 0x6c <__stop_program>
#include
header files don't create separate compilation units. \$\endgroup\$