[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