summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/pc386
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-20 12:08:42 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-20 13:52:19 +0200
commite0dd8a5ad830798bc8082b03b8c42c32fb9660e0 (patch)
treed147bfc4d670fcdfbd2e2d2e75eb209f92e07df1 /c/src/lib/libbsp/i386/pc386
parentbsps: Move startup files to bsps (diff)
downloadrtems-e0dd8a5ad830798bc8082b03b8c42c32fb9660e0.tar.bz2
bsps: Move benchmark timer to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'c/src/lib/libbsp/i386/pc386')
-rw-r--r--c/src/lib/libbsp/i386/pc386/Makefile.am4
-rw-r--r--c/src/lib/libbsp/i386/pc386/timer/timer.c552
-rw-r--r--c/src/lib/libbsp/i386/pc386/timer/timerisr.S56
3 files changed, 2 insertions, 610 deletions
diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.am b/c/src/lib/libbsp/i386/pc386/Makefile.am
index 094697ed57..2e9441e5bc 100644
--- a/c/src/lib/libbsp/i386/pc386/Makefile.am
+++ b/c/src/lib/libbsp/i386/pc386/Makefile.am
@@ -122,8 +122,8 @@ librtemsbsp_a_SOURCES += ../shared/irq/irq_asm.S
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c
# timer
-librtemsbsp_a_SOURCES += timer/timer.c
-librtemsbsp_a_SOURCES += timer/timerisr.S
+librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/btimer/btimer.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/btimer/timerisr.S
if HAS_IDE
# ide
diff --git a/c/src/lib/libbsp/i386/pc386/timer/timer.c b/c/src/lib/libbsp/i386/pc386/timer/timer.c
deleted file mode 100644
index 16d3d66176..0000000000
--- a/c/src/lib/libbsp/i386/pc386/timer/timer.c
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- * This file contains the PC386 timer package.
- *
- * Rosimildo daSilva -ConnectTel, Inc - Fixed infinite loop in the Calibration
- * routine. I've seen this problems with faster machines ( pentiums ). Sometimes
- * RTEMS just hangs at startup.
- *
- * Joel 9 May 2010: This is now seen sometimes on qemu.
- *
- * Modifications by:
- * (C) Copyright 1997 -
- * NavIST Group - Real-Time Distributed Systems and Industrial Automation
- * http://pandora.ist.utl.pt
- * Instituto Superior Tecnico * Lisboa * PORTUGAL
- *
- * This file is provided "AS IS" without warranty of any kind, either
- * expressed or implied.
- *
- * Based upon code by
- * COPYRIGHT (c) 1989-1999.
- * 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/btimer.h>
-#include <bsp/irq-generic.h>
-#include <libcpu/cpuModel.h>
-
-/*
- * Constants
- */
-#define AVG_OVERHEAD 0 /* 0.1 microseconds to start/stop timer. */
-#define LEAST_VALID 1 /* Don't trust a value lower than this. */
-#define SLOW_DOWN_IO 0x80 /* io which does nothing */
-
-#define TWO_MS (uint32_t)(2000) /* TWO_MS = 2000us (sic!) */
-
-#define MSK_NULL_COUNT 0x40 /* bit counter available for reading */
-
-#define CMD_READ_BACK_STATUS 0xE2 /* command read back status */
-
-RTEMS_INTERRUPT_LOCK_DEFINE( /* visible global variable */ ,
- rtems_i386_i8254_access_lock, "rtems_i386_i8254_access_lock" );
-
-/*
- * Global Variables
- */
-volatile uint32_t Ttimer_val;
-bool benchmark_timer_find_average_overhead = true;
-volatile unsigned int fastLoop1ms, slowLoop1ms;
-
-void (*benchmark_timer_initialize_function)(void) = 0;
-benchmark_timer_t (*benchmark_timer_read_function)(void) = 0;
-void (*Timer_exit_function)(void) = 0;
-
-/* timer (int 08h) Interrupt Service Routine (defined in 'timerisr.s') */
-extern void timerisr(void);
-
-void Timer_exit(void);
-
-/*
- * Pentium optimized timer handling.
- */
-
-/*
- * Timer cleanup routine at RTEMS exit.
- *
- * NOTE: This routine is not really necessary, since there will be
- * a reset at exit.
- */
-static void tsc_timer_exit(void)
-{
-}
-
-static void tsc_timer_initialize(void)
-{
- static bool First = true;
-
- if (First) {
- First = false;
-
- atexit(Timer_exit); /* Try not to hose the system at exit. */
- }
- Ttimer_val = rdtsc(); /* read starting time */
-}
-
-/*
- * Read TSC timer value.
- */
-static uint32_t tsc_read_timer(void)
-{
- register uint32_t total;
-
- total = (uint32_t)(rdtsc() - Ttimer_val);
-
- if (benchmark_timer_find_average_overhead)
- return total;
-
- if (total < LEAST_VALID)
- return 0; /* below timer resolution */
-
- return (total - AVG_OVERHEAD);
-}
-
-/*
- * Non-Pentium timer handling.
- */
-#define US_PER_ISR 250 /* Number of micro-seconds per timer interruption */
-
-/*
- * Timer cleanup routine at RTEMS exit. NOTE: This routine is
- * not really necessary, since there will be a reset at exit.
- */
-static void timerOff(const rtems_raw_irq_connect_data* used)
-{
- rtems_interrupt_lock_context lock_context;
- /*
- * disable interrrupt at i8259 level
- */
- bsp_interrupt_vector_disable(used->idtIndex - BSP_IRQ_VECTOR_BASE);
-
- rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
-
- /* reset timer mode to standard (DOS) value */
- outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
- outport_byte(TIMER_CNTR0, 0);
- outport_byte(TIMER_CNTR0, 0);
-
- rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
-}
-
-static void timerOn(const rtems_raw_irq_connect_data* used)
-{
- rtems_interrupt_lock_context lock_context;
-
- rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
-
- /* load timer for US_PER_ISR microsecond period */
- outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN);
- outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 0 & 0xff);
- outport_byte(TIMER_CNTR0, US_TO_TICK(US_PER_ISR) >> 8 & 0xff);
-
- rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
-
- /*
- * enable interrrupt at i8259 level
- */
- bsp_interrupt_vector_enable(used->idtIndex - BSP_IRQ_VECTOR_BASE);
-}
-
-static rtems_raw_irq_connect_data timer_raw_irq_data = {
- BSP_PERIODIC_TIMER + BSP_IRQ_VECTOR_BASE,
- timerisr,
- timerOn,
- timerOff,
- NULL
-};
-
-/*
- * Timer cleanup routine at RTEMS exit.
- *
- * NOTE: This routine is not really necessary, since there will be
- * a reset at exit.
- */
-static void i386_timer_exit(void)
-{
- i386_delete_idt_entry (&timer_raw_irq_data);
-}
-
-extern void rtems_irq_prologue_0(void);
-static void i386_timer_initialize(void)
-{
- static bool First = true;
-
- if (First) {
- rtems_raw_irq_connect_data raw_irq_data = {
- BSP_PERIODIC_TIMER + BSP_IRQ_VECTOR_BASE,
- rtems_irq_prologue_0,
- NULL,
- NULL,
- NULL
- };
-
- First = false;
- i386_delete_idt_entry (&raw_irq_data);
-
- atexit(Timer_exit); /* Try not to hose the system at exit. */
- if (!i386_set_idt_entry (&timer_raw_irq_data)) {
- printk("raw handler connection failed\n");
- rtems_fatal_error_occurred(1);
- }
- }
- /* wait for ISR to be called at least once */
- Ttimer_val = 0;
- while (Ttimer_val == 0)
- continue;
- Ttimer_val = 0;
-}
-
-/*
- * Read hardware timer value.
- */
-static uint32_t i386_read_timer(void)
-{
- register uint32_t total, clicks;
- register uint8_t lsb, msb;
- rtems_interrupt_lock_context lock_context;
-
- rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
- outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_LATCH);
- inport_byte(TIMER_CNTR0, lsb);
- inport_byte(TIMER_CNTR0, msb);
- rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
-
- clicks = (msb << 8) | lsb;
- total = (Ttimer_val * US_PER_ISR) + (US_PER_ISR - TICK_TO_US(clicks));
-
- if (benchmark_timer_find_average_overhead)
- return total;
-
- if (total < LEAST_VALID)
- return 0; /* below timer resolution */
-
- return (total - AVG_OVERHEAD);
-}
-
-/*
- * General timer functions using either TSC-based implementation
- * or interrupt-based implementation
- */
-
-void benchmark_timer_initialize(void)
-{
- static bool First = true;
-
- if (First) {
- if (x86_has_tsc()) {
-#if defined(DEBUG)
- printk("TSC: timer initialization\n");
-#endif /* DEBUG */
- benchmark_timer_initialize_function = &tsc_timer_initialize;
- benchmark_timer_read_function = &tsc_read_timer;
- Timer_exit_function = &tsc_timer_exit;
- } else {
-#if defined(DEBUG)
- printk("ISR: timer initialization\n");
-#endif /* DEBUG */
- benchmark_timer_initialize_function = &i386_timer_initialize;
- benchmark_timer_read_function = &i386_read_timer;
- Timer_exit_function = &i386_timer_exit;
- }
- First = false;
- }
- (*benchmark_timer_initialize_function)();
-}
-
-uint32_t benchmark_timer_read(void)
-{
- return (*benchmark_timer_read_function)();
-}
-
-void Timer_exit(void)
-{
- if ( Timer_exit_function )
- return (*Timer_exit_function)();
-}
-
-/*
- * Set internal benchmark_timer_find_average_overhead flag value.
- */
-void benchmark_timer_disable_subtracting_average_overhead(bool find_flag)
-{
- benchmark_timer_find_average_overhead = find_flag;
-}
-
-static unsigned short lastLoadedValue;
-
-/*
- * Loads timer 0 with value passed as arguemnt.
- *
- * Returns: Nothing. Loaded value must be a number of clock bits...
- */
-static void loadTimerValue( unsigned short loadedValue )
-{
- rtems_interrupt_lock_context lock_context;
- rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
- lastLoadedValue = loadedValue;
- outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_SQWAVE);
- outport_byte(TIMER_CNTR0, loadedValue & 0xff);
- outport_byte(TIMER_CNTR0, (loadedValue >> 8) & 0xff);
- rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
-}
-
-/*
- * Reads the current value of the timer, and converts the
- * number of ticks to micro-seconds.
- *
- * Returns: number of clock bits elapsed since last load.
- */
-static unsigned int readTimer0(void)
-{
- unsigned short lsb, msb;
- unsigned char status;
- unsigned int count;
- rtems_interrupt_lock_context lock_context;
- rtems_interrupt_lock_acquire(&rtems_i386_i8254_access_lock, &lock_context);
-
- outport_byte(
- TIMER_MODE,
- (TIMER_RD_BACK | (RB_COUNT_0 & ~(RB_NOT_STATUS | RB_NOT_COUNT)))
- );
- inport_byte(TIMER_CNTR0, status);
- inport_byte(TIMER_CNTR0, lsb);
- inport_byte(TIMER_CNTR0, msb);
-
- rtems_interrupt_lock_release(&rtems_i386_i8254_access_lock, &lock_context);
-
- count = ( msb << 8 ) | lsb ;
- if (status & RB_OUTPUT )
- count += lastLoadedValue;
-
- return (2*lastLoadedValue - count);
-}
-
-static void Timer0Reset(void)
-{
- loadTimerValue(0xffff);
- readTimer0();
-}
-
-static void fastLoop (unsigned int loopCount)
-{
- unsigned int i;
- for( i=0; i < loopCount; i++ )outport_byte( SLOW_DOWN_IO, 0 );
-}
-
-static void slowLoop (unsigned int loopCount)
-{
- unsigned int j;
- for (j=0; j <100 ; j++) {
- fastLoop (loopCount);
- }
-}
-
-/*
- * #define DEBUG_CALIBRATE
- */
-void
-Calibrate_loop_1ms(void)
-{
- unsigned int offset, offsetTmp, emptyCall, emptyCallTmp, res, i, j;
- unsigned int targetClockBits, currentClockBits;
- unsigned int slowLoopGranularity, fastLoopGranularity;
- rtems_interrupt_level level;
- int retries = 0;
-
- /*
- * This code is designed to run before interrupt management
- * is enabled and running it on multiple CPUs and or after
- * secondary CPUs are bring up seems really broken.
- * Disabling of local interrupts is enough.
- */
- rtems_interrupt_local_disable(level);
-
-retry:
- if ( ++retries >= 5 ) {
- printk( "Calibrate_loop_1ms: too many attempts. giving up!!\n" );
- while (1);
- }
-#ifdef DEBUG_CALIBRATE
- printk("Calibrate_loop_1ms is starting, please wait (but not too long.)\n");
-#endif
- targetClockBits = US_TO_TICK(1000);
- /*
- * Fill up the cache to get a correct offset
- */
- Timer0Reset();
- readTimer0();
- /*
- * Compute the minimal offset to apply due to read counter register.
- */
- offset = 0xffffffff;
- for (i=0; i <1000; i++) {
- Timer0Reset();
- offsetTmp = readTimer0();
- offset += offsetTmp;
- }
- offset = offset / 1000; /* compute average */
- /*
- * calibrate empty call
- */
- fastLoop (0);
- emptyCall = 0;
- j = 0;
- for (i=0; i <10; i++) {
- Timer0Reset();
- fastLoop (0);
- res = readTimer0();
- /* res may be inferior to offset on fast
- * machine because we took an average for offset
- */
- if (res > offset) {
- ++j;
- emptyCallTmp = res - offset;
- emptyCall += emptyCallTmp;
- }
- }
- if (j == 0) emptyCall = 0;
- else emptyCall = emptyCall / j; /* compute average */
- /*
- * calibrate fast loop
- */
- Timer0Reset();
- fastLoop (10000);
- res = readTimer0() - offset;
- if (res < emptyCall) {
- printk(
- "Problem #1 in offset computation in Calibrate_loop_1ms "
- " in file libbsp/i386/pc386/timer/timer.c\n"
- );
- goto retry;
- }
- fastLoopGranularity = (res - emptyCall) / 10000;
- /*
- * calibrate slow loop
- */
- Timer0Reset();
- slowLoop(10);
- res = readTimer0();
- if (res < offset + emptyCall) {
- printk(
- "Problem #2 in offset computation in Calibrate_loop_1ms "
- " in file libbsp/i386/pc386/timer/timer.c\n"
- );
- goto retry;
- }
- slowLoopGranularity = (res - offset - emptyCall)/ 10;
-
- if (slowLoopGranularity == 0) {
- printk(
- "Problem #3 in offset computation in Calibrate_loop_1ms "
- " in file libbsp/i386/pc386/timer/timer.c\n"
- );
- goto retry;
- }
-
- targetClockBits += offset;
-#ifdef DEBUG_CALIBRATE
- printk("offset = %u, emptyCall = %u, targetClockBits = %u\n",
- offset, emptyCall, targetClockBits);
- printk("slowLoopGranularity = %u fastLoopGranularity = %u\n",
- slowLoopGranularity, fastLoopGranularity);
-#endif
- slowLoop1ms = (targetClockBits - emptyCall) / slowLoopGranularity;
- if (slowLoop1ms != 0) {
- fastLoop1ms = targetClockBits % slowLoopGranularity;
- if (fastLoop1ms > emptyCall) fastLoop1ms -= emptyCall;
- }
- else
- fastLoop1ms = targetClockBits - emptyCall / fastLoopGranularity;
-
- if (slowLoop1ms != 0) {
- /*
- * calibrate slow loop
- */
-
- while(1)
- {
- int previousSign = 0; /* 0 = unset, 1 = incrementing, 2 = decrementing */
- Timer0Reset();
- slowLoop(slowLoop1ms);
- currentClockBits = readTimer0();
- if (currentClockBits > targetClockBits) {
- if ((currentClockBits - targetClockBits) < slowLoopGranularity) {
- /* decrement loop counter anyway to be sure slowLoop(slowLoop1ms) < targetClockBits */
- --slowLoop1ms;
- break;
- }
- else {
- --slowLoop1ms;
- if (slowLoop1ms == 0) break;
- if (previousSign == 0) previousSign = 2;
- if (previousSign == 1) break;
- }
- }
- else {
- if ((targetClockBits - currentClockBits) < slowLoopGranularity) {
- break;
- }
- else {
- ++slowLoop1ms;
- if (previousSign == 0) previousSign = 1;
- if (previousSign == 2) break;
- }
- }
- }
- }
- /*
- * calibrate fast loop
- */
-
- if (fastLoopGranularity != 0 ) {
- while(1) {
- int previousSign = 0; /* 0 = unset, 1 = incrementing, 2 = decrementing */
- Timer0Reset();
- if (slowLoop1ms != 0) slowLoop(slowLoop1ms);
- fastLoop(fastLoop1ms);
- currentClockBits = readTimer0();
- if (currentClockBits > targetClockBits) {
- if ((currentClockBits - targetClockBits) < fastLoopGranularity)
- break;
- else {
- --fastLoop1ms;
- if (previousSign == 0) previousSign = 2;
- if (previousSign == 1) break;
- }
- }
- else {
- if ((targetClockBits - currentClockBits) < fastLoopGranularity)
- break;
- else {
- ++fastLoop1ms;
- if (previousSign == 0) previousSign = 1;
- if (previousSign == 2) break;
- }
- }
- }
- }
-#ifdef DEBUG_CALIBRATE
- printk("slowLoop1ms = %u, fastLoop1ms = %u\n", slowLoop1ms, fastLoop1ms);
-#endif
- rtems_interrupt_local_enable(level);
-
-}
-
-/*
- * loop which waits at least timeToWait ms
- */
-void Wait_X_ms( unsigned int timeToWait)
-{
- unsigned int j;
-
- for (j=0; j<timeToWait ; j++) {
- if (slowLoop1ms != 0) slowLoop(slowLoop1ms);
- fastLoop(fastLoop1ms);
- }
-}
diff --git a/c/src/lib/libbsp/i386/pc386/timer/timerisr.S b/c/src/lib/libbsp/i386/pc386/timer/timerisr.S
deleted file mode 100644
index da2a07845a..0000000000
--- a/c/src/lib/libbsp/i386/pc386/timer/timerisr.S
+++ /dev/null
@@ -1,56 +0,0 @@
-/*-------------------------------------------------------------------------+
-| timerisr.s v1.1 - PC386 BSP - 1997/08/07
-+--------------------------------------------------------------------------+
-| This file contains the PC386 timer interrupt handler.
-+--------------------------------------------------------------------------+
-| (C) Copyright 1997 -
-| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
-|
-| http://pandora.ist.utl.pt
-|
-| Instituto Superior Tecnico * Lisboa * PORTUGAL
-+--------------------------------------------------------------------------+
-| Disclaimer:
-|
-| This file is provided "AS IS" without warranty of any kind, either
-| expressed or implied.
-+--------------------------------------------------------------------------+
-| This code is base on:
-| timerisr.s,v 1.5 1995/12/19 20:07:45 joel Exp - go32 BSP
-| With the following copyright notice:
-| **************************************************************************
-| * COPYRIGHT (c) 1989-1999.
-| * 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 <rtems/asm.h>
-
-BEGIN_CODE
-
- EXTERN(Ttimer_val)
-
-/*-------------------------------------------------------------------------+
-| Function: rtems_isr timerisr(rtems_vector_number);
-| Description: ISR for the timer. The timer is set up to generate an
-| interrupt at maximum intervals.
-| Global Variables: None.
-| Arguments: standard - see RTEMS documentation.
-| Returns: standard return value - see RTEMS documentation.
-+--------------------------------------------------------------------------*/
- PUBLIC(timerisr)
-SYM (timerisr):
- incl Ttimer_val # another tick
- pushl eax
- movb $0x20, al
- outb al, $0x20 # signal generic End Of Interrupt (EOI) to PIC
- popl eax
- iret
-
-END_CODE
-
-END