[PATCH 4/7] generic_or1k BSP clock driver correction
Jakob Viketoft
jakob.viketoft at aacmicrotec.com
Fri Feb 19 09:12:07 UTC 2016
diff --git a/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c b/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c
index e01d2e5..2dc914a 100644
--- a/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c
+++ b/c/src/lib/libbsp/or1k/generic_or1k/clock/clockdrv.c
@@ -3,13 +3,15 @@
*
* @ingroup bsp_clock
*
- * @brief or1k clock support.
+ * @brief generic_or1k clock support.
*/
/*
* generic_or1k Clock driver
*
* COPYRIGHT (c) 2014-2015 Hesham ALMatary <heshamelmatary at gmail.com>
+ * Copyright (c) 2014-2016 ÅAC Microtec AB <www.aacmicrotec.com>
+ * Jakob Viketoft <jakob.viketoft at aacmicrotec.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -25,35 +27,30 @@
#include <rtems/timecounter.h>
/* The number of clock cycles before generating a tick timer interrupt. */
-#define TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT 0x09ED9
-#define OR1K_CLOCK_CYCLE_TIME_NANOSECONDS 10
+#define OR1K_CLOCK_CYCLE_TIME_NANOSECONDS (1000000000 / OR1K_BSP_CLOCK_FREQ)
-static struct timecounter or1ksim_tc;
-
-/* CPU counter */
+static struct timecounter generic_or1k_tc;
static CPU_Counter_ticks cpu_counter_ticks;
+static uint32_t timer_counts_per_clock_tick;
-/* This prototype is added here to Avoid warnings */
+/* These prototypes are added here to avoid warnings */
void Clock_isr(void *arg);
+static uint32_t generic_or1k_get_timecount(struct timecounter *tc);
static void generic_or1k_clock_at_tick(void)
{
- uint32_t TTMR;
+ uint32_t ttmr;
- /* For TTMR register,
- * The least significant 28 bits are the number of clock cycles
- * before generating a tick timer interrupt. While the most
- * significant 4 bits are used for mode configuration, tick timer
- * interrupt enable and pending interrupts status.
- */
- TTMR = (CPU_OR1K_SPR_TTMR_MODE_RESTART | CPU_OR1K_SPR_TTMR_IE |
- (TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT & CPU_OR1K_SPR_TTMR_TP_MASK)
- ) & ~(CPU_OR1K_SPR_TTMR_IP);
+ /* Get TTMR value */
+ ttmr = _OR1K_mfspr(CPU_OR1K_SPR_TTMR);
- _OR1K_mtspr(CPU_OR1K_SPR_TTMR, TTMR);
- _OR1K_mtspr(CPU_OR1K_SPR_TTCR, 0);
+ /* Clear interrupt */
+ ttmr &= ~(CPU_OR1K_SPR_TTMR_IP);
- cpu_counter_ticks += TTMR_NUM_OF_CLOCK_TICKS_INTERRUPT;
+ /* Write it back */
+ _OR1K_mtspr(CPU_OR1K_SPR_TTMR, ttmr);
+
+ cpu_counter_ticks += timer_counts_per_clock_tick;
}
static void generic_or1k_clock_handler_install(
@@ -61,35 +58,19 @@ static void generic_or1k_clock_handler_install(
proc_ptr old_isr
)
{
- rtems_status_code sc = RTEMS_SUCCESSFUL;
old_isr = NULL;
_CPU_ISR_install_vector(OR1K_EXCEPTION_TICK_TIMER,
new_isr,
old_isr);
-
- if (sc != RTEMS_SUCCESSFUL) {
- rtems_fatal_error_occurred(0xdeadbeef);
- }
-}
-
-static uint32_t or1ksim_get_timecount(struct timecounter *tc)
-{
- uint32_t ticks_since_last_timer_interrupt;
-
- ticks_since_last_timer_interrupt = _OR1K_mfspr(CPU_OR1K_SPR_TTCR);
-
- return cpu_counter_ticks + ticks_since_last_timer_interrupt;
-}
-
-CPU_Counter_ticks _CPU_Counter_read(void)
-{
- return or1ksim_get_timecount(NULL);
}
static void generic_or1k_clock_initialize(void)
{
- uint64_t frequency = (1000000000 / OR1K_CLOCK_CYCLE_TIME_NANOSECONDS);
- uint32_t TTMR;
+ uint32_t ttmr;
+
+ /* Calculate timer value for given time per clock tick */
+ timer_counts_per_clock_tick = (1000 * rtems_configuration_get_microseconds_per_tick()) /
+ OR1K_CLOCK_CYCLE_TIME_NANOSECONDS;
/* For TTMR register,
* The least significant 28 bits are the number of clock cycles
@@ -101,36 +82,52 @@ static void generic_or1k_clock_initialize(void)
/* FIXME: Long interval should pass since initializing the tick timer
* registers fires exceptions dispite interrupts has not been enabled yet.
*/
- TTMR = (CPU_OR1K_SPR_TTMR_MODE_RESTART | CPU_OR1K_SPR_TTMR_IE |
- (0xFFED9 & CPU_OR1K_SPR_TTMR_TP_MASK)
- ) & ~(CPU_OR1K_SPR_TTMR_IP);
+ ttmr = (CPU_OR1K_SPR_TTMR_MODE_RESTART | CPU_OR1K_SPR_TTMR_IE |
+ (timer_counts_per_clock_tick & CPU_OR1K_SPR_TTMR_TP_MASK)) &
+ ~(CPU_OR1K_SPR_TTMR_IP);
- _OR1K_mtspr(CPU_OR1K_SPR_TTMR, TTMR);
+ _OR1K_mtspr(CPU_OR1K_SPR_TTMR, ttmr);
_OR1K_mtspr(CPU_OR1K_SPR_TTCR, 0);
+ /* Initialize CPU Counter */
+ cpu_counter_ticks = 0;
+
/* Initialize timecounter */
- or1ksim_tc.tc_get_timecount = or1ksim_get_timecount;
- or1ksim_tc.tc_counter_mask = 0xffffffff;
- or1ksim_tc.tc_frequency = frequency;
- or1ksim_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
- rtems_timecounter_install(&or1ksim_tc);
+ generic_or1k_tc.tc_get_timecount = generic_or1k_get_timecount;
+ generic_or1k_tc.tc_counter_mask = 0xffffffff;
+ generic_or1k_tc.tc_frequency = OR1K_BSP_CLOCK_FREQ;
+ generic_or1k_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ rtems_timecounter_install(&generic_or1k_tc);
}
static void generic_or1k_clock_cleanup(void)
{
- uint32_t sr;
+ uint32_t sr;
sr = _OR1K_mfspr(CPU_OR1K_SPR_SR);
/* Disable tick timer exceptions */
- _OR1K_mtspr(CPU_OR1K_SPR_SR, (sr & ~CPU_OR1K_SPR_SR_IEE)
- & ~CPU_OR1K_SPR_SR_TEE);
+ _OR1K_mtspr(CPU_OR1K_SPR_SR, sr & ~CPU_OR1K_SPR_SR_TEE);
/* Invalidate tick timer config registers */
_OR1K_mtspr(CPU_OR1K_SPR_TTCR, 0);
_OR1K_mtspr(CPU_OR1K_SPR_TTMR, 0);
}
+static uint32_t generic_or1k_get_timecount(struct timecounter *tc)
+{
+ uint32_t counts_since_last_timer_interrupt;
+
+ counts_since_last_timer_interrupt = _OR1K_mfspr(CPU_OR1K_SPR_TTCR);
+
+ return cpu_counter_ticks + counts_since_last_timer_interrupt;
+}
+
+CPU_Counter_ticks _CPU_Counter_read(void)
+{
+ return generic_or1k_get_timecount(NULL);
+}
+
CPU_Counter_ticks _CPU_Counter_difference(
CPU_Counter_ticks second,
CPU_Counter_ticks first
@@ -146,7 +143,7 @@ CPU_Counter_ticks _CPU_Counter_difference(
#define Clock_driver_support_install_isr(isr, old_isr) \
do { \
old_isr = NULL; \
- generic_or1k_clock_handler_install(isr, old_isr); \
+ generic_or1k_clock_handler_install(isr, old_isr); \
} while (0)
#define Clock_driver_support_shutdown_hardware() generic_or1k_clock_cleanup()
Jakob Viketoft
Senior Engineer in RTL and embedded software
ÅAC Microtec AB
Dag Hammarskjölds väg 48
SE-751 83 Uppsala, Sweden
T: +46 702 80 95 97
http://www.aacmicrotec.com
More information about the devel
mailing list