I'm reading a library file timer.h for STM core library that I just installed in Arduino hardware folder.
Of course, there has to be a lot of questions for me as a beginner about many approaches/stratgegies that programmers rule in writing the code.
One thing is that calling a function with a function pointer that only call one function, but the difference is that the function pointer is declared/defined as an inline function.
void timer_init(timer_dev *dev);
void timer_disable(timer_dev *dev);
void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode);
void timer_foreach(void (*fn)(timer_dev*));
int timer_has_cc_channel(timer_dev *dev, uint8 channel);
/**
* @brief Timer interrupt number.
*
* Not all timers support all of these values. All timers support
* TIMER_UPDATE_INTERRUPT. "General purpose" timers can be a special
* nuisance in this regard, as they individually support different
* subsets of the available interupts. Consult your target's reference
* manual for the details.
*/
typedef enum timer_interrupt_id {
TIMER_UPDATE_INTERRUPT, /**< Update interrupt. */
TIMER_CC1_INTERRUPT, /**< Capture/compare 1 interrupt. */
TIMER_CC2_INTERRUPT, /**< Capture/compare 2 interrupt. */
TIMER_CC3_INTERRUPT, /**< Capture/compare 3 interrupt. */
TIMER_CC4_INTERRUPT, /**< Capture/compare 4 interrupt. */
TIMER_COM_INTERRUPT, /**< COM interrupt. */
TIMER_TRG_INTERRUPT, /**< Trigger interrupt. */
TIMER_BREAK_INTERRUPT, /**< Break interrupt. */
} timer_interrupt_id;
void timer_attach_interrupt(timer_dev *dev,
uint8 interrupt,
voidFuncPtr handler);
void timer_detach_interrupt(timer_dev *dev, uint8 interrupt);
//CARLOS
uint8 get_direction(timer_dev *dev);
/**
* Initialize all timer devices on the chip.
*/
static inline void timer_init_all(void) {
timer_foreach(timer_init);
}
/**
* Disables all timers on the device.
*/
static inline void timer_disable_all(void) {
timer_foreach(timer_disable);
}
/**
* @brief Stop a timer's counter from changing.
*
* Does not affect the timer's mode or other settings.
*
* @param dev Device whose counter to pause.
*/
static inline void timer_pause(timer_dev *dev) {
*bb_perip(&(dev->regs).bas->CR1, TIMER_CR1_CEN_BIT) = 0;
}
/**
* @brief Start a timer's counter.
*
* Does not affect the timer's mode or other settings.
*
* @param dev Device whose counter to resume
*/
static inline void timer_resume(timer_dev *dev) {
*bb_perip(&(dev->regs).bas->CR1, TIMER_CR1_CEN_BIT) = 1;
}
/**
* @brief Get the status register.
* @param dev Timer device
* @return Status register value (16bits).
*/
static inline uint16 timer_get_status(timer_dev *dev) {
return (dev->regs).gen->SR;
}
static inline void timer_reset_status_bit(timer_dev *dev, uint8 bit) {
*bb_perip(&(dev->regs).gen->SR, bit) = 0;
}
/**
* @brief Returns the timer's counter value.
*
* This value is likely to be inaccurate if the counter is running
* with a low prescaler.
*
* @param dev Timer whose counter to return
*/
static inline uint16 timer_get_count(timer_dev *dev) {
return (uint16)(dev->regs).bas->CNT;
}
/**
* @brief Sets the counter value for the given timer.
* @param dev Timer whose counter to set
* @param value New counter value
*/
static inline void timer_set_count(timer_dev *dev, uint16 value) {
(dev->regs).bas->CNT = value;
}
/**
* @brief Returns the given timer's prescaler.
*
* Note that if the timer's prescaler is set (e.g. via
* timer_set_prescaler() or accessing a TIMx_PSC register), the value
* returned by this function will reflect the new setting, but the
* timer's counter will only reflect the new prescaler at the next
* update event.
*
* @param dev Timer whose prescaler to return
* @see timer_generate_update()
*/
static inline uint16 timer_get_prescaler(timer_dev *dev) {
return (uint16)(dev->regs).bas->PSC;
}
/**
* @brief Set a timer's prescale value.
*
* Divides the input clock by (PSC+1). The new value will not take
* effect until the next update event.
*
* @param dev Timer whose prescaler to set
* @param psc New prescaler value
* @see timer_generate_update()
*/
static inline void timer_set_prescaler(timer_dev *dev, uint16 psc) {
(dev->regs).bas->PSC = psc;
}
/**
* @brief Returns a timer's reload value.
* @param dev Timer whose reload value to return
*/
static inline uint16 timer_get_reload(timer_dev *dev) {
return (uint16)(dev->regs).bas->ARR;
}
/**
* @brief Set a timer's reload value.
* @param dev Timer whose reload value to set
* @param arr New reload value to use. Takes effect at next update event.
* @see timer_generate_update()
*/
static inline void timer_set_reload(timer_dev *dev, uint16 arr) {
(dev->regs).bas->ARR = arr;
}
/**
* @brief Get the compare value for the given timer channel.
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL.
* @param channel Channel whose compare value to get.
*/
static inline uint16 timer_get_compare(timer_dev *dev, uint8 channel) {
__IO uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1);
return *ccr;
}
/**
* @brief Set the compare value for the given timer channel.
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL.
* @param channel Channel whose compare value to set.
* @param value New compare value.
*/
static inline void timer_set_compare(timer_dev *dev,
uint8 channel,
uint16 value) {
__IO uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1);
*ccr = value;
}
/**
* @brief Generate an update event for the given timer.
*
* Normally, this will cause the prescaler and auto-reload values in
* the PSC and ARR registers to take immediate effect. However, this
* function will do nothing if the UDIS bit is set in the timer's CR1
* register (UDIS is cleared by default).
*
* @param dev Timer device to generate an update for.
*/
static inline void timer_generate_update(timer_dev *dev) {
*bb_perip(&(dev->regs).bas->EGR, TIMER_EGR_UG_BIT) = 1;
}
/**
* @brief Enable a timer's trigger DMA request
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL
*/
static inline void timer_dma_enable_trg_req(timer_dev *dev) {
*bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_TDE_BIT) = 1;
}
/**
* @brief Disable a timer's trigger DMA request
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL
*/
static inline void timer_dma_disable_trg_req(timer_dev *dev) {
*bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_TDE_BIT) = 0;
}
/**
* @brief Enable a timer's update DMA request
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL
*/
static inline void timer_dma_enable_upd_req(timer_dev *dev) {
*bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_UDE_BIT) = 1;
}
/**
* @brief Disable a timer's update DMA request
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL
*/
static inline void timer_dma_disable_upd_req(timer_dev *dev) {
*bb_perip(&(dev->regs).gen->DIER, TIMER_DIER_UDE_BIT) = 0;
}
/**
* @brief Enable a timer channel's DMA request.
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL
* @param channel Channel whose DMA request to enable.
*/
static inline void timer_dma_enable_req(timer_dev *dev, uint8 channel) {
*bb_perip(&(dev->regs).gen->DIER, channel + 8) = 1;
}
/**
* @brief Disable a timer channel's DMA request.
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL.
* @param channel Channel whose DMA request to disable.
*/
static inline void timer_dma_disable_req(timer_dev *dev, uint8 channel) {
*bb_perip(&(dev->regs).gen->DIER, channel + 8) = 0;
}
/**
* @brief Enable a timer interrupt.
* @param dev Timer device.
* @param interrupt Interrupt number to enable; this may be any
* timer_interrupt_id value appropriate for the timer.
* @see timer_interrupt_id
* @see timer_channel
*/
static inline void timer_enable_irq(timer_dev *dev, uint8 interrupt) {
// clear interrupt flag, use different masks for reserved bits
(dev->regs).adv->SR = (~BIT(interrupt)) & ( (dev->type==TIMER_ADVANCED) ? 0x1EFF :
( (dev->type==TIMER_GENERAL) ? 0x1E5F : 0x0001) );
*bb_perip(&(dev->regs).adv->DIER, interrupt) = 1;
}
/**
* @brief Disable a timer interrupt.
* @param dev Timer device.
* @param interrupt Interrupt number to disable; this may be any
* timer_interrupt_id value appropriate for the timer.
* @see timer_interrupt_id
* @see timer_channel
*/
static inline void timer_disable_irq(timer_dev *dev, uint8 interrupt) {
*bb_perip(&(dev->regs).adv->DIER, interrupt) = 0;
}
/**
* @brief Enable a timer channel's capture/compare signal.
*
* If the channel is configured as output, the corresponding output
* compare signal will be output on the corresponding output pin. If
* the channel is configured as input, enables capture of the counter
* value into the input capture/compare register.
*
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL.
* @param channel Channel to enable, from 1 to 4.
*/
static inline void timer_cc_enable(timer_dev *dev, uint8 channel) {
*bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1)) = 1;
}
/**
* @brief Disable a timer channel's output compare or input capture signal.
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL.
* @param channel Channel to disable, from 1 to 4.
* @see timer_cc_enable()
*/
static inline void timer_cc_disable(timer_dev *dev, uint8 channel) {
*bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1)) = 0;
}
/**
* @brief Get a channel's capture/compare output polarity
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL.
* @param channel Channel whose capture/compare output polarity to get.
* @return Polarity, either 0 or 1.
* @see timer_cc_set_polarity()
*/
static inline uint8 timer_cc_get_pol(timer_dev *dev, uint8 channel) {
return *bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1) + 1);
}
/**
* @brief Set a timer channel's capture/compare output polarity.
*
* If the timer channel is configured as output: polarity == 0 means
* the output channel will be active high; polarity == 1 means active
* low.
*
* If the timer channel is configured as input: polarity == 0 means
* capture is done on the rising edge of ICn; when used as an external
* trigger, ICn is non-inverted. polarity == 1 means capture is done
* on the falling edge of ICn; when used as an external trigger, ICn
* is inverted.
*
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL.
* @param channel Channel whose capture/compare output polarity to set.
* @param pol New polarity, 0 or 1.
*/
static inline void timer_cc_set_pol(timer_dev *dev, uint8 channel, uint8 pol) {
*bb_perip(&(dev->regs).gen->CCER, 4 * (channel - 1) + 1) = pol;
}
/**
* @brief Get a timer's DMA burst length.
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL.
* @return Number of transfers per read or write to timer DMA register,
* from 1 to 18.
*/
static inline uint8 timer_dma_get_burst_len(timer_dev *dev) {
uint32 dbl = ((dev->regs).gen->DCR & TIMER_DCR_DBL) >> 8;
return dbl + 1; /* 0 means 1 transfer, etc. */
}
/**
* @brief Set a timer's DMA burst length.
* @param dev Timer device, must have type TIMER_ADVANCED or TIMER_GENERAL.
* @param length DMA burst length; i.e., number of DMA transfers per
* read/write to timer DMA register, from 1 to 18.
*/
static inline void timer_dma_set_burst_len(timer_dev *dev, uint8 length) {
uint32 tmp = (dev->regs).gen->DCR;
tmp &= ~TIMER_DCR_DBL;
tmp |= (length - 1) << 8;
(dev->regs).gen->DCR = tmp;
}
My question, why they just call that function alone ? Why they have to put it inside a function pointer ?