On Mon, 2006-10-30 at 16:12 +0100, Sebastian Smolorz wrote:
> On Mon, 30 Oct 2006, Schlägl Manfred jun. wrote:
> 
> > Should be a hint, if anyone has similar Problems:
> >
> > Xenomai (rev. 1772) was not running on my platform. (no
> > timer_tick-calls; timer stopped)
> >
> > I had to do following downgrade:
> >
> > Index: include/asm-arm/hal.h
> > ===================================================================
> > --- include/asm-arm/hal.h       (revision 1772)
> > +++ include/asm-arm/hal.h       (working copy)
> > @@ -103,10 +103,13 @@
> >
> > static inline void rthal_timer_program_shot (unsigned long delay)
> > {
> > +    if(!delay)
> > +        delay = 10;
> > +    __ipipe_mach_set_dec(delay);
> > -    if(!delay)
> > -        rthal_trigger_irq(RTHAL_TIMER_IRQ);
> > -     else
> > -       __ipipe_mach_set_dec(delay);
> > }
> >
> >     /* Private interface -- Internal use only */
> >
> >
> > It's simply a workaround yet. I'll try to find the error in my
> > timer-handling.
> 
> What is your timer operation mode? Free-running or counting down and 
> aperiodic?
> 
> Sebastian

Using arm926 with Xenomai rev. 1790 (2.6.15.7 with ipipe-1.5-01)

I'm using an aperiodic timer without wraparound. the problem:
To ack the timer interrrupt I have to disable the timer (!TEN) and the
timer_interrupt generation (!INTS) first.
When i disable the timer (!TEN) the timer-read-register is automatically
reloaded with the timer-count-register. So a timer-read (getticksoffset)
after __ipipe_mach_acktimer returns the reload value not 0. Is this the
right behavior.
Or my solution (to backup the timer-value before disabling the timer for
later reads).

My solution works for the old xenomai implementation (2.2.3) 
hal.h:
static inline void rthal_timer_program_shot (unsigned long delay)
{
   if(!delay)
      delay = 10;
   __ipipe_mach_set_dec(delay);
}
but not for the new one:
static inline void rthal_timer_program_shot (unsigned long delay)
{
   if(!delay)
      rthal_trigger_irq(RTHAL_TIMER_IRQ);
   else
      __ipipe_mach_set_dec(delay);
}




My timer-implementation:

#include <linux/module.h>       /* EXPORT_SYMBOL */
#include <linux/ioport.h>       /* request_resource */
#include <linux/interrupt.h>    /* irqreturn_t */

#include <asm/io.h>             /* writel */
#include <asm/mach-types.h>

#include <asm/arch/ns9750_sys.h> /* NS_SYS */
#include <asm/arch/irqs.h>      /* IRQ_TIMER_0 */
#include <asm/arch/time.h>      /* ns_time_init */


#include<linux/delay.h>


/* activate sequence lock while interrupt (from integrator) */
#define SEQ_LOCK

/* start default debug-level */
#define DEBUG_ENABLED
#define DEFAULT_DEBUG 1


/*************************************************************************************
# begin         DEFINITIONS
**************************************************************************************/

/* full clock-frequency */
#if 0
#define CFG_HZ          (CPU_CLK_FREQ/64)
#else
#define CFG_HZ          (CPU_CLK_FREQ)
#endif

#define TIMER_USED      0


static irqreturn_t ns9750_timer_interrupt( /[EMAIL PROTECTED]@*/ int irq,
                                           void* dev_id,
                                           struct pt_regs* regs );


static struct irqaction ns_timer_irq = {
        .name           = "NS9750 Timer Tick",
        .flags          = SA_INTERRUPT | SA_TIMER,
        .handler        = ns9750_timer_interrupt
};

/* reload value for timer */
static unsigned int ns_timer_reload;

/* correct ticks */
static unsigned long ns_timer_delta_old;
static unsigned int ns_timer_jiffies_old;

/* lost ticks, saved if __ipipe_mach_set_sec while running timer */
static unsigned long ns_timer_lxlost;

