Open GoogleCodeExporter opened 9 years ago
In addition to the allocation of timer handlers, there is a need for functions
that
dealocates timers and returns them back to their startup state after wiring
Init.
Original comment by memargolis@gmail.com
on 13 Feb 2010 at 11:19
Original comment by dmel...@gmail.com
on 13 Feb 2010 at 11:47
Original comment by dmel...@gmail.com
on 6 May 2010 at 6:09
Issue 249 has been merged into this issue.
Original comment by dmel...@gmail.com
on 12 Jul 2010 at 11:13
Original comment by dmel...@gmail.com
on 16 Aug 2011 at 10:37
This will likely take the form of something like Wiring's Timer library:
http://wiring.uniandes.edu.co/source/trunk/wiring/firmware/cores/AVR8Bit/WHardwa
reTimer.h?view=markup
http://wiring.uniandes.edu.co/source/trunk/wiring/firmware/cores/AVR8Bit/WHardwa
reTimer.cpp?view=markup
Or the one for the LeafLabs Maple board:
http://leaflabs.com/docs/lang/api/hardwaretimer.html
In particular, note that they both involve runtime registering of timer
interrupt handlers via function pointer, which isn't necessarily the most
efficient implementation. Compile-time registration, however, has
complications for user code syntax and compilation.
Original comment by dmel...@gmail.com
on 18 Aug 2011 at 3:22
Original comment by dmel...@gmail.com
on 18 Aug 2011 at 3:44
Issue 241 has been merged into this issue.
Original comment by dmel...@gmail.com
on 18 Aug 2011 at 3:45
There's another implementation to look in this ATtiny core for Arduino:
http://code.google.com/p/arduino-tiny/
In particular:
http://code.google.com/p/arduino-tiny/source/browse/trunk/hardware/tiny/cores/ti
ny/UserTimer.h
http://code.google.com/p/arduino-tiny/source/browse/trunk/hardware/tiny/cores/ti
ny/core_timers.h
http://code.google.com/p/arduino-tiny/source/browse/trunk/hardware/tiny/cores/ti
ny/PwmTimer.h
http://code.google.com/p/arduino-tiny/source/browse/trunk/hardware/tiny/cores/ti
ny/ToneTimer.h
I think I'd prefer the syntax used by Maple or Wiring, though.
Original comment by dmel...@gmail.com
on 18 Aug 2011 at 6:51
[deleted comment]
AVR micros have a lot of different timers, just looking at the Atmega328
datasheet we could see:
- an 8-bit timer
- a 16-bit timer
- an 8-bit timer with asynchronous operation.
Every timer have different registers and bits to set to make it work properly,
so the first step is to write a class that handle all the basic operations with
all this kinds of timers. IMHO The Wiring lib is the one that best fit this
requirement. At the end of initialization we got a set of instances of
HardwareTimer class called:
Timer0
Timer1
Timer2 etc..
I think we can easily save them in an array and build a very simple managemnt
class called Timers with the following two methods:
HardwareTimer T = Timers.allocate();
/* ... do something with timer T ... */
Timers.free(T);
Another step could be to abstract HardwareTimer and declare an interface Timer
common to other type of timers.
Original comment by c.mag...@bug.st
on 18 Aug 2011 at 8:55
I've tested here:
https://github.com/cmaglie/Arduino/commit/7f96c73553109c45950bcf226fc8d4b7101030
13
it's a draft but is a starting point for discussion.
The class HardwareTimer needs to be included in the core, because the core
itself uses timers.
I've ported the initialization of the arduino timers to use the new
HardwareTimer class. Unfortunately the init() function is a "C" function and
cannot call "C++" methods. To solve this i provided a __timers_init() function
inside HardwareTimer.cpp (with cdecl function format) that is called from
init().
I tried it with this simple test program:
void setup() {
Serial.begin(9600);
Serial.print(NUM_TIMERS);
Serial.println(" timers!");
}
void loop() {
delay(200);
Serial.println(millis());
}
and seems that delay and millis still works... (pheew!)
The HardwareTimer interface needs a little bit of refactoring (some costants
needs to be added for example).
The final increase in size of the code is over a Kb, its very huge.
Any thought?
Original comment by c.mag...@bug.st
on 18 Aug 2011 at 11:26
This looks pretty reasonable to me.
I have a couple of small disagreements on style. For example, I don't think we
need both setInterrupt(), and enable / disableInterrupt(). Actually, I don't
think we really need any of those, as you can just detach the interrupt to stop
it from being called. Also, I don't like the use of the name OCR; I'd prefer
setCompare() or setOutputCompare() or something. But I guess you can leave
this and I can just change it when I merge your branch.
There's been some discussion on the developers list about whether we need to
support ISRs with performance requirements that make a function call too slow.
Can you look into making the ISR weakly linked (with a GCC attribute) so they
can be overridden by a library? Have you been watching the discussion? If
there's a conclusion, we can support it, but I'm still not convinced we need to
do anything besides a function pointer (attachInterrupt()-style) and weakly
linked ISR handlers.
Do you want to write the developers list and ask people to look this over? Or
would you prefer I do?
Original comment by dmel...@gmail.com
on 19 Aug 2011 at 4:18
David write to the developer list, i'll follow the discussion.
About allocation of ISR: the library for now use predefined ISR that calls
function pointer inside Timer objects. Moreover, the access to timer register
is done indirectly using pointers that are initialized during objects creation.
This is the do_it_all_in_runtime approach that wastes most resources but its,
indeed, the simplest. I'm courious about Paul Stoffregen idea about templates
to allocate all the resources in compile time, I've tried similar approaches
before, but failed because of the weirdness of avr-libraries.
Original comment by c.mag...@bug.st
on 19 Aug 2011 at 6:33
Here another implementation that exploits templates to optimize register access
https://github.com/cmaglie/Arduino/commit/35a986323f7d1668b2cd593f9735e2f6f6ceab
bb
this one is based on discussion on developer list:
- the first part defines a series of classes with static methods to access
registers.
- the second part is a template class that implements a driver for an 8-bit
timer. With the help of templates we can use the same code to drive two
different timers with two different set of registers but keeping all the
optimiziations.
the last part to resolve is the allocation of ISR, for now i used a macro, but
this part is still to be done...
Original comment by c.mag...@bug.st
on 22 Aug 2011 at 4:10
Interesting. So the idea would be to add something similar for the 16-bit
registers?
How much optimization do the templates buy us? As I understand, most of the
efficiency concerns are about the execution speed of the handler itself, not so
much about the functions for configuring the timers. Is there a need to worry
about the performance of the configuration too?
Also, we need to think about how timers would be allocated between different
libraries, based on the needs of the sketch. For example, with the current
scheme (hardcoded ISRs), we're picking at compile time the number of timers to
dedicate to tone() and the number to Servo. That means, for example, that we
only get one timer for tone(). The macros don't really help with this, do they?
Do you have any thoughts on how we might allow the user to configure, in their
sketch, how many timers to allocate to which library, without a confusing
syntax?
In any case, can you respond to the email on the developers list with this?
Original comment by dmel...@gmail.com
on 22 Aug 2011 at 7:55
David,
you're right the optimization that templates give us in this version is limited
on timer initialization that is not so relevant. Anyway it's interesting the
fact that templates used this way will replace all those indirect pointers
access:
_tcntnh = NULL;
_tcntnl = &TCNT0;
_timskn = &TIMSK;
_tccrna = &TCCR0;
_tccrnb = &TCCR0;
with a direct register access, and all the work is done at compile-time.
Is still missing the 16Bit version for the timer, i'll did it after we discover
some more pro/cons, and if the pros are more than the cons :). I'm going to
post this to the dev-list.
Original comment by c.mag...@bug.st
on 23 Aug 2011 at 8:15
I don't think there's enough consensus on this to get it into Arduino 1.0.
Since it's not really breaking existing functionality but adding new
functionality, I don't think it should be a problem to add later.
Original comment by dmel...@gmail.com
on 31 Aug 2011 at 7:47
I would think that the cost to implement a seconds function would be quite low.
The function would be like "millis()" except it would "Returns the number of
seconds since the Arduino board began running the current program." The
function could be called something like "secs()".
With this functionality in place. Future enhancements could easily implement a
Real Time Clock.
Original comment by Randall....@gmail.com
on 20 Mar 2012 at 11:22
I have added the functions I was thinking about to the core system
(arduino-1.0.1-rc1). I compiled and tested it on a Nano that was handy.
Arduino.h
unsigned long secs(void);
void setSecs(unsigned long);
wiring.c
volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_secs = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;
static unsigned int timer0_sec_fract = 0;
#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) ||
defined(__AVR_ATtiny84__)
SIGNAL(TIM0_OVF_vect)
#else
SIGNAL(TIMER0_OVF_vect)
#endif
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned int s = timer0_sec_fract;
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
m += MILLIS_INC; s += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1; s++;
}
if (s >= 1000) {
s-=1000; timer0_secs++;
}
timer0_sec_fract = s;
timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}
unsigned long secs()
{
unsigned long s;
uint8_t oldSREG = SREG;
cli();
s = timer0_secs;
SREG = oldSREG;
return s;
}
void setSecs(unsigned long s)
{
uint8_t oldSREG = SREG;
cli();
timer0_secs = s;
SREG = oldSREG;
}
After these updates, implementing software clocks and time functions become
very simple. Granted, the clock will drift but it should be fairly accurate.
Original comment by Randall....@gmail.com
on 21 Mar 2012 at 3:06
Original issue reported on code.google.com by
dmel...@gmail.com
on 3 Jan 2010 at 11:18