Hi again!

I've the presumption, there is something wrong with my timer-handling.
Could you please take a look at my handling.

Thanks in advance!



__ipipe_mach_get_tsc should return the absolute timer-ticks since
bootup, right?


my current handling:

INIT:
 * ns_timer_reload=ticks_per_jiffy
 * timer is loaded with ns_timer_reload
 * timer is configured to start counting down from ns_timer_reload to
zero and trigger an interrupt; after triggering it reloads automatically
with ns_timer_reload.


IPIPE-FUNCTIONS:

#define ns_getticksoffset(timer)        \
        (likely(ns_tscok) ? ns_timer_reload - TIMER_READ(timer) : 0)


/* called after each timer-interrupt */
/* never called, if interrupt is triggered manually! */
void __ipipe_mach_acktimer(void)
{
/* int -> ns_timer_reload ticks are done; timer has already reloaded
with ns_timer_reload and is counting */
        __ipipe_mach_tsc+=ns_timer_reload;
        ns_timer_lxlost+=ns_timer_reload;

        /* ack interrupt */
        TIMER_ACKINT(TIMER_USED);
}
EXPORT_SYMBOL(__ipipe_mach_acktimer);

/* get ticks since start */
unsigned long long __ipipe_mach_get_tsc(void)
{
        unsigned long long result;
        unsigned long flags;

        spin_lock_irqsave_hw(&timer_lock, flags);

/* ticks before last interrupt + ticks since last interrupt (ack) */
        result = __ipipe_mach_tsc + ns_getticksoffset(TIMER_USED); 

        spin_unlock_irqrestore_hw(&timer_lock, flags);

        return result;
}
EXPORT_SYMBOL(__ipipe_mach_get_tsc);

/* set new timer reload */
void __ipipe_mach_set_dec(unsigned long reload)
{
        unsigned long ticks;
        unsigned long flags;

        spin_lock_irqsave_hw(&timer_lock, flags);
        
/* ticks since last interrupt (since ack) */
        ticks = ns_getticksoffset(TIMER_USED); 
        __ipipe_mach_tsc += ticks;
        ns_timer_lxlost += ticks;

        /* reprogramm timer */
        set_dec(TIMER_USED,reload);

        spin_unlock_irqrestore_hw(&timer_lock, flags);
}

EXPORT_SYMBOL(__ipipe_mach_set_dec);


/* get timer value */
unsigned long __ipipe_mach_get_dec(void)
{
        return TIMER_READ(TIMER_USED);
}
EXPORT_SYMBOL(__ipipe_mach_get_dec);




whole source see attachment



 - Manfred
/*
 *  linux/include/asm-arm/arch-ns9750/time.h
 *
 * Copyright (C) 2004 by FS Forth-Systeme GmbH.
 * All rights reserved.
 * Markus Pietrek <[EMAIL PROTECTED]>
 * @References: [1] NS9750 Hardware Reference/December 2003
 *              [2] derived from arch-integrator/time.h
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
/***********************************************************************
 *  @History:
 *     2006/09/01 : Adeos/ipipe support by Schlaegl Manfred jun. 
 * 			<[EMAIL PROTECTED]>
 *     2004/09/02 : implemented gettimeoffset
 *     2004/08/20 : ported to kernel 2.6.8
 ***********************************************************************/

#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 <asm/arch/timex.h> 		/* frequency */


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

/* timer used as system timer */
#define TIMER_USED			0

/* activate sequence lock while system-timer-isr (from integrator) */
#define SEQ_LOCK


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

#define CAT(x,y)	x ## y
#define XCAT(x,y)	CAT(x,y)
#define NS_SYS_TIMER_CTRL_TLCS(tlcs) 	XCAT(NS_SYS_TIMER_CTRL_TLCS_,tlcs)

#if 0
/* timer frequency = full clock-frequency / TLCS */
#define	CFG_HZ		(CPU_CLK_FREQ/TIMER_FDIV)
#endif

/* isr */
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;



/*************************************************************************************
# begin		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;

/* timer lock */
static DEFINE_SPINLOCK(timer_lock);

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

/*************************************************************************************
# end		IPIPE-SPECIFIC VARIABLES
**************************************************************************************/
#endif /* CONFIG_IPIPE */



/* 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		DEBUG-HANDLING
**************************************************************************************/

int DEBUG = DEFAULT_DEBUG;

#define MY_NAME "time.c"
/* debug messages */

