bsps: Convert clock drivers to use a timecounter

Update #2271.
This commit is contained in:
Alexander Krutwig
2015-04-01 15:33:25 +02:00
committed by Sebastian Huber
parent 7cd2484c4c
commit 75acd9e69f
48 changed files with 689 additions and 644 deletions

View File

@@ -22,8 +22,6 @@
#include <at91rm9200.h>
#include <at91rm9200_pmc.h>
static unsigned long st_pimr_reload;
/**
* Enables clock interrupt.
*
@@ -77,17 +75,16 @@ rtems_irq_connect_data clock_isr_data = {
BSP_install_rtems_irq_handler(&clock_isr_data); \
} while(0)
uint16_t st_pimr_value;
static void Clock_driver_support_initialize_hardware(void)
{
uint32_t st_str;
int slck;
unsigned long value;
/* the system timer is driven from SLCK */
slck = at91rm9200_get_slck();
st_pimr_value = (((rtems_configuration_get_microseconds_per_tick() * slck) +
value = (((rtems_configuration_get_microseconds_per_tick() * slck) +
(1000000/2))/ 1000000);
st_pimr_reload = st_pimr_value;
/* read the status to clear the int */
st_str = ST_REG(ST_SR);
@@ -97,21 +94,9 @@ static void Clock_driver_support_initialize_hardware(void)
AIC_SMR_REG(AIC_SMR_SYSIRQ) = AIC_SMR_PRIOR(0x7);
/* set the timer value */
ST_REG(ST_PIMR) = st_pimr_reload;
ST_REG(ST_PIMR) = value;
}
static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
{
uint16_t slck_counts;
slck_counts = st_pimr_value - st_pimr_reload;
return (rtems_configuration_get_microseconds_per_tick() * slck_counts * 1000)
/ st_pimr_value;
}
#define Clock_driver_nanoseconds_since_last_tick \
bsp_clock_nanoseconds_since_last_tick
#define Clock_driver_support_at_tick() \
do { \
uint32_t st_str; \
@@ -126,4 +111,6 @@ static void Clock_driver_support_shutdown_hardware( void )
BSP_remove_rtems_irq_handler(&clock_isr_data);
}
#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
#include "../../../../libbsp/shared/clockdrv_shell.h"

View File

@@ -17,12 +17,39 @@
#include <bsp/irq.h>
#include <lpc22xx.h>
#include <rtems/bspIo.h> /* for printk */
#include <rtems/timecounter.h>
void Clock_isr(rtems_irq_hdl_param arg);
static void clock_isr_on(const rtems_irq_connect_data *unused);
static void clock_isr_off(const rtems_irq_connect_data *unused);
static int clock_isr_is_on(const rtems_irq_connect_data *irq);
static rtems_timecounter_simple lpc22xx_tc;
static uint32_t lpc22xx_tc_get(rtems_timecounter_simple *tc)
{
return T0TC;
}
static bool lpc22xx_tc_is_pending(rtems_timecounter_simple *tc)
{
return (T0IR & 0x1) != 0;
}
static uint32_t lpc22xx_tc_get_timecount(struct timecounter *tc)
{
return rtems_timecounter_simple_upcounter_get(
tc,
lpc22xx_tc_get,
lpc22xx_tc_is_pending
);
}
static void lpc22xx_tc_tick(void)
{
rtems_timecounter_simple_upcounter_tick(&lpc22xx_tc, lpc22xx_tc_get);
}
/* Replace the first value with the clock's interrupt name. */
rtems_irq_connect_data clock_isr_data = {
.name = LPC22xx_INTERRUPT_TIMER0,
@@ -74,9 +101,10 @@ rtems_irq_connect_data clock_isr_data = {
*/
#define Clock_driver_support_initialize_hardware() \
do { \
uint32_t mask; \
/* disable and clear timer 0, set to */ \
T0TCR &= 0; \
/* TC is incrementet on every pclk.*/ \
/* TC is incremented on every pclk.*/ \
T0PC = 0; \
/* initialize the timer period and prescaler */ \
T0MR0 = ((LPC22xx_Fpclk/1000 * \
@@ -89,6 +117,13 @@ rtems_irq_connect_data clock_isr_data = {
T0TCR = 1; \
/* enable interrupt, skyeye will check this*/ \
T0IR |= 0x01; \
/* install timecounter */ \
rtems_timecounter_simple_install( \
&lpc22xx_tc, \
LPC22xx_Fpclk, \
T0MR0, \
lpc22xx_tc_get_timecount \
); \
} while (0)
/**
@@ -104,20 +139,6 @@ rtems_irq_connect_data clock_isr_data = {
BSP_remove_rtems_irq_handler(&clock_isr_data); \
} while (0)
static uint32_t bsp_clock_nanoseconds_since_last_tick(void)
{
uint32_t clicks;
uint32_t microseconds;
clicks = T0TC; /* T0TC is the 32bit time counter 0 */
microseconds = (rtems_configuration_get_microseconds_per_tick() - clicks);
return microseconds * 1000;
}
#define Clock_driver_nanoseconds_since_last_tick \
bsp_clock_nanoseconds_since_last_tick
/**
* Enables clock interrupt.
*
@@ -149,6 +170,8 @@ static int clock_isr_is_on(const rtems_irq_connect_data *irq)
return T0IR & 0x01; /* MR0 mask */
}
#define Clock_driver_timecounter_tick() lpc22xx_tc_tick()
/* Make sure to include this, and only at the end of the file */
#include "../../../../libbsp/shared/clockdrv_shell.h"

View File

@@ -130,5 +130,8 @@ static int clock_isr_is_on(const rtems_irq_connect_data *irq)
return MC9328MXL_TMR1_TCTL & MC9328MXL_TMR_TCTL_IRQEN;
}
#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
/* Make sure to include this, and only at the end of the file */
#include "../../../../libbsp/shared/clockdrv_shell.h"

View File

@@ -116,4 +116,6 @@ static void Clock_driver_support_shutdown_hardware( void )
BSP_remove_rtems_irq_handler(&clock_isr_data);
}
#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
#include "../../../../libbsp/shared/clockdrv_shell.h"

View File

@@ -27,17 +27,6 @@ rtems_irq_connect_data clock_isr_data = {
.isOn = clock_isr_is_on,
};
/**
* Return the nanoseconds since last tick
*/
static uint32_t clock_driver_get_nanoseconds_since_last_tick(void)
{
return 0;
}
#define Clock_driver_nanoseconds_since_last_tick \
clock_driver_get_nanoseconds_since_last_tick
/**
* When we get the clock interrupt
* - clear the interrupt bit?
@@ -74,6 +63,7 @@ static uint32_t clock_driver_get_nanoseconds_since_last_tick(void)
do { \
uint32_t cr; \
uint32_t freq; \
uint32_t mask; \
/* set MUX for Timer4 to 1/16 */ \
cr=rTCFG1 & 0xFFF0FFFF; \
rTCFG1=(cr | (3<<16)); \
@@ -131,5 +121,7 @@ static int clock_isr_is_on(const rtems_irq_connect_data *irq)
return 1;
}
#define CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER
/* Make sure to include this, and only at the end of the file */
#include "../../../../libbsp/shared/clockdrv_shell.h"

View File

@@ -29,6 +29,7 @@
#include <libcpu/spr.h>
#include <rtems/bspIo.h> /* for printk() */
#include <libcpu/powerpc-utility.h>
#include <rtems/timecounter.h>
#include <bspopts.h> /* for CLOCK_DRIVER_USE_FAST_IDLE */
@@ -48,11 +49,12 @@ volatile uint32_t Clock_driver_ticks;
*/
static uint32_t Clock_Decrementer_value;
/*
* This is the value by which elapsed count down timer ticks are multiplied to
* give an elapsed duration in nanoseconds, left-shifted by 32 bits
*/
static uint64_t Clock_Decrementer_reference;
static struct timecounter Clock_TC;
static uint32_t Clock_Get_timecount(struct timecounter *tc)
{
return ppc_time_base();
}
void clockOff(void* unused)
{
@@ -94,16 +96,27 @@ void clockOn(void* unused)
static void clockHandler(void)
{
#if (CLOCK_DRIVER_USE_FAST_IDLE == 1)
do {
rtems_clock_tick();
} while (
rtems_interrupt_level level;
uint32_t tb;
rtems_interrupt_disable(level);
tb = ppc_time_base();
rtems_timecounter_tick();
while (
_Thread_Heir == _Thread_Executing
&& _Thread_Executing->Start.entry_point
== (Thread_Entry) rtems_configuration_get_idle_task()
);
) {
tb += Clock_Decrementer_value;
ppc_set_time_base( tb );
rtems_timecounter_tick();
}
rtems_interrupt_enable(level);
#else
rtems_clock_tick();
rtems_timecounter_tick();
#endif
}
@@ -141,7 +154,6 @@ void clockIsr(void *unused)
rtems_interrupt_enable(flags);
Clock_driver_ticks += 1;
/*
* Real Time Clock counter/timer is set to automatically reload.
*/
@@ -187,7 +199,6 @@ int clockIsOn(void* unused)
return 0;
}
/*
* Clock_exit
*
@@ -199,53 +210,6 @@ void Clock_exit( void )
(void) BSP_disconnect_clock_handler ();
}
static uint32_t Clock_driver_nanoseconds_since_last_tick(void)
{
uint32_t clicks, tmp;
PPC_Get_decrementer( clicks );
/*
* Multiply by 1000 here separately from below so we do not overflow
* and get a negative value.
*/
tmp = (Clock_Decrementer_value - clicks) * 1000;
tmp /= (BSP_bus_frequency/BSP_time_base_divisor);
return tmp * 1000;
}
static uint32_t Clock_driver_nanoseconds_since_last_tick_bookE(void)
{
uint32_t clicks;
uint64_t c;
PPC_Get_decrementer( clicks );
c = Clock_Decrementer_value - clicks;
/*
* Check whether a clock tick interrupt is pending and hence that the
* decrementer's wrapped. If it has, we'll compensate by returning a time one
* tick period longer.
*
* We have to check interrupt status after reading the decrementer. If we
* don't, we may miss an interrupt and read a wrapped decrementer value
* without compensating for it
*/
if ( _read_BOOKE_TSR() & BOOKE_TSR_DIS )
{
/*
* Re-read the decrementer: The tick interrupt may have been
* generated and the decrementer wrapped during the time since we
* last read it and the time we checked the interrupt status
*/
PPC_Get_decrementer( clicks );
c = (Clock_Decrementer_value - clicks) + Clock_Decrementer_value;
}
return (uint32_t)((c * Clock_Decrementer_reference) >> 32);
}
/*
* Clock_initialize
*
@@ -262,9 +226,6 @@ rtems_device_driver Clock_initialize(
Clock_Decrementer_value = (BSP_bus_frequency/BSP_time_base_divisor)*
rtems_configuration_get_milliseconds_per_tick();
Clock_Decrementer_reference = ((uint64_t)1000000U<<32)/
(BSP_bus_frequency/BSP_time_base_divisor);
/* set the decrementer now, prior to installing the handler
* so no interrupts will happen in a while.
*/
@@ -283,23 +244,13 @@ rtems_device_driver Clock_initialize(
_write_BOOKE_TCR(tcr);
rtems_interrupt_enable(l);
}
/*
* Set the nanoseconds since last tick handler
*/
rtems_clock_set_nanoseconds_extension(
Clock_driver_nanoseconds_since_last_tick_bookE
);
}
else
{
/*
* Set the nanoseconds since last tick handler
*/
rtems_clock_set_nanoseconds_extension(
Clock_driver_nanoseconds_since_last_tick
);
}
Clock_TC.tc_get_timecount = Clock_Get_timecount;
Clock_TC.tc_counter_mask = 0xffffffff;
Clock_TC.tc_frequency = (1000 * BSP_bus_frequency) / BSP_time_base_divisor;
Clock_TC.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
rtems_timecounter_install(&Clock_TC);
/*
* If a decrementer exception was pending, it is cleared by