From b04fc94cfc991855544625af7e67ecf07c02f542 Mon Sep 17 00:00:00 2001 From: Marti Bolivar Date: Thu, 7 Apr 2011 16:24:25 -0400 Subject: Timer tweaks. --- notes/timers.txt | 152 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 78 insertions(+), 74 deletions(-) (limited to 'notes') diff --git a/notes/timers.txt b/notes/timers.txt index 3f5b9f4..647e92e 100644 --- a/notes/timers.txt +++ b/notes/timers.txt @@ -1,82 +1,87 @@ +Timers +====== -Each timer (1-4) has 4 capture/compare channels (1-4). These are directly used -by PWM but have a ton of other possible functionality. The STM32 implementation -is particularly complicated with, eg, the ability to chain together timers - -Timer1 is an "advanced timer" with many more features. I think if we use just -the "Capture and compare interrupt", and enable MOE during initialization -everything will be ok. There are seperate Break, Update, and Trigger interrupts -as well that we will ignore for now. - -Timer2,Ch 3+4 are D0 and D1, which conflict with Serial2. USART should work -fine as long as pins aren't in output mode? and timers should work fine if -Serial2 isn't in use? - -Caveats ------------------------------------------------------------------------------- -There are probably subtle bugs with the way register settings get read in; eg, -it is often required to have the counter fully overflow before new settings -come into effect? -Getting really good timing is still an art, not a science here... usually you -need to fiddle with an oscilloscope and the exact overflow/compare numbers to -get just the right time values. -Any other interrupts (SysTick, USB, Serial, etc) can blow away all the nice -timing stuff. - -Misc Notes ------------------------------------------------------------------------------- -Implementation with case/switch in the interrupt handlers doesn't work; a lot -of the time multiple interrupt flags are active at the same time (or become -active?) +Medium-density chips have timers 1 through 4. High- and XL-density +chips additionally have timers 5 through 8. XL-density chips +additionally have timers 9--14, which we don't support yet. + +Timer Capabilities +------------------ + +Each of timers 1--4 has 4 capture/compare (C/C) channels (also numbered +1--4). These are directly used by PWM, but may serve other purposes as +well (including handling user-specified periodic interrupts). The +STM32 implementation is particularly featureful, with, e.g., the +ability to chain together timers. + +Timers 1 and 8 are an advanced timers, with many more features. +Wirish just uses just their capture/compare interrupts and enables MOE +during initialization, essentially treating them as general purpose +timers (like timers 2--5). Advanced timers also have separate break, +update, and trigger interrupts that we only provide low-level +(i.e. libmaple proper) support for. + +Timers 6 and 7 are basic timers, without C/C channels. They are still +useful for interrupts (via NVIC_TIMER6, NVIC_TIMER7 IRQs, which can +fire upon an update event), but they're most useful for controlling +periodic DAC output. + +Known Issues and Other Caveats +------------------------------ + +There are some conflicts between timer C/C outputs and USART 1 and 2 +TX/RX. Wirish tries to handle this gracefully, but (as of 7 April +2011) not all the bugs are sorted yet. In particular, if you call +HardwareSerial::disable(), then try to use PWM, the USART TX pins +don't cooperate. + +Resetting the prescaler or reload value only takes effect at the next +update event. You can use timer_generate_update() to generate an +update event via software. + +Other interrupts (SysTick, USB, Serial, etc.) can interfere with +timing-critical applications. If your program requires precise +timing, you should probably at least disable USB and SysTick. Note +that this also disables the bootloader and stops millis()/micros() +from counting. + +Getting really good timing is a bit of an art. If things don't work +at first, you need to fiddle with an oscilloscope and the exact +overflow/compare numbers to get precise behavior. TODO ------------------------------------------------------------------------------- -- document carefully (eg, determine clock-wise and overflow-wise behavior for - each function) -- track down and handle all pin conflicts -- implement the update interrupt as a "5th channel" -- "pulse in" stuff, both c and c++ -- function to read out CCR registers -- allow comparison output to the pin (a la PWM) -- additional modes and configuration (up, down, up/down, etc) - -Possible Wirish implementation ------------------------------------------------------------------------------- -Inspired by Timer1 Library for arduino -http://arduino.cc/pipermail/developers_arduino.cc/2010-June/002845.html +---- + +- Document more carefully (e.g., determine clock-wise and + overflow-wise behavior for each function). - class HardwareTimer { - - public: - - void pause(); - void resume(); - void setPrescaleFactor(uint8 factor); - void setOverflow(uint16 val); // truncates to overflow - void setCount(uint16 val); // truncates to overflow - uint16 getCount(); - uint16 setPeriod(uint32 microseconds); // tries to set prescaler and overflow wisely; returns overflow - void setMode(uint8 mode); - void setCompare1(uint16 val); // truncates to overflow - void setCompare2(uint16 val); // truncates to overflow - void setCompare3(uint16 val); // truncates to overflow - void setCompare4(uint16 val); // truncates to overflow - void attachCompare1Interrupt(void (*f)(void)); - void attachCompare2Interrupt(void (*f)(void)); - void attachCompare3Interrupt(void (*f)(void)); - void attachCompare4Interrupt(void (*f)(void)); - void detachCompare1Interrupt(); - void detachCompare2Interrupt(); - void detachCompare3Interrupt(); - void detachCompare4Interrupt(); - }; - - HardwareTimer Timer1 = HardwareTimer(1); - HardwareTimer Timer2 = HardwareTimer(2); - HardwareTimer Timer3 = HardwareTimer(3); - HardwareTimer Timer4 = HardwareTimer(4); +- Track down and handle pin conflicts. + +- Input capture interface. DON'T WRITE pulseIn() IN TERMS OF THIS. + Do that as a simple, Arduino style implementation that just + busy-waits and uses micros(), to allow a pulseIn() on arbitrary + pins. Eventually, expose the more precise/harder to use timer-based + API via a convenience library. + +- Complementary outputs, with convenient break/dead time interface. + +- Additional modes (center-aligned PWM, one pulse mode, etc.) and + count configuration (down, up/down). + +Alternative Wirish Implementations +---------------------------------- + +The current Wirish API is big and clunky. Its inclusion by default +also threatens making everyone's sketches bigger unnecessarily. We +need to deprecate the parts of it that are bad for 0.0.10, and remove +them when 0.1.0 comes out. + +Current implementation was inspired by Timer1 Library for Arduino: + +http://arduino.cc/pipermail/developers_arduino.cc/2010-June/002845.html Here's one of the more standard libaries out there: + http://www.arduino.cc/playground/Code/Timer1 void initialize(long microseconds=1000000); @@ -89,4 +94,3 @@ http://www.arduino.cc/playground/Code/Timer1 void disablePwm(char pin); void attachInterrupt(void (*isr)(), long microseconds=-1); void detachInterrupt(); - -- cgit v1.2.3