source: rtems/c/src/lib/libcpu/arm/at91rm9200/clock/clock.c @ 2ba4b72

4.104.114.84.95
Last change on this file since 2ba4b72 was 75bf564, checked in by Joel Sherrill <joel.sherrill@…>, on 03/07/06 at 21:05:28

2006-03-07 Lars Munch <lars@…>

  • at91rm9200/clock/clock.c: The clock tick is not very precise on at91rm9200. The attached patch improves the situation by: (1) Not reloading the "period interval timer" register in the

interrupt handler since this is done automatically.

(2) Use integer rounding in the calculation of the "period interval

timer" register value to get as close as posible to the
CONFIGURE_MICROSECONDS_PER_TICK value.

  • Property mode set to 100644
File size: 4.0 KB
Line 
1/*
2 *  AT91RM9200 clock specific using the System Timer
3 *
4 *  Copyright (c) 2003 by Cogent Computer Systems
5 *  Written by Mike Kelly <mike@cogcomp.com>
6 *         and Jay Monkman <jtm@lopingdog.com>
7 *
8 *  The license and distribution terms for this file may be
9 *  found in the file LICENSE in this distribution or at
10 *
11 *  http://www.OARcorp.com/rtems/license.html.
12 *
13 *
14 *  $Id$
15 */
16#include <rtems.h>
17#include <rtems/clockdrv.h>
18#include <rtems/libio.h>
19
20#include <stdlib.h>
21#include <bsp.h>
22#include <irq.h>
23#include <at91rm9200.h>
24#include <at91rm9200_pmc.h>
25
26
27rtems_device_major_number rtems_clock_major = ~0;
28rtems_device_minor_number rtems_clock_minor;
29volatile uint32_t Clock_driver_ticks;
30static unsigned long st_pimr_reload;
31
32rtems_isr clock_isr(rtems_vector_number vector);
33void Clock_exit(void);
34static void clock_isr_on(const rtems_irq_connect_data *unused);
35static void clock_isr_off(const rtems_irq_connect_data *unused);
36static int clock_isr_is_on(const rtems_irq_connect_data *irq);
37
38/* Replace the first value with the clock's interrupt name. */
39rtems_irq_connect_data clock_isr_data = {AT91RM9200_INT_SYSIRQ,   
40                                         (rtems_irq_hdl)clock_isr,
41                                         clock_isr_on,
42                                         clock_isr_off,
43                                         clock_isr_is_on,
44                                         3,     /* unused for ARM cpus */
45                                         0 };   /* unused for ARM cpus */
46
47
48rtems_isr clock_isr(rtems_vector_number vector)
49{
50    uint32_t st_str;
51
52    Clock_driver_ticks++;
53
54    /* read the status to clear the int */
55    st_str = ST_REG(ST_SR);
56
57    rtems_clock_tick();
58}
59
60void Install_clock(rtems_isr_entry clock_isr)
61{
62    uint32_t st_str;
63    int slck;
64
65    Clock_driver_ticks = 0;
66
67    BSP_install_rtems_irq_handler(&clock_isr_data);
68
69    /* the system timer is driven from SLCK */
70    slck = at91rm9200_get_slck();
71    st_pimr_reload = (((BSP_Configuration.microseconds_per_tick * slck) + (1000000/2))/
72                      1000000);
73
74    /* read the status to clear the int */
75    st_str = ST_REG(ST_SR);
76   
77    /* set priority */
78    AIC_SMR_REG(AIC_SMR_SYSIRQ) = AIC_SMR_PRIOR(0x7);
79
80    /* set the timer value */
81    ST_REG(ST_PIMR) = st_pimr_reload;
82
83    atexit( Clock_exit );
84}
85
86void Clock_exit( void )
87{
88    BSP_remove_rtems_irq_handler(&clock_isr_data);
89}
90
91rtems_device_driver Clock_initialize(
92    rtems_device_major_number major,
93    rtems_device_minor_number minor,
94    void *pargp
95    )
96{
97    Install_clock( clock_isr );
98 
99    rtems_clock_major = major;
100    rtems_clock_minor = minor;
101
102    return RTEMS_SUCCESSFUL;
103}
104
105rtems_device_driver Clock_control(
106    rtems_device_major_number major,
107    rtems_device_minor_number minor,
108    void *pargp
109)
110{
111    uint32_t  isrlevel;
112    rtems_libio_ioctl_args_t *args = pargp;
113   
114    if (args == 0) {
115        return RTEMS_SUCCESSFUL;
116    }
117 
118    if (args->command == rtems_build_name('I', 'S', 'R', ' ')) {
119        clock_isr(0);
120    } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) {
121        rtems_interrupt_disable(isrlevel);
122
123        BSP_install_rtems_irq_handler(args->buffer);
124
125        rtems_interrupt_enable(isrlevel);
126    }
127 
128    return RTEMS_SUCCESSFUL;
129}
130
131/**
132 * Enables clock interrupt.
133 *
134 * If the interrupt is always on, this can be a NOP.
135 */
136static void clock_isr_on(const rtems_irq_connect_data *unused)
137{
138    /* enable timer interrupt */
139    ST_REG(ST_IER) = ST_SR_PITS;
140}
141
142/**
143 * Disables clock interrupts
144 *
145 * If the interrupt is always on, this can be a NOP.
146 */
147static void clock_isr_off(const rtems_irq_connect_data *unused)
148{
149    /* disable timer interrupt */
150    ST_REG(ST_IDR) = ST_SR_PITS;
151    return;
152}
153
154/**
155 * Tests to see if clock interrupt is enabled, and returns 1 if so.
156 * If interrupt is not enabled, returns 0.
157 *
158 * If the interrupt is always on, this always returns 1.
159 */
160static int clock_isr_is_on(const rtems_irq_connect_data *irq)
161{
162    /* check timer interrupt */
163    return ST_REG(ST_IMR) & ST_SR_PITS;
164}
Note: See TracBrowser for help on using the repository browser.