/* timer ok - flag */
static int ns_tscok;



/* IPIPE-SPECIFIC VARIABLES */
#ifdef CONFIG_IPIPE
#ifdef CONFIG_NO_IDLE_HZ
#error "dynamic tick timer not yet supported with IPIPE"
#endif /* CONFIG_NO_IDLE_HZ */

/* the timer interrupt */
int __ipipe_mach_timerint = IRQ_TIMER_0 + TIMER_USED;
EXPORT_SYMBOL(__ipipe_mach_timerint);

/* ticks-counter */
static unsigned long long __ipipe_mach_tsc;

static DEFINE_SPINLOCK(timer_lock);

static int ns_valid=1;

/* timer stolen - flag */
int __ipipe_mach_timerstolen = 0;
EXPORT_SYMBOL(__ipipe_mach_timerstolen);
#endif


/* timer-ticks per jiffy (init in ns_time_init) */
unsigned int __ipipe_mach_ticks_per_jiffy;
EXPORT_SYMBOL(__ipipe_mach_ticks_per_jiffy); 


void __tm_init_timer(void);



/*************************************************************************************
# begin         TIMER-SPECIFIC HELP-FUNCTIONS
**************************************************************************************/

/* begin
TODO ?????????????????????????????????????????????????????????????????????? */

/* backup for timer-value if timer gets disabled */
static unsigned long timer_value_backup;

unsigned long ns_read_timer_value(void ) 
{
        if(ns_valid==1) {
                return readl(NS_SYS_TIMER_READ( TIMER_USED ));
        } else {
                return timer_value_backup;              
//              return ns_timer_reload;
//              return 0;
//              return readl(NS_SYS_TIMER_READ( TIMER_USED ));
        }
}


/* disable timer */
#define DISABLE_TIMER()                                                         
                                                                                
                \
do {                                                                            
                                                                                
                                \
timer_value_backup=ns_read_timer_value(); \
        rmwl( NS_SYS_TIMER_CTRL( TIMER_USED ), & ~NS_SYS_TIMER_CTRL_TEN &
~NS_SYS_TIMER_CTRL_INTS);               \
} while(0)



/* end
TODO ?????????????????????????????????????????????????????????????????????? */

#define ENABLE_TIMER()                          \
        rmwl( NS_SYS_TIMER_CTRL( TIMER_USED ), | NS_SYS_TIMER_CTRL_TEN |
NS_SYS_TIMER_CTRL_INTS)

#define CLEAR_TIMER()                           \
        writel(0,NS_SYS_TIMER_CTRL( TIMER_USED ) )

#define INIT_TIMER()                                                            
                                                \
        writel(                                                                 
                                                                \
                NS_SYS_TIMER_CTRL_TDBG |        /* stop timer in debug-mode */  
                \
                NS_SYS_TIMER_CTRL_INTS |        /* generate irq */              
                                \
                NS_SYS_TIMER_CTRL_UDS |         /* down-counter */              
                                \
                NS_SYS_TIMER_CTRL_TSZ           /* 32 bit */                    
                                \
                , NS_SYS_TIMER_CTRL( TIMER_USED ) )

#define ACK_TIMER_INT()                                                         
                                                \
do {                                                                            
                                                                \
        rmwl( NS_SYS_TIMER_CTRL( TIMER_USED ), | NS_SYS_TIMER_CTRL_INTC );      
        \
        rmwl( NS_SYS_TIMER_CTRL( TIMER_USED ), & ~NS_SYS_TIMER_CTRL_INTC );     
        \
}while (0)




/*************************************************************************************
# end           TIMER-SPECIFIC HELP-FUNCTIONS
**************************************************************************************/


/*************************************************************************************
# begin         GENERAL TIMER-FUNCTIONS
**************************************************************************************/


static inline void set_dec(unsigned long reload)
{
        /* disable timer (not nessecary?)*/
        DISABLE_TIMER();

        /* reload */
        writel( reload, NS_SYS_TIMER_COUNT( TIMER_USED ) );

        /* activate timer */
        ENABLE_TIMER();

        /* save reload */
        ns_timer_reload = reload;
}

