All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Schlägl Manfred jun." <manfred.schlaegl@domain.hid>
To: xenomai-help <xenomai@xenomai.org>
Subject: [Xenomai-help] timer-handling adeos/xenomai on arm
Date: Mon, 06 Nov 2006 12:03:15 +0100	[thread overview]
Message-ID: <1162810995.5144.20.camel@domain.hid> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 2161 bytes --]

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

[-- Attachment #1.2: time.c --]
[-- Type: text/x-csrc, Size: 13173 bytes --]

/*
 *  linux/include/asm-arm/arch-ns9750/time.h
 *
 * Copyright (C) 2004 by FS Forth-Systeme GmbH.
 * All rights reserved.
 * Markus Pietrek <mpietrek@fsforth.de>
 * @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. 
 * 			<manfred.schlaegl@gmx.at>
 *     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( /*@unused@*/ 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( /*@unused@*/ 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 #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

             reply	other threads:[~2006-11-06 11:03 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-11-06 11:03 Schlägl Manfred jun. [this message]
2006-11-11 11:05 ` [Xenomai-help] timer-handling adeos/xenomai on arm Gilles Chanteperdrix
2006-11-11 11:39   ` Philippe Gerum
2006-11-11 12:54     ` Gilles Chanteperdrix
2006-11-11 11:52   ` Sebastian Smolorz
2006-11-11 14:33     ` Sebastian Smolorz
2006-11-11 16:31       ` Gilles Chanteperdrix
2006-11-11 18:45         ` Sebastian Smolorz
2006-11-11 21:01           ` Gilles Chanteperdrix
2006-11-12 18:51             ` Sebastian Smolorz
2006-11-13  8:44               ` Gilles Chanteperdrix
2006-11-13  9:17                 ` Sebastian Smolorz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1162810995.5144.20.camel@domain.hid \
    --to=manfred.schlaegl@domain.hid \
    --cc=xenomai@xenomai.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.