92 lines
2.3 KiB
C
92 lines
2.3 KiB
C
/*
|
|
* Copyright 2019, Data61
|
|
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
|
|
* ABN 41 687 119 230.
|
|
*
|
|
* This software may be distributed and modified according to the terms of
|
|
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
|
|
* See "LICENSE_GPLv2.txt" for details.
|
|
*
|
|
* @TAG(DATA61_GPL)
|
|
*/
|
|
#ifndef __DRIVERS_TIMER_ARM_GLOBAL_H
|
|
#define __DRIVERS_TIMER_ARM_GLOBAL_H
|
|
|
|
#include <util.h>
|
|
#include <config.h>
|
|
#include <model/statedata.h>
|
|
|
|
#ifndef CONFIG_KERNEL_MCS
|
|
#error "This driver should only be selected for MCS kernel"
|
|
#endif /* CONFIG_KERNEL_MCS */
|
|
|
|
/* ARM Cortex-A9 MPCore global timer driver
|
|
* Documentation for this timer is available in
|
|
* the Cortex-A9 MPCore Technical Reference Manual
|
|
* section "Global Timer Counter Registers"
|
|
*/
|
|
struct timer {
|
|
uint32_t countLower;
|
|
uint32_t countUpper;
|
|
uint32_t control;
|
|
uint32_t isr;
|
|
uint32_t comparatorLower;
|
|
uint32_t comparatorUpper;
|
|
uint32_t autoInc;
|
|
};
|
|
typedef volatile struct timer timer_t;
|
|
extern timer_t *const globalTimer;
|
|
|
|
enum control {
|
|
ENABLE = 0,
|
|
COMP_ENABLE = 1,
|
|
IRQ_ENABLE = 2,
|
|
AUTO_INC = 3,
|
|
RESERVED = 4,
|
|
PRESCALER = 8,
|
|
RESERVED_2 = 16
|
|
};
|
|
|
|
/** DONT_TRANSLATE */
|
|
static inline ticks_t getCurrentTime(void)
|
|
{
|
|
uint32_t upper, upper2, lower;
|
|
|
|
upper = globalTimer->countUpper;
|
|
lower = globalTimer->countLower;
|
|
upper2 = globalTimer->countUpper;
|
|
|
|
/* account for race: upper could have increased while we
|
|
* read lower */
|
|
if (upper != upper2) {
|
|
lower = globalTimer->countLower;
|
|
}
|
|
|
|
return (((ticks_t) upper2 << 32llu) + (ticks_t) lower);
|
|
}
|
|
|
|
/** DONT_TRANSLATE */
|
|
static inline void setDeadline(ticks_t deadline)
|
|
{
|
|
/* disable cmp */
|
|
globalTimer->control &= ~(BIT(COMP_ENABLE));
|
|
/* set low bits */
|
|
globalTimer->comparatorLower = (uint32_t) deadline;
|
|
/* set high bits */
|
|
globalTimer->comparatorUpper = (uint32_t)(deadline >> 32llu);
|
|
/* enable cmp */
|
|
globalTimer->control |= BIT(COMP_ENABLE);
|
|
/* if this fails PRECISION is too low */
|
|
assert(getCurrentTime() < deadline || globalTimer->isr == 1u);
|
|
}
|
|
|
|
/** DONT_TRANSLATE */
|
|
static inline void ackDeadlineIRQ(void)
|
|
{
|
|
/* disable cmp */
|
|
globalTimer->control &= ~(BIT(COMP_ENABLE));
|
|
/* ack the isr */
|
|
globalTimer->isr = 1;
|
|
}
|
|
|
|
#endif /* __DRIVERS_TIMER_ARM_GLOBAL_H */
|