/* get ticks-offset */
#define ns_getticksoffset()                                     \
        (likely(ns_tscok) ? ns_timer_reload - ns_read_timer_value() : 0)


/*
 * Returns number of us since last clock interrupt.  Note that
interrupts
 * will have been disabled by do_gettimeoffset()
 */
unsigned long ns9750_gettimeoffset(void)
{
        /* get ticks */
        unsigned long timer_delta = ns_getticksoffset();

#if 1 /* correction from original-implementation */
        if( ns_timer_jiffies_old == jiffies && ns_timer_delta_old >
timer_delta ) {
                /* we are called by arm/kernel/time.c:do_gettimeofday with
                 * interrupts disabled.
                 * It may happen then that there is a timer reload after
                 * interrupts disable. Therefore jiffies is not incremented.
                 * So while jiffies has not been updated, return the old
                 * time. */
                timer_delta = ns_timer_delta_old;
        } else {
                ns_timer_delta_old = timer_delta;
                ns_timer_jiffies_old = jiffies;
        }
#endif

        /* calc */
        return ( (1000 * (ns_timer_lxlost + timer_delta)) /
(__ipipe_mach_ticks_per_jiffy / 10) );
}
EXPORT_SYMBOL(ns9750_gettimeoffset);

/*
 * IRQ handler for the timer
 */
static irqreturn_t ns9750_timer_interrupt( /[EMAIL PROTECTED]@*/ int irq,
                                           void* dev_id,
                                           struct pt_regs* regs )
{
#ifdef SEQ_LOCK
        write_seqlock(&xtime_lock);
#endif

        ns_timer_lxlost = 0;


#ifdef CONFIG_IPIPE
        /*
         * - if Linux is running natively (no ipipe), ack and reprogram the
timer
         * - if Linux is running under ipipe, but it still has the control over
         *   the timer (no Xenomai for example), then reprogram the timer
(ipipe
         *   has already acked it)
         * - if some other domain has taken over the timer, then do nothing
         *   (ipipe has acked it, and the other domain has reprogramed it)
         */
        if (!__ipipe_mach_timerstolen) {
                __ipipe_mach_tsc += ns_getticksoffset();
#else
        /* ack interrupt and disable timer */
        DISABLE_TIMER();
        ACK_TIMER_INT();
#endif

                /* activate timer */
                ENABLE_TIMER();

#ifdef CONFIG_IPIPE
        } 
#endif

        /* linux timer tick */
        timer_tick( regs );

#ifdef SEQ_LOCK
        write_sequnlock(&xtime_lock);
#endif

        return IRQ_HANDLED;
}

static struct resource timer_resource[ 3 ] = {
        {
                .name   = "system timer",
                .start  = (NS_SYS_TIMER_CTRL( TIMER_USED ) ),
                .end    = (NS_SYS_TIMER_CTRL( TIMER_USED ) ) + 3,
        },
        {
                .name   = "system timer",
                .start  = (NS_SYS_TIMER_READ( TIMER_USED ) ),
                .end    = (NS_SYS_TIMER_READ( TIMER_USED ) ) + 3,
        },
        {
                .name   = "system timer",
                .start  = (NS_SYS_TIMER_COUNT( TIMER_USED ) ),
                .end    = (NS_SYS_TIMER_COUNT( TIMER_USED ) ) + 3,
        }
};

/*
 * Set up timer interrupt, and return the current time in seconds.
 */
