mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 17:41:54 +00:00
nrf51: Make timer handling names more obvious
There are three timers, each with four capture/compare (CC) registers. The timer code uses 3 CC registers from one timer. Use macros for the defines, so that it is more obvious which timer and which register are being used. TEST=make BOARD=hadoken BRANCH=NONE BUG=None Change-Id: Icb058d9717800a87b394270eef38a3a744a13b7d Signed-off-by: Myles Watson <mylesgw@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/361793 Reviewed-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Levi Oliver <levio@google.com>
This commit is contained in:
@@ -6,12 +6,8 @@
|
||||
/*
|
||||
* Hardware timers driver.
|
||||
*
|
||||
* nRF51x has one hardware counter, but 4 stand-alone capture/compare (CC)
|
||||
* registers.
|
||||
*
|
||||
* CC(0) -- used to interrupt next clock event.
|
||||
* CC(1) -- used to capture the current value.
|
||||
* CC(2) -- used to detect overflow on virtual timer (not hardware).
|
||||
* nRF51x has one fully functional hardware counter, but 4 stand-alone
|
||||
* capture/compare (CC) registers.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
@@ -20,11 +16,25 @@
|
||||
#include "hwtimer.h"
|
||||
#include "registers.h"
|
||||
#include "task.h"
|
||||
#include "util.h"
|
||||
|
||||
#define CPUTS(outstr) cputs(CC_CLOCK, outstr)
|
||||
#define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args)
|
||||
#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args)
|
||||
|
||||
/*
|
||||
* capture/compare (CC) registers:
|
||||
* CC_INTERRUPT -- used to interrupt next clock event.
|
||||
* CC_CURRENT -- used to capture the current value.
|
||||
* CC_OVERFLOW -- used to detect overflow on virtual timer (not hardware).
|
||||
*/
|
||||
|
||||
#define CC_INTERRUPT 0
|
||||
#define CC_CURRENT 1
|
||||
#define CC_OVERFLOW 2
|
||||
|
||||
/* The nRF51 has 3 timers, use HWTIMER to specify which one is used here. */
|
||||
#define HWTIMER 0
|
||||
|
||||
static uint32_t last_deadline; /* cache of event set */
|
||||
|
||||
@@ -60,10 +70,11 @@ static uint32_t shift;
|
||||
void __hw_clock_event_set(uint32_t deadline)
|
||||
{
|
||||
last_deadline = deadline;
|
||||
NRF51_TIMER0_CC0 = deadline - shift;
|
||||
NRF51_TIMER_CC(HWTIMER, CC_INTERRUPT) = deadline - shift;
|
||||
|
||||
/* enable interrupt */
|
||||
NRF51_TIMER0_INTENSET = 1 << NRF51_TIMER_COMPARE0_BIT;
|
||||
NRF51_TIMER_INTENSET(HWTIMER) =
|
||||
1 << NRF51_TIMER_COMPARE_BIT(CC_INTERRUPT);
|
||||
}
|
||||
|
||||
uint32_t __hw_clock_event_get(void)
|
||||
@@ -74,14 +85,15 @@ uint32_t __hw_clock_event_get(void)
|
||||
void __hw_clock_event_clear(void)
|
||||
{
|
||||
/* disable interrupt */
|
||||
NRF51_TIMER0_INTENCLR = 1 << NRF51_TIMER_COMPARE0_BIT;
|
||||
NRF51_TIMER_INTENCLR(HWTIMER) =
|
||||
1 << NRF51_TIMER_COMPARE_BIT(CC_INTERRUPT);
|
||||
}
|
||||
|
||||
uint32_t __hw_clock_source_read(void)
|
||||
{
|
||||
/* to capture the current value */
|
||||
NRF51_TIMER0_CAPTURE1 = 1;
|
||||
return NRF51_TIMER0_CC1 + shift;
|
||||
NRF51_TIMER_CAPTURE(HWTIMER, CC_CURRENT) = 1;
|
||||
return NRF51_TIMER_CC(HWTIMER, CC_CURRENT) + shift;
|
||||
}
|
||||
|
||||
void __hw_clock_source_set(uint32_t ts)
|
||||
@@ -89,17 +101,17 @@ void __hw_clock_source_set(uint32_t ts)
|
||||
shift = ts;
|
||||
|
||||
/* reset counter to zero */
|
||||
NRF51_TIMER0_STOP = 1;
|
||||
NRF51_TIMER0_CLEAR = 1;
|
||||
NRF51_TIMER_STOP(HWTIMER) = 1;
|
||||
NRF51_TIMER_CLEAR(HWTIMER) = 1;
|
||||
|
||||
/* So that no interrupt until next __hw_clock_event_set() */
|
||||
NRF51_TIMER0_CC0 = ts - 1;
|
||||
NRF51_TIMER_CC(HWTIMER, CC_INTERRUPT) = ts - 1;
|
||||
|
||||
/* Update the overflow point */
|
||||
NRF51_TIMER0_CC2 = 0 - shift;
|
||||
NRF51_TIMER_CC(HWTIMER, CC_OVERFLOW) = 0 - shift;
|
||||
|
||||
/* Start the timer again */
|
||||
NRF51_TIMER0_START = 1;
|
||||
NRF51_TIMER_START(HWTIMER) = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,55 +121,59 @@ void timer_irq(void)
|
||||
int overflow = 0;
|
||||
|
||||
/* clear status */
|
||||
NRF51_TIMER0_COMPARE0 = 0;
|
||||
NRF51_TIMER_COMPARE(HWTIMER, CC_INTERRUPT) = 0;
|
||||
|
||||
if (NRF51_TIMER0_COMPARE2) {
|
||||
NRF51_TIMER0_COMPARE2 = 0;
|
||||
if (NRF51_TIMER_COMPARE(HWTIMER, CC_OVERFLOW)) {
|
||||
NRF51_TIMER_COMPARE(HWTIMER, CC_OVERFLOW) = 0;
|
||||
overflow = 1;
|
||||
}
|
||||
|
||||
process_timers(overflow);
|
||||
}
|
||||
DECLARE_IRQ(NRF51_PERID_TIMER0, timer_irq, 1);
|
||||
|
||||
/* DECLARE_IRQ doesn't like the NRF51_PERID_TIMER(n) macro */
|
||||
BUILD_ASSERT(NRF51_PERID_TIMER(HWTIMER) == NRF51_PERID_TIMER0);
|
||||
DECLARE_IRQ(NRF51_PERID_TIMER0, timer_irq, 1);
|
||||
|
||||
int __hw_clock_source_init(uint32_t start_t)
|
||||
{
|
||||
|
||||
/* Start the high freq crystal oscillator */
|
||||
NRF51_CLOCK_HFCLKSTART = 1;
|
||||
/* TODO: check if the crystal oscillator is running (HFCLKSTAT) */
|
||||
|
||||
/* 32-bit timer mode */
|
||||
NRF51_TIMER0_MODE = NRF51_TIMER0_MODE_TIMER;
|
||||
NRF51_TIMER0_BITMODE = NRF51_TIMER0_BITMODE_32;
|
||||
NRF51_TIMER_MODE(HWTIMER) = NRF51_TIMER_MODE_TIMER;
|
||||
NRF51_TIMER_BITMODE(HWTIMER) = NRF51_TIMER_BITMODE_32;
|
||||
|
||||
/*
|
||||
* The external crystal oscillator is 16MHz (HFCLK).
|
||||
* Set the prescaler to 16 so that the timer counter is increasing
|
||||
* every micro-second (us).
|
||||
*/
|
||||
NRF51_TIMER0_PRESCALER = 4; /* actual value is 2**4 = 16 */
|
||||
NRF51_TIMER_PRESCALER(HWTIMER) = 4; /* actual value is 2**4 = 16 */
|
||||
|
||||
/* Not to trigger interrupt until __hw_clock_event_set() is called. */
|
||||
NRF51_TIMER0_CC0 = 0xffffffff;
|
||||
NRF51_TIMER_CC(HWTIMER, CC_INTERRUPT) = 0xffffffff;
|
||||
|
||||
/* Set to 0 so that the next overflow can trigger timer_irq(). */
|
||||
NRF51_TIMER0_CC2 = 0;
|
||||
NRF51_TIMER0_INTENSET = 1 << NRF51_TIMER_COMPARE2_BIT;
|
||||
NRF51_TIMER_CC(HWTIMER, CC_OVERFLOW) = 0;
|
||||
NRF51_TIMER_INTENSET(HWTIMER) =
|
||||
1 << NRF51_TIMER_COMPARE_BIT(CC_OVERFLOW);
|
||||
|
||||
/* Clear the timer counter */
|
||||
NRF51_TIMER0_CLEAR = 1;
|
||||
NRF51_TIMER_CLEAR(HWTIMER) = 1;
|
||||
|
||||
/* Override the count with the start value now that counting has
|
||||
* started. */
|
||||
__hw_clock_source_set(start_t);
|
||||
|
||||
/* Enable interrupt */
|
||||
task_enable_irq(NRF51_PERID_TIMER0);
|
||||
task_enable_irq(NRF51_PERID_TIMER(HWTIMER));
|
||||
|
||||
/* Start the timer */
|
||||
NRF51_TIMER0_START = 1;
|
||||
NRF51_TIMER_START(HWTIMER) = 1;
|
||||
|
||||
return NRF51_PERID_TIMER0;
|
||||
return NRF51_PERID_TIMER(HWTIMER);
|
||||
}
|
||||
|
||||
|
||||
@@ -494,55 +494,39 @@
|
||||
* Timer / Counter
|
||||
*/
|
||||
#define NRF51_TIMER0_BASE 0x40008000
|
||||
#define NRF51_TIMER_BASE(n) (NRF51_TIMER0_BASE + (n) * 0x1000)
|
||||
#define NRF51_PERID_TIMER(n) (NRF51_PERID_TIMER0 + (n))
|
||||
/* Tasks */
|
||||
#define NRF51_TIMER0_START REG32(NRF51_TIMER0_BASE + 0x000)
|
||||
#define NRF51_TIMER0_STOP REG32(NRF51_TIMER0_BASE + 0x004)
|
||||
#define NRF51_TIMER0_COUNT REG32(NRF51_TIMER0_BASE + 0x008)
|
||||
#define NRF51_TIMER0_CLEAR REG32(NRF51_TIMER0_BASE + 0x00C)
|
||||
#define NRF51_TIMER0_CAPTURE0 REG32(NRF51_TIMER0_BASE + 0x040)
|
||||
#define NRF51_TIMER0_CAPTURE1 REG32(NRF51_TIMER0_BASE + 0x044)
|
||||
#define NRF51_TIMER0_CAPTURE2 REG32(NRF51_TIMER0_BASE + 0x048)
|
||||
#define NRF51_TIMER0_CAPTURE3 REG32(NRF51_TIMER0_BASE + 0x04C)
|
||||
#define NRF51_TIMER_START(n) REG32(NRF51_TIMER_BASE(n) + 0x000)
|
||||
#define NRF51_TIMER_STOP(n) REG32(NRF51_TIMER_BASE(n) + 0x004)
|
||||
#define NRF51_TIMER_COUNT(n) REG32(NRF51_TIMER_BASE(n) + 0x008)
|
||||
#define NRF51_TIMER_CLEAR(n) REG32(NRF51_TIMER_BASE(n) + 0x00C)
|
||||
#define NRF51_TIMER_CAPTURE(n, c) REG32(NRF51_TIMER_BASE(n) + 0x040 + 4 * (c))
|
||||
/* Events */
|
||||
#define NRF51_TIMER0_COMPARE0 REG32(NRF51_TIMER0_BASE + 0x140)
|
||||
#define NRF51_TIMER0_COMPARE1 REG32(NRF51_TIMER0_BASE + 0x144)
|
||||
#define NRF51_TIMER0_COMPARE2 REG32(NRF51_TIMER0_BASE + 0x148)
|
||||
#define NRF51_TIMER0_COMPARE3 REG32(NRF51_TIMER0_BASE + 0x14C)
|
||||
#define NRF51_TIMER_COMPARE(n, c) REG32(NRF51_TIMER_BASE(n) + 0x140 + 4 * (c))
|
||||
/* Registers */
|
||||
#define NRF51_TIMER0_SHORTCUT REG32(NRF51_TIMER0_BASE + 0x200)
|
||||
#define NRF51_TIMER0_INTENSET REG32(NRF51_TIMER0_BASE + 0x304)
|
||||
#define NRF51_TIMER0_INTENCLR REG32(NRF51_TIMER0_BASE + 0x308)
|
||||
#define NRF51_TIMER0_MODE REG32(NRF51_TIMER0_BASE + 0x504)
|
||||
#define NRF51_TIMER0_BITMODE REG32(NRF51_TIMER0_BASE + 0x508)
|
||||
#define NRF51_TIMER0_PRESCALER REG32(NRF51_TIMER0_BASE + 0x510)
|
||||
#define NRF51_TIMER0_CC0 REG32(NRF51_TIMER0_BASE + 0x540)
|
||||
#define NRF51_TIMER0_CC1 REG32(NRF51_TIMER0_BASE + 0x544)
|
||||
#define NRF51_TIMER0_CC2 REG32(NRF51_TIMER0_BASE + 0x548)
|
||||
#define NRF51_TIMER0_CC3 REG32(NRF51_TIMER0_BASE + 0x54C)
|
||||
#define NRF51_TIMER_SHORTCUT(n) REG32(NRF51_TIMER_BASE(n) + 0x200)
|
||||
#define NRF51_TIMER_INTENSET(n) REG32(NRF51_TIMER_BASE(n) + 0x304)
|
||||
#define NRF51_TIMER_INTENCLR(n) REG32(NRF51_TIMER_BASE(n) + 0x308)
|
||||
#define NRF51_TIMER_MODE(n) REG32(NRF51_TIMER_BASE(n) + 0x504)
|
||||
#define NRF51_TIMER_BITMODE(n) REG32(NRF51_TIMER_BASE(n) + 0x508)
|
||||
#define NRF51_TIMER_PRESCALER(n) REG32(NRF51_TIMER_BASE(n) + 0x510)
|
||||
#define NRF51_TIMER_CC(n, c) REG32(NRF51_TIMER_BASE(n) + 0x540 + 4 * (c))
|
||||
/* For Timer.INTEN bits */
|
||||
#define NRF51_TIMER_COMPARE0_BIT ((0x140 - 0x100) / 4)
|
||||
#define NRF51_TIMER_COMPARE1_BIT ((0x144 - 0x100) / 4)
|
||||
#define NRF51_TIMER_COMPARE2_BIT ((0x148 - 0x100) / 4)
|
||||
#define NRF51_TIMER_COMPARE3_BIT ((0x14C - 0x100) / 4)
|
||||
#define NRF51_TIMER_COMPARE_BIT(n) (((0x140 - 0x100) / 4) + (n))
|
||||
/* For Timer Shortcuts */
|
||||
#define NRF51_TIMER_COMPARE0_CLEAR (1 << 0)
|
||||
#define NRF51_TIMER_COMPARE1_CLEAR (1 << 1)
|
||||
#define NRF51_TIMER_COMPARE2_CLEAR (1 << 2)
|
||||
#define NRF51_TIMER_COMPARE3_CLEAR (1 << 3)
|
||||
#define NRF51_TIMER_COMPARE0_STOP (1 << 8)
|
||||
#define NRF51_TIMER_COMPARE1_STOP (1 << 9)
|
||||
#define NRF51_TIMER_COMPARE2_STOP (1 << 10)
|
||||
#define NRF51_TIMER_COMPARE3_STOP (1 << 11)
|
||||
/* Timer Mode (NRF51_TIMER0_MODE) */
|
||||
#define NRF51_TIMER0_MODE_TIMER 0 /* reset default */
|
||||
#define NRF51_TIMER0_MODE_COUNTER 0
|
||||
#define NRF51_TIMER_COMPARE_CLEAR(n) (1 << (n))
|
||||
#define NRF51_TIMER_COMPARE_STOP(n) (1 << (8 + (n)))
|
||||
/* Timer Mode (NRF51_TIMER_MODE) */
|
||||
#define NRF51_TIMER_MODE_TIMER 0 /* reset default */
|
||||
#define NRF51_TIMER_MODE_COUNTER 1
|
||||
/* Prescaler */
|
||||
#define NRF51_TIMER0_PRESCALER_MASK (0xf) /* range: 0-9, reset default: 4 */
|
||||
/* Bit length (NRF51_TIMER0_BITMODE) */
|
||||
#define NRF51_TIMER0_BITMODE_16 0 /* reset default */
|
||||
#define NRF51_TIMER0_BITMODE_8 1
|
||||
#define NRF51_TIMER0_BITMODE_24 2
|
||||
#define NRF51_TIMER0_BITMODE_32 3
|
||||
#define NRF51_TIMER_PRESCALER_MASK (0xf) /* range: 0-9, reset default: 4 */
|
||||
/* Bit length (NRF51_TIMER_BITMODE) */
|
||||
#define NRF51_TIMER_BITMODE_16 0 /* reset default */
|
||||
#define NRF51_TIMER_BITMODE_8 1
|
||||
#define NRF51_TIMER_BITMODE_24 2
|
||||
#define NRF51_TIMER_BITMODE_32 3
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user