summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaranjeiro2009-03-27 13:24:42 +0000
committerlaranjeiro2009-03-27 13:24:42 +0000
commitff7ebdf9b134e2cddb51120ff9ac5343bc6dd8e5 (patch)
tree1ad1171c47efe5fa017039560b1735294f412d36
parent87f38bdfe918198bc0338a42450d0d81186e9db6 (diff)
hal/timer: Added the possibility to reprogram the timer on the callback
instance. (Closes #313). git-svn-id: svn+ssh://pessac/svn/cesar/trunk@4319 017c9cb6-072f-447c-8318-d5b54f68fe89
-rw-r--r--cesar/hal/leon/src/timer.c1
-rw-r--r--cesar/hal/timer/src/timer.c37
-rw-r--r--cesar/hal/timer/test/host-Makefile5
-rw-r--r--cesar/hal/timer/test/sparc-Makefile9
-rw-r--r--cesar/hal/timer/test/sparc-ecos.ecc.sh9
-rw-r--r--cesar/hal/timer/test/src/leon_timer_stub.c1
-rw-r--r--cesar/hal/timer/test/src/timer.c66
-rw-r--r--cesar/hal/timer/test/src/timer2.c95
8 files changed, 198 insertions, 25 deletions
diff --git a/cesar/hal/leon/src/timer.c b/cesar/hal/leon/src/timer.c
index 399e17c659..f6ff0fe7ba 100644
--- a/cesar/hal/leon/src/timer.c
+++ b/cesar/hal/leon/src/timer.c
@@ -142,7 +142,6 @@ leon_timer_program (leon_timer_t *ctx, u32 date)
u32 leon_date;
dbg_assert (ctx);
- dbg_assert (date);
dbg_assert (ctx->status == LEON_TIMER_STATUS_STOP);
leon_date = PHY_DATE_TO_LEON_DATE (date - phy_date (ctx->phy));
diff --git a/cesar/hal/timer/src/timer.c b/cesar/hal/timer/src/timer.c
index 83cb1eefbf..d3c689a502 100644
--- a/cesar/hal/timer/src/timer.c
+++ b/cesar/hal/timer/src/timer.c
@@ -64,6 +64,10 @@ hal_timer_instance_uninit (hal_timer_t *ctx, hal_timer_instance_t *instance)
dbg_assert (ctx);
dbg_assert (instance);
+ if (instance->status == HAL_TIMER_STATUS_ARMED)
+ {
+ hal_timer_instance_cancel (ctx, instance);
+ }
instance->status = HAL_TIMER_STATUS_NOT_ARMED;
}
@@ -79,20 +83,23 @@ hal_timer_instance_program (hal_timer_t *ctx,
cyg_scheduler_lock ();
if ((instance->status == HAL_TIMER_STATUS_NOT_ARMED)
- || (less_mod2p32(phy_date(ctx->phy), date)))
+ && (less_mod2p32(phy_date(ctx->phy), date)))
{
heap_node_init (&instance->node);
instance->date = date;
instance->status = HAL_TIMER_STATUS_ARMED;
heap_insert (&ctx->heap, &instance->node);
+ }
- if ((ctx->current_instance
- && (less_mod2p32(date, ctx->current_instance->date)))
- || (ctx->current_instance == NULL))
- {
- ctx->current_instance = instance;
- leon_timer_program (ctx->leon_timer, instance->date);
- }
+ /* Change the current instance in the timer if this new one is lesser. */
+ if ((ctx->current_instance == NULL)
+ || ((ctx->current_instance != NULL)
+ && lesseq_mod2p32 (instance->date, ctx->current_instance->date)))
+ {
+ leon_timer_cancel (ctx->leon_timer);
+ ctx->current_instance = instance;
+ // program the hardware timer.
+ leon_timer_program (ctx->leon_timer, instance->date);
}
/* Unlock the scheduler. */
@@ -117,9 +124,13 @@ hal_timer_reprogram (hal_timer_t *ctx)
instance = PARENT_OF (hal_timer_instance_t, node,
heap_get_root(&ctx->heap));
- ctx->current_instance = instance;
- // program the hardware timer.
- leon_timer_program (ctx->leon_timer, instance->date);
+ if (ctx->current_instance != instance)
+ {
+ leon_timer_cancel (ctx->leon_timer);
+ ctx->current_instance = instance;
+ // program the hardware timer.
+ leon_timer_program (ctx->leon_timer, instance->date);
+ }
}
cyg_scheduler_unlock ();
@@ -158,6 +169,7 @@ hal_timer_instance_process (hal_timer_t *ctx)
dbg_assert (ctx);
cyg_scheduler_lock ();
+ leon_timer_cancel (ctx->leon_timer);
ctx->current_instance = NULL;
// Verify the instance in the heap, if it has a previous date
// the callback will be called and the instance will be removed.
@@ -168,12 +180,15 @@ hal_timer_instance_process (hal_timer_t *ctx)
if (lesseq_mod2p32(instance->date, phy_date (ctx->phy)))
{
+ ctx->current_instance = NULL;
heap_remove (&ctx->heap, &instance->node);
instance->status = HAL_TIMER_STATUS_NOT_ARMED;
(*instance->cb) (instance->user_data);
}
else
+ {
break;
+ }
}
cyg_scheduler_unlock ();
diff --git a/cesar/hal/timer/test/host-Makefile b/cesar/hal/timer/test/host-Makefile
index a9fca27c6e..f3368c59ca 100644
--- a/cesar/hal/timer/test/host-Makefile
+++ b/cesar/hal/timer/test/host-Makefile
@@ -3,10 +3,13 @@ BASE = ../../..
ECOS = y
VARIANT=host
-TARGET_PROGRAMS = timer
+TARGET_PROGRAMS = timer timer_one_thread
timer_SOURCES = timer.c leon_timer_stub.c
timer_MODULES = lib hal/timer
+timer_one_thread_SOURCES = timer2.c leon_timer_stub.c
+timer_one_thread_MODULES = lib hal/timer
+
include $(BASE)/common/make/top.mk
diff --git a/cesar/hal/timer/test/sparc-Makefile b/cesar/hal/timer/test/sparc-Makefile
index 0b7bfb9d4b..d40fd3fb17 100644
--- a/cesar/hal/timer/test/sparc-Makefile
+++ b/cesar/hal/timer/test/sparc-Makefile
@@ -4,10 +4,13 @@ ECOS = y
TARGET=sparc
VARIANT=sparc
-TARGET_PROGRAMS = timer
+TARGET_PROGRAMS = timer timer_one_thread
-timer_SOURCES = timer.c leon_timer_stub.c
-timer_MODULES = lib hal/timer hal/phy hal/arch
+timer_SOURCES = timer.c
+timer_MODULES = lib hal/timer hal/phy hal/arch hal/leon
+
+timer_one_thread_SOURCES = timer2.c
+timer_one_thread_MODULES = lib hal/timer hal/phy hal/arch hal/leon
include $(BASE)/common/make/top.mk
diff --git a/cesar/hal/timer/test/sparc-ecos.ecc.sh b/cesar/hal/timer/test/sparc-ecos.ecc.sh
index db2208c6cc..53c27b36a6 100644
--- a/cesar/hal/timer/test/sparc-ecos.ecc.sh
+++ b/cesar/hal/timer/test/sparc-ecos.ecc.sh
@@ -1,5 +1,14 @@
config=${1:-ecos-gen.ecc}
ecosconfig --config=$config new sparc_leon default
cat >> $config <<'EOF'
+cdl_option CYGNUM_HAL_SYSTEM_CLOCK_FREQ {
+ user_value 150
+}
+cdl_option CYGNUM_HAL_UART_TRACE_FREQ {
+ user_value 50
+}
+cdl_option CYGNUM_KERNEL_SYNCH_MBOX_QUEUE_SIZE {
+ user_value 100
+}
EOF
ecosconfig --config=$config check
diff --git a/cesar/hal/timer/test/src/leon_timer_stub.c b/cesar/hal/timer/test/src/leon_timer_stub.c
index 88063e567f..b6d055bd7d 100644
--- a/cesar/hal/timer/test/src/leon_timer_stub.c
+++ b/cesar/hal/timer/test/src/leon_timer_stub.c
@@ -91,6 +91,7 @@ leon_timer_uninit (leon_timer_t *ctx)
void
leon_timer_program (leon_timer_t *ctx, u32 sysdate)
{
+ dbg_assert (ctx->status == false);
ctx->prgm_date = sysdate;
ctx->status = true;
}
diff --git a/cesar/hal/timer/test/src/timer.c b/cesar/hal/timer/test/src/timer.c
index b283912933..922c2de44e 100644
--- a/cesar/hal/timer/test/src/timer.c
+++ b/cesar/hal/timer/test/src/timer.c
@@ -19,18 +19,19 @@
#include "hal/timer/timer.h"
#include "hal/timer/inc/context.h"
-#include "stdio.h"
#include <cyg/kernel/kapi.h>
+#include <cyg/infra/diag.h>
+
+#include <string.h>
#define THREADS_PRIO 10
#define THREAD1_PRIO THREADS_PRIO
#define THREAD2_PRIO THREADS_PRIO
+#define THREAD3_PRIO THREADS_PRIO
#ifdef __sparc__
-#define RTC_TO_TCK(x) ((x) * 250000)
static volatile uint count;
#else
-#define RTC_TO_TCK(x) (x)
static uint count;
#endif
@@ -48,15 +49,26 @@ u8 thread2_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
cyg_handle_t handle_thread2;
cyg_thread thread2;
+/* Thread 3. */
+u8 thread3_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+cyg_handle_t handle_thread3;
+cyg_thread thread3;
+
+struct toto_t
+{
+ hal_timer_t *hal_timer;
+ hal_timer_instance_t *instance;
+};
+
+static struct toto_t t3_data;
void
increment_val (void *date)
{
count ++;
- diag_printf ("[CB] phy date : %x, current time : %d, count %d\n",
- phy_date (phy),
- (u32) cyg_current_time (), count);
+ diag_printf ("[CB] phy date : %x, count %d\n",
+ phy_date (phy), count);
}
void
@@ -71,7 +83,7 @@ thread1_entry_function(cyg_addrword_t data)
for (i = 0; i < 20; i++)
{
hal_timer_instance_program (hal_timer, &t1_instance,
- phy_date (phy) + RTC_TO_TCK (20));
+ phy_date (phy) + 200000);
cyg_thread_delay (25);
diag_printf ("[Thread1] date : %x, phy : %x, count : %d\n", date,
(u32) cyg_current_time(), count);
@@ -91,12 +103,12 @@ thread2_entry_function(cyg_addrword_t data)
hal_timer_instance_init (hal_timer, &t2_instance, &date, &increment_val);
hal_timer_instance_program (hal_timer, &t2_instance,
- phy_date (phy) + RTC_TO_TCK(21));
+ phy_date (phy) + 210000);
for (i = 0; i < 20; i++)
{
hal_timer_instance_program (hal_timer, &t2_instance,
- phy_date (phy) + RTC_TO_TCK(21));
+ phy_date (phy) + 210000);
cyg_thread_delay (26);
diag_printf ("[Thread2] date : %x, phy : %x, count : %d\n", date,
(u32) cyg_current_time (), count);
@@ -113,6 +125,34 @@ thread2_entry_function(cyg_addrword_t data)
#endif
}
+void
+instance_th3_cb (void *data)
+{
+ hal_timer_instance_t *instance = data;
+ dbg_assert (instance);
+
+ hal_timer_instance_program (t3_data.hal_timer,
+ t3_data.instance,
+ phy_date (phy) + 40000);
+ diag_printf ("[Thread3] cb\n");
+}
+
+void
+thread3_entry_function(cyg_addrword_t data)
+{
+ hal_timer_instance_t t3_instance;
+
+ t3_data.hal_timer = hal_timer;
+ t3_data.instance = &t3_instance;
+
+ hal_timer_instance_init (t3_data.hal_timer, &t3_instance, &t3_data, &instance_th3_cb);
+
+ hal_timer_instance_program (hal_timer, &t3_instance,
+ phy_date (phy) + 40000);
+
+ diag_printf ("[Thread 3] Timer armed\n");
+ cyg_thread_suspend (handle_thread3);
+}
int
cyg_user_start (void)
@@ -132,8 +172,16 @@ cyg_user_start (void)
CYGNUM_HAL_STACK_SIZE_TYPICAL,
&handle_thread2, &thread2);
+ cyg_thread_create(THREAD3_PRIO, &thread3_entry_function,
+ 0, "Thread 3", thread3_stack,
+ CYGNUM_HAL_STACK_SIZE_TYPICAL,
+ &handle_thread3, &thread3);
+
+
cyg_thread_resume (handle_thread1);
cyg_thread_resume (handle_thread2);
+ cyg_thread_resume (handle_thread3);
+
return 0;
}
diff --git a/cesar/hal/timer/test/src/timer2.c b/cesar/hal/timer/test/src/timer2.c
new file mode 100644
index 0000000000..9903bbd2a7
--- /dev/null
+++ b/cesar/hal/timer/test/src/timer2.c
@@ -0,0 +1,95 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2008 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file hal/timer/test/src/timer.c
+ * \brief Test the API timer.
+ * \ingroup hal/timer.
+ *
+ *
+ * Implement three threads to simulate 3 actors.
+ */
+#include "common/std.h"
+#include "lib/test.h"
+#include "lib/blk.h"
+
+#include "hal/timer/timer.h"
+#include "hal/timer/inc/context.h"
+#include <cyg/kernel/kapi.h>
+#include <cyg/infra/diag.h>
+
+#include <string.h>
+
+#define THREAD_PRIO 10
+
+static test_t test;
+static hal_timer_t *hal_timer;
+static phy_t *phy;
+
+/* Thread 1. */
+u8 thread1_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+cyg_handle_t handle_thread1;
+cyg_thread thread1;
+hal_timer_instance_t t1_instance;
+
+void
+timer_cb (void *nothing)
+{
+ diag_printf ("Reprogram timer for 30350 ticks.\n");
+
+ hal_timer_instance_program (hal_timer, &t1_instance,
+ phy_date (phy) + 30350);
+}
+
+void
+thread1_entry_function(cyg_addrword_t data)
+{
+ hal_timer_instance_init (hal_timer, &t1_instance, NULL, &timer_cb);
+
+ hal_timer_instance_program (hal_timer, &t1_instance,
+ phy_date (phy) + 30250);
+
+ diag_printf ("Current instance prgmed : %p\n",
+ hal_timer->current_instance);
+ diag_printf ("This instance : %p\n", &t1_instance);
+ diag_printf ("Going to a rest\n");
+ cyg_thread_delay (10000);
+ diag_printf ("Test ended\n");
+ cyg_thread_suspend (handle_thread1);
+ hal_timer_uninit (hal_timer);
+ test_result (test);
+
+#ifndef __sparc__
+ HAL_PLATFORM_EXIT (test_nb_failed (test) == 0 ? 0 : 1);
+#endif
+}
+
+int
+cyg_user_start (void)
+{
+ test_init (test, 0, NULL);
+
+ phy = (phy_t *) 123;
+ hal_timer = hal_timer_init (phy);
+
+ cyg_thread_create(THREAD_PRIO, &thread1_entry_function,
+ 0, "Thread 1", thread1_stack,
+ CYGNUM_HAL_STACK_SIZE_TYPICAL,
+ &handle_thread1, &thread1);
+
+ cyg_thread_resume (handle_thread1);
+
+ return 0;
+}
+
+#ifndef __sparc__
+u32
+phy_date (phy_t *phy_useless)
+{
+ return cyg_current_time ();
+}
+#endif