Skip to main content
Fixed link.
Source Link
Edgar Bonet
  • 45.2k
  • 4
  • 42
  • 81

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.


Edit: I deleted the code and posted a link for it in github.

stm32/timer header filestm32/timer header file

OK, the part that I started to think about starts from line 595.

It's functions declarations.

In line 598, it's a declaration for a function that receiver a pointer to a function.

In later lines, starting from line 634, these functions have only one line to execute. So my question is why to develop a function to only execute one line ?

Why they didn't just put that line directly instead of putting it inside function ?

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.


Edit: I deleted the code and posted a link for it in github.

stm32/timer header file

OK, the part that I started to think about starts from line 595.

It's functions declarations.

In line 598, it's a declaration for a function that receiver a pointer to a function.

In later lines, starting from line 634, these functions have only one line to execute. So my question is why to develop a function to only execute one line ?

Why they didn't just put that line directly instead of putting it inside function ?

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.


Edit: I deleted the code and posted a link for it in github.

stm32/timer header file

OK, the part that I started to think about starts from line 595.

It's functions declarations.

In line 598, it's a declaration for a function that receiver a pointer to a function.

In later lines, starting from line 634, these functions have only one line to execute. So my question is why to develop a function to only execute one line ?

Why they didn't just put that line directly instead of putting it inside function ?

edit post
Source Link
R1S8K
  • 283
  • 3
  • 21

Edit: I deleted the code and posted a link for it in github.

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;
}

stm32/timer header file

My questionOK, why they just callthe part that I started to think about starts from line 595.

It's functions declarations.

In line 598, it's a declaration for a function alonethat receiver a pointer to a function.

In later lines, starting from line 634, these functions have only one line to execute. So my question is why to develop a function to only execute one line ? 

Why they have todidn't just put that line directly instead of putting it inside a function pointer ?

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 ?


Edit: I deleted the code and posted a link for it in github.

stm32/timer header file

OK, the part that I started to think about starts from line 595.

It's functions declarations.

In line 598, it's a declaration for a function that receiver a pointer to a function.

In later lines, starting from line 634, these functions have only one line to execute. So my question is why to develop a function to only execute one line ? 

Why they didn't just put that line directly instead of putting it inside function ?

I edited the code
Source Link
R1S8K
  • 283
  • 3
  • 21
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;
}
/**
 * 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;
}
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;
}
Source Link
R1S8K
  • 283
  • 3
  • 21
Loading