/* * Timer Library (TLIB) * * The Library rely on timer drivers, the timer presented by the * timer driver must look like a down-counter timer, which generates * interrupt (if configured) when underflown. * * If Timer hardware is an up-counter the Timer driver must recalculate * into values that would match as if it was a down-counter. * * COPYRIGHT (c) 2011. * Cobham Gaisler AB. * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.com/license/LICENSE. */ struct tlib_dev; typedef void (*tlib_isr_t)(void *data); struct tlib_drv { /*** Functions ***/ void (*reset)(struct tlib_dev *hand); void (*get_freq)( struct tlib_dev *hand, unsigned int *basefreq, unsigned int *tickrate); int (*set_freq)(struct tlib_dev *hand, unsigned int tickrate); void (*irq_reg)(struct tlib_dev *hand, tlib_isr_t func, void *data); void (*irq_unreg)(struct tlib_dev *hand, tlib_isr_t func,void *data); void (*start)(struct tlib_dev *hand, int once); void (*stop)(struct tlib_dev *hand); void (*restart)(struct tlib_dev *hand); void (*get_counter)(struct tlib_dev *hand, unsigned int *counter); int (*custom)(struct tlib_dev *hand, int cmd, void *arg); int (*int_pend)(struct tlib_dev *hand, int ack); }; struct tlib_dev { struct tlib_dev *next; char status; /* 0=closed, 1=open, 2=timer started */ char index; /* Timer Index */ tlib_isr_t isr_func; void *isr_data; struct tlib_drv *drv; }; #ifdef RTEMS_DRVMGR_STARTUP /* Clock Driver Timer register function. Only used when the TLIB-Clock * driver is used. A specific Timer is registered as the System Clock * timer. */ extern void Clock_timer_register(int timer_number); #endif /* Register Timer. Called by Timer Drivers in order to register * a Timer to the Timer Library. The registration order determines * the Timer Number used in tlib_open() to identify a specific * Timer. */ extern int tlib_dev_reg(struct tlib_dev *newdev); /* Allocate a Timer. * * A Timer handle is returned identifying the timer in later calls. */ extern void *tlib_open(int timer_no); /* Close Timer */ extern void tlib_close(void *hand); /* Returns Number of Timers currently registered to Timer Library */ extern int tlib_ntimer(void); static inline void tlib_reset(void *hand) { struct tlib_dev *dev = hand; dev->drv->reset(dev); } /* Get Frequencies: * - Base Frequency (unchangable base freq rate of timer, prescaler, clkinput) * - Current Tick Rate [in multiples of Base Frequency] */ static inline void tlib_get_freq( void *hand, unsigned int *basefreq, unsigned int *tickrate) { struct tlib_dev *dev = hand; dev->drv->get_freq(dev, basefreq, tickrate); } /* Set current Tick Rate in number of "Base-Frequency ticks" */ static inline int tlib_set_freq(void *hand, unsigned int tickrate) { struct tlib_dev *dev = hand; return dev->drv->set_freq(dev, tickrate); } /* Register ISR at Timer ISR */ static inline void tlib_irq_unregister(void *hand) { struct tlib_dev *dev = hand; if ( dev->isr_func ) { dev->drv->irq_unreg(dev, dev->isr_func, dev->isr_data); dev->isr_func = NULL; } } /* Register ISR at Timer ISR */ static inline void tlib_irq_register(void *hand, tlib_isr_t func, void *data) { struct tlib_dev *dev = hand; /* Unregister previous ISR if installed */ tlib_irq_unregister(hand); dev->isr_func = func; dev->isr_data = data; dev->drv->irq_reg(dev, func, data); } /* Start Timer, ISRs will be generated if enabled. * * once determines if timer should restart (=0) on underflow automatically, * or stop when underflow is reached (=1). */ static inline void tlib_start(void *hand, int once) { struct tlib_dev *dev = hand; dev->drv->start(dev, once); } /* Stop Timer, no more ISRs will be generated */ static inline void tlib_stop(void *hand) { struct tlib_dev *dev = hand; dev->drv->stop(dev); } /* Restart/Reload Timer, may be usefull if a Watchdog Timer */ static inline void tlib_restart(void *hand) { struct tlib_dev *dev = hand; dev->drv->restart(dev); } /* Get current counter value (since last tick) */ static inline void tlib_get_counter(void *hand, unsigned int *counter) { struct tlib_dev *dev = hand; dev->drv->get_counter(dev, counter); } /* Do a custom operation */ static inline void tlib_custom(void *hand, int cmd, void *arg) { struct tlib_dev *dev = hand; dev->drv->custom(dev, cmd, arg); } static inline int tlib_interrupt_pending(void *hand, int ack) { struct tlib_dev *dev = hand; return dev->drv->int_pend(dev, ack); }