arm: Use DWT CYCCNT for timecounter if available

This commit is contained in:
Sebastian Huber
2016-01-21 10:53:16 +01:00
parent 12bc6c58fe
commit 370cdefdbc
2 changed files with 74 additions and 15 deletions

View File

@@ -25,19 +25,20 @@ static void Clock_isr(void *arg);
typedef struct {
rtems_timecounter_simple base;
void (*tick)(void);
bool countflag;
} ARMV7M_Timecounter;
static ARMV7M_Timecounter _ARMV7M_TC;
static uint32_t _ARMV7M_TC_get(rtems_timecounter_simple *tc)
static uint32_t _ARMV7M_TC_systick_get(rtems_timecounter_simple *tc)
{
volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
return systick->cvr;
}
static bool _ARMV7M_TC_is_pending(rtems_timecounter_simple *base)
static bool _ARMV7M_TC_systick_is_pending(rtems_timecounter_simple *base)
{
ARMV7M_Timecounter *tc = (ARMV7M_Timecounter *) base;
rtems_interrupt_level level;
@@ -58,16 +59,16 @@ static bool _ARMV7M_TC_is_pending(rtems_timecounter_simple *base)
return countflag;
}
static uint32_t _ARMV7M_TC_get_timecount(struct timecounter *tc)
static uint32_t _ARMV7M_TC_systick_get_timecount(struct timecounter *tc)
{
return rtems_timecounter_simple_downcounter_get(
tc,
_ARMV7M_TC_get,
_ARMV7M_TC_is_pending
_ARMV7M_TC_systick_get,
_ARMV7M_TC_systick_is_pending
);
}
static void _ARMV7M_TC_at_tick(rtems_timecounter_simple *base)
static void _ARMV7M_TC_systick_at_tick(rtems_timecounter_simple *base)
{
ARMV7M_Timecounter *tc = (ARMV7M_Timecounter *) base;
volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
@@ -78,15 +79,32 @@ static void _ARMV7M_TC_at_tick(rtems_timecounter_simple *base)
systick->csr;
}
static void _ARMV7M_TC_tick(void)
static void _ARMV7M_TC_systick_tick(void)
{
rtems_timecounter_simple_downcounter_tick(
&_ARMV7M_TC.base,
_ARMV7M_TC_get,
_ARMV7M_TC_at_tick
_ARMV7M_TC_systick_get,
_ARMV7M_TC_systick_at_tick
);
}
static uint32_t _ARMV7M_TC_dwt_get_timecount(struct timecounter *tc)
{
volatile ARMV7M_DWT *dwt = _ARMV7M_DWT;
return dwt->cyccnt;
}
static void _ARMV7M_TC_dwt_tick(void)
{
rtems_timecounter_tick();
}
static void _ARMV7M_TC_tick(void)
{
(*_ARMV7M_TC.tick)();
}
static void _ARMV7M_Systick_handler(void)
{
_ARMV7M_Interrupt_service_enter();
@@ -105,6 +123,7 @@ static void _ARMV7M_Systick_handler_install(void)
static void _ARMV7M_Systick_initialize(void)
{
volatile ARMV7M_DWT *dwt = _ARMV7M_DWT;
volatile ARMV7M_Systick *systick = _ARMV7M_Systick;
#ifdef BSP_ARMV7M_SYSTICK_FREQUENCY
uint64_t freq = BSP_ARMV7M_SYSTICK_FREQUENCY;
@@ -113,6 +132,7 @@ static void _ARMV7M_Systick_initialize(void)
#endif
uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
uint64_t interval = (freq * us_per_tick) / 1000000ULL;
uint32_t dwt_ctrl;
systick->rvr = (uint32_t) interval;
systick->cvr = 0;
@@ -120,12 +140,24 @@ static void _ARMV7M_Systick_initialize(void)
| ARMV7M_SYSTICK_CSR_TICKINT
| ARMV7M_SYSTICK_CSR_CLKSOURCE;
dwt_ctrl = dwt->ctrl;
if ((dwt_ctrl & ARMV7M_DWT_CTRL_NOCYCCNT) == 0) {
dwt->ctrl = dwt_ctrl | ARMV7M_DWT_CTRL_CYCCNTENA;
_ARMV7M_TC.base.tc.tc_get_timecount = _ARMV7M_TC_dwt_get_timecount;
_ARMV7M_TC.base.tc.tc_counter_mask = 0xffffffff;
_ARMV7M_TC.base.tc.tc_frequency = freq;
_ARMV7M_TC.base.tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
_ARMV7M_TC.tick = _ARMV7M_TC_dwt_tick;
rtems_timecounter_install(&_ARMV7M_TC.base.tc);
} else {
_ARMV7M_TC.tick = _ARMV7M_TC_systick_tick;
rtems_timecounter_simple_install(
&_ARMV7M_TC.base,
freq,
interval,
_ARMV7M_TC_get_timecount
_ARMV7M_TC_systick_get_timecount
);
}
}
static void _ARMV7M_Systick_cleanup(void)

View File

@@ -74,6 +74,30 @@ typedef struct {
#endif
} ARMV7M_Exception_frame;
typedef struct {
uint32_t comp;
uint32_t mask;
uint32_t function;
uint32_t reserved;
} ARMV7M_DWT_comparator;
typedef struct {
#define ARMV7M_DWT_CTRL_NOCYCCNT (1U << 25)
#define ARMV7M_DWT_CTRL_CYCCNTENA (1U << 0)
uint32_t ctrl;
uint32_t cyccnt;
uint32_t cpicnt;
uint32_t exccnt;
uint32_t sleepcnt;
uint32_t lsucnt;
uint32_t foldcnt;
uint32_t pcsr;
ARMV7M_DWT_comparator comparator[249];
uint32_t reserved_e0001fb0[1];
uint32_t lar;
uint32_t lsr;
} ARMV7M_DWT;
typedef struct {
uint32_t cpuid;
@@ -323,6 +347,7 @@ typedef struct {
0 \
}
#define ARMV7M_DWT_BASE 0xe0001000
#define ARMV7M_SCS_BASE 0xe000e000
#define ARMV7M_ICTAC_BASE (ARMV7M_SCS_BASE + 0x0)
#define ARMV7M_SYSTICK_BASE (ARMV7M_SCS_BASE + 0x10)
@@ -330,6 +355,8 @@ typedef struct {
#define ARMV7M_SCB_BASE (ARMV7M_SCS_BASE + 0xd00)
#define ARMV7M_MPU_BASE (ARMV7M_SCS_BASE + 0xd90)
#define _ARMV7M_DWT \
((volatile ARMV7M_DWT *) ARMV7M_DWT_BASE)
#define _ARMV7M_ICTAC \
((volatile ARMV7M_ICTAC *) ARMV7M_ICTAC_BASE)
#define _ARMV7M_SCB \