forked from Imagelibrary/rtems
bsps: Move clock drivers to bsps
This patch is a part of the BSP source reorganization. Update #3285.
This commit is contained in:
61
bsps/m68k/av5282/clock/clock.c
Normal file
61
bsps/m68k/av5282/clock/clock.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Use the last periodic interval timer (PIT3) as the system clock.
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <bsp.h>
|
||||
#include <mcf5282/mcf5282.h>
|
||||
|
||||
/*
|
||||
* Use INTC0 base
|
||||
*/
|
||||
#define CLOCK_VECTOR (64+58)
|
||||
|
||||
/*
|
||||
* Periodic interval timer interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_at_tick() \
|
||||
do { \
|
||||
MCF5282_PIT3_PCSR |= MCF5282_PIT_PCSR_PIF; \
|
||||
} while (0) \
|
||||
|
||||
/*
|
||||
* Attach clock interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_install_isr( _new ) \
|
||||
set_vector(_new, CLOCK_VECTOR, 1)
|
||||
|
||||
/*
|
||||
* Turn off the clock
|
||||
*/
|
||||
#define Clock_driver_support_shutdown_hardware() \
|
||||
do { \
|
||||
MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Set up the clock hardware
|
||||
*
|
||||
* We need to have 1 interrupt every 10,000 microseconds
|
||||
* so we need to set prescaler to 64 and the PMR register to 0x23FE
|
||||
*/
|
||||
#define Clock_driver_support_initialize_hardware() \
|
||||
do { \
|
||||
int level; \
|
||||
int preScaleCode = 5; \
|
||||
MCF5282_INTC0_ICR58 = MCF5282_INTC_ICR_IL(PIT3_IRQ_LEVEL) | \
|
||||
MCF5282_INTC_ICR_IP(PIT3_IRQ_PRIORITY); \
|
||||
rtems_interrupt_disable( level ); \
|
||||
MCF5282_INTC0_IMRH &= ~MCF5282_INTC_IMRH_INT58; \
|
||||
MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN; \
|
||||
rtems_interrupt_enable( level ); \
|
||||
MCF5282_PIT3_PMR = 0x23FE; \
|
||||
MCF5282_PIT3_PCSR = MCF5282_PIT_PCSR_PRE(preScaleCode) | \
|
||||
MCF5282_PIT_PCSR_PIE | \
|
||||
MCF5282_PIT_PCSR_RLD | \
|
||||
MCF5282_PIT_PCSR_EN; \
|
||||
} while (0)
|
||||
|
||||
#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
|
||||
|
||||
#include "../../../shared/dev/clock/clockimpl.h"
|
||||
104
bsps/m68k/gen68340/clock/ckinit.c
Normal file
104
bsps/m68k/gen68340/clock/ckinit.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This routine initializes the MC68340/349 Periodic Interval Timer
|
||||
*/
|
||||
|
||||
/*
|
||||
* Based on the `gen68360' board support package, and covered by the
|
||||
* original distribution terms.
|
||||
*
|
||||
* Geoffroy Montel
|
||||
* France Telecom - CNET/DSM/TAM/CAT
|
||||
* 4, rue du Clos Courtel
|
||||
* 35512 CESSON-SEVIGNE
|
||||
* FRANCE
|
||||
*
|
||||
* e-mail: g_montel@yahoo.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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> /* for atexit() */
|
||||
#include <bsp.h>
|
||||
#include <m68340.h>
|
||||
#include <rtems/clockdrv.h>
|
||||
|
||||
#define CLOCK_VECTOR 120 /* clock isr routine vector in the vbr */
|
||||
#define CLOCK_IRQ_LEVEL 6 /* clock isr level */
|
||||
|
||||
/*
|
||||
* Clock_driver_ticks is a monotonically increasing counter of the
|
||||
* number of clock ticks since the driver was initialized.
|
||||
*/
|
||||
volatile uint32_t Clock_driver_ticks;
|
||||
|
||||
/*
|
||||
* Periodic interval timer interrupt handler
|
||||
*/
|
||||
static rtems_isr
|
||||
Clock_isr (rtems_vector_number vector)
|
||||
{
|
||||
/*
|
||||
* Announce the clock tick
|
||||
*/
|
||||
Clock_driver_ticks++;
|
||||
rtems_clock_tick();
|
||||
}
|
||||
|
||||
void
|
||||
Clock_exit (void)
|
||||
{
|
||||
/*
|
||||
* Turn off periodic interval timer
|
||||
*/
|
||||
SIMPITR = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
Install_clock (rtems_isr_entry clock_isr)
|
||||
{
|
||||
uint32_t pitr_tmp;
|
||||
uint32_t usecs_per_tick;
|
||||
|
||||
Clock_driver_ticks = 0;
|
||||
|
||||
set_vector (clock_isr, CLOCK_VECTOR, 1);
|
||||
|
||||
/* sets the Periodic Interrupt Control Register PICR */
|
||||
SIMPICR = ( CLOCK_IRQ_LEVEL << 8 ) | ( CLOCK_VECTOR );
|
||||
|
||||
/* sets the PITR count value */
|
||||
/* this assumes a 32.765 kHz crystal */
|
||||
|
||||
usecs_per_tick = rtems_configuration_get_microseconds_per_tick();
|
||||
/* find out whether prescaler should be enabled or not */
|
||||
if ( usecs_per_tick <= 31128 ) {
|
||||
pitr_tmp = ( usecs_per_tick * 8192 ) / 1000000 ;
|
||||
} else {
|
||||
pitr_tmp = ( usecs_per_tick / 1000000 ) * 16;
|
||||
/* enable it */
|
||||
pitr_tmp |= 0x100;
|
||||
}
|
||||
|
||||
SIMPITR = (unsigned char) pitr_tmp;
|
||||
|
||||
atexit (Clock_exit);
|
||||
}
|
||||
|
||||
rtems_device_driver
|
||||
Clock_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *pargp
|
||||
)
|
||||
{
|
||||
Install_clock (Clock_isr);
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
101
bsps/m68k/gen68360/clock/clock.c
Normal file
101
bsps/m68k/gen68360/clock/clock.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This routine initializes the MC68360 Periodic Interval Timer
|
||||
*
|
||||
* The PIT has rather poor resolution, but it is easy to set up
|
||||
* and requires no housekeeping once it is going.
|
||||
*
|
||||
* W. Eric Norum
|
||||
* Saskatchewan Accelerator Laboratory
|
||||
* University of Saskatchewan
|
||||
* Saskatoon, Saskatchewan, CANADA
|
||||
* eric@skatter.usask.ca
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <bsp.h>
|
||||
#include <rtems/m68k/m68360.h>
|
||||
|
||||
#define CLOCK_VECTOR 120
|
||||
#define CLOCK_IRQ_LEVEL 4
|
||||
|
||||
char M360DefaultWatchdogFeeder = 1;
|
||||
|
||||
/*
|
||||
* RTEMS and hardware have different notions of clock rate.
|
||||
*/
|
||||
static unsigned long rtems_nsec_per_tick;
|
||||
static unsigned long pit_nsec_per_tick;
|
||||
static unsigned long nsec;
|
||||
|
||||
/*
|
||||
* Periodic interval timer interrupt handler
|
||||
* See if it's really time for a `tick'
|
||||
* Perform a dummy read of DPRAM (work around bug in Rev. B of the 68360).
|
||||
* Feed the watchdog
|
||||
* Application code can override this by
|
||||
* setting M360DefaultWatchdogFeeder to zero.
|
||||
*/
|
||||
#define Clock_driver_support_at_tick() \
|
||||
do { \
|
||||
nsec += pit_nsec_per_tick; \
|
||||
if (nsec >= rtems_nsec_per_tick) \
|
||||
return; \
|
||||
nsec -= rtems_nsec_per_tick; \
|
||||
m360.dpram0[0]; \
|
||||
if (M360DefaultWatchdogFeeder) { \
|
||||
m360.swsr = 0x55; \
|
||||
m360.swsr = 0xAA; \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
/*
|
||||
* Attach clock interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_install_isr( _new ) \
|
||||
set_vector(_new, CLOCK_VECTOR, 1)
|
||||
|
||||
/*
|
||||
* Turn off the clock
|
||||
*/
|
||||
#define Clock_driver_support_shutdown_hardware() \
|
||||
do { \
|
||||
m360.pitr &= ~0xFF; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Set up the clock hardware
|
||||
* The rate at which the periodic interval timer
|
||||
* can generate interrupts is almost certainly not
|
||||
* the same as desired by the BSP configuration.
|
||||
* Handle the difference by choosing the largest PIT
|
||||
* interval which is less than or equal to the RTEMS
|
||||
* interval and skipping some hardware interrupts.
|
||||
* To reduce the jitter in the calls to RTEMS the
|
||||
* hardware interrupt interval is never greater than
|
||||
* the maximum non-prescaled value from the PIT.
|
||||
*
|
||||
* For a 25 MHz external clock the basic clock rate is
|
||||
* 40 nsec * 128 * 4 = 20.48 usec/tick
|
||||
*/
|
||||
extern int m360_clock_rate;
|
||||
|
||||
#define Clock_driver_support_initialize_hardware() \
|
||||
do { \
|
||||
unsigned int divisor; \
|
||||
unsigned long nsec_per_chip_tick = 1000000000 / m360_clock_rate; \
|
||||
unsigned long nsec_per_pit_tick = 512 * nsec_per_chip_tick; \
|
||||
rtems_nsec_per_tick = rtems_configuration_get_microseconds_per_tick() * 1000; \
|
||||
divisor = rtems_nsec_per_tick / nsec_per_pit_tick; \
|
||||
if (divisor > 255) \
|
||||
divisor = 255; \
|
||||
else if (divisor == 0) \
|
||||
divisor = 1; \
|
||||
pit_nsec_per_tick = nsec_per_pit_tick * divisor; \
|
||||
m360.pitr &= ~0x1FF; \
|
||||
m360.picr = (CLOCK_IRQ_LEVEL << 8) | CLOCK_VECTOR; \
|
||||
m360.pitr |= divisor; \
|
||||
} while (0)
|
||||
|
||||
#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
|
||||
|
||||
#include "../../../shared/dev/clock/clockimpl.h"
|
||||
102
bsps/m68k/genmcf548x/clock/clock.c
Normal file
102
bsps/m68k/genmcf548x/clock/clock.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/*===============================================================*\
|
||||
| Project: RTEMS generic mcf548x BSP |
|
||||
+-----------------------------------------------------------------+
|
||||
| File: clock.c |
|
||||
+-----------------------------------------------------------------+
|
||||
| The file contains the clock driver code of generic MCF548x BSP. |
|
||||
+-----------------------------------------------------------------+
|
||||
| Copyright (c) 2007 |
|
||||
| Embedded Brains GmbH |
|
||||
| Obere Lagerstr. 30 |
|
||||
| D-82178 Puchheim |
|
||||
| Germany |
|
||||
| rtems@embedded-brains.de |
|
||||
+-----------------------------------------------------------------+
|
||||
| |
|
||||
| Parts of the code has been derived from the "dBUG source code" |
|
||||
| package Freescale is providing for M548X EVBs. The usage of |
|
||||
| the modified or unmodified code and it's integration into the |
|
||||
| generic mcf548x BSP has been done according to the Freescale |
|
||||
| license terms. |
|
||||
| |
|
||||
| The Freescale license terms can be reviewed in the file |
|
||||
| |
|
||||
| Freescale_license.txt |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
| |
|
||||
| The generic mcf548x BSP has been developed on the basic |
|
||||
| structures and modules of the av5282 BSP. |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
| |
|
||||
| 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. |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
| |
|
||||
| date history ID |
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
||||
| 12.11.07 1.0 ras |
|
||||
| |
|
||||
\*===============================================================*/
|
||||
|
||||
/*
|
||||
* Use first slice timer (SLT0) as the system clock.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <bsp.h>
|
||||
#include <bsp/irq-generic.h>
|
||||
#include <mcf548x/mcf548x.h>
|
||||
|
||||
/*
|
||||
* Use SLT 0
|
||||
*/
|
||||
#define CLOCK_IRQ MCF548X_IRQ_SLT0
|
||||
|
||||
/*
|
||||
* Periodic interval timer interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_at_tick() \
|
||||
do { \
|
||||
MCF548X_SLT_SSR0 = MCF548X_SLT_SSR_ST; \
|
||||
} while (0) \
|
||||
|
||||
/*
|
||||
* Attach clock interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_install_isr( _new ) \
|
||||
set_vector(_new, CLOCK_IRQ + 64, 1)
|
||||
|
||||
/*
|
||||
* Turn off the clock
|
||||
*/
|
||||
#define Clock_driver_support_shutdown_hardware() \
|
||||
do { \
|
||||
MCF548X_SLT_SCR0 &= ~(MCF548X_SLT_SCR_TEN | MCF548X_SLT_SCR_RUN | MCF548X_SLT_SCR_IEN); \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Set up the clock hardware
|
||||
*
|
||||
* We need to have 1 interrupt every 10,000 microseconds
|
||||
* XLB clock 100 MHz / MCF548X_SLT_SLTCNT0 = XLB clock/100
|
||||
*/
|
||||
#define Clock_driver_support_initialize_hardware() \
|
||||
do { \
|
||||
bsp_interrupt_vector_enable(CLOCK_IRQ); \
|
||||
MCF548X_SLT_SLTCNT0 = get_CPU_clock_speed() \
|
||||
/ 1000 \
|
||||
* rtems_configuration_get_microseconds_per_tick() \
|
||||
/ 1000; \
|
||||
MCF548X_SLT_SCR0 |= (MCF548X_SLT_SCR_TEN | MCF548X_SLT_SCR_RUN | MCF548X_SLT_SCR_IEN); \
|
||||
} while (0)
|
||||
|
||||
#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
|
||||
|
||||
#include "../../../shared/dev/clock/clockimpl.h"
|
||||
|
||||
106
bsps/m68k/mcf52235/clock/clock.c
Normal file
106
bsps/m68k/mcf52235/clock/clock.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Use the last periodic interval timer (PIT2) as the system clock.
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/timecounter.h>
|
||||
#include <bsp.h>
|
||||
|
||||
/*
|
||||
* Use INTC0 base
|
||||
*/
|
||||
#define CLOCK_VECTOR (64+56)
|
||||
|
||||
static rtems_timecounter_simple mcf52235_tc;
|
||||
|
||||
static uint32_t mcf52235_tc_get(rtems_timecounter_simple *tc)
|
||||
{
|
||||
return MCF_PIT1_PCNTR;
|
||||
}
|
||||
|
||||
static bool mcf52235_tc_is_pending(rtems_timecounter_simple *tc)
|
||||
{
|
||||
return (MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF) != 0;
|
||||
}
|
||||
|
||||
static uint32_t mcf52235_tc_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
return rtems_timecounter_simple_downcounter_get(
|
||||
tc,
|
||||
mcf52235_tc_get,
|
||||
mcf52235_tc_is_pending
|
||||
);
|
||||
}
|
||||
|
||||
static void mcf52235_tc_at_tick(rtems_timecounter_simple *tc)
|
||||
{
|
||||
MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;
|
||||
}
|
||||
|
||||
static void mcf52235_tc_tick(void)
|
||||
{
|
||||
rtems_timecounter_simple_downcounter_tick(
|
||||
&mcf52235_tc,
|
||||
mcf52235_tc_get,
|
||||
mcf52235_tc_at_tick
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach clock interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_install_isr( _new ) \
|
||||
set_vector(_new, CLOCK_VECTOR, 1)
|
||||
|
||||
/*
|
||||
* Turn off the clock
|
||||
*/
|
||||
#define Clock_driver_support_shutdown_hardware() \
|
||||
do { \
|
||||
MCF_PIT1_PCSR &= ~MCF_PIT_PCSR_EN; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Set up the clock hardware
|
||||
*
|
||||
* We need to have 1 interrupt every rtems_configuration_get_microseconds_per_tick()
|
||||
*/
|
||||
static void Clock_driver_support_initialize_hardware(void)
|
||||
{
|
||||
int level;
|
||||
uint32_t pmr;
|
||||
uint32_t preScaleCode = 0;
|
||||
uint32_t clk = bsp_get_CPU_clock_speed() >> 1;
|
||||
uint32_t tps = 1000000 / rtems_configuration_get_microseconds_per_tick();
|
||||
|
||||
while (preScaleCode < 15) {
|
||||
pmr = (clk >> preScaleCode) / tps;
|
||||
if (pmr < (1 << 15))
|
||||
break;
|
||||
preScaleCode++;
|
||||
}
|
||||
|
||||
MCF_INTC0_ICR56 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL) |
|
||||
MCF_INTC_ICR_IP(PIT3_IRQ_PRIORITY);
|
||||
rtems_interrupt_disable(level);
|
||||
MCF_INTC0_IMRH &= ~MCF_INTC_IMRH_MASK56;
|
||||
MCF_PIT1_PCSR &= ~MCF_PIT_PCSR_EN;
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
|
||||
MCF_PIT_PCSR_OVW | MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD;
|
||||
MCF_PIT1_PMR = pmr;
|
||||
MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
|
||||
MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN;
|
||||
|
||||
rtems_timecounter_simple_install(
|
||||
&mcf52235_tc,
|
||||
clk >> preScaleCode,
|
||||
pmr,
|
||||
mcf52235_tc_get_timecount
|
||||
);
|
||||
}
|
||||
|
||||
#define Clock_driver_timecounter_tick() mcf52235_tc_tick()
|
||||
|
||||
#include "../../../shared/dev/clock/clockimpl.h"
|
||||
106
bsps/m68k/mcf5225x/clock/clock.c
Normal file
106
bsps/m68k/mcf5225x/clock/clock.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Use the last periodic interval timer (PIT2) as the system clock.
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/timecounter.h>
|
||||
#include <bsp.h>
|
||||
|
||||
/*
|
||||
* Use INTC0 base
|
||||
*/
|
||||
#define CLOCK_VECTOR (64+56)
|
||||
|
||||
static rtems_timecounter_simple mcf5225x_tc;
|
||||
|
||||
static uint32_t mcf5225x_tc_get(rtems_timecounter_simple *tc)
|
||||
{
|
||||
return MCF_PIT1_PCNTR;
|
||||
}
|
||||
|
||||
static bool mcf5225x_tc_is_pending(rtems_timecounter_simple *tc)
|
||||
{
|
||||
return (MCF_PIT1_PCSR & MCF_PIT_PCSR_PIF) != 0;
|
||||
}
|
||||
|
||||
static uint32_t mcf5225x_tc_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
return rtems_timecounter_simple_downcounter_get(
|
||||
tc,
|
||||
mcf5225x_tc_get,
|
||||
mcf5225x_tc_is_pending
|
||||
);
|
||||
}
|
||||
|
||||
static void mcf5225x_tc_at_tick(rtems_timecounter_simple *tc)
|
||||
{
|
||||
MCF_PIT1_PCSR |= MCF_PIT_PCSR_PIF;
|
||||
}
|
||||
|
||||
static void mcf5225x_tc_tick(void)
|
||||
{
|
||||
rtems_timecounter_simple_downcounter_tick(
|
||||
&mcf5225x_tc,
|
||||
mcf5225x_tc_get,
|
||||
mcf5225x_tc_at_tick
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach clock interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_install_isr( _new ) \
|
||||
set_vector(_new, CLOCK_VECTOR, 1)
|
||||
|
||||
/*
|
||||
* Turn off the clock
|
||||
*/
|
||||
#define Clock_driver_support_shutdown_hardware() \
|
||||
do { \
|
||||
MCF_PIT1_PCSR &= ~MCF_PIT_PCSR_EN; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Set up the clock hardware
|
||||
*
|
||||
* We need to have 1 interrupt every BSP_rtems_configuration_get_microseconds_per_tick()
|
||||
*/
|
||||
static void Clock_driver_support_initialize_hardware(void)
|
||||
{
|
||||
int level;
|
||||
uint32_t pmr;
|
||||
uint32_t preScaleCode = 0;
|
||||
uint32_t clk = bsp_get_CPU_clock_speed() >> 1;
|
||||
uint32_t tps = 1000000 / rtems_configuration_get_microseconds_per_tick();
|
||||
|
||||
while (preScaleCode < 15) {
|
||||
pmr = (clk >> preScaleCode) / tps;
|
||||
if (pmr < (1 << 15))
|
||||
break;
|
||||
preScaleCode++;
|
||||
}
|
||||
|
||||
MCF_INTC0_ICR56 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL) |
|
||||
MCF_INTC_ICR_IP(PIT3_IRQ_PRIORITY);
|
||||
rtems_interrupt_disable(level);
|
||||
MCF_INTC0_IMRH &= ~MCF_INTC_IMRH_MASK56;
|
||||
MCF_PIT1_PCSR &= ~MCF_PIT_PCSR_EN;
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
|
||||
MCF_PIT_PCSR_OVW | MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD;
|
||||
MCF_PIT1_PMR = pmr;
|
||||
MCF_PIT1_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
|
||||
MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN;
|
||||
|
||||
rtems_timecounter_simple_install(
|
||||
&mcf5225x_tc,
|
||||
clk >> preScaleCode,
|
||||
pmr,
|
||||
mcf5225x_tc_get_timecount
|
||||
);
|
||||
}
|
||||
|
||||
#define Clock_driver_timecounter_tick() mcf5225x_tc_tick()
|
||||
|
||||
#include "../../../shared/dev/clock/clockimpl.h"
|
||||
61
bsps/m68k/mcf5235/clock/clock.c
Normal file
61
bsps/m68k/mcf5235/clock/clock.c
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Use the last periodic interval timer (PIT3) as the system clock.
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <bsp.h>
|
||||
#include <mcf5235/mcf5235.h>
|
||||
|
||||
/*
|
||||
* Use INTC0 base
|
||||
*/
|
||||
#define CLOCK_VECTOR (64+39)
|
||||
|
||||
/*
|
||||
* Periodic interval timer interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_at_tick() \
|
||||
do { \
|
||||
MCF5235_PIT_PCSR3 |= MCF5235_PIT_PCSR_PIF; \
|
||||
} while (0) \
|
||||
|
||||
/*
|
||||
* Attach clock interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_install_isr( _new ) \
|
||||
set_vector(_new, CLOCK_VECTOR, 1)
|
||||
|
||||
/*
|
||||
* Turn off the clock
|
||||
*/
|
||||
#define Clock_driver_support_shutdown_hardware() \
|
||||
do { \
|
||||
MCF5235_PIT_PCSR3 &= ~MCF5235_PIT_PCSR_EN; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Set up the clock hardware
|
||||
*
|
||||
* We need to have 1 interrupt every 10,000 microseconds
|
||||
* so we need to set prescaler to 64 and the PMR register to 0x2DC6
|
||||
*/
|
||||
#define Clock_driver_support_initialize_hardware() \
|
||||
do { \
|
||||
int level; \
|
||||
int preScaleCode = 6; \
|
||||
MCF5235_INTC0_ICR39 = MCF5235_INTC_ICR_IL(PIT3_IRQ_LEVEL) | \
|
||||
MCF5235_INTC_ICR_IP(PIT3_IRQ_PRIORITY); \
|
||||
rtems_interrupt_disable( level ); \
|
||||
MCF5235_INTC0_IMRH &= ~MCF5235_INTC0_IMRH_INT39; \
|
||||
MCF5235_PIT_PCSR3 &= ~MCF5235_PIT_PCSR_EN; \
|
||||
rtems_interrupt_enable( level ); \
|
||||
MCF5235_PIT_PMR3 = 0x2DC6; \
|
||||
MCF5235_PIT_PCSR3 = MCF5235_PIT_PCSR_PRE(preScaleCode) | \
|
||||
MCF5235_PIT_PCSR_PIE | \
|
||||
MCF5235_PIT_PCSR_RLD | \
|
||||
MCF5235_PIT_PCSR_EN; \
|
||||
} while (0)
|
||||
|
||||
#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
|
||||
|
||||
#include "../../../shared/dev/clock/clockimpl.h"
|
||||
105
bsps/m68k/mcf5329/clock/clock.c
Normal file
105
bsps/m68k/mcf5329/clock/clock.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Use the last periodic interval timer (PIT2) as the system clock.
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/timecounter.h>
|
||||
#include <bsp.h>
|
||||
|
||||
/*
|
||||
* Use INTC1 base
|
||||
*/
|
||||
#define CLOCK_VECTOR (128+46)
|
||||
|
||||
static rtems_timecounter_simple mcf5329_tc;
|
||||
|
||||
static uint32_t mcf5329_tc_get(rtems_timecounter_simple *tc)
|
||||
{
|
||||
return MCF_PIT3_PCNTR;
|
||||
}
|
||||
|
||||
static bool mcf5329_tc_is_pending(rtems_timecounter_simple *tc)
|
||||
{
|
||||
return (MCF_PIT3_PCSR & MCF_PIT_PCSR_PIF) != 0;
|
||||
}
|
||||
|
||||
static uint32_t mcf5329_tc_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
return rtems_timecounter_simple_downcounter_get(
|
||||
tc,
|
||||
mcf5329_tc_get,
|
||||
mcf5329_tc_is_pending
|
||||
);
|
||||
}
|
||||
|
||||
static void mcf5329_tc_at_tick(rtems_timecounter_simple *tc)
|
||||
{
|
||||
MCF_PIT3_PCSR |= MCF_PIT_PCSR_PIF;
|
||||
}
|
||||
|
||||
static void mcf5329_tc_tick(void)
|
||||
{
|
||||
rtems_timecounter_simple_downcounter_tick(
|
||||
&mcf5329_tc,
|
||||
mcf5329_tc_get,
|
||||
mcf5329_tc_at_tick
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach clock interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_install_isr( _new ) \
|
||||
set_vector(_new, CLOCK_VECTOR, 1)
|
||||
|
||||
/*
|
||||
* Turn off the clock
|
||||
*/
|
||||
#define Clock_driver_support_shutdown_hardware() \
|
||||
do { \
|
||||
MCF_PIT3_PCSR &= ~MCF_PIT_PCSR_EN; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Set up the clock hardware
|
||||
*
|
||||
* We need to have 1 interrupt every rtems_configuration_get_microseconds_per_tick()
|
||||
*/
|
||||
static void Clock_driver_support_initialize_hardware(void)
|
||||
{
|
||||
int level;
|
||||
uint32_t pmr;
|
||||
uint32_t preScaleCode = 0;
|
||||
uint32_t clk = bsp_get_BUS_clock_speed();
|
||||
uint32_t tps = 1000000 / rtems_configuration_get_microseconds_per_tick();
|
||||
|
||||
while (preScaleCode < 15) {
|
||||
pmr = (clk >> preScaleCode) / tps;
|
||||
if (pmr < (1 << 15))
|
||||
break;
|
||||
preScaleCode++;
|
||||
}
|
||||
MCF_INTC1_ICR46 = MCF_INTC_ICR_IL(PIT3_IRQ_LEVEL);
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
MCF_INTC1_IMRH &= ~MCF_INTC_IMRH_INT_MASK46;
|
||||
MCF_PIT3_PCSR &= ~MCF_PIT_PCSR_EN;
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
MCF_PIT3_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
|
||||
MCF_PIT_PCSR_OVW | MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD;
|
||||
MCF_PIT3_PMR = pmr;
|
||||
MCF_PIT3_PCSR = MCF_PIT_PCSR_PRE(preScaleCode) |
|
||||
MCF_PIT_PCSR_PIE | MCF_PIT_PCSR_RLD | MCF_PIT_PCSR_EN;
|
||||
|
||||
rtems_timecounter_simple_install(
|
||||
&mcf5329_tc,
|
||||
clk >> preScaleCode,
|
||||
pmr,
|
||||
mcf5329_tc_get_timecount
|
||||
);
|
||||
}
|
||||
|
||||
#define Clock_driver_timecounter_tick() mcf5329_tc_tick()
|
||||
|
||||
#include "../../../shared/dev/clock/clockimpl.h"
|
||||
75
bsps/m68k/mrm332/clock/ckinit.c
Normal file
75
bsps/m68k/mrm332/clock/ckinit.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This routine initailizes the periodic interrupt timer on
|
||||
* the Motorola 68332.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <mrm332.h>
|
||||
#include <rtems/clockdrv.h>
|
||||
#include <rtems/m68k/sim.h>
|
||||
|
||||
#define CLOCK_VECTOR MRM_PIV
|
||||
|
||||
uint32_t Clock_isrs; /* ISRs until next tick */
|
||||
volatile uint32_t Clock_driver_ticks; /* ticks since initialization */
|
||||
static rtems_isr_entry Old_ticker;
|
||||
|
||||
void Clock_exit( void );
|
||||
|
||||
static rtems_isr Clock_isr(rtems_vector_number vector)
|
||||
{
|
||||
Clock_driver_ticks += 1;
|
||||
|
||||
if ( Clock_isrs == 1 ) {
|
||||
rtems_clock_tick();
|
||||
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
|
||||
}
|
||||
else
|
||||
Clock_isrs -= 1;
|
||||
}
|
||||
|
||||
static void Install_clock(rtems_isr_entry clock_isr)
|
||||
{
|
||||
Clock_driver_ticks = 0;
|
||||
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
|
||||
|
||||
Old_ticker = (rtems_isr_entry) set_vector( clock_isr, CLOCK_VECTOR, 1 );
|
||||
|
||||
/* enable 1mS interrupts */
|
||||
*PITR = (unsigned short int)( SAM(0x09,0,PITM) );/* load counter */
|
||||
*PICR = (unsigned short int) /* enable interrupt */
|
||||
( SAM(ISRL_PIT,8,PIRQL) | SAM(CLOCK_VECTOR,0,PIV) );
|
||||
|
||||
atexit( Clock_exit );
|
||||
}
|
||||
|
||||
void Clock_exit( void )
|
||||
{
|
||||
/* shutdown the periodic interrupt */
|
||||
*PICR = (unsigned short int)
|
||||
( SAM(0,8,PIRQL) | SAM(CLOCK_VECTOR,0,PIV) );
|
||||
/* ^^ zero disables interrupt */
|
||||
|
||||
/* do not restore old vector */
|
||||
}
|
||||
|
||||
rtems_device_driver Clock_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *pargp
|
||||
)
|
||||
{
|
||||
Install_clock( Clock_isr );
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
82
bsps/m68k/mvme147/clock/ckinit.c
Normal file
82
bsps/m68k/mvme147/clock/ckinit.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This routine initializes the Tick Timer 2 on the MVME147 board.
|
||||
* The tick frequency is 1 millisecond.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* MVME147 port for TNI - Telecom Bretagne
|
||||
* by Dominique LE CAMPION (Dominique.LECAMPION@enst-bretagne.fr)
|
||||
* May 1996
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <rtems/clockdrv.h>
|
||||
|
||||
#define MS_COUNT 65376 /* 1ms */
|
||||
/* MS_COUNT = 0x10000 - 1e-3/6.25e-6 */
|
||||
#define CLOCK_INT_LEVEL 6 /* T2's interrupt level */
|
||||
|
||||
uint32_t Clock_isrs; /* ISRs until next tick */
|
||||
volatile uint32_t Clock_driver_ticks; /* ticks since initialization */
|
||||
rtems_isr_entry Old_ticker;
|
||||
|
||||
void Clock_exit( void );
|
||||
|
||||
/*
|
||||
* ISR Handler
|
||||
*/
|
||||
static rtems_isr Clock_isr(rtems_vector_number vector)
|
||||
{
|
||||
Clock_driver_ticks += 1;
|
||||
pcc->timer2_int_control |= 0x80; /* Acknowledge interr. */
|
||||
|
||||
if (Clock_isrs == 1) {
|
||||
rtems_clock_tick();
|
||||
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
|
||||
}
|
||||
else
|
||||
Clock_isrs -= 1;
|
||||
}
|
||||
|
||||
static void Install_clock(rtems_isr_entry clock_isr )
|
||||
{
|
||||
|
||||
Clock_driver_ticks = 0;
|
||||
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
|
||||
|
||||
Old_ticker = (rtems_isr_entry) set_vector( clock_isr, TIMER_2_VECTOR, 1 );
|
||||
|
||||
pcc->timer2_int_control = 0x00; /* Disable T2 Interr. */
|
||||
pcc->timer2_preload = MS_COUNT;
|
||||
/* write preload value */
|
||||
pcc->timer2_control = 0x07; /* clear T2 overflow counter, enable counter */
|
||||
pcc->timer2_int_control = CLOCK_INT_LEVEL|0x08;
|
||||
/* Enable Timer 2 and set its int. level */
|
||||
|
||||
atexit( Clock_exit );
|
||||
}
|
||||
|
||||
void Clock_exit( void )
|
||||
{
|
||||
pcc->timer2_int_control = 0x00; /* Disable T2 Interr. */
|
||||
}
|
||||
|
||||
rtems_device_driver Clock_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *pargp
|
||||
)
|
||||
{
|
||||
Install_clock( Clock_isr );
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
89
bsps/m68k/mvme162/clock/ckinit.c
Normal file
89
bsps/m68k/mvme162/clock/ckinit.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* This routine initializes the Tick Timer 2 on the MVME162 board.
|
||||
* The tick frequency is 1 millisecond.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Modifications of respective RTEMS file: COPYRIGHT (c) 1994.
|
||||
* EISCAT Scientific Association. M.Savitski
|
||||
*
|
||||
* This material is a part of the MVME162 Board Support Package
|
||||
* for the RTEMS executive. Its licensing policies are those of the
|
||||
* RTEMS above.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <rtems/clockdrv.h>
|
||||
|
||||
#define MS_COUNT 1000 /* T2's countdown constant (1 ms) */
|
||||
#define CLOCK_INT_LEVEL 6 /* T2's interrupt level */
|
||||
|
||||
uint32_t Clock_isrs; /* ISRs until next tick */
|
||||
volatile uint32_t Clock_driver_ticks; /* ticks since initialization */
|
||||
rtems_isr_entry Old_ticker;
|
||||
|
||||
void Clock_exit( void );
|
||||
|
||||
#define CLOCK_VECTOR (VBR0 * 0x10 + 0x9)
|
||||
|
||||
/*
|
||||
* ISR Handler
|
||||
*/
|
||||
static rtems_isr Clock_isr(rtems_vector_number vector)
|
||||
{
|
||||
Clock_driver_ticks += 1;
|
||||
lcsr->timer_cnt_2 = 0; /* clear counter */
|
||||
lcsr->intr_clear |= 0x02000000;
|
||||
|
||||
if ( Clock_isrs == 1 ) {
|
||||
rtems_clock_tick();
|
||||
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
|
||||
}
|
||||
else
|
||||
Clock_isrs -= 1;
|
||||
}
|
||||
|
||||
static void Install_clock(rtems_isr_entry clock_isr )
|
||||
{
|
||||
|
||||
Clock_driver_ticks = 0;
|
||||
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
|
||||
|
||||
Old_ticker = (rtems_isr_entry) set_vector( clock_isr, CLOCK_VECTOR, 1 );
|
||||
lcsr->vector_base |= MASK_INT; /* unmask VMEchip2 interrupts */
|
||||
lcsr->to_ctl = 0xE7; /* prescaler to 1 MHz (see Appendix A1) */
|
||||
lcsr->timer_cmp_2 = MS_COUNT;
|
||||
lcsr->timer_cnt_2 = 0; /* clear counter */
|
||||
lcsr->board_ctl |= 0x700; /* increment, reset-on-compare, and */
|
||||
/* clear-overflow-cnt */
|
||||
|
||||
lcsr->intr_level[0] |= CLOCK_INT_LEVEL * 0x10; /* set int level */
|
||||
lcsr->intr_ena |= 0x02000000; /* enable tick timer 2 interrupt */
|
||||
|
||||
atexit( Clock_exit );
|
||||
}
|
||||
|
||||
void Clock_exit( void )
|
||||
{
|
||||
/* Dummy for now. See other m68k BSP's for code examples */
|
||||
}
|
||||
|
||||
rtems_device_driver Clock_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *pargp
|
||||
)
|
||||
{
|
||||
Install_clock( Clock_isr );
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
159
bsps/m68k/mvme167/clock/ckinit.c
Normal file
159
bsps/m68k/mvme167/clock/ckinit.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Implementation of the Clock_initialize() functions
|
||||
* prototyped in rtems/c/src/lib/include/clockdrv.h.
|
||||
*
|
||||
* This port does not allow the application to select which timer on the
|
||||
* MVME167 to use for the clock, nor does it allow the application to
|
||||
* configure the clock. The clock uses the VMEchip2 Tick Timer #2. This
|
||||
* timer is set up to raise a MC680x0 level-6 interrupt every 1 ms. The
|
||||
* interrupt vector is 0x69.
|
||||
*
|
||||
* All page references are to the MVME166/MVME167/MVME187 Single Board
|
||||
* Computer Programmer's Reference Guide (MVME187PG/D2) with the April
|
||||
* 1993 supplements/addenda (MVME187PG/D2A1).
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Modifications of respective RTEMS files:
|
||||
* Copyright (c) 1998, National Research Council of Canada
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <bsp.h>
|
||||
#include <rtems/clockdrv.h>
|
||||
|
||||
#define MS_COUNT 1000 /* T2's countdown constant (1 ms) */
|
||||
#define CLOCK_INT_LEVEL 6 /* T2's interrupt level */
|
||||
#define CLOCK_VECTOR (VBR0 * 0x10 + 0x9) /* T2 is vector $X9 (p. 2-71)*/
|
||||
|
||||
/*
|
||||
* Clock_driver_ticks is a monotonically increasing counter of the number of
|
||||
* VMEchip2 timer #2 ticks since the driver was initialized.
|
||||
*/
|
||||
volatile uint32_t Clock_driver_ticks;
|
||||
|
||||
/*
|
||||
* Clock_isrs is the number of clock ISRs until the next invocation of the
|
||||
* RTEMS clock tick routine. This clock tick device driver gets an interrupt
|
||||
* once a millisecond and counts down until the length of time between the
|
||||
* user configured microseconds per tick has passed. This allows the clock
|
||||
* device to "tick" faster than the kernel clock. Of course, the kernel clock
|
||||
* cannot tick faster than the hardware clock. Therefore, the kernel clock
|
||||
* ticks cannot occur more frequently than every 1 millisecond.
|
||||
*/
|
||||
uint32_t Clock_isrs;
|
||||
|
||||
/*
|
||||
* Records the previous clock ISR (should be NULL)
|
||||
*/
|
||||
rtems_isr_entry Old_ticker;
|
||||
|
||||
/*
|
||||
* Called when the kernel exits.
|
||||
*/
|
||||
void clock_exit( void );
|
||||
|
||||
/*
|
||||
* VMEchip2_T2_isr
|
||||
*
|
||||
* C ISR Handler. Increment the number of internal ticks. If it is time for a
|
||||
* kernel clock tick (if Clock_isrs == 1), call rtems_clock_tick() to signal
|
||||
* the event and reset the Clock_isrs counter; else, just decrement it.
|
||||
*/
|
||||
static rtems_isr VMEchip2_T2_isr(
|
||||
rtems_vector_number vector
|
||||
)
|
||||
{
|
||||
char overflow; /* Content of overflow counter */
|
||||
long i;
|
||||
long ct; /* Number of T2 ticks per RTEMS ticks */
|
||||
|
||||
ct = rtems_configuration_get_microseconds_per_tick() / 1000;
|
||||
|
||||
/*
|
||||
* May have missed interrupts, so should look at the overflow counter.
|
||||
*/
|
||||
lcsr->intr_clear |= 0x02000000; /* Clear the interrupt */
|
||||
overflow = (lcsr->board_ctl >> 12) & 0xF;
|
||||
lcsr->board_ctl |= 0x400; /* Reset overflow counter */
|
||||
|
||||
/* Attempt to protect against one more period */
|
||||
if ( overflow == 0 )
|
||||
overflow = 16;
|
||||
|
||||
Clock_driver_ticks += overflow; /* One or more internal ticks */
|
||||
|
||||
if ( Clock_isrs <= overflow ) {
|
||||
/* If its time for kernel clock ticks, signal the events to RTEMS */
|
||||
for( i = overflow - Clock_isrs; i >= 0; i -= ct ) {
|
||||
rtems_clock_tick();
|
||||
}
|
||||
/* Reset the counter */
|
||||
Clock_isrs = (uint32_t)-i;
|
||||
}
|
||||
else
|
||||
Clock_isrs -= overflow;
|
||||
}
|
||||
|
||||
/*
|
||||
* VMEchip2_T2_initialize
|
||||
*
|
||||
* Initialize the VMEchip2 Tick Timer #2.
|
||||
*
|
||||
* THE VMECHIP2 PRESCALER REGISTER IS ASSUMED TO BE SET!
|
||||
* The prescaler is used by all VMEchip2 timers, including the VMEbus grant
|
||||
* timeout counter, the DMAC time off timer, the DMAC timer on timer, and the
|
||||
* VMEbus global timeout timer. The prescaler value is normally set by the
|
||||
* boot ROM to provide a 1 MHz clock to the timers. For a 25 MHz MVME167, the
|
||||
* prescaler value should be 0xE7 (page 2-63).
|
||||
*/
|
||||
static void VMEchip2_T2_initialize( void )
|
||||
{
|
||||
Clock_driver_ticks = 0;
|
||||
Clock_isrs = rtems_configuration_get_microseconds_per_tick() / 1000;
|
||||
|
||||
lcsr->intr_ena &= 0xFDFFFFFF; /* Disable tick timer 2 interrupt */
|
||||
lcsr->intr_clear = 0x02000000; /* Clear tick timer 2 interrupt */
|
||||
lcsr->intr_level[0] = /* Set tick timer 2 interrupt level */
|
||||
(lcsr->intr_level[0] & 0xFFFFFF0F ) | (CLOCK_INT_LEVEL << 4);
|
||||
lcsr->timer_cmp_2 = MS_COUNT; /* Period in compare register */
|
||||
lcsr->timer_cnt_2 = 0; /* Clear tick timer 2 counter */
|
||||
Old_ticker = /* Install C ISR */
|
||||
(rtems_isr_entry) set_vector( VMEchip2_T2_isr, CLOCK_VECTOR, 1 );
|
||||
lcsr->board_ctl |= 0x700; /* Start tick timer 2, reset-on-compare, */
|
||||
/* and clear tick timer 2 overflow counter */
|
||||
lcsr->intr_ena |= 0x02000000; /* Enable tick timer 2 interrupt */
|
||||
lcsr->vector_base |= 0x00800000;/* Unmask VMEchip2 interrupts */
|
||||
atexit( clock_exit ); /* Turn off T2 interrupts when we exit */
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine stops the VMEchip2 T2 timer, disables its interrupt, and
|
||||
* re-install the old interrupt vectors.
|
||||
*/
|
||||
void clock_exit( void )
|
||||
{
|
||||
lcsr->board_ctl &= 0xFFFFFEFF; /* Stop tick timer 2 */
|
||||
lcsr->intr_ena &= 0xFDFFFFFF; /* Disable tick timer 2 interrupt */
|
||||
lcsr->intr_clear = 0x02000000; /* Clear tick timer 2 interrupt */
|
||||
|
||||
set_vector( Old_ticker, CLOCK_VECTOR, 1 );
|
||||
}
|
||||
|
||||
rtems_device_driver Clock_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *pargp
|
||||
)
|
||||
{
|
||||
VMEchip2_T2_initialize();
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
161
bsps/m68k/uC5282/clock/clock.c
Normal file
161
bsps/m68k/uC5282/clock/clock.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Use the last periodic interval timer (PIT3) as the system clock.
|
||||
*
|
||||
* Author: W. Eric Norum <norume@aps.anl.gov>
|
||||
*
|
||||
* COPYRIGHT (c) 2005.
|
||||
* 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.h>
|
||||
#include <rtems/timecounter.h>
|
||||
#include <bsp.h>
|
||||
#include <mcf5282/mcf5282.h>
|
||||
|
||||
/*
|
||||
* CPU load counters
|
||||
* Place in static RAM so updates don't hit the SDRAM
|
||||
*/
|
||||
#define IDLE_COUNTER __SRAMBASE.idle_counter
|
||||
#define FILTERED_IDLE __SRAMBASE.filtered_idle
|
||||
#define MAX_IDLE_COUNT __SRAMBASE.max_idle_count
|
||||
#define PITC_PER_TICK __SRAMBASE.pitc_per_tick
|
||||
#define NSEC_PER_PITC __SRAMBASE.nsec_per_pitc
|
||||
#define FILTER_SHIFT 6
|
||||
|
||||
/*
|
||||
* Use INTC0 base
|
||||
*/
|
||||
#define CLOCK_VECTOR (64+58)
|
||||
|
||||
static rtems_timecounter_simple uC5282_tc;
|
||||
|
||||
static uint32_t uC5282_tc_get(rtems_timecounter_simple *tc)
|
||||
{
|
||||
return MCF5282_PIT3_PCNTR;
|
||||
}
|
||||
|
||||
static bool uC5282_tc_is_pending(rtems_timecounter_simple *tc)
|
||||
{
|
||||
return (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF) != 0;
|
||||
}
|
||||
|
||||
static uint32_t uC5282_tc_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
return rtems_timecounter_simple_downcounter_get(
|
||||
tc,
|
||||
uC5282_tc_get,
|
||||
uC5282_tc_is_pending
|
||||
);
|
||||
}
|
||||
|
||||
static void uC5282_tc_at_tick(rtems_timecounter_simple *tc)
|
||||
{
|
||||
unsigned idle = IDLE_COUNTER;
|
||||
IDLE_COUNTER = 0;
|
||||
if (idle > MAX_IDLE_COUNT)
|
||||
MAX_IDLE_COUNT = idle;
|
||||
FILTERED_IDLE = idle + FILTERED_IDLE - (FILTERED_IDLE>>FILTER_SHIFT);
|
||||
MCF5282_PIT3_PCSR |= MCF5282_PIT_PCSR_PIF;
|
||||
}
|
||||
|
||||
static void uC5282_tc_tick(void)
|
||||
{
|
||||
rtems_timecounter_simple_downcounter_tick(
|
||||
&uC5282_tc,
|
||||
uC5282_tc_get,
|
||||
uC5282_tc_at_tick
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach clock interrupt handler
|
||||
*/
|
||||
#define Clock_driver_support_install_isr( _new ) \
|
||||
set_vector(_new, CLOCK_VECTOR, 1)
|
||||
|
||||
/*
|
||||
* Turn off the clock
|
||||
*/
|
||||
#define Clock_driver_support_shutdown_hardware() \
|
||||
do { \
|
||||
MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Set up the clock hardware
|
||||
*
|
||||
* f_pit = f_clk / 2^(preScaleCode+1) / N = 1/(us_per_tick/us_per_s)
|
||||
*
|
||||
* N = f_clk / 2^(preScaleCode+1) * us_per_tick / us_per_s
|
||||
*
|
||||
* ns_per_pit_clk = ns_per_s / (f_clk / 2^(preScaleCode+1))
|
||||
* = ns_per_s * 2^(preScaleCode+1) / f_clk;
|
||||
*/
|
||||
#define Clock_driver_support_initialize_hardware() \
|
||||
do { \
|
||||
unsigned long long N; \
|
||||
int level; \
|
||||
int preScaleCode = 0; \
|
||||
N = bsp_get_CPU_clock_speed(); \
|
||||
N *= rtems_configuration_get_microseconds_per_tick(); \
|
||||
N /= 2*1000000; /* min_prescale * us_per_s */ \
|
||||
while ( N > 0x10000 ) { \
|
||||
preScaleCode++; \
|
||||
N >>= 1; \
|
||||
} \
|
||||
PITC_PER_TICK = N; \
|
||||
N = 2000000000ULL << preScaleCode; \
|
||||
N /= bsp_get_CPU_clock_speed(); \
|
||||
NSEC_PER_PITC = N; \
|
||||
IDLE_COUNTER = 0; \
|
||||
FILTERED_IDLE = 0; \
|
||||
MAX_IDLE_COUNT = 0; \
|
||||
bsp_allocate_interrupt(PIT3_IRQ_LEVEL, PIT3_IRQ_PRIORITY); \
|
||||
MCF5282_INTC0_ICR58 = MCF5282_INTC_ICR_IL(PIT3_IRQ_LEVEL) | \
|
||||
MCF5282_INTC_ICR_IP(PIT3_IRQ_PRIORITY); \
|
||||
rtems_interrupt_disable( level ); \
|
||||
MCF5282_INTC0_IMRH &= ~MCF5282_INTC_IMRH_INT58; \
|
||||
MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN; \
|
||||
rtems_interrupt_enable( level ); \
|
||||
MCF5282_PIT3_PCSR = MCF5282_PIT_PCSR_PRE(preScaleCode) | \
|
||||
MCF5282_PIT_PCSR_OVW | \
|
||||
MCF5282_PIT_PCSR_PIE | \
|
||||
MCF5282_PIT_PCSR_RLD; \
|
||||
MCF5282_PIT3_PMR = PITC_PER_TICK - 1; \
|
||||
MCF5282_PIT3_PCSR = MCF5282_PIT_PCSR_PRE(preScaleCode) | \
|
||||
MCF5282_PIT_PCSR_PIE | \
|
||||
MCF5282_PIT_PCSR_RLD | \
|
||||
MCF5282_PIT_PCSR_EN; \
|
||||
rtems_timecounter_simple_install( \
|
||||
&uC5282_tc, \
|
||||
bsp_get_CPU_clock_speed() >> (preScaleCode + 1), \
|
||||
PITC_PER_TICK, \
|
||||
uC5282_tc_get_timecount \
|
||||
); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Provide our own version of the idle task
|
||||
*/
|
||||
void * bsp_idle_thread(uint32_t ignored)
|
||||
{
|
||||
/* Atomic increment */
|
||||
for(;;)
|
||||
__asm__ volatile ("addq.l #1,%0"::"m"(IDLE_COUNTER));
|
||||
}
|
||||
|
||||
int bsp_cpu_load_percentage(void)
|
||||
{
|
||||
return MAX_IDLE_COUNT ?
|
||||
(100 - ((100 * (FILTERED_IDLE >> FILTER_SHIFT)) / MAX_IDLE_COUNT)) :
|
||||
0;
|
||||
}
|
||||
|
||||
#define Clock_driver_timecounter_tick() uC5282_tc_tick()
|
||||
|
||||
#include "../../../shared/dev/clock/clockimpl.h"
|
||||
Reference in New Issue
Block a user