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: Re: [Xenomai-help] xenomai revision 1772 on arm
Date: Thu, 02 Nov 2006 15:08:53 +0100	[thread overview]
Message-ID: <1162476533.5015.19.camel@domain.hid> (raw)
In-Reply-To: <Pine.GSO.4.64.0610301611060.6748@domain.hid>

[-- Attachment #1: Type: text/plain, Size: 12900 bytes --]

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( /*@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;



/* 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( /*@unused@*/ 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 #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

      reply	other threads:[~2006-11-02 14:08 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-10-30 14:30 [Xenomai-help] xenomai revision 1772 on arm Schlägl Manfred jun.
2006-10-30 15:01 ` Gilles Chanteperdrix
2006-10-30 15:16   ` Gilles Chanteperdrix
2006-10-30 15:12 ` Sebastian Smolorz
2006-11-02 14:08   ` Schlägl Manfred jun. [this message]

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=1162476533.5015.19.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.