#ifdef DEBUG_ENABLED
#define dbg_raw(level, fmt, arg...) 						\
	do {									\
		if (level<=DEBUG)						\
			printk (fmt, ## arg);					\
	} while (0)
#else
#define dbg_raw(level, fmt, arg...)
#endif

/* debug messages with module- and function-information */
#define dbg(level, fmt, arg...) 						\
	dbg_raw(level, "%s: %s:\t\t" fmt, MY_NAME , __FUNCTION__ , ## arg)	

/*************************************************************************************
# end		DEBUG-HANDLING
**************************************************************************************/


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

/* read timer value */
#define TIMER_READ(timer)					\
	readl(NS_SYS_TIMER_READ(timer))

/* set timer reload */
#define TIMER_SET_RELOAD(timer, reload)		\
	writel( reload, NS_SYS_TIMER_COUNT(timer) )

/* set timer ctrl */
#define TIMER_SET_CTRL(timer, ctrl)			\
	writel( ctrl, NS_SYS_TIMER_CTRL(timer) )

/* disable timer (TEN and generate interrupt) */
#define TIMER_DISABLE(timer)				\
	rmwl( NS_SYS_TIMER_CTRL(timer), & ~NS_SYS_TIMER_CTRL_TEN & ~NS_SYS_TIMER_CTRL_INTS);

/* enable timer (TEN and generate interrupt) */
#define TIMER_ENABLE(timer)					\
	rmwl( NS_SYS_TIMER_CTRL(timer), | NS_SYS_TIMER_CTRL_TEN | NS_SYS_TIMER_CTRL_INTS)

/* clear timer */
#define TIMER_CLEAR(timer)					\
do {										\
	writel(0,NS_SYS_TIMER_CTRL(timer) );	\
	TIMER_SET_RELOAD(timer,0);				\
} while(0)

/* ack timer interrupt */
#define TIMER_ACKINT(timer)													\
do {																		\
	rmwl( NS_SYS_TIMER_CTRL(timer), | NS_SYS_TIMER_CTRL_INTC );				\
	rmwl( NS_SYS_TIMER_CTRL(timer), & ~NS_SYS_TIMER_CTRL_INTC );			\
}while (0)


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

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


/* init system-timer */
#define TIMER_INIT(timer)															\
	TIMER_SET_CTRL(timer,															\
		NS_SYS_TIMER_CTRL_TLCS(TIMER_FDIV) |	/* clockfreq / TIMER_FDIV */		\
		NS_SYS_TIMER_CTRL_REN |					/* periodic */						\
		NS_SYS_TIMER_CTRL_TDBG |				/* stop timer in debug-mode */		\
		NS_SYS_TIMER_CTRL_UDS |					/* down-counter */					\
		NS_SYS_TIMER_CTRL_TSZ 					/* 32 bit */						\
	)



/* reprogramm timer */
static inline void set_dec(int timer, unsigned long reload)
{
	/* disable timer */
	TIMER_DISABLE(timer);

	/* set new reload-value */
	TIMER_SET_RELOAD(timer,reload);

	/* activate timer */
	TIMER_ENABLE(timer);

	/* save reload */
	ns_timer_reload = reload;
}


/* get ticks-offset */
#define ns_getticksoffset(timer) 											\
	(likely(ns_tscok) ? ns_timer_reload - TIMER_READ(timer) : 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(TIMER_USED);

#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

#ifdef CONFIG_IPIPE
	/*
	 * - if Linux is running natively (no ipipe), ack the timer (reprogramming automatically)
	 * - if Linux is running under ipipe, but it still has the control over
	 *   the timer (no Xenomai for example), then do nothing (ipipe
	 *   has already acked it; reprogramming automatically)
	 * - if some other domain has taken over the timer, then do nothing
	 *   (ipipe has acked it, and the other domain has reprogramed it)
	 */
	/* save ticks since boot */
	if (!__ipipe_mach_timerstolen) {
		/* ticks since last int (already done in ack)*/
//		__ipipe_mach_tsc += ns_timer_reload;

	}
#else
	/* ack_timer */
	TIMER_ACKINT(TIMER_USED);
#endif

	/* clear lost ticks since last timer_tick */
	ns_timer_lxlost = 0;

	/* 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 ] );

	__ipipe_mach_ticks_per_jiffy = LATCH;

	dbg(0,"\n"
        " system-clock:                %d Hz\n"
		" timer-clock:                 %d Hz   (=system-clock/%d) \n"
		" ticks_per_jiffy:             %d \n"
		" jiffis per usecs             %d      (HZ-value)\n"
		,
		CPU_CLK_FREQ,
		CLOCK_TICK_RATE, TIMER_FDIV, 
		__ipipe_mach_ticks_per_jiffy,
		HZ
	);

	/* clear timer*/
	TIMER_CLEAR(TIMER_USED);

	/* set timer-isr */
	setup_irq( IRQ_TIMER_0 + TIMER_USED, &ns_timer_irq );

	/* init timer */
	TIMER_INIT(TIMER_USED);

	/* reload timer */
	set_dec(TIMER_USED,__ipipe_mach_ticks_per_jiffy); /* a tick every HZ */

	/* ok */
	ns_tscok = 1;
}



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




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

/* called after each timer-interrupt */
/* never called, if interrupt is triggered manually! */
void __ipipe_mach_acktimer(void)
{
	/* int -> ns_timer_reload ticks done */
	__ipipe_mach_tsc+=ns_timer_reload;
	ns_timer_lxlost+=ns_timer_reload;

	/* ack interrupt */
	TIMER_ACKINT(TIMER_USED);
}
EXPORT_SYMBOL(__ipipe_mach_acktimer);

/* get ticks since start */
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(TIMER_USED);
	spin_unlock_irqrestore_hw(&timer_lock, flags);

	return result;
}
EXPORT_SYMBOL(__ipipe_mach_get_tsc);

/* set new timer reload */
void __ipipe_mach_set_dec(unsigned long reload)
{
	unsigned long ticks;
	unsigned long flags;

	spin_lock_irqsave_hw(&timer_lock, flags);
	
	/* ticks since last int */
	ticks = ns_getticksoffset(TIMER_USED);
	__ipipe_mach_tsc += ticks;
	ns_timer_lxlost += ticks;

	/* reprogramm timer */
	set_dec(TIMER_USED,reload);

	spin_unlock_irqrestore_hw(&timer_lock, flags);
}

EXPORT_SYMBOL(__ipipe_mach_set_dec);


/* get timer value */
unsigned long __ipipe_mach_get_dec(void)
{
	return TIMER_READ(TIMER_USED);
}
EXPORT_SYMBOL(__ipipe_mach_get_dec);


/*************************************************************************************
# end		IPIPE-FUNCTIONS
**************************************************************************************/
#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