This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
patch for timer_pit.c in at91 var - solves possible kernel-timer problem...
- From: "oliver munz @ s p e a g" <munz at speag dot ch>
- To: ecos-patches at sourceware dot org, Andrew Lunn <andrew at lunn dot ch>
- Date: Fri, 29 May 2009 13:04:16 +0200
- Subject: patch for timer_pit.c in at91 var - solves possible kernel-timer problem...
- Reply-to: munz at speag dot ch
If the PIT is used as system-timer and the kernel does the
initialisation of it late - may be after hanging a long time in a
boot-monitor - then it's possible, that the kernel delay_us dont work
korrekt. This is because the PIT looks at exact matches, and thus, if
You set the compare-register while the counter is already higher, then
You have a big counter reading as the couter periode for a long time and
this must not be...
This patch will initalize the PIT in every circumstance correct and is
important, because of the possible blocking of drivers that uese the
delay_us from the kernel.
Index: packages/hal/arm/at91/var/current/src/timer_pit.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/at91/var/current/src/timer_pit.c,v
retrieving revision 1.4
diff -u -r1.4 timer_pit.c
--- packages/hal/arm/at91/var/current/src/timer_pit.c 20 Feb 2007 21:33:03 -0000 1.4
+++ packages/hal/arm/at91/var/current/src/timer_pit.c 29 May 2009 10:49:56 -0000
@@ -39,9 +39,9 @@
//
// Author(s): asl, Oliver Munz
// Contributors: asl, Oliver Munz
-// Date: 2006-02-12
+// Date: 2009-05-29
// Purpose: Clock support using the PIT
-// Description:
+// Description:
//
//####DESCRIPTIONEND####
//
@@ -59,19 +59,42 @@
void
hal_clock_initialize(cyg_uint32 period)
{
- cyg_uint32 sr;
-
+ cyg_uint32 ir;
+ cyg_uint32 pimr;
+
CYG_ASSERT(CYGNUM_HAL_INTERRUPT_RTC == CYGNUM_HAL_INTERRUPT_PITC,
"Invalid timer interrupt");
-
- /* Set Period Interval timer and enable interrupt */
- HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
- (period - 1) |
- AT91_PITC_PIMR_PITEN |
- AT91_PITC_PIMR_PITIEN);
-
- // Read the status register to clear any pending interrupt
- HAL_READ_UINT32(AT91_PITC + AT91_PITC_PISR, sr);
+ CYG_ASSERT(period < AT91_PITC_VALUE_MASK,
+ "Invalid timer period");
+
+ pimr = (period - 1); /* This is what we want */
+ do { /* Test if the new PITC-Moduls is overrun by the counter */
+
+ HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIIR, ir); /* Counter */
+ ir = ir & AT91_PITC_VALUE_MASK; /* The current counts */
+
+ if (ir > pimr){ /* If the counter is already to high */
+
+ pimr = (ir + 100) & AT91_PITC_VALUE_MASK; /* Set the comparator a head */
+ HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
+ pimr | AT91_PITC_PIMR_PITEN);
+ }
+ if (ir < (period - 1)){ /* If we can try it */
+
+ pimr = (period - 1); /* This is what we want */
+ /* Set the real Period Interval timer */
+ HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
+ pimr | AT91_PITC_PIMR_PITEN);
+ }
+
+ } while (ir > (period -1) || pimr != (period - 1)); // Is it correct?
+
+ /* Enable interrupt */
+ HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
+ pimr | AT91_PITC_PIMR_PITEN | AT91_PITC_PIMR_PITIEN);
+
+ /* Read the status register to clear any pending interrupt */
+ HAL_READ_UINT32(AT91_PITC + AT91_PITC_PISR, ir);
}