void __init ns_time_init( void )
{
        request_resource( &iomem_resource, &timer_resource[ 0 ] );
        request_resource( &iomem_resource, &timer_resource[ 1 ] );
        request_resource( &iomem_resource, &timer_resource[ 2 ] );

        /* clear */
        CLEAR_TIMER();

        /* init */
        INIT_TIMER();

        __ipipe_mach_ticks_per_jiffy = CFG_HZ/HZ;

        dbg(0,"\n CFG_HZ:            %d\n"
                " HZ:                %d\n"
                " ticks_per_jiffy:   %d\n"
                " uSecs_per_jiffy:   %d\n"
                ,
                CFG_HZ,
                HZ,
                __ipipe_mach_ticks_per_jiffy,
                10000
        );

        setup_irq( IRQ_TIMER_0 + TIMER_USED, &ns_timer_irq );

        /* programm and enable timer */
        set_dec(__ipipe_mach_ticks_per_jiffy); /* a tick every HZ */

        ns_tscok = 1;

        __tm_init_timer();
}

/*************************************************************************************
# end           GENERAL TIMER-FUNCTIONS
**************************************************************************************/




#ifdef CONFIG_IPIPE
/*************************************************************************************
# begin         IPIPE-FUNCTIONS
**************************************************************************************/

/* called after each timer-interrupt if stolen */
void __ipipe_mach_acktimer(void)
{
        if(ns_valid==-1) {
                nop();
        }

        if(readl(NS_SYS_TIMER_READ( TIMER_USED ))) {
                nop();
//              printk("1 : %u\n", readl(NS_SYS_TIMER_READ( TIMER_USED )));
//              printk("2 : %u\n", readl(NS_SYS_TIMER_READ( TIMER_USED )));
        }

        DISABLE_TIMER();
        ns_valid=0;
        ACK_TIMER_INT();
//      rmwl( NS_SYS_TIMER_CTRL( TIMER_USED ), | NS_SYS_TIMER_CTRL_INTS);
//      rmwl( NS_SYS_TIMER_CTRL( TIMER_USED ), | NS_SYS_TIMER_CTRL_TEN);
//      ENABLE_TIMER();
}
EXPORT_SYMBOL(__ipipe_mach_acktimer);

unsigned long long __ipipe_mach_get_tsc(void)
{
        unsigned long long result;
        unsigned long flags;

        spin_lock_irqsave_hw(&timer_lock, flags);
        result = __ipipe_mach_tsc + ns_getticksoffset();
        spin_unlock_irqrestore_hw(&timer_lock, flags);

        return result;
}
EXPORT_SYMBOL(__ipipe_mach_get_tsc);


/* begin
TODO ?????????????????????????????????????????????????????????????????????? */
/* see include/asm/xenomai/hal.h rthal_timer_program_shot too */
void __ipipe_mach_set_dec(unsigned long reload)
{
        unsigned long ticks;
        unsigned long flags;

#if 1
        /* test new xenomai-handling (xeno 2.2.3 rthal_timer_program_shot is
used) *
        if(reload==10) {
                ns_valid=-1;
                ipipe_trigger_irq(IRQ_TIMER_0 + TIMER_USED);
                return;

//              reload=1;
        }
#endif
        spin_lock_irqsave_hw(&timer_lock, flags);
        
        ticks = ns_getticksoffset();
        __ipipe_mach_tsc += ticks;

        ns_timer_lxlost += ticks;

        if(reload>0) {
                set_dec(reload);
                ns_valid=1;
                spin_unlock_irqrestore_hw(&timer_lock, flags);
        } else {
                /* trigger manually */
                spin_unlock_irqrestore_hw(&timer_lock, flags);
                ipipe_trigger_irq(IRQ_TIMER_0 + TIMER_USED);
        }
}
EXPORT_SYMBOL(__ipipe_mach_set_dec);
/* end
TODO ?????????????????????????????????????????????????????????????????????? */

unsigned long __ipipe_mach_get_dec(void)
{
        if(unlikely(ns_valid<1)) printk("GET_DEC INVALID ################# %ul
\n",readl(NS_SYS_TIMER_READ( TIMER_USED )));
        return readl(NS_SYS_TIMER_READ( TIMER_USED ));
}
EXPORT_SYMBOL(__ipipe_mach_get_dec);

#endif /* CONFIG_IPIPE */

Attachment: signature.asc
Description: This is a digitally signed message part

_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help

Reply via email to