aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorMarti Bolivar <mbolivar@leaflabs.com>2012-04-10 15:24:01 -0400
committerMarti Bolivar <mbolivar@leaflabs.com>2012-04-11 16:56:57 -0400
commit44d1b1c763291283da8e346849ffc2a187032884 (patch)
tree45e491ca7c5700db66526b6be797c00f93cb57ab /examples
parent31fbdb5994338592c1b122b52c04bffaaddb3be8 (diff)
downloadlibrambutan-44d1b1c763291283da8e346849ffc2a187032884.tar.gz
librambutan-44d1b1c763291283da8e346849ffc2a187032884.zip
Update examples/test.timers.cpp.
Currently passing on STM32F2. Signed-off-by: Marti Bolivar <mbolivar@leaflabs.com>
Diffstat (limited to 'examples')
-rw-r--r--examples/test-timers.cpp708
1 files changed, 474 insertions, 234 deletions
diff --git a/examples/test-timers.cpp b/examples/test-timers.cpp
index 2a8223c..1f376b7 100644
--- a/examples/test-timers.cpp
+++ b/examples/test-timers.cpp
@@ -1,288 +1,528 @@
-// Program to test the timer.h implementation's essential functionality.
-
-#include <wirish/wirish.h>
+//
+// This is a mostly Wirish-free timer test. Wirish usage is minimized
+// because this is a test of the C timer interface in
+// <libmaple/timer.h>, so it's good if it can be made to work even
+// when most or all of Wirish is missing. Because of that, you may
+// need to customize the following output configuration:
+//
+// Output is printed:
+// - on COMM_USART,
+// - via TX pin on port COMM_USART_PORT, bit COMM_USART_TX_BIT
+// - via RX pin on port COMM_USART_PORT, bit COMM_USART_RX_BIT
+// - at COMM_USART_BAUD baud.
+#define COMM_USART USART6
+#define COMM_USART_BAUD 115200
+#define COMM_USART_PORT GPIOG
+#define COMM_USART_TX_BIT 14
+#define COMM_USART_RX_BIT 9
+// Other optional configuration below.
+
+#include <libmaple/libmaple.h>
+#include <libmaple/gpio.h>
+#include <libmaple/usart.h>
+#include <libmaple/systick.h>
#include <libmaple/timer.h>
-
-void handler1(void);
-void handler2(void);
-void handler3(void);
-void handler4(void);
-
-void handler3b(void);
-void handler4b(void);
-
-int t;
-
-int count1 = 0;
-int count2 = 0;
-int count3 = 0;
-int count4 = 0;
-uint16 rate1 = 1000;
-uint16 rate2 = 2000;
-uint16 rate3 = 4000;
-uint16 rate4 = 8000;
-uint16 val1 = 10000;
-uint16 val2 = 10000;
-uint16 val3 = 10000;
-uint16 val4 = 10000;
-
-// FIXME [0.1.0] high density timer test (especially basic timers + DAC)
-timer_dev *timers[] = {TIMER1, TIMER2, TIMER3, TIMER4};
-voidFuncPtr handlers[] = {handler1, handler2, handler3, handler4};
-
-void initTimer(timer_dev *dev);
-void setTimerPeriod(timer_dev *dev, uint32 period_us);
-void testSetTimerPeriod(uint32 period);
-void testTimerChannels(timer_dev *dev);
-int timerNumber(timer_dev *dev);
+#include <wirish/boards.h>
+
+//
+// Configuration
+//
+
+// More output if true
+static bool verbose = true;
+
+// Timers to test
+// FIXME use feature test macros for smaller MCUs
+static timer_dev *timers[] = {
+ // Available on all currently supported MCUs
+ TIMER1, TIMER2, TIMER3, TIMER4,
+ // Available on F1 (HD and up), F2
+ TIMER5, TIMER6, TIMER7, TIMER8,
+ // Available on F1 (XL), F2
+ TIMER9, TIMER10, TIMER11, TIMER12, TIMER13, TIMER14,
+};
+
+//
+// Test routines
+//
+
+typedef void (*timer_test_t)(timer_dev *);
+
+static void runTest(const char description[], timer_test_t test);
+static void runTests(void);
+
+static void testGetAndSetCount(timer_dev*);
+static void testPauseAndResume(timer_dev*);
+static void testTimerChannels(timer_dev*);
+
+//
+// Helpers
+//
+
+static void initTimer(timer_dev *dev);
+static int timerNumber(timer_dev *dev);
+// Hack: a systick-based delay, useful until delay_us() is fixed
+static void _delay(uint32 msec);
+// Wirish-less USART initialization routine
+static void init_usart(usart_dev *dev, gpio_dev *gdev, uint8 tx, uint8 rx);
+// Return whether or not the timer has capture/compare channel `ch'.
+// TODO: does something like this belong in the standard timer library?
+static bool timer_has_cc_ch(timer_dev *dev, int ch);
+
+// Printing routines and variants for verbose mode
+static void putstr(const char str[]);
+static void println(void);
+static void putstrln(const char str[]);
+static void putudec(uint32 val);
+static void puttimn(timer_dev *dev);
+static void v_putstr(const char str[]);
+static void v_println();
+static void v_putstrln(const char str[]);
+static void v_putudec(uint32 val);
+static void v_puttimn(timer_dev *dev);
+// Used to visually separate output from different tests
+static void printBanner(void);
+
+//
+// Handler state
+//
+
+static int count1 = 0;
+static int count2 = 0;
+static int count3 = 0;
+static int count4 = 0;
+static int timer_num; // Current timer we're considering
+
+//
+// Timer capture/compare interrupt handlers
+//
+// These are shared between timers. The global variable timer_num
+// controls which timer they affect.
+//
+
+static void handler1(void);
+static void handler2(void);
+static void handler3(void);
+static void handler4(void);
+static voidFuncPtr handlers[] = {handler1, handler2, handler3, handler4};
+
+//
+// setup() and loop()
+//
void setup() {
- // Set up the LED to blink
- pinMode(BOARD_LED_PIN, OUTPUT);
-
- // Setup the button as input
- pinMode(BOARD_BUTTON_PIN, INPUT);
-
- // Send a message out Serial2
- Serial2.begin(115200);
- Serial2.println("*** Initializing timers...");
+ init_usart(COMM_USART, COMM_USART_PORT,
+ COMM_USART_TX_BIT, COMM_USART_RX_BIT);
+ _delay(5);
+ println();
+ printBanner();
+ putstr("Initializing timers...\r\n");
timer_foreach(initTimer);
- Serial2.println("*** Done. Beginning timer test.");
+ putstr("Done. Running tests.\r\n");
+ runTests();
+ printBanner();
+ putstr("Done testing timers.\r\n");
}
void loop() {
- Serial2.println("-----------------------------------------------------");
-
- Serial2.println("Testing timer_get_count()/timer_set_count()");
- Serial2.print("TIMER1 count = ");
- Serial2.println(timer_get_count(TIMER1));
- Serial2.println("timer_set_count(TIMER1, 1234)");
- timer_set_count(TIMER1, 1234);
- Serial2.print("timer_get_count(TIMER1) = ");
- Serial2.println(timer_get_count(TIMER1));
-
- Serial2.println("-----------------------------------------------------");
- Serial2.println("Testing pause/resume; button roughly controls TIMER4");
- // when BUT is held down, TIMER4 is in the "pause" state and the
- // timer doesn't increment, so the final counts should reflect the
- // ratio of time that BUT was held down.
- count3 = 0;
- count4 = 0;
- timer_set_mode(TIMER3, TIMER_CH1, TIMER_OUTPUT_COMPARE);
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_OUTPUT_COMPARE);
- timer_pause(TIMER3);
- timer_pause(TIMER4);
- timer_set_count(TIMER3, 0);
- timer_set_count(TIMER4, 0);
- timer_set_reload(TIMER3, 30000);
- timer_set_reload(TIMER4, 30000);
- timer_set_compare(TIMER3, 1, 1000);
- timer_set_compare(TIMER4, 1, 1000);
- timer_attach_interrupt(TIMER3, TIMER_CC1_INTERRUPT, handler3b);
- timer_attach_interrupt(TIMER4, TIMER_CC1_INTERRUPT, handler4b);
- timer_resume(TIMER3);
- timer_resume(TIMER4);
-
- Serial2.println("Testing for ~4 seconds...");
- for(int i = 0; i < 4000; i++) {
- if (isButtonPressed()) {
- timer_pause(TIMER4);
- } else {
- timer_resume(TIMER4);
- }
- delay(1);
- }
+}
+
+//
+// Test routine implementations
+//
- timer_set_mode(TIMER3, TIMER_CH1, TIMER_DISABLED);
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_DISABLED);
-
- Serial2.print("TIMER3 count: ");
- Serial2.println(timer_get_count(TIMER3));
- Serial2.print("TIMER4 count: ");
- Serial2.println(timer_get_count(TIMER4));
-
- Serial2.println("-----------------------------------------------------");
- Serial2.println("Testing setTimerPeriod()");
- testSetTimerPeriod(10);
- testSetTimerPeriod(30000);
- testSetTimerPeriod(300000);
- testSetTimerPeriod(30000);
-
- Serial2.println("Sanity check (with hand-coded reload and prescaler for "
- "72 MHz timers):");
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_OUTPUT_COMPARE);
- timer_set_prescaler(TIMER4, 33);
- timer_set_reload(TIMER4, 65454);
- timer_pause(TIMER4);
- timer_set_count(TIMER4, 0);
- timer_set_compare(TIMER4, TIMER_CH1, 1);
- timer_attach_interrupt(TIMER4, TIMER_CC1_INTERRUPT, handler4b);
- Serial2.println("Period 30000ms, wait 2 seconds...");
- count4 = 0;
- timer_resume(TIMER4);
- delay(2000);
- timer_pause(TIMER4);
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_DISABLED);
- Serial2.print("TIMER4 count: ");
- Serial2.println(count4);
- Serial2.println(" (Should be around 2sec/30000ms ~ 67)");
-
- // Test all the individual timer channels
- timer_foreach(testTimerChannels);
+static void runTests(void) {
+ runTest("timer_get_count()/timer_set_count()", testGetAndSetCount);
+ runTest("timer_pause()/timer_resume()", testPauseAndResume);
+ runTest("capture/compare channels and interrupts",
+ testTimerChannels);
}
-void initTimer(timer_dev *dev) {
- switch (dev->type) {
- case TIMER_ADVANCED:
- case TIMER_GENERAL:
- Serial2.print("Initializing timer ");
- Serial2.println(timerNumber(dev));
- for (int c = 1; c <= 4; c++) {
- timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE);
- }
- Serial2.println("Done.");
- break;
- case TIMER_BASIC:
- break;
+static void runTest(const char description[], timer_test_t test) {
+ printBanner();
+ putstr("Testing ");
+ putstr(description);
+ putstrln(".");
+ timer_foreach(test);
+}
+
+static void testGetAndSetCount(timer_dev *dev) {
+ unsigned before, after;
+ unsigned val_to_set = 1234;
+
+ timer_pause(dev);
+ before = timer_get_count(dev);
+ timer_set_count(dev, val_to_set);
+ after = timer_get_count(dev);
+ timer_resume(dev);
+
+ if (after != val_to_set) {
+ puttimn(dev);
+ putstr(": ");
+ putstr("*** FAIL: get/set count for ");
+ puttimn(dev);
+ putstr(".");
+ putstr("Start count = ");
+ putudec(before);
+ putstr(". Count set to ");
+ putudec(val_to_set);
+ putstr(", and now count is = ");
+ putudec(after);
+ println();
+ } else if (verbose) {
+ puttimn(dev);
+ putstr(": ");
+ putstrln("[ok]");
}
}
-void testSetTimerPeriod(uint32 period) {
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_OUTPUT_COMPARE);
- timer_set_compare(TIMER4, TIMER_CH1, 1);
- setTimerPeriod(TIMER4, period);
- timer_pause(TIMER4);
- timer_set_count(TIMER4, 0);
- timer_attach_interrupt(TIMER4, TIMER_CC1_INTERRUPT, handler4b);
- Serial2.println("Period ");
- Serial2.print(period);
- Serial2.print(" ms. Waiting 2 seconds...");
- count4 = 0;
- timer_resume(TIMER4);
- delay(2000);
- timer_pause(TIMER4);
- timer_set_mode(TIMER4, TIMER_CH1, TIMER_DISABLED);
- Serial2.print("TIMER4 count: ");
- Serial2.println(timer_get_count(TIMER4));
- Serial2.print(" (Should be around 2 sec / ");
- Serial2.print(period);
- Serial2.print(" ms = ");
- Serial2.print(double(2) / period * 1000);
- Serial2.println(", modulo delays due to interrupts)");
+// This hack works on all currently supported STM32 series, but you
+// may need to do something smarter in the future. The assertions
+// ensure that our assumptions hold for your target.
+static timer_dev *getDifferentTimerOnSameBusAs(timer_dev *dev) {
+ rcc_clk_domain dev_domain = rcc_dev_clk(dev->clk_id);
+ ASSERT(RCC_APB1 == dev_domain || RCC_APB2 == dev_domain);
+ ASSERT(rcc_dev_clk(TIMER1->clk_id) == RCC_APB2);
+ ASSERT(rcc_dev_clk(TIMER2->clk_id) == RCC_APB1);
+ ASSERT(rcc_dev_clk(TIMER8->clk_id) == RCC_APB2);
+ ASSERT(rcc_dev_clk(TIMER3->clk_id) == RCC_APB1);
+
+ if (dev->clk_id == RCC_TIMER1) {
+ return TIMER8;
+ }
+ if (dev->clk_id == RCC_TIMER2) {
+ return TIMER3;
+ }
+ return dev_domain == RCC_APB2 ? TIMER1 : TIMER2;
}
-int timerNumber(timer_dev *dev) {
- switch (dev->clk_id) {
- case RCC_TIMER1:
- return 1;
- case RCC_TIMER2:
- return 2;
- case RCC_TIMER3:
- return 3;
- case RCC_TIMER4:
- return 4;
-#ifdef STM32_HIGH_DENSITY
- case RCC_TIMER5:
- return 5;
- case RCC_TIMER6:
- return 6;
- case RCC_TIMER7:
- return 7;
- case RCC_TIMER8:
- return 8;
-#endif
- default:
- ASSERT(0);
- return 0;
+// Rough test of pause and resume.
+//
+// Approximately half the time, dev is in the "pause" state and the
+// timer doesn't increment, while another timer (`base_dev') on the
+// same bus continues. dev and base_dev have identical start counts
+// and prescalers.
+//
+// Since dev and base_dev share a bus (and thus a base clock), and we
+// configure them to have the same prescaler and start count, the
+// ratio of their end counts should be approximately 1 : 2. We check
+// to make sure this is true, up to tolerance `epsilon'.
+static void testPauseAndResume(timer_dev *dev) {
+ timer_dev *base_dev = getDifferentTimerOnSameBusAs(dev);
+ unsigned start_count = 0, reload = 65535;
+ // This prescaler should be enough to ensure that we don't
+ // overflow, while still giving us a reasonably large number of
+ // timer ticks.
+ uint16 prescaler = CYCLES_PER_MICROSECOND * 50;
+ double epsilon = .02;
+
+ if (rcc_dev_clk(base_dev->clk_id) != rcc_dev_clk(dev->clk_id)) {
+ putstrln("*** ERROR: cannot run test. Bus info is messed up.");
+ return;
+ }
+
+ // Pause and set up timers
+ timer_pause(base_dev);
+ timer_pause(dev);
+ timer_set_count(base_dev, start_count);
+ timer_set_count(dev, start_count);
+ timer_set_reload(base_dev, reload);
+ timer_set_reload(dev, reload);
+ timer_set_prescaler(base_dev, prescaler);
+ timer_set_prescaler(dev, prescaler);
+ timer_generate_update(base_dev);
+ timer_generate_update(dev);
+
+ // Resume the timers and run the test
+ ASSERT(timer_get_count(base_dev) == start_count);
+ ASSERT(timer_get_count(dev) == start_count);
+ timer_resume(base_dev);
+ timer_resume(dev);
+ _delay(1000);
+ timer_pause(dev);
+ _delay(1000);
+ timer_pause(base_dev);
+
+ // Check the results
+ unsigned dev_count = timer_get_count(dev);
+ unsigned base_count = timer_get_count(base_dev);
+ double count_ratio = ((double)dev_count / base_count);
+ bool fail = false;
+ if (count_ratio > 0.5 + epsilon || count_ratio < 0.5 - epsilon) {
+ fail = true;
+ }
+ if (fail || verbose) {
+ puttimn(dev);
+ putstr(" vs. ");
+ puttimn(base_dev);
+ putstr(": ");
+ if (fail) putstr("*** FAIL: ");
+ else putstr("[ok] ");
+ putstr("(dev = ");
+ putudec(dev_count);
+ putstr(") / (base = ");
+ putudec(base_count);
+ putstr(") = ");
+ // hack hack hack
+ putudec((int)count_ratio);
+ count_ratio -= (int)count_ratio;
+ putstr(".");
+ int cr_x_100 = (int)(count_ratio * 100);
+ int hundredths = cr_x_100 % 10;
+ cr_x_100 /= 10;
+ int tenths = cr_x_100 % 10;
+ putudec(tenths);
+ putudec(hundredths);
+ println();
}
}
-/* This function touches every channel of a given timer. The output
- * ratios should reflect the ratios of the rate variables. It
- * demonstrates that, over time, the actual timing rates get blown
- * away by other system interrupts. */
-void testTimerChannels(timer_dev *dev) {
- t = timerNumber(dev);
- toggleLED();
- delay(100);
- Serial2.println("-----------------------------------------------------");
+// This function touches every capture/compare channel of a given
+// timer. The channel counts should be equal within a timer
+// regardless of other interrupts on the system (note that this
+// doesn't really test timers with only a single capture/compare
+// channel; for that, you'll want to do visual inspection of timers
+// that share a bus, in verbose mode).
+static void testTimerChannels(timer_dev *dev) {
switch (dev->type) {
case TIMER_BASIC:
- Serial2.print("NOT testing channels for basic timer ");
- Serial2.println(t);
- break;
+ v_putstr("Skipping basic timer ");
+ v_puttimn(dev);
+ v_println();
+ return;
case TIMER_ADVANCED:
case TIMER_GENERAL:
- Serial2.print("Testing channels for timer ");
- Serial2.println(t);
+ // Set up
+ v_puttimn(dev);
+ v_println();
+ v_putstr("\tchannels: ");
+
+ timer_num = timerNumber(dev);
timer_pause(dev);
- count1 = count2 = count3 = count4 = 0;
+ count1 = 0;
+ count2 = 0;
+ count3 = 0;
+ count4 = 0;
timer_set_reload(dev, 0xFFFF);
timer_set_prescaler(dev, 1);
for (int c = 1; c <= 4; c++) {
- timer_set_compare(dev, c, 65535);
- timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE);
- timer_attach_interrupt(dev, c, handlers[c - 1]);
+ if (timer_has_cc_ch(dev, c)) {
+ v_putudec(c);
+ v_putstr("\t");
+ timer_set_compare(dev, c, 0xFFFF);
+ timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE);
+ timer_attach_interrupt(dev, c, handlers[c - 1]);
+ }
}
+ v_println();
+
+ // Run test
+ timer_generate_update(dev);
timer_resume(dev);
- delay(3000);
+ _delay(250);
+ timer_pause(dev);
+
+ // Print results
+ v_putstr("\tcounts: ");
+ bool fail = false;
+ bool mismatched[4] = {false, false, false, false};
+ int counts[4];
+ counts[0] = count1;
+ counts[1] = count2;
+ counts[2] = count3;
+ counts[3] = count4;
+ bool first = true;
+ int first_count = -1;
for (int c = 1; c <= 4; c++) {
- timer_set_mode(dev, c, TIMER_DISABLED);
+ if (timer_has_cc_ch(dev, c)) {
+ if (first) {
+ first_count = counts[c - 1];
+ first = false;
+ }
+ if (!first && (counts[c - 1] != first_count)) {
+ mismatched[c - 1] = true;
+ fail = true;
+ }
+ v_putudec(counts[c - 1]);
+ v_putstr("\t");
+ }
+ }
+ v_println();
+ if (fail) {
+ for (int i = 0; i < 4; i++) {
+ if (mismatched[i]) {
+ putstr("*** FAIL: mismatch on ");
+ puttimn(dev);
+ putstr(", channel ");
+ putudec(i + 1);
+ putstr(": expected ");
+ putudec(first_count);
+ putstr(", got ");
+ putudec(counts[i]);
+ println();
+ }
+ }
+ } else {
+ puttimn(dev);
+ putstrln(" [ok]");
+ }
+ v_println();
+
+ // Clean up
+ for (int c = 1; c <= 4; c++) {
+ if (timer_has_cc_ch(dev, c)) {
+ timer_set_mode(dev, c, TIMER_DISABLED);
+ }
}
- Serial2.print("Channel 1 count: "); Serial2.println(count1);
- Serial2.print("Channel 2 count: "); Serial2.println(count2);
- Serial2.print("Channel 3 count: "); Serial2.println(count3);
- Serial2.print("Channel 4 count: "); Serial2.println(count4);
break;
}
}
-// FIXME [0.1.0] move some incarnation of this into timer.h
-void setTimerPeriod(timer_dev *dev, uint32 period_us) {
- if (!period_us) {
- // FIXME handle this case
- ASSERT(0);
- return;
- }
+//
+// Helper implementations
+//
- uint32 cycles = period_us * CYCLES_PER_MICROSECOND;
- uint16 pre = (uint16)((cycles >> 16) + 1);
- timer_set_prescaler(dev, pre);
- timer_set_reload(dev, cycles / pre - 1);
+static void _delay(uint32 msec) {
+ uint32 end = systick_uptime() + msec;
+ while (systick_uptime() < end)
+ ;
}
-void handler1(void) {
- val1 += rate1;
- timer_set_compare(timers[t], TIMER_CH1, val1);
- count1++;
+static void init_usart(usart_dev *dev, gpio_dev *gdev, uint8 tx, uint8 rx) {
+ usart_async_gpio_cfg(dev, gdev, rx, gdev, tx, 0);
+ usart_init(dev);
+ usart_set_baud_rate(dev, USART_USE_PCLK, COMM_USART_BAUD);
+ usart_enable(dev);
}
-void handler2(void) {
- val2 += rate2;
- timer_set_compare(timers[t], TIMER_CH2, val2);
- count2++;
+static bool timer_has_cc_ch(timer_dev *dev, int ch) {
+ ASSERT(1 <= ch && ch <= 4);
+ if (dev->type == TIMER_BASIC)
+ return false;
+ int tn = timerNumber(dev);
+ return (// TIM1-5 and 8 have all four channels
+ (tn <= 5 || tn == 8) ||
+ // TIM9 and 12 only have channels 1 and 2
+ ((tn == 9 || tn == 12) && ch <= 2) ||
+ // All other general purpose timers only have channel 1
+ (ch == 1));
}
-void handler3(void) {
- val3 += rate3;
- timer_set_compare(timers[t], TIMER_CH3, val3);
- count3++;
+static void putstr(const char str[]) {
+ usart_putstr(COMM_USART, str);
}
-void handler4(void) {
- val4 += rate4;
- timer_set_compare(timers[t], TIMER_CH4, val4);
- count4++;
+static void println(void) {
+ putstr("\r\n");
+}
+
+static void putstrln(const char str[]) {
+ putstr(str);
+ println();
+}
+
+static void putudec(uint32 val) {
+ usart_putudec(COMM_USART, val);
+}
+
+static void puttimn(timer_dev *dev) {
+ putstr("TIM");
+ putudec(timerNumber(dev));
+}
+
+static void v_putstr(const char str[]) {
+ if (verbose) putstr(str);
}
-void handler3b(void) {
+static void v_println() {
+ if (verbose) println();
+}
+
+__attribute__((unused)) /* (shut up, gcc) */
+static void v_putstrln(const char str[]) {
+ if (verbose) putstrln(str);
+}
+
+static void v_putudec(uint32 val) {
+ if (verbose) putudec(val);
+}
+
+static void v_puttimn(timer_dev *dev) {
+ if (verbose) puttimn(dev);
+}
+
+// Used to visually separate output from different tests
+static void printBanner(void) {
+ putstrln("-----------------------------------------------------");
+}
+
+static void initTimer(timer_dev *dev) {
+ v_puttimn(dev);
+ timer_init(dev);
+ switch (dev->type) {
+ case TIMER_ADVANCED:
+ case TIMER_GENERAL:
+ v_putstr(" channels ");
+ for (int c = 1; c <= 4; c++) {
+ if (timer_has_cc_ch(dev, c)) {
+ v_putudec(c);
+ v_putstr(" ");
+ timer_set_mode(dev, c, TIMER_OUTPUT_COMPARE);
+ }
+ }
+ break;
+ case TIMER_BASIC:
+ break;
+ }
+ v_println();
+}
+
+static int timerNumber(timer_dev *dev) {
+ switch (dev->clk_id) {
+ case RCC_TIMER1: return 1;
+ case RCC_TIMER2: return 2;
+ case RCC_TIMER3: return 3;
+ case RCC_TIMER4: return 4;
+ case RCC_TIMER5: return 5;
+ case RCC_TIMER6: return 6;
+ case RCC_TIMER7: return 7;
+ case RCC_TIMER8: return 8;
+ case RCC_TIMER9: return 9;
+ case RCC_TIMER10: return 10;
+ case RCC_TIMER11: return 11;
+ case RCC_TIMER12: return 12;
+ case RCC_TIMER13: return 13;
+ case RCC_TIMER14: return 14;
+ default:
+ ASSERT(0);
+ return 0;
+ }
+}
+
+//
+// IRQ Handlers
+//
+
+static void handler1(void) {
+ count1++;
+}
+
+static void handler2(void) {
+ count2++;
+}
+
+static void handler3(void) {
count3++;
}
-void handler4b(void) {
+static void handler4(void) {
count4++;
}
+//
+// init() and main()
+//
+
__attribute__((constructor)) void premain() {
init();
}