source: rtems/c/src/lib/libbsp/arm/shared/armv7m/clock/armv7m-clock-config.c @ 248f867

Last change on this file since 248f867 was 248f867, checked in by Christian Mauderer <Christian.Mauderer@…>, on Oct 17, 2017 at 9:46:15 AM

bsps/arm: Remove DWT based clock.

It seems that the DWT CYCCNT does not advance when the CPU waits on a
WFI instruction.

That leads to the effect that for example on the atsamv BSP a sleep(1)
needs something in the range of a few minutes (depending on the
configured systick). A debugger might disables some deep sleep modes so
that the problem only appears if the application is executed without a
debugger.

  • Property mode set to 100644
File size: 3.6 KB
Line 
1/*
2 * Copyright (c) 2011-2012 Sebastian Huber.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Obere Lagerstr. 30
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <rtems.h>
16#include <rtems/timecounter.h>
17#include <rtems/score/armv7m.h>
18
19#include <bsp.h>
20
21#ifdef ARM_MULTILIB_ARCH_V7M
22
23/* This is defined in clockdrv_shell.h */
24static void Clock_isr(void *arg);
25
26typedef struct {
27  rtems_timecounter_simple base;
28  void (*tick)(void);
29  bool countflag;
30} ARMV7M_Timecounter;
31
32static ARMV7M_Timecounter _ARMV7M_TC;
33
34static uint32_t _ARMV7M_TC_systick_get(rtems_timecounter_simple *tc)
35{
36  volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
37
38  return systick->cvr;
39}
40
41static bool _ARMV7M_TC_systick_is_pending(rtems_timecounter_simple *base)
42{
43  ARMV7M_Timecounter *tc = (ARMV7M_Timecounter *) base;
44  rtems_interrupt_level level;
45  bool countflag;
46
47  rtems_interrupt_disable(level);
48
49  countflag = tc->countflag;
50  if (!countflag) {
51    volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
52
53    countflag = ((systick->csr & ARMV7M_SYSTICK_CSR_COUNTFLAG) != 0);
54    tc->countflag = countflag;
55  }
56
57  rtems_interrupt_enable(level);
58
59  return countflag;
60}
61
62static uint32_t _ARMV7M_TC_systick_get_timecount(struct timecounter *tc)
63{
64  return rtems_timecounter_simple_downcounter_get(
65    tc,
66    _ARMV7M_TC_systick_get,
67    _ARMV7M_TC_systick_is_pending
68  );
69}
70
71static void _ARMV7M_TC_systick_at_tick(rtems_timecounter_simple *base)
72{
73  ARMV7M_Timecounter *tc = (ARMV7M_Timecounter *) base;
74  volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
75
76  tc->countflag = false;
77
78  /* Clear COUNTFLAG */
79  systick->csr;
80}
81
82static void _ARMV7M_TC_systick_tick(void)
83{
84  rtems_timecounter_simple_downcounter_tick(
85    &_ARMV7M_TC.base,
86    _ARMV7M_TC_systick_get,
87    _ARMV7M_TC_systick_at_tick
88  );
89}
90
91static void _ARMV7M_TC_tick(void)
92{
93  (*_ARMV7M_TC.tick)();
94}
95
96static void _ARMV7M_Systick_handler(void)
97{
98  _ARMV7M_Interrupt_service_enter();
99  Clock_isr(NULL);
100  _ARMV7M_Interrupt_service_leave();
101}
102
103static void _ARMV7M_Systick_handler_install(void)
104{
105  _ARMV7M_Set_exception_priority_and_handler(
106    ARMV7M_VECTOR_SYSTICK,
107    BSP_ARMV7M_SYSTICK_PRIORITY,
108    _ARMV7M_Systick_handler
109  );
110}
111
112static void _ARMV7M_Systick_initialize(void)
113{
114  volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
115  #ifdef BSP_ARMV7M_SYSTICK_FREQUENCY
116    uint64_t freq = BSP_ARMV7M_SYSTICK_FREQUENCY;
117  #else
118    uint64_t freq = ARMV7M_SYSTICK_CALIB_TENMS_GET(systick->calib) * 100ULL;
119  #endif
120  uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
121  uint64_t interval = (freq * us_per_tick) / 1000000ULL;
122
123  systick->rvr = (uint32_t) interval;
124  systick->cvr = 0;
125  systick->csr = ARMV7M_SYSTICK_CSR_ENABLE
126    | ARMV7M_SYSTICK_CSR_TICKINT
127    | ARMV7M_SYSTICK_CSR_CLKSOURCE;
128
129  _ARMV7M_TC.tick = _ARMV7M_TC_systick_tick;
130  rtems_timecounter_simple_install(
131    &_ARMV7M_TC.base,
132    freq,
133    interval,
134    _ARMV7M_TC_systick_get_timecount
135  );
136}
137
138static void _ARMV7M_Systick_cleanup(void)
139{
140  volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
141
142  systick->csr = 0;
143}
144
145#define Clock_driver_timecounter_tick() _ARMV7M_TC_tick()
146
147#define Clock_driver_support_initialize_hardware() \
148  _ARMV7M_Systick_initialize()
149
150#define Clock_driver_support_install_isr(isr) \
151  _ARMV7M_Systick_handler_install()
152
153#define Clock_driver_support_shutdown_hardware() \
154  _ARMV7M_Systick_cleanup()
155
156/* Include shared source clock driver code */
157#include "../../../../shared/clockdrv_shell.h"
158
159#endif /* ARM_MULTILIB_ARCH_V7M */
Note: See TracBrowser for help on using the repository browser.