But Ticks256 is declared into the .bss so of course the C compiler initialises it?!?
Well, it is true that for static variables the C standard says that they are initialized to 0.
But you know, if you get the habit of initializing all your variables this will pay in time, no more random bugs because a missing initializetion. I always do it, even if I waste a few bytes, I think it is a good practice ;-)
But there's no point in doing it for globals - you are just wasting code - the C compiler already generated about 20 bytes to do it all in a single block for you - that's the whole point of it gathering them all together in the single .bss (block started by symbol) block. You just need to do it for automatics.
I'm a computer programmer and normaly I worry about the possibility of bugs, but never for the amount of code generated ;-)
In this case you are right, if the compiler does it we should not waste code doing it again.
You do realise you are posting on a board about programming microcontrollers don't you? In the bloatware world of unlimited resources that is Windows/Linux you can waste mega or giga bytes of resource at will. When programming 2K or 4K micrcontrollers 20 bytes can be the difference between using a $1.10 and a $1.32 part. 500,000 lots of $0.22 is a fairly significant reason to save 20 bytes!
When programming 2K or 4K micrcontrollers 20 bytes can be the difference between using a $1.10 and a $1.32 part. 500,000 lots of $0.22 is a fairly significant reason to save 20 bytes!
I never thought about it that way...! Ok, you win :)
Posted by lacis_alfredo: Thu. Nov 15, 2007 - 10:29 AM
1
2
3
4
5
Total votes: 0
Hi,
I'm getting thoroughly confused. I've got an ATmega168, 12.9024MHx crystal and all I want (ha-ha) is to have an ISR triggered every millisecond.
I just can't seem to get the right combination of registers and counters and stuff. I tried ajcrm125's example and get nothing (I was going to worry about prescalers once I got this going):
void TimerInit(void)
{
TCNT0 = 0x00; // clear Timer/Counter
TCCR0B |= 0x05;
// enable interrupts on timer 0 overflow
TIMSK0 |= _BV(TOIE0);
}
ISR(TIM0_OVF_vect)
{
// do my stuff every millisecond
}
Suggest you do a search here for "avrcalc" - it's a very useful utility. I just plugged in the numbers you gave (12.9024, 1ms) and it shows the following. I tried each pre-scale setting but 'none' gets you closest to 1ms but you aren't going to get it exactly. As shown it'll be 1.000031002945ms in fact.
And guess what CLOCK_FREQUENCY / 1000ul is! 12902400 / 1000 is 12902 which in hex is 0x3266 which is exactly what avrcalc is showing above - so now you know how it's working behind the scenes! (the /1000 is obviously because of your requirement for 1/1000th of a second (1ms) ticks)
referring to avr134 APhttp://www.atmel.com/Images/Avr134.zip, can somebody tell me why I've to disable TC0 interrupts (clear TOIE0 and OCIE0) before setting asynchronous clock source for the timer (set AS0) ?
PS: why I should avoid -O0 optimisation at all cost?
PS: why I should avoid -O0 optimisation at all cost?
Because its only a test mode for the compiler. Apart from the fact that you lose out on about 90% of the clever stuff the compiler can do and your code could be several times larger and several times slower than it could be many things simply won't work if built -O0.
Thank you sir. You have just proven a point I often make about the use of macros in code. It's possible to obfuscate the operation of code by using macros. If you look closely you will actually see:
#define START_TIMER TCCR0B |= 0x05
...
void ConfigureDevice(void)
{
cli(); // disable interrupts just in case
// configure PORTB... and other settings
TCNT0 = 0x00; // clear Timer/Counter
START_TIMER;
// enable interrupts on timer 0 overflow
TIMSK0 |= _BV(TOIE0);
sei(); // enable interrupts
}
Now, when the author already makes direct register assignments to TCNT0 and TIMSK0 in that routine it's not entirely clear why he has "hidden" the write to TCCR0B inside a macro called START_TIMER. But that's what he has done. Presumably someone thought this makes the code "easier to read" - it clearly doesn't.
When I build the code ("avr-gcc -mmcu=attiny13 -Os -g avr.c -o avr.elf") I get:
0000008a <ConfigureDevice>:
///////////////////////////////////////////////////////////////////////////////
// Configure device configures the micro's setting per our requirements
///////////////////////////////////////////////////////////////////////////////
void ConfigureDevice(void)
{
cli(); // disable interrupts just in case
8a: f8 94 cli
// configure PORTB... and other settings
TCNT0 = 0x00; // clear Timer/Counter
8c: 12 be out 0x32, r1 ; 50
START_TIMER;
8e: 83 b7 in r24, 0x33 ; 51
90: 85 60 ori r24, 0x05 ; 5
92: 83 bf out 0x33, r24 ; 51
// enable interrupts on timer 0 overflow
TIMSK0 |= _BV(TOIE0);
94: 89 b7 in r24, 0x39 ; 57
96: 82 60 ori r24, 0x02 ; 2
98: 89 bf out 0x39, r24 ; 57
sei(); // enable interrupts
9a: 78 94 sei
}
9c: 08 95 ret
That actually raises another point. He is doing a read-modify-write (using OR) to the TCCR0B register. It could just have been a direct assignment as all other bits in that register will be 0.
But Ticks256 is declared into the .bss so of course the C compiler initialises it?!?
- Log in or register to post comments
TopWell, it is true that for static variables the C standard says that they are initialized to 0.
But you know, if you get the habit of initializing all your variables this will pay in time, no more random bugs because a missing initializetion. I always do it, even if I waste a few bytes, I think it is a good practice ;-)
- Log in or register to post comments
TopBut there's no point in doing it for globals - you are just wasting code - the C compiler already generated about 20 bytes to do it all in a single block for you - that's the whole point of it gathering them all together in the single .bss (block started by symbol) block. You just need to do it for automatics.
- Log in or register to post comments
TopI'm a computer programmer and normaly I worry about the possibility of bugs, but never for the amount of code generated ;-)
In this case you are right, if the compiler does it we should not waste code doing it again.
- Log in or register to post comments
TopYou do realise you are posting on a board about programming microcontrollers don't you? In the bloatware world of unlimited resources that is Windows/Linux you can waste mega or giga bytes of resource at will. When programming 2K or 4K micrcontrollers 20 bytes can be the difference between using a $1.10 and a $1.32 part. 500,000 lots of $0.22 is a fairly significant reason to save 20 bytes!
- Log in or register to post comments
TopI never thought about it that way...! Ok, you win :)
- Log in or register to post comments
TopHi,
I'm getting thoroughly confused. I've got an ATmega168, 12.9024MHx crystal and all I want (ha-ha) is to have an ISR triggered every millisecond.
I just can't seem to get the right combination of registers and counters and stuff. I tried ajcrm125's example and get nothing (I was going to worry about prescalers once I got this going):
Enabling of interrupts is done elsewhere.
Confused,
Alf
- Log in or register to post comments
TopAlf,
Suggest you do a search here for "avrcalc" - it's a very useful utility. I just plugged in the numbers you gave (12.9024, 1ms) and it shows the following. I tried each pre-scale setting but 'none' gets you closest to 1ms but you aren't going to get it exactly. As shown it'll be 1.000031002945ms in fact.
Cliff
Attachment(s):
- Log in or register to post comments
TopHi,
Actually got help from a friend: he sent me this:
Thanks, will remember avrcalc for future projects,
Alf
- Log in or register to post comments
TopAnd guess what CLOCK_FREQUENCY / 1000ul is! 12902400 / 1000 is 12902 which in hex is 0x3266 which is exactly what avrcalc is showing above - so now you know how it's working behind the scenes! (the /1000 is obviously because of your requirement for 1/1000th of a second (1ms) ticks)
- Log in or register to post comments
Topreferring to avr134 APhttp://www.atmel.com/Images/Avr134.zip, can somebody tell me why I've to disable TC0 interrupts (clear TOIE0 and OCIE0) before setting asynchronous clock source for the timer (set AS0) ?
PS: why I should avoid -O0 optimisation at all cost?
- Log in or register to post comments
TopBecause its only a test mode for the compiler. Apart from the fact that you lose out on about 90% of the clever stuff the compiler can do and your code could be several times larger and several times slower than it could be many things simply won't work if built -O0.
- Log in or register to post comments
TopCould someone please explain how TCCR0B becomes set to 0x05 here - the 1024 pre-scale? Its not immediately clear. Thanks
ConfigureDevice:
cli ;disable interrupts clr temp
out TCNT0, temp ;clear the timer ldi temp, 0x01
out TCCR0B, temp ;set the timer to a prescaler of 1024 (also starts timer)
ldi temp, 1<<TOIE0
out TIMSK0, temp ;enable the timer0 overflow interrupt sei ;enable interrupts
ret
- Log in or register to post comments
TopThank you sir. You have just proven a point I often make about the use of macros in code. It's possible to obfuscate the operation of code by using macros. If you look closely you will actually see:
Now, when the author already makes direct register assignments to TCNT0 and TIMSK0 in that routine it's not entirely clear why he has "hidden" the write to TCCR0B inside a macro called START_TIMER. But that's what he has done. Presumably someone thought this makes the code "easier to read" - it clearly doesn't.
When I build the code ("avr-gcc -mmcu=attiny13 -Os -g avr.c -o avr.elf") I get:
That actually raises another point. He is doing a read-modify-write (using OR) to the TCCR0B register. It could just have been a direct assignment as all other bits in that register will be 0.
- Log in or register to post comments
TopPages