diff options
Diffstat (limited to 'libmaple/timers.h')
-rw-r--r-- | libmaple/timers.h | 210 |
1 files changed, 137 insertions, 73 deletions
diff --git a/libmaple/timers.h b/libmaple/timers.h index f5694ac..7589283 100644 --- a/libmaple/timers.h +++ b/libmaple/timers.h @@ -82,7 +82,7 @@ extern "C"{ #endif -typedef volatile uint32* TimerCCR; +typedef volatile uint16* TimerCCR; #define TIMER1_BASE 0x40012C00 #define TIMER2_BASE 0x40000000 @@ -96,41 +96,43 @@ typedef volatile uint32* TimerCCR; #define ARPE BIT(7) // Auto-reload preload enable #define NOT_A_TIMER 0 -#define TIMER_CCR(NUM,CHAN) TIMER ## NUM ## _CH ## CHAN ## _CRR +#define TIMER_CCR(NUM,CHAN) (TIMER ## NUM ## _CH ## CHAN ## _CRR) -#define TIMER1_CH1_CCR TIMER1_BASE + 0x34 -#define TIMER1_CH2_CCR TIMER1_BASE + 0x38 -#define TIMER1_CH3_CCR TIMER1_BASE + 0x3C -#define TIMER1_CH4_CCR TIMER1_BASE + 0x40 +/* Timers 1-4 are present on the entire STM32 line. */ -#define TIMER2_CH1_CCR TIMER2_BASE + 0x34 -#define TIMER2_CH2_CCR TIMER2_BASE + 0x38 -#define TIMER2_CH3_CCR TIMER2_BASE + 0x3C -#define TIMER2_CH4_CCR TIMER2_BASE + 0x40 +#define TIMER1_CH1_CCR ((TimerCCR)(TIMER1_BASE + 0x34)) +#define TIMER1_CH2_CCR ((TimerCCR)(TIMER1_BASE + 0x38)) +#define TIMER1_CH3_CCR ((TimerCCR)(TIMER1_BASE + 0x3C)) +#define TIMER1_CH4_CCR ((TimerCCR)(TIMER1_BASE + 0x40)) -#define TIMER3_CH1_CCR TIMER3_BASE + 0x34 -#define TIMER3_CH2_CCR TIMER3_BASE + 0x38 -#define TIMER3_CH3_CCR TIMER3_BASE + 0x3C -#define TIMER3_CH4_CCR TIMER3_BASE + 0x40 +#define TIMER2_CH1_CCR ((TimerCCR)(TIMER2_BASE + 0x34)) +#define TIMER2_CH2_CCR ((TimerCCR)(TIMER2_BASE + 0x38)) +#define TIMER2_CH3_CCR ((TimerCCR)(TIMER2_BASE + 0x3C)) +#define TIMER2_CH4_CCR ((TimerCCR)(TIMER2_BASE + 0x40)) -#define TIMER4_CH1_CCR TIMER4_BASE + 0x34 -#define TIMER4_CH2_CCR TIMER4_BASE + 0x38 -#define TIMER4_CH3_CCR TIMER4_BASE + 0x3C -#define TIMER4_CH4_CCR TIMER4_BASE + 0x40 +#define TIMER3_CH1_CCR ((TimerCCR)(TIMER3_BASE + 0x34)) +#define TIMER3_CH2_CCR ((TimerCCR)(TIMER3_BASE + 0x38)) +#define TIMER3_CH3_CCR ((TimerCCR)(TIMER3_BASE + 0x3C)) +#define TIMER3_CH4_CCR ((TimerCCR)(TIMER3_BASE + 0x40)) -/* Timer5 and Timer8 are in high-density devices only (such as Maple - Native). Timer6 and Timer7 in these devices have no output compare +#define TIMER4_CH1_CCR ((TimerCCR)(TIMER4_BASE + 0x34)) +#define TIMER4_CH2_CCR ((TimerCCR)(TIMER4_BASE + 0x38)) +#define TIMER4_CH3_CCR ((TimerCCR)(TIMER4_BASE + 0x3C)) +#define TIMER4_CH4_CCR ((TimerCCR)(TIMER4_BASE + 0x40)) + +/* Timers 5 and 8 are in high-density devices only (such as Maple + Native). Timers 6 and 7 in these devices have no output compare pins. */ -#define TIMER5_CH1_CCR TIMER5_BASE + 0x34 -#define TIMER5_CH2_CCR TIMER5_BASE + 0x38 -#define TIMER5_CH3_CCR TIMER5_BASE + 0x3C -#define TIMER5_CH4_CCR TIMER5_BASE + 0x40 +#define TIMER5_CH1_CCR ((TimerCCR)(TIMER5_BASE + 0x34)) +#define TIMER5_CH2_CCR ((TimerCCR)(TIMER5_BASE + 0x38)) +#define TIMER5_CH3_CCR ((TimerCCR)(TIMER5_BASE + 0x3C)) +#define TIMER5_CH4_CCR ((TimerCCR)(TIMER5_BASE + 0x40)) -#define TIMER8_CH1_CCR TIMER8_BASE + 0x34 -#define TIMER8_CH2_CCR TIMER8_BASE + 0x38 -#define TIMER8_CH3_CCR TIMER8_BASE + 0x3C -#define TIMER8_CH4_CCR TIMER8_BASE + 0x40 +#define TIMER8_CH1_CCR ((TimerCCR)(TIMER8_BASE + 0x34)) +#define TIMER8_CH2_CCR ((TimerCCR)(TIMER8_BASE + 0x38)) +#define TIMER8_CH3_CCR ((TimerCCR)(TIMER8_BASE + 0x3C)) +#define TIMER8_CH4_CCR ((TimerCCR)(TIMER8_BASE + 0x40)) /** * Used to configure the behavior of a timer. @@ -149,6 +151,8 @@ typedef enum TimerMode { } TimerMode; typedef struct { + /* Fields up to ARR common to general purpose (2,3,4,5), advanced + control (1,8) and basic (6, 7) timers: */ volatile uint16 CR1; uint16 RESERVED0; volatile uint16 CR2; @@ -173,8 +177,9 @@ typedef struct { uint16 RESERVED10; volatile uint16 ARR; uint16 RESERVED11; - volatile uint16 RCR; - uint16 RESERVED12; + /* Basic timers have none of the following: */ + volatile uint16 RCR; /* Advanced control timers only */ + uint16 RESERVED12; /* Advanced control timers only */ volatile uint16 CCR1; uint16 RESERVED13; volatile uint16 CCR2; @@ -183,8 +188,8 @@ typedef struct { uint16 RESERVED15; volatile uint16 CCR4; uint16 RESERVED16; - volatile uint16 BDTR; // Not used in general purpose timers - uint16 RESERVED17; // Not used in general purpose timers + volatile uint16 BDTR; /* Advanced control timers only */ + uint16 RESERVED17; /* Advanced control timers only */ volatile uint16 DCR; uint16 RESERVED18; volatile uint16 DMAR; @@ -192,18 +197,23 @@ typedef struct { } timer_port; /** - * All possible timer device numbers. + * Timer device numbers. See STM32 reference manual, chapters 13-15. */ +/* several locations depend on TIMER1=0, etc.; don't change the + enumerator values to start at 1. */ typedef enum { - TIMER1, - TIMER2, - TIMER3, - TIMER4, - TIMER5, // High density only - TIMER6, // High density only; no compare - TIMER7, // High density only; no compare - TIMER8, // High density only -} timer_num_t; + TIMER1, /*< Advanced control timer TIM1 */ + TIMER2, /*< General purpose timer TIM2 */ + TIMER3, /*< General purpose timer TIM3 */ + TIMER4, /*< General purpose timer TIM4 */ +#if NR_TIMERS >= 8 + TIMER5, /*< General purpose timer TIM5; high density only */ + /* TIMER6, /\*< Basic timer TIM6; high density only *\/ */ + /* TIMER7, /\*< Basic timer TIM7; high density only *\/ */ + TIMER8, /*< Advanced control timer TIM8; high density only */ +#endif + TIMER_INVALID /* FIXME: this is starting to seem like a bad idea */ +} timer_dev_num; /* timer descriptor */ struct timer_dev { @@ -216,7 +226,7 @@ struct timer_dev { extern struct timer_dev timer_dev_table[]; /** - * Turn on timer with prescale as the clock divisor. + * Initializes timer with prescale as the clock divisor. * * @param timer Timer number. Valid values are TIMER1, TIMER2, * TIMER3, TIMER4, and (on high-density devices) TIMER5, TIMER8. @@ -227,7 +237,7 @@ extern struct timer_dev timer_dev_table[]; * @see timer_set_prescaler() * @see timer_set_mode() */ -void timer_init(uint8 timer, uint16 prescale); +void timer_init(timer_dev_num, uint16); /** * Quickly disable all timers. Calling this function is faster than, @@ -241,8 +251,10 @@ void timer_disable_all(void); * with a low prescaler. * * @param timer the timer whose counter to return. + * + * @pre Timer has been initialized. */ -uint16 timer_get_count(uint8 timer); +uint16 timer_get_count(timer_dev_num); /** * Sets the counter value for the given timer. @@ -250,8 +262,10 @@ uint16 timer_get_count(uint8 timer); * @param timer the timer whose counter to set. * * @param value the new counter value. + * + * @pre Timer has been initialized. */ -void timer_set_count(uint8 timer, uint16 value); +void timer_set_count(timer_dev_num,uint16); /** * Stops the timer's counter from incrementing. Does not modify the @@ -260,8 +274,10 @@ void timer_set_count(uint8 timer, uint16 value); * @param timer the timer to pause. * * @see timer_resume() + * + * @pre Timer has been initialized. */ -void timer_pause(uint8 timer); +void timer_pause(timer_dev_num); /** * Starts the counter for the given timer. Does not modify the @@ -272,28 +288,45 @@ void timer_pause(uint8 timer); * @param timer the timer to resume. * * @see timer_pause() + * + * @pre Timer has been initialized. */ -void timer_resume(uint8 timer); +void timer_resume(timer_dev_num); /** - * Sets the prescaler for the given timer. The prescaler acts as a - * clock divider of the STM32 72MHz system clock, in that the timer's - * counter will subsequently increment with frequency equal to 72MHz / - * prescale. + * Returns the prescaler for the given timer. + * + * @see timer_set_prescaler() * - * Note that the timer will continue with its current prescaler until - * the next time its counter reaches its overflow value, starting a - * counting cycle. The new prescale value will be in effect for that - * subsequent counting cycle. + * @pre Timer has been initialized. + */ +uint16 timer_get_prescaler(timer_dev_num timer_num); + +/** + * Sets the prescaler for the given timer. This value goes into the + * PSC register, so it's 0-based (i.e., a prescale of 0 counts 1 tick + * per clock cycle). This prescale does not take effect until the + * next update event. * * @param timer the timer whose prescaler to set. * - * @param prescale the new prescaler, from 1--65,535. + * @param prescale the new prescaler. + * + * @pre Timer has been initialized. + */ +void timer_set_prescaler(timer_dev_num timer_num, uint16 prescale); + +/** + * Gets the reload value for the timer. + * + * @see timer_set_reload() + * + * @pre Timer has been initialized. */ -void timer_set_prescaler(uint8 timer, uint16 prescale); +uint16 timer_get_reload(timer_dev_num timer_num); /** - * Sets the reload value for the entire timer. + * Sets the reload value for the timer. * * After this function returns, the timer's counter will reset to 0 * after it has reached the value max_reload. @@ -301,8 +334,12 @@ void timer_set_prescaler(uint8 timer, uint16 prescale); * @param timer the timer whose reload to set. * * @param max_reload the new reload value. + * + * @pre Timer has been initialized. */ -void timer_set_reload(uint8 timer, uint16 max_reload); +void timer_set_reload(timer_dev_num timer_num, uint16 max_reload); + +/* TODO: timer_get_mode */ /** * Set the mode of an individual timer channel. @@ -320,8 +357,18 @@ void timer_set_reload(uint8 timer, uint16 max_reload); * @see TimerMode * * @see timer_disable_all() + * + * @pre Timer has been initialized. */ -void timer_set_mode(uint8 timer, uint8 channel, TimerMode mode); +void timer_set_mode(timer_dev_num timer_num, uint8 channel_num, uint8 mode); + +/** + * Get the compare value for the given timer channel. + * @see timer_set_compare_value() + * + * @pre Timer has been initialized. + */ +uint16 timer_get_compare_value(timer_dev_num timer_num, uint8 channel_num); /** * Sets the compare value for a given timer channel. Useful for @@ -339,8 +386,27 @@ void timer_set_mode(uint8 timer, uint8 channel, TimerMode mode); * @see timer_detach_interrupt() * * @see timer_set_reload() + * + * @pre Timer has been initialized. + */ +void timer_set_compare_value(timer_dev_num timer_num, uint8 channel_num, + uint16 value); + +/** + * Detach the interrupt handler for the given timer channel, if any. + * After this function returns, any handler attached to the given + * channel will no longer be called. + * + * @param timer the timer whose channel to detach the interrupt + * handler from. + * + * @param channel the channel from which to detach the interrupt handler. + * + * @see timer_attach_interrupt() + * + * @pre Timer has been initialized. */ -void timer_set_compare_value(uint8 timer, uint8 channel, uint16 compare); +void timer_detach_interrupt(timer_dev_num timer_num, uint8 channel_num); /** * Attach an interrupt handler for the given timer and channel. The @@ -365,22 +431,20 @@ void timer_set_compare_value(uint8 timer, uint8 channel, uint16 compare); * @see timer_detach_interrupt() * * @see timer_set_mode() + * + * @pre Timer has been initialized. */ -void timer_attach_interrupt(uint8 timer, uint8 channel, voidFuncPtr handler); +void timer_attach_interrupt(timer_dev_num timer_num, uint8 channel_num, + voidFuncPtr handler); /** - * Detach the interrupt handler for the given timer channel, if any. - * After this function returns, any handler attached to the given - * channel will no longer be called. - * - * @param timer the timer whose channel to detach the interrupt - * handler from. + * Programmatically generate an update event on the given timer. This + * updates the prescaler, reloads the compare value (in upcounting + * mode, etc.). * - * @param channel the channel from which to detach the interrupt handler. - * - * @see timer_attach_interrupt() + * @pre Timer has been initialized. */ -void timer_detach_interrupt(uint8 timer, uint8 channel); +void timer_generate_update(timer_dev_num timer_num); /** * Turn on PWM with duty_cycle. |