1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/lpc2387/hwtimer_cpu.c
Oleg Hahm 17929a5ce4 cpu: lpc2387: integrated lpc_common into lpc2387
Rationale 1: The common part made only sense for (some) NXP ARM7 MCUs,
but was misleading for MCUs like the LPC1768.

Rationale 2: The common part was only used by one specific MCU
implementation - no need to outsource it.
2014-12-02 17:47:10 +01:00

207 lines
6.5 KiB
C

/*
* Copyright (C) 2014 INRIA
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu
* @file
* @internal
* @brief ARM kernel timer CPU dependent functions implementation
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
*
*/
#include "cpu.h"
#include "bitarithm.h"
#include "hwtimer_cpu.h"
#include "arch/hwtimer_arch.h"
#include "irq.h"
#define VULP(x) ((volatile unsigned long*) (x))
/* High level interrupt handler */
static void (*int_handler)(int);
/* Timer 0-3 interrupt handler */
static void timer_irq(void) __attribute__((interrupt("IRQ")));
inline static unsigned long get_base_address(short timer)
{
return (volatile unsigned long)(TMR0_BASE_ADDR + (timer / 8) * 0x6C000 + (timer / 4 - (timer / 8) * 2) * 0x4000);
}
static void timer_irq(void)
{
short timer = 0;
if (T0IR) {
timer = 0;
}
else if (T1IR) {
timer = 4;
}
else if (T2IR) {
timer = 8;
}
volatile unsigned long base = get_base_address(timer);
if (*VULP(base + TXIR) & BIT0) {
*VULP(base + TXMCR) &= ~BIT0;
*VULP(base + TXIR) = BIT0;
int_handler(timer);
}
if (*VULP(base + TXIR) & BIT1) {
*VULP(base + TXMCR) &= ~BIT3;
*VULP(base + TXIR) = BIT1;
int_handler(timer + 1);
}
if (*VULP(base + TXIR) & BIT2) {
*VULP(base + TXMCR) &= ~BIT6;
*VULP(base + TXIR) = BIT2;
int_handler(timer + 2);
}
if (*VULP(base + TXIR) & BIT3) {
*VULP(base + TXMCR) &= ~BIT9;
*VULP(base + TXIR) = BIT3;
int_handler(timer + 3);
}
VICVectAddr = 0; /* acknowledge interrupt (if using VIC IRQ) */
}
static void timer0_init(uint32_t cpsr)
{
PCONP |= PCTIM0; /* power up timer */
T0TCR = 2; /* disable and reset timer */
T0MCR = 0; /* disable compare */
T0CCR = 0; /* capture is disabled */
T0EMR = 0; /* no external match output */
T0PR = cpsr; /* set prescaler */
install_irq(TIMER0_INT, &timer_irq, 1);
T0TCR = 1; /* reset counter */
}
static void timer1_init(uint32_t cpsr)
{
PCONP |= PCTIM1; /* power up timer */
T1TCR = 2; /* disable and reset timer */
T1MCR = 0; /* disable compare */
T1CCR = 0; /* capture is disabled */
T1EMR = 0; /* no external match output */
T1PR = cpsr; /* set prescaler */
install_irq(TIMER1_INT, &timer_irq, 1);
T1TCR = 1; /* reset counter */
}
static void timer2_init(uint32_t cpsr)
{
PCONP |= PCTIM2; /* power up timer */
T2TCR = 2; /* disable and reset timer */
T2MCR = 0; /* disable compare */
T2CCR = 0; /* capture is disabled */
T2EMR = 0; /* no external match output */
T2PR = cpsr; /* set prescaler */
install_irq(TIMER2_INT, &timer_irq, 1);
T2TCR = 1; /* reset counter */
}
void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu)
{
uint32_t cpsr;
int_handler = handler;
cpu_clock_scale(fcpu, HWTIMER_SPEED, &cpsr);
timer0_init(cpsr);
timer1_init(cpsr);
timer2_init(cpsr);
}
/*---------------------------------------------------------------------------*/
void hwtimer_arch_enable_interrupt(void)
{
VICIntEnable = 1 << TIMER0_INT; /* Enable Interrupt */
VICIntEnable = 1 << TIMER1_INT; /* Enable Interrupt */
VICIntEnable = 1 << TIMER2_INT; /* Enable Interrupt */
}
/*---------------------------------------------------------------------------*/
void hwtimer_arch_disable_interrupt(void)
{
VICIntEnClr = 1 << TIMER0_INT; /* Disable Interrupt */
VICIntEnClr = 1 << TIMER1_INT; /* Disable Interrupt */
VICIntEnClr = 1 << TIMER2_INT; /* Disable Interrupt */
}
/*---------------------------------------------------------------------------*/
void hwtimer_arch_set(unsigned long offset, short timer)
{
/* Calculate base address of timer register */
/* Timer 0-3 are matched to TIMER0 */
/* Timer 4-7 are matched to TIMER1 */
/* Timer 8-11 are matched to TIMER2 */
volatile unsigned long base = get_base_address(timer);
/* Calculate match register address of corresponding timer */
timer %= 4;
unsigned long cpsr = disableIRQ();
volatile unsigned long *addr = VULP(base + TXMR0 + 4 * timer);
/* Calculate match register value */
unsigned long value = *VULP(base + TXTC) + offset;
*addr = value; /* set match register */
*VULP(base + TXIR) = 0x01 << timer; /* reset interrupt register value for corresponding match register */
*VULP(base + TXMCR) &= ~(7 << (3 * timer)); /* Clear all bits */
*VULP(base + TXMCR) |= (MR0I << (3 * timer)); /* enable interrupt for match register */
restoreIRQ(cpsr);
}
void hwtimer_arch_set_absolute(unsigned long value, short timer)
{
/* Calculate base address of timer register */
/* Timer 0-3 are matched to TIMER0 */
/* Timer 4-7 are matched to TIMER1 */
/* Timer 8-11 are matched to TIMER2 */
volatile unsigned long base = get_base_address(timer);
/* Calculate match register address of corresponding timer */
timer %= 4;
volatile unsigned long *addr = VULP(base + TXMR0 + 4 * timer);
/* Calculate match register value */
*addr = value; /* set match register */
*VULP(base + TXIR) = 0x01 << timer; /* reset interrupt register value for corresponding match register */
*VULP(base + TXMCR) &= ~(7 << (3 * timer)); /* Clear all bits */
*VULP(base + TXMCR) |= (MR0I << (3 * timer)); /* enable interrupt for match register */
}
/*---------------------------------------------------------------------------*/
void hwtimer_arch_unset(short timer)
{
volatile unsigned long base = get_base_address(timer);
timer %= 4;
*VULP(base + TXMCR) &= ~(MR0I << (3 * timer)); /* disable interrupt for match register */
*VULP(base + TXIR) = 0x01 << timer; /* reset interrupt register value for corresponding match register */
}
/*---------------------------------------------------------------------------*/
unsigned long hwtimer_arch_now(void)
{
return T0TC;
}
void hwtimer_arch_setcounter(unsigned int val)
{
T0TC = val;
}