aboutsummaryrefslogtreecommitdiffstats
path: root/notes
diff options
context:
space:
mode:
authorMarti Bolivar <mbolivar@leaflabs.com>2011-04-07 16:24:25 -0400
committerMarti Bolivar <mbolivar@leaflabs.com>2011-04-07 16:28:14 -0400
commitb04fc94cfc991855544625af7e67ecf07c02f542 (patch)
tree19fc95bf209b004b303af70d7904e9ebd5beb9c3 /notes
parentf044b9af59a5db69ae8dbf8f9a1097c82c716f7f (diff)
downloadlibrambutan-b04fc94cfc991855544625af7e67ecf07c02f542.tar.gz
librambutan-b04fc94cfc991855544625af7e67ecf07c02f542.zip
Timer tweaks.
Diffstat (limited to 'notes')
-rw-r--r--notes/timers.txt152
1 files changed, 78 insertions, 74 deletions
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();
-