summaryrefslogtreecommitdiffstats
path: root/bsps/shared/dev/clock
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-19 06:35:52 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-20 09:57:01 +0200
commit7632906fc290b652416ab59eb5fb49356c064ed6 (patch)
treeac036b1f95637e044e10138ceea8d2b56d80ec97 /bsps/shared/dev/clock
parentbsps: Move bspsmpgetcurrentprocessor.c to bsps (diff)
downloadrtems-7632906fc290b652416ab59eb5fb49356c064ed6.tar.bz2
bsps: Move clock drivers to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps/shared/dev/clock')
-rw-r--r--bsps/shared/dev/clock/clock-simidle.c59
-rw-r--r--bsps/shared/dev/clock/clockimpl.h260
2 files changed, 319 insertions, 0 deletions
diff --git a/bsps/shared/dev/clock/clock-simidle.c b/bsps/shared/dev/clock/clock-simidle.c
new file mode 100644
index 0000000000..def406a1df
--- /dev/null
+++ b/bsps/shared/dev/clock/clock-simidle.c
@@ -0,0 +1,59 @@
+/*
+ * Instantiate the clock driver shell.
+ *
+ * Since there is no clock source on the simulator, we fake
+ * it with a special IDLE task.
+ */
+
+#include <rtems.h>
+#include <rtems/score/percpu.h>
+#include <rtems/score/threaddispatch.h>
+
+#define CLOCK_VECTOR 0
+
+volatile bool clock_driver_enabled;
+
+#define Clock_driver_support_initialize_hardware() \
+ do { \
+ clock_driver_enabled = true; \
+ } while (0)
+
+#define Clock_driver_support_shutdown_hardware() \
+ do { \
+ clock_driver_enabled = false; \
+ } while (0)
+
+#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
+
+#include "clockimpl.h"
+
+/*
+ * If this is defined, then the BSP has defined a delay of some sort so
+ * time passage appears somewhat correctly. Otherwise, it runs extremely
+ * fast with no delays.
+ */
+#ifndef BSP_CLOCK_DRIVER_DELAY
+#define BSP_CLOCK_DRIVER_DELAY()
+#endif
+
+/*
+ * Since there is no interrupt on this simulator, let's just
+ * fake time passing. This will not let preemption from an
+ * interrupt work but is enough for many tests.
+ */
+void *clock_driver_sim_idle_body(
+ uintptr_t ignored
+)
+{
+ for( ; ; ) {
+ if ( clock_driver_enabled ) {
+ Per_CPU_Control *cpu = _Thread_Dispatch_disable();
+ _ISR_Nest_level++;
+ rtems_clock_tick();
+ _ISR_Nest_level--;
+ _Thread_Dispatch_enable( cpu );
+ BSP_CLOCK_DRIVER_DELAY();
+ }
+ }
+ return 0; /* to avoid warning */
+}
diff --git a/bsps/shared/dev/clock/clockimpl.h b/bsps/shared/dev/clock/clockimpl.h
new file mode 100644
index 0000000000..6eaa6c94e5
--- /dev/null
+++ b/bsps/shared/dev/clock/clockimpl.h
@@ -0,0 +1,260 @@
+/**
+ * @file
+ *
+ * @ingroup bsp_clock
+ *
+ * @brief Clock Tick Device Driver Shell
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2014.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <stdlib.h>
+
+#include <bsp.h>
+#include <rtems/clockdrv.h>
+#include <rtems/score/percpu.h>
+#include <rtems/score/smpimpl.h>
+#include <rtems/score/watchdogimpl.h>
+
+#ifdef Clock_driver_nanoseconds_since_last_tick
+#error "Update driver to use the timecounter instead of nanoseconds extension"
+#endif
+
+/**
+ * @defgroup bsp_clock Clock Support
+ *
+ * @ingroup bsp_shared
+ *
+ * @brief Clock support
+ *
+ */
+#if CLOCK_DRIVER_USE_FAST_IDLE && CLOCK_DRIVER_ISRS_PER_TICK
+#error "Fast Idle PLUS n ISRs per tick is not supported"
+#endif
+
+/**
+ * @brief Do nothing by default.
+ */
+#ifndef Clock_driver_support_install_isr
+ #define Clock_driver_support_install_isr(isr)
+#endif
+
+/**
+ * @brief This method is rarely used so default it.
+ */
+#ifndef Clock_driver_support_find_timer
+ #define Clock_driver_support_find_timer()
+#endif
+
+/**
+ * @brief Do nothing by default.
+ */
+#ifndef Clock_driver_support_at_tick
+ #define Clock_driver_support_at_tick()
+#endif
+
+/**
+ * @brief Do nothing by default.
+ */
+#ifndef Clock_driver_support_set_interrupt_affinity
+ #define Clock_driver_support_set_interrupt_affinity(online_processors)
+#endif
+
+/*
+ * A specialized clock driver may use for example rtems_timecounter_tick_simple()
+ * instead of the default.
+ */
+#ifndef Clock_driver_timecounter_tick
+static void Clock_driver_timecounter_tick( void )
+{
+#if defined(CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER)
+ rtems_clock_tick();
+#elif defined(RTEMS_SMP) && defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
+ uint32_t cpu_count = _SMP_Get_processor_count();
+ uint32_t cpu_index;
+
+ for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
+ Per_CPU_Control *cpu;
+
+ cpu = _Per_CPU_Get_by_index( cpu_index );
+
+ if ( _Per_CPU_Is_boot_processor( cpu ) ) {
+ rtems_timecounter_tick();
+ } else if ( _Processor_mask_Is_set( _SMP_Get_online_processors(), cpu_index ) ) {
+ _Watchdog_Tick( cpu );
+ }
+ }
+#else
+ rtems_timecounter_tick();
+#endif
+}
+#endif
+
+/**
+ * @brief ISRs until next clock tick
+ */
+#if CLOCK_DRIVER_ISRS_PER_TICK
+ volatile uint32_t Clock_driver_isrs;
+#endif
+
+/**
+ * @brief Clock ticks since initialization
+ */
+volatile uint32_t Clock_driver_ticks;
+
+#ifdef Clock_driver_support_shutdown_hardware
+void Clock_exit( void );
+#endif
+
+/**
+ * @brief Clock_isr
+ *
+ * This is the clock tick interrupt handler.
+ *
+ * @param vector Vector number.
+ */
+#if defined(BSP_FEATURE_IRQ_EXTENSION) || \
+ (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
+void Clock_isr(void *arg);
+void Clock_isr(void *arg)
+{
+#else
+rtems_isr Clock_isr(rtems_vector_number vector);
+rtems_isr Clock_isr(
+ rtems_vector_number vector
+)
+{
+#endif
+ /*
+ * Accurate count of ISRs
+ */
+ Clock_driver_ticks += 1;
+
+ #if CLOCK_DRIVER_USE_FAST_IDLE
+ {
+ struct timecounter *tc = _Timecounter;
+ uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
+ uint32_t interval = (uint32_t)
+ ((tc->tc_frequency * us_per_tick) / 1000000);
+
+ Clock_driver_timecounter_tick();
+
+ if (!rtems_configuration_is_smp_enabled()) {
+ while (
+ _Thread_Heir == _Thread_Executing && _Thread_Executing->is_idle
+ ) {
+ ISR_lock_Context lock_context;
+
+ _Timecounter_Acquire(&lock_context);
+ _Timecounter_Tick_simple(
+ interval,
+ (*tc->tc_get_timecount)(tc),
+ &lock_context
+ );
+ }
+ }
+
+ Clock_driver_support_at_tick();
+ }
+ #else
+ /*
+ * Do the hardware specific per-tick action.
+ *
+ * The counter/timer may or may not be set to automatically reload.
+ */
+ Clock_driver_support_at_tick();
+
+ #if CLOCK_DRIVER_ISRS_PER_TICK
+ /*
+ * The driver is multiple ISRs per clock tick.
+ */
+ if ( !Clock_driver_isrs ) {
+ Clock_driver_timecounter_tick();
+
+ Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK;
+ }
+ Clock_driver_isrs--;
+ #else
+ /*
+ * The driver is one ISR per clock tick.
+ */
+ Clock_driver_timecounter_tick();
+ #endif
+ #endif
+}
+
+#ifdef Clock_driver_support_shutdown_hardware
+/**
+ * @brief Clock_exit
+ *
+ * This routine allows the clock driver to exit by masking the interrupt and
+ * disabling the clock's counter.
+ */
+void Clock_exit( void )
+{
+ Clock_driver_support_shutdown_hardware();
+
+ /* do not restore old vector */
+}
+#endif
+
+/**
+ * @brief Clock_initialize
+ *
+ * This routine initializes the clock driver.
+ *
+ * @param[in] major Clock device major number.
+ * @param[in] minor Clock device minor number.
+ * @param[in] parg Pointer to optional device driver arguments
+ *
+ * @retval rtems_device_driver status code
+ */
+rtems_device_driver Clock_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ Clock_driver_ticks = 0;
+
+ /*
+ * Find timer -- some BSPs search buses for hardware timer
+ */
+ Clock_driver_support_find_timer();
+
+ /*
+ * Install vector
+ */
+ Clock_driver_support_install_isr( Clock_isr );
+
+ #ifdef RTEMS_SMP
+ Clock_driver_support_set_interrupt_affinity(
+ _SMP_Get_online_processors()
+ );
+ #endif
+
+ /*
+ * Now initialize the hardware that is the source of the tick ISR.
+ */
+ Clock_driver_support_initialize_hardware();
+
+#ifdef Clock_driver_support_shutdown_hardware
+ atexit( Clock_exit );
+#endif
+
+ /*
+ * If we are counting ISRs per tick, then initialize the counter.
+ */
+ #if CLOCK_DRIVER_ISRS_PER_TICK
+ Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
+ #endif
+
+ return RTEMS_SUCCESSFUL;
+}