From 7632906fc290b652416ab59eb5fb49356c064ed6 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 19 Apr 2018 06:35:52 +0200 Subject: bsps: Move clock drivers to bsps This patch is a part of the BSP source reorganization. Update #3285. --- bsps/shared/dev/clock/clock-simidle.c | 59 ++++++++ bsps/shared/dev/clock/clockimpl.h | 260 ++++++++++++++++++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 bsps/shared/dev/clock/clock-simidle.c create mode 100644 bsps/shared/dev/clock/clockimpl.h (limited to 'bsps/shared/dev/clock') 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 +#include +#include + +#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 + +#include +#include +#include +#include +#include + +#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; +} -- cgit v1.2.3