source: rtems/c/src/lib/libbsp/m68k/uC5282/clock/clock.c @ 76ac1ee3

5
Last change on this file since 76ac1ee3 was 76ac1ee3, checked in by Sebastian Huber <sebastian.huber@…>, on 12/23/15 at 06:29:47

score: Fix simple timecounter support

Update #2502.

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Use the last periodic interval timer (PIT3) as the system clock.
3 *
4 *  Author: W. Eric Norum <norume@aps.anl.gov>
5 *
6 *  COPYRIGHT (c) 2005.
7 *  On-Line Applications Research Corporation (OAR).
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.rtems.org/license/LICENSE.
12 */
13
14#include <rtems.h>
15#include <rtems/timecounter.h>
16#include <bsp.h>
17#include <mcf5282/mcf5282.h>
18
19/*
20 * CPU load counters
21 * Place in static RAM so updates don't hit the SDRAM
22 */
23#define IDLE_COUNTER    __SRAMBASE.idle_counter
24#define FILTERED_IDLE   __SRAMBASE.filtered_idle
25#define MAX_IDLE_COUNT  __SRAMBASE.max_idle_count
26#define PITC_PER_TICK   __SRAMBASE.pitc_per_tick
27#define NSEC_PER_PITC   __SRAMBASE.nsec_per_pitc
28#define FILTER_SHIFT    6
29
30/*
31 * Use INTC0 base
32 */
33#define CLOCK_VECTOR (64+58)
34
35static rtems_timecounter_simple uC5282_tc;
36
37static uint32_t uC5282_tc_get(rtems_timecounter_simple *tc)
38{
39  return MCF5282_PIT3_PCNTR;
40}
41
42static bool uC5282_tc_is_pending(rtems_timecounter_simple *tc)
43{
44  return (MCF5282_PIT3_PCSR & MCF5282_PIT_PCSR_PIF) != 0;
45}
46
47static uint32_t uC5282_tc_get_timecount(struct timecounter *tc)
48{
49  return rtems_timecounter_simple_downcounter_get(
50    tc,
51    uC5282_tc_get,
52    uC5282_tc_is_pending
53  );
54}
55
56static void uC5282_tc_at_tick(rtems_timecounter_simple *tc)
57{
58  unsigned idle = IDLE_COUNTER;
59  IDLE_COUNTER = 0;
60  if (idle > MAX_IDLE_COUNT)
61    MAX_IDLE_COUNT = idle;
62  FILTERED_IDLE = idle + FILTERED_IDLE - (FILTERED_IDLE>>FILTER_SHIFT);
63  MCF5282_PIT3_PCSR |= MCF5282_PIT_PCSR_PIF;
64}
65
66static void uC5282_tc_tick(void)
67{
68  rtems_timecounter_simple_downcounter_tick(
69    &uC5282_tc,
70    uC5282_tc_get,
71    uC5282_tc_at_tick
72  );
73}
74
75/*
76 * Attach clock interrupt handler
77 */
78#define Clock_driver_support_install_isr( _new, _old )              \
79    do {                                                            \
80        _old = (rtems_isr_entry)set_vector(_new, CLOCK_VECTOR, 1);  \
81    } while(0)
82
83/*
84 * Turn off the clock
85 */
86#define Clock_driver_support_shutdown_hardware()   \
87    do {                                           \
88        MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN; \
89    } while(0)
90
91/*
92 * Set up the clock hardware
93 *
94 * f_pit = f_clk / 2^(preScaleCode+1) / N  = 1/(us_per_tick/us_per_s)
95 *
96 * N = f_clk / 2^(preScaleCode+1) * us_per_tick / us_per_s
97 *
98 * ns_per_pit_clk = ns_per_s / (f_clk / 2^(preScaleCode+1))
99 *                = ns_per_s * 2^(preScaleCode+1) / f_clk;
100 */
101#define Clock_driver_support_initialize_hardware()                       \
102    do {                                                                 \
103        unsigned long long N;                                            \
104        int level;                                                       \
105        int preScaleCode = 0;                                            \
106                N  = bsp_get_CPU_clock_speed();                                  \
107                N *= rtems_configuration_get_microseconds_per_tick();            \
108                N /= 2*1000000; /* min_prescale * us_per_s */                    \
109                while ( N > 0x10000 ) {                                          \
110                        preScaleCode++;                                              \
111                        N >>= 1;                                                     \
112                }                                                                \
113                PITC_PER_TICK  = N;                                              \
114                N  = 2000000000ULL << preScaleCode;                              \
115                N /= bsp_get_CPU_clock_speed();                                  \
116                NSEC_PER_PITC  = N;                                              \
117        IDLE_COUNTER   = 0;                                              \
118        FILTERED_IDLE  = 0;                                              \
119        MAX_IDLE_COUNT = 0;                                              \
120        bsp_allocate_interrupt(PIT3_IRQ_LEVEL, PIT3_IRQ_PRIORITY);       \
121        MCF5282_INTC0_ICR58 = MCF5282_INTC_ICR_IL(PIT3_IRQ_LEVEL) |      \
122                              MCF5282_INTC_ICR_IP(PIT3_IRQ_PRIORITY);    \
123        rtems_interrupt_disable( level );                                \
124        MCF5282_INTC0_IMRH &= ~MCF5282_INTC_IMRH_INT58;                  \
125        MCF5282_PIT3_PCSR &= ~MCF5282_PIT_PCSR_EN;                       \
126        rtems_interrupt_enable( level );                                 \
127        MCF5282_PIT3_PCSR = MCF5282_PIT_PCSR_PRE(preScaleCode) |         \
128                            MCF5282_PIT_PCSR_OVW |                       \
129                            MCF5282_PIT_PCSR_PIE |                       \
130                            MCF5282_PIT_PCSR_RLD;                        \
131        MCF5282_PIT3_PMR = PITC_PER_TICK - 1;                            \
132        MCF5282_PIT3_PCSR = MCF5282_PIT_PCSR_PRE(preScaleCode) |         \
133                            MCF5282_PIT_PCSR_PIE |                       \
134                            MCF5282_PIT_PCSR_RLD |                       \
135                            MCF5282_PIT_PCSR_EN;                         \
136         rtems_timecounter_simple_install( \
137           &uC5282_tc, \
138           bsp_get_CPU_clock_speed() >> (preScaleCode + 1), \
139           PITC_PER_TICK, \
140           uC5282_tc_get_timecount \
141         ); \
142    } while (0)
143
144/*
145 * Provide our own version of the idle task
146 */
147Thread bsp_idle_thread(uint32_t ignored)
148{
149  /* Atomic increment */
150  for(;;)
151    __asm__ volatile ("addq.l #1,%0"::"m"(IDLE_COUNTER));
152}
153
154int bsp_cpu_load_percentage(void)
155{
156    return MAX_IDLE_COUNT ?
157           (100 - ((100 * (FILTERED_IDLE >> FILTER_SHIFT)) / MAX_IDLE_COUNT)) :
158           0;
159}
160
161#define Clock_driver_timecounter_tick() uC5282_tc_tick()
162
163#include "../../../shared/clockdrv_shell.h"
Note: See TracBrowser for help on using the repository browser.