summaryrefslogtreecommitdiff
path: root/ecos/packages/hal/cortexm/a2fxxx/var/current/tests/timers.c
diff options
context:
space:
mode:
Diffstat (limited to 'ecos/packages/hal/cortexm/a2fxxx/var/current/tests/timers.c')
-rw-r--r--ecos/packages/hal/cortexm/a2fxxx/var/current/tests/timers.c336
1 files changed, 336 insertions, 0 deletions
diff --git a/ecos/packages/hal/cortexm/a2fxxx/var/current/tests/timers.c b/ecos/packages/hal/cortexm/a2fxxx/var/current/tests/timers.c
new file mode 100644
index 0000000..a82ca52
--- /dev/null
+++ b/ecos/packages/hal/cortexm/a2fxxx/var/current/tests/timers.c
@@ -0,0 +1,336 @@
+/*=============================================================================
+//
+// timers.c
+//
+// Test for Cortex-M3 Actel Smartfusion Timers
+//
+//=============================================================================
+// ####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// eCos 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 or (at your option) any later
+// version.
+//
+// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+// As a special exception, if other files instantiate templates or use
+// macros or inline functions from this file, or you compile this file
+// and link it with other works to produce a work based on this file,
+// this file does not by itself cause the resulting work to be covered by
+// the GNU General Public License. However the source code for this file
+// must still be made available in accordance with section (3) of the GNU
+// General Public License v2.
+//
+// This exception does not invalidate any other reasons why a work based
+// on this file might be covered by the GNU General Public License.
+// -------------------------------------------
+// ####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): nickg for STM32
+// ccoutand updated for Cortex-M3 Actel Smartfusion Devices
+// Date: 2011-03-06
+//
+//####DESCRIPTIONEND####
+//
+//===========================================================================*/
+
+#include <pkgconf/system.h>
+#include <pkgconf/hal.h>
+
+#if defined(CYGPKG_KERNEL)
+#include <pkgconf/kernel.h>
+#endif
+
+#include <cyg/infra/testcase.h>
+
+//=============================================================================
+// Check all required packages and components are present
+
+#if !defined(CYGPKG_KERNEL) || !defined(CYGPKG_KERNEL_API)
+
+#define NA_MSG "Configuration insufficient"
+
+#endif
+
+//=============================================================================
+// If everything is present, compile the full test.
+
+#ifndef NA_MSG
+
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_if.h>
+
+#include <cyg/kernel/kapi.h>
+#include <cyg/infra/diag.h>
+#include <string.h>
+
+//=============================================================================
+
+#define LOOPS 24 // == 2 minutes
+
+#define STACK_SIZE 8000
+
+static int test_stack[(STACK_SIZE/sizeof(int))];
+static cyg_thread test_thread;
+static cyg_handle_t main_thread;
+
+//=============================================================================
+
+struct timer
+{
+ cyg_uint32 timer;
+ cyg_uint32 base;
+ cyg_uint32 vector;
+ cyg_uint32 priority;
+ cyg_uint32 interval;
+
+ cyg_uint32 ticks;
+
+ cyg_uint32 preempt[10];
+
+ cyg_uint32 preempt_dsr[10];
+ cyg_uint32 dsr_count[10];
+
+ cyg_interrupt interrupt_object;
+ cyg_handle_t interrupt_handle;
+};
+
+struct timer timers[] =
+{
+ { 1, CYGHWR_HAL_A2FXXX_TIMER1, CYGNUM_HAL_INTERRUPT_TIM0_1, 0x20, 127 },
+ { 2, CYGHWR_HAL_A2FXXX_TIMER2, CYGNUM_HAL_INTERRUPT_TIM0_2, 0x30, 355 },
+ { 0, 0, 0, 0 }
+};
+
+//=============================================================================
+
+volatile cyg_uint32 ticks = 0;
+volatile cyg_uint32 nesting = 0;
+volatile cyg_uint32 max_nesting = 0;
+volatile cyg_uint32 max_nesting_seen = 0;
+volatile cyg_uint32 current = 0;
+volatile cyg_uint32 in_dsr = 0;
+
+//=============================================================================
+
+__externC cyg_uint32 hal_a2fxxx_pclk0;
+
+void init_timer( cyg_uint32 base, cyg_uint32 interval )
+{
+ cyg_uint32 period = hal_a2fxxx_pclk0;
+
+ period = period / 1000000;
+ period = period * interval;
+
+ HAL_WRITE_UINT32(base+CYGHWR_HAL_A2FXXX_TIMER_TIMx_BGLOADVAL, period-1 );
+
+ HAL_WRITE_UINT32(base+CYGHWR_HAL_A2FXXX_TIMER_TIMx_CTRL, \
+ CYGHWR_HAL_A2FXXX_TIMER_TIMx_CTRL_EN | CYGHWR_HAL_A2FXXX_TIMER_TIMx_CTRL_INTEN);
+}
+
+//=============================================================================
+
+cyg_uint32 timer_isr( cyg_uint32 vector, CYG_ADDRWORD data )
+{
+ struct timer *t = (struct timer *)data;
+ cyg_uint32 preempt = current;
+ CYG_ADDRWORD base = t->base;
+ cyg_uint32 cnt;
+
+ current = t->timer;
+ t->ticks++;
+ ticks++;
+ t->preempt[preempt]++;
+ nesting++;
+
+ // Count only first ISR to preempt a DSR
+ if( preempt == 0 )
+ t->preempt_dsr[in_dsr]++;
+
+ HAL_WRITE_UINT32(t->base+CYGHWR_HAL_A2FXXX_TIMER_TIMx_RIS, 1 );
+
+ if( nesting > max_nesting )
+ max_nesting = nesting;
+
+ // Loiter here for a proportion of the timer interval to give
+ // other timers the chance to preempt us.
+ do
+ {
+ HAL_READ_UINT32( base+CYGHWR_HAL_A2FXXX_TIMER_TIMx_VAL, cnt );
+ } while( cnt < t->interval/10 );
+
+ nesting--;
+ current = preempt;
+
+ if( (t->ticks % 10) == 0 )
+ return 3;
+ else
+ return 1;
+}
+
+//=============================================================================
+
+void timer_dsr( cyg_uint32 vector, cyg_uint32 count, CYG_ADDRWORD data )
+{
+ struct timer *t = (struct timer *)data;
+ int i;
+
+ in_dsr = t->timer;
+
+ if( count >= 8 )
+ count = 8;
+
+ t->dsr_count[count]++;
+
+ // Loiter for a while
+ for( i = 0; i < t->interval/10; i++)
+ continue;
+
+ in_dsr = 0;
+}
+
+//=============================================================================
+
+void
+timers_test(cyg_addrword_t data)
+{
+ int loops = LOOPS;
+ int i;
+ CYG_INTERRUPT_STATE istate;
+
+ CYG_TEST_INIT();
+
+ CYG_TEST_INFO("Start Timers test");
+
+ CYGHWR_HAL_A2FXXX_PERIPH_RELEASE( CYGHWR_HAL_A2FXXX_PERIPH_SOFTRST(TIMER) );
+
+ for( i = 0; timers[i].timer != 0; i++ )
+ {
+ struct timer *t = &timers[i];
+
+ init_timer( t->base, t->interval );
+
+ cyg_interrupt_create( t->vector,
+ t->priority,
+ (cyg_addrword_t)t,
+ timer_isr,
+ timer_dsr,
+ &t->interrupt_handle,
+ &t->interrupt_object
+ );
+
+ cyg_interrupt_attach( t->interrupt_handle );
+ cyg_interrupt_unmask( t->vector );
+
+ }
+
+ while( loops-- )
+ {
+ int j;
+
+ // 5 second delay
+ cyg_thread_delay( 5*100 );
+
+ // Disable interrupts while we print details, otherwise it
+ // comes out very slowly.
+ HAL_DISABLE_INTERRUPTS( istate );
+
+ if( max_nesting > max_nesting_seen )
+ max_nesting_seen = max_nesting;
+
+ diag_printf("\nISRs max_nesting %d max_nesting_seen %d\n", max_nesting, max_nesting_seen );
+ max_nesting = 0;
+
+ diag_printf(" T Ticks ");
+
+ for( j = 0; j < 9; j++ )
+ diag_printf("%9d ", j );
+ diag_printf("\n");
+
+ for( i = 0; timers[i].timer != 0; i++ )
+ {
+ struct timer *t = &timers[i];
+
+ diag_printf("%2d: %9d ", t->timer, t->ticks );
+
+ for( j = 0; j < 9; j++ )
+ diag_printf("%9d ", t->preempt[j] );
+ diag_printf("\n");
+
+ }
+
+ diag_printf("DSRs\n");
+
+ diag_printf(" T: ");
+
+ for( j = 0; j < 9; j++ )
+ diag_printf("%9d ", j );
+ diag_printf("\n");
+
+ for( i = 0; timers[i].timer != 0; i++ )
+ {
+ struct timer *t = &timers[i];
+
+ diag_printf("%2d: preempt: ", t->timer);
+
+ for( j = 0; j < 9; j++ )
+ diag_printf("%9d ", t->preempt_dsr[j] );
+ diag_printf("\n");
+
+ diag_printf(" count: ");
+
+ for( j = 0; j < 9; j++ )
+ diag_printf("%9d ", t->dsr_count[j] );
+ diag_printf("\n");
+ }
+
+ HAL_RESTORE_INTERRUPTS( istate );
+ }
+
+ CYG_TEST_PASS_FINISH("Timers test");
+}
+
+//=============================================================================
+
+void cyg_user_start(void)
+{
+ cyg_thread_create(0, // Priority
+ timers_test,
+ 0,
+ "timers test", // Name
+ test_stack, // Stack
+ STACK_SIZE, // Size
+ &main_thread, // Handle
+ &test_thread // Thread data structure
+ );
+ cyg_thread_resume( main_thread);
+}
+
+//=============================================================================
+// Print a message if we cannot run
+
+#else // NA_MSG
+
+void cyg_user_start(void)
+{
+ CYG_TEST_NA(NA_MSG);
+}
+
+#endif // NA_MSG
+
+//=============================================================================
+/* EOF timers.c */