forked from Imagelibrary/rtems
arm: Simplify CPU counter support
Use the standard ARMv7-M systick module for the ARMv7-M CPU counter instead of DWT counter since the DWT counter is affected by power saving states. Use an inline function for _CPU_Counter_difference() for all ARM BSPs. Update #3456.
This commit is contained in:
78
bsps/arm/include/bsp/clock-armv7m.h
Normal file
78
bsps/arm/include/bsp/clock-armv7m.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2018 Sebastian Huber. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef BSP_CLOCK_ARMV7M_H
|
||||
#define BSP_CLOCK_ARMV7M_H
|
||||
|
||||
#include <rtems/score/armv7m.h>
|
||||
#include <rtems/timecounter.h>
|
||||
|
||||
#include <bsp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef ARM_MULTILIB_ARCH_V7M
|
||||
|
||||
typedef struct {
|
||||
struct timecounter base;
|
||||
uint32_t ticks;
|
||||
} ARMV7M_Timecounter;
|
||||
|
||||
extern ARMV7M_Timecounter _ARMV7M_TC;
|
||||
|
||||
static inline uint32_t _ARMV7M_Clock_frequency(void)
|
||||
{
|
||||
#ifdef BSP_ARMV7M_SYSTICK_FREQUENCY
|
||||
return BSP_ARMV7M_SYSTICK_FREQUENCY;
|
||||
#else
|
||||
volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
|
||||
return ARMV7M_SYSTICK_CALIB_TENMS_GET(systick->calib) * 100;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t _ARMV7M_Clock_counter(ARMV7M_Timecounter *tc)
|
||||
{
|
||||
volatile ARMV7M_Systick *systick;
|
||||
rtems_interrupt_level level;
|
||||
uint32_t interval;
|
||||
uint32_t counter;
|
||||
uint32_t ticks;
|
||||
|
||||
systick = _ARMV7M_Systick;
|
||||
interval = systick->rvr;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
counter = systick->cvr;
|
||||
ticks = tc->ticks;
|
||||
|
||||
if ((systick->csr & ARMV7M_SYSTICK_CSR_COUNTFLAG) != 0) {
|
||||
ticks += interval;
|
||||
tc->ticks = ticks;
|
||||
}
|
||||
|
||||
counter = interval - counter + ticks;
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
#endif /* ARM_MULTILIB_ARCH_V7M */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* BSP_CLOCK_ARMV7M_H */
|
||||
@@ -118,12 +118,3 @@ CPU_Counter_ticks _CPU_Counter_read( void )
|
||||
{
|
||||
return lpc176x_get_timer1();
|
||||
}
|
||||
|
||||
inline CPU_Counter_ticks _CPU_Counter_difference(
|
||||
CPU_Counter_ticks second,
|
||||
CPU_Counter_ticks first
|
||||
)
|
||||
{
|
||||
return second - first;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2012 Sebastian Huber. All rights reserved.
|
||||
* Copyright (c) 2011, 2018 Sebastian Huber. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* Dornierstr. 4
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
@@ -12,146 +12,97 @@
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/timecounter.h>
|
||||
#include <rtems/score/armv7m.h>
|
||||
#include <bsp/clock-armv7m.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <rtems.h>
|
||||
#include <rtems/sysinit.h>
|
||||
|
||||
#ifdef ARM_MULTILIB_ARCH_V7M
|
||||
|
||||
/* This is defined in dev/clock/clockimpl.h */
|
||||
static void Clock_isr(void *arg);
|
||||
|
||||
typedef struct {
|
||||
rtems_timecounter_simple base;
|
||||
void (*tick)(void);
|
||||
bool countflag;
|
||||
} ARMV7M_Timecounter;
|
||||
ARMV7M_Timecounter _ARMV7M_TC;
|
||||
|
||||
static ARMV7M_Timecounter _ARMV7M_TC;
|
||||
|
||||
static uint32_t _ARMV7M_TC_systick_get(rtems_timecounter_simple *tc)
|
||||
static uint32_t _ARMV7M_TC_get_timecount(struct timecounter *base)
|
||||
{
|
||||
volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
|
||||
|
||||
return systick->cvr;
|
||||
return _ARMV7M_Clock_counter((ARMV7M_Timecounter *) base);
|
||||
}
|
||||
|
||||
static bool _ARMV7M_TC_systick_is_pending(rtems_timecounter_simple *base)
|
||||
{
|
||||
ARMV7M_Timecounter *tc = (ARMV7M_Timecounter *) base;
|
||||
rtems_interrupt_level level;
|
||||
bool countflag;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
countflag = tc->countflag;
|
||||
if (!countflag) {
|
||||
volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
|
||||
|
||||
countflag = ((systick->csr & ARMV7M_SYSTICK_CSR_COUNTFLAG) != 0);
|
||||
tc->countflag = countflag;
|
||||
}
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
return countflag;
|
||||
}
|
||||
|
||||
static uint32_t _ARMV7M_TC_systick_get_timecount(struct timecounter *tc)
|
||||
{
|
||||
return rtems_timecounter_simple_downcounter_get(
|
||||
tc,
|
||||
_ARMV7M_TC_systick_get,
|
||||
_ARMV7M_TC_systick_is_pending
|
||||
);
|
||||
}
|
||||
|
||||
static void _ARMV7M_TC_systick_at_tick(rtems_timecounter_simple *base)
|
||||
{
|
||||
ARMV7M_Timecounter *tc = (ARMV7M_Timecounter *) base;
|
||||
volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
|
||||
|
||||
tc->countflag = false;
|
||||
|
||||
/* Clear COUNTFLAG */
|
||||
systick->csr;
|
||||
}
|
||||
|
||||
static void _ARMV7M_TC_systick_tick(void)
|
||||
{
|
||||
rtems_timecounter_simple_downcounter_tick(
|
||||
&_ARMV7M_TC.base,
|
||||
_ARMV7M_TC_systick_get,
|
||||
_ARMV7M_TC_systick_at_tick
|
||||
);
|
||||
}
|
||||
|
||||
static void _ARMV7M_TC_tick(void)
|
||||
{
|
||||
(*_ARMV7M_TC.tick)();
|
||||
}
|
||||
|
||||
static void _ARMV7M_Systick_handler(void)
|
||||
static void _ARMV7M_Clock_handler(void)
|
||||
{
|
||||
_ARMV7M_Interrupt_service_enter();
|
||||
Clock_isr(NULL);
|
||||
_ARMV7M_Interrupt_service_leave();
|
||||
}
|
||||
|
||||
static void _ARMV7M_Systick_handler_install(void)
|
||||
static void _ARMV7M_Clock_handler_install(void)
|
||||
{
|
||||
_ARMV7M_Set_exception_priority_and_handler(
|
||||
ARMV7M_VECTOR_SYSTICK,
|
||||
BSP_ARMV7M_SYSTICK_PRIORITY,
|
||||
_ARMV7M_Systick_handler
|
||||
_ARMV7M_Clock_handler
|
||||
);
|
||||
}
|
||||
|
||||
static void _ARMV7M_Systick_initialize(void)
|
||||
static void _ARMV7M_Clock_initialize(void)
|
||||
{
|
||||
volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
|
||||
#ifdef BSP_ARMV7M_SYSTICK_FREQUENCY
|
||||
uint64_t freq = BSP_ARMV7M_SYSTICK_FREQUENCY;
|
||||
#else
|
||||
uint64_t freq = ARMV7M_SYSTICK_CALIB_TENMS_GET(systick->calib) * 100ULL;
|
||||
#endif
|
||||
uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
|
||||
uint64_t interval = (freq * us_per_tick) / 1000000ULL;
|
||||
volatile ARMV7M_Systick *systick;
|
||||
ARMV7M_Timecounter *tc;
|
||||
|
||||
systick = _ARMV7M_Systick;
|
||||
tc = &_ARMV7M_TC;
|
||||
|
||||
systick->rvr = (uint32_t) interval;
|
||||
systick->cvr = 0;
|
||||
systick->csr = ARMV7M_SYSTICK_CSR_ENABLE
|
||||
| ARMV7M_SYSTICK_CSR_TICKINT
|
||||
| ARMV7M_SYSTICK_CSR_CLKSOURCE;
|
||||
|
||||
_ARMV7M_TC.tick = _ARMV7M_TC_systick_tick;
|
||||
rtems_timecounter_simple_install(
|
||||
&_ARMV7M_TC.base,
|
||||
freq,
|
||||
interval,
|
||||
_ARMV7M_TC_systick_get_timecount
|
||||
);
|
||||
tc->base.tc_get_timecount = _ARMV7M_TC_get_timecount;
|
||||
tc->base.tc_counter_mask = 0xffffffff;
|
||||
tc->base.tc_frequency = _ARMV7M_Clock_frequency();
|
||||
tc->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
|
||||
rtems_timecounter_install(&tc->base);
|
||||
}
|
||||
|
||||
static void _ARMV7M_Systick_cleanup(void)
|
||||
static void _ARMV7M_Clock_initialize_early(void)
|
||||
{
|
||||
volatile ARMV7M_Systick *systick;
|
||||
uint32_t us_per_tick;
|
||||
uint64_t freq;
|
||||
uint32_t interval;
|
||||
|
||||
systick = _ARMV7M_Systick;
|
||||
us_per_tick = rtems_configuration_get_microseconds_per_tick();
|
||||
freq = _ARMV7M_Clock_frequency();
|
||||
|
||||
interval = (uint32_t) ((freq * us_per_tick) / 1000000);
|
||||
|
||||
systick->rvr = interval;
|
||||
systick->cvr = 0;
|
||||
systick->csr = ARMV7M_SYSTICK_CSR_ENABLE | ARMV7M_SYSTICK_CSR_CLKSOURCE;
|
||||
}
|
||||
|
||||
RTEMS_SYSINIT_ITEM(
|
||||
_ARMV7M_Clock_initialize_early,
|
||||
RTEMS_SYSINIT_CPU_COUNTER,
|
||||
RTEMS_SYSINIT_ORDER_FIRST
|
||||
);
|
||||
|
||||
static void _ARMV7M_Clock_cleanup(void)
|
||||
{
|
||||
volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
|
||||
|
||||
systick->csr = 0;
|
||||
}
|
||||
|
||||
#define Clock_driver_timecounter_tick() _ARMV7M_TC_tick()
|
||||
|
||||
#define Clock_driver_support_initialize_hardware() \
|
||||
_ARMV7M_Systick_initialize()
|
||||
_ARMV7M_Clock_initialize()
|
||||
|
||||
#define Clock_driver_support_install_isr(isr) \
|
||||
_ARMV7M_Systick_handler_install()
|
||||
_ARMV7M_Clock_handler_install()
|
||||
|
||||
#define Clock_driver_support_shutdown_hardware() \
|
||||
_ARMV7M_Systick_cleanup()
|
||||
_ARMV7M_Clock_cleanup()
|
||||
|
||||
/* Include shared source clock driver code */
|
||||
#include "../../../shared/dev/clock/clockimpl.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016 embedded brains GmbH. All rights reserved.
|
||||
* Copyright (c) 2016, 2018 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
@@ -12,43 +12,14 @@
|
||||
* http://www.rtems.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <rtems/score/armv7m.h>
|
||||
#include <rtems/counter.h>
|
||||
#include <rtems/sysinit.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <bsp/fatal.h>
|
||||
#include <bsp/clock-armv7m.h>
|
||||
|
||||
uint32_t _CPU_Counter_frequency(void)
|
||||
{
|
||||
#ifdef BSP_ARMV7M_SYSTICK_FREQUENCY
|
||||
return = BSP_ARMV7M_SYSTICK_FREQUENCY;
|
||||
#else
|
||||
volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
|
||||
return ARMV7M_SYSTICK_CALIB_TENMS_GET(systick->calib) * 100;
|
||||
#endif
|
||||
return _ARMV7M_Clock_frequency();
|
||||
}
|
||||
|
||||
CPU_Counter_ticks _CPU_Counter_read(void)
|
||||
{
|
||||
volatile ARMV7M_DWT *dwt = _ARMV7M_DWT;
|
||||
|
||||
return dwt->cyccnt;
|
||||
return _ARMV7M_Clock_counter(&_ARMV7M_TC);
|
||||
}
|
||||
|
||||
static void armv7m_cpu_counter_initialize(void)
|
||||
{
|
||||
bool cyccnt_enabled;
|
||||
|
||||
cyccnt_enabled = _ARMV7M_DWT_Enable_CYCCNT();
|
||||
|
||||
if (!cyccnt_enabled) {
|
||||
bsp_fatal(BSP_ARM_ARMV7M_CPU_COUNTER_INIT);
|
||||
}
|
||||
}
|
||||
|
||||
RTEMS_SYSINIT_ITEM(
|
||||
armv7m_cpu_counter_initialize,
|
||||
RTEMS_SYSINIT_CPU_COUNTER,
|
||||
RTEMS_SYSINIT_ORDER_FIRST
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user