Skip to content

Commit

Permalink
Merge pull request #262 from thomaseichinger/vic
Browse files Browse the repository at this point in the history
mc1322x change to a VIC like interrupt system
  • Loading branch information
OlegHahm committed Dec 18, 2013
2 parents 41da848 + 0afb992 commit 6d2ed29
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 88 deletions.
2 changes: 2 additions & 0 deletions cpu/arm_common/bootloader.c
Expand Up @@ -174,7 +174,9 @@ void bootloader(void)
bl_init_clks();

/* initialize bss and data */
#if CPU != mc1322x
bl_init_data();
#endif

/* board specific setup of i/o pins */
bl_init_ports();
Expand Down
7 changes: 6 additions & 1 deletion cpu/arm_common/common.s
Expand Up @@ -136,11 +136,16 @@ arm_irq_handler:
MRS R1, CPSR
MSR SPSR, R1

#if CPU != mc1322x
/* jump into vic interrupt */
mov r0, #0xffffff00 /* lpc23xx */

ldr r0, [r0]
add lr,pc,#4
#else
/* mc1322x seems to lack a VIC, distinction of IRQ has to be done in SW */
ldr r0, =isr /* mc1322x */
#endif

mov pc, r0

/* restore spsr from stack */
Expand Down
23 changes: 23 additions & 0 deletions cpu/mc1322x/cpu.c
@@ -1,6 +1,7 @@
/*
* cpu.c - MC1322X architecture common support functions
* Copyright (C) 2013 Oliver Hahm <oliver.hahm@inria.fr>
* Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de>
*
* This source code is licensed under the GNU Lesser General Public License,
* Version 2. See the file LICENSE for more details.
Expand All @@ -10,7 +11,9 @@
*/

#include "mc1322x.h"
#include "cpu.h"
#include "lpm.h"
#include "arm_cpu.h"

__attribute__((naked,noreturn)) void arm_reset(void)
{
Expand All @@ -20,5 +23,25 @@ __attribute__((naked,noreturn)) void arm_reset(void)
}

enum lpm_mode lpm_set(enum lpm_mode target) {
(void) target;
return LPM_ON;
}

/******************************************************************************
** Function name: install_irq
**
** Descriptions: Install interrupt handler.
** A wrapper to register_isr to be consistant to lpc2387
** implementation.
** parameters: Interrupt number, interrupt handler address,
** interrupt priority
** Returned value: true or false, return false if IntNum is out of range
**
******************************************************************************/

bool install_irq(int int_number, void *handler_addr, int priority)
{
(void) priority;
register_isr(int_number, handler_addr);
return (true);
}
68 changes: 53 additions & 15 deletions cpu/mc1322x/hwtimer_cpu.c
Expand Up @@ -11,15 +11,48 @@

#include <stdint.h>
#include "mc1322x.h"
#include "cpu.h"
#include "hwtimer_arch.h"
#include "irq.h"

#include <stdio.h>

/* High level interrupt handler */
static void (*int_handler)(int);

#define TMRx_ANY_INTERRUPT 0xa800

void tmr_isr(void) {
/* detemine which timer caused the interrupt */
if (TMR0->SCTRLbits.TCF && TMR0->SCTRLbits.TCFIE) {
TMR0->SCTRLbits.TCF = 0;
TMR0->CSCTRLbits.TCF1 = 0;
TMR0->ENBL &= ~(1<<0);
int_handler(0);
}
else if (TMR1->SCTRLbits.TCF && TMR1->SCTRLbits.TCFIE) {
TMR1->SCTRLbits.TCF = 0;
TMR1->CSCTRLbits.TCF1 = 0;
TMR0->ENBL &= ~(1<<1);
int_handler(1);
}
else if (TMR2->SCTRLbits.TCF && TMR2->SCTRLbits.TCFIE) {
TMR2->SCTRLbits.TCF = 0;
TMR2->CSCTRLbits.TCF1 = 0;
TMR0->ENBL &= ~(1<<2);
int_handler(2);
}
else if (TMR3->SCTRLbits.TCF && TMR3->SCTRLbits.TCFIE) {
TMR3->SCTRLbits.TCF = 0;
TMR3->CSCTRLbits.TCF1 = 0;
TMR0->ENBL &= ~(1<<3);
int_handler(3);
}
}

void timer_x_init(volatile struct TMR_struct* const TMRx) {
/* Reset the timer */
TMRx->ENBL = 0;

/* Clear status */
TMRx->SCTRL = 0;
/* disable interrupt */
Expand All @@ -32,21 +65,17 @@ void timer_x_init(volatile struct TMR_struct* const TMRx) {
TMRx->CMPLD1 = 0;

/* set counter to zero */
TMRx->CNTR = 0;
TMRx->CNTR = TMRx->LOAD;

/* set timer control bits */
TMRx->CTRLbits.COUNT_MODE = 1; /* use rising edge of primary source */
TMRx->CTRLbits.PRIMARY_CNT_SOURCE = 0x0f; /* Perip. clock with 128 prescale (for 24MHz = 187500Hz) */
TMRx->CTRLbits.SECONDARY_CNT_SOURCE = 0x00; /* don't need this */
TMRx->CTRLbits.ONCE = 0x00; /* keep counting */
TMRx->CTRLbits.ONCE = 0x01; /* don't keep counting */
TMRx->CTRLbits.LENGTH = 0x00; /* continue counting */
TMRx->CTRLbits.DIR = 0x00; /* count up */
TMRx->CTRLbits.CO_INIT = 0x00; /* other counters cannot force a reinitialization of this counter*/
TMRx->CTRLbits.OUTPUT_MODE = 0x00; /* OFLAG is asserted while counter is active */

TMRx->ENBL = 0xf; /* enable all the timers --- why not? */

/* TODO: install ISR */
}

void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu) {
Expand All @@ -55,10 +84,15 @@ void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu) {
/* TODO: do scaling voodoo */
(void) fcpu;

/* disable all timers */
TMR0->ENBL = 0;
timer_x_init(TMR0);
timer_x_init(TMR1);
timer_x_init(TMR2);
timer_x_init(TMR3);

register_isr(INT_NUM_TMR, &tmr_isr);
hwtimer_arch_enable_interrupt();
}

/*---------------------------------------------------------------------------*/
Expand All @@ -74,40 +108,44 @@ void hwtimer_arch_disable_interrupt(void) {
/* this disables timer interrupts in general by using the ITC.
* Timer specific interrupt control is given by the TMRx structs. */
//disable_irq(INT_NUM_TMR);
ITC->INTENABLEbits.TMR = 1;
ITC->INTENABLEbits.TMR = 0;
}

/*---------------------------------------------------------------------------*/
void hwtimer_arch_set(unsigned long offset, short timer) {
/* get corresponding struct for the given ::timer parameter */
struct TMR_struct* tmr = (void *) TMR_BASE + (timer + TMR_OFFSET);
struct TMR_struct* tmr = (void *) TMR_BASE + (timer * TMR_OFFSET);

/* disable IRQs and save the status register */
unsigned long cpsr = disableIRQ();

uint32_t cpsr = disableIRQ();

TMR0->ENBL &= ~(1<<timer); /* disable timer */
tmr->COMP1 = tmr->CNTR + offset; /* load the current value + offset into the compare register */
tmr->CSCTRLbits.TCF1 = 0; /* reset compare flag */
tmr->CSCTRLbits.TCF1EN = 1; /* enable intterupts when TCF1 is set \ */
TMR0->ENBL |= (1<<timer); /* enable timer */
tmr->SCTRLbits.TCFIE = 1; /* enable interrupts when TCF is one - do we need both?*/

/* restor status register */
/* restore status register */
restoreIRQ(cpsr);
}

/*---------------------------------------------------------------------------*/
void hwtimer_arch_set_absolute(unsigned long value, short timer) {
/* get corresponding struct for the given ::timer parameter */
struct TMR_struct* tmr = (void *) TMR_BASE + (timer + TMR_OFFSET);
struct TMR_struct* tmr = (void *) TMR_BASE + (timer * TMR_OFFSET);

/* disable IRQs and save the status register */
unsigned long cpsr = disableIRQ();
uint32_t cpsr = disableIRQ();

TMR0->ENBL &= ~(1<<timer); /* disable timer */
tmr->COMP1 = value; /* load the value into the compare register */
tmr->CSCTRLbits.TCF1 = 0; /* reset compare flag */
tmr->CSCTRLbits.TCF1EN = 1; /* enable interrupts when TCF1 is set \ */
TMR0->ENBL |= (1<<timer); /* enable timer */
tmr->SCTRLbits.TCFIE = 1; /* enable interrupts when TCF is one - do we need both?*/

/* restor status register */
/* restore status register */
restoreIRQ(cpsr);
}

Expand Down
12 changes: 10 additions & 2 deletions cpu/mc1322x/include/cpu.h
Expand Up @@ -15,10 +15,18 @@
#ifndef CPU_H
#define CPU_H

#include <stdint.h>
/**
* @defgroup mc1322x Freescale mc1322x
* @ingroup cpu
* @{
*/

#include <stdbool.h>
#include "arm_cpu.h"
#include "mc1322x.h"

extern uintptr_t __stack_start; ///< end of user stack memory space
extern uintptr_t __stack_start; ///< end of user stack memory space
bool install_irq(int int_number, void *handler_addr, int priority);

/** @} */
#endif /* CPU_H */
15 changes: 11 additions & 4 deletions cpu/mc1322x/include/mc1322x.h
Expand Up @@ -415,12 +415,11 @@ enum interrupt_nums {
x; \
__int_enable(); } while(0)

extern void register_isr(uint8_t interrupt, void (*isr)(void));

extern void tmr0_isr(void) __attribute__((weak));
extern void tmr1_isr(void) __attribute__((weak));
extern void tmr2_isr(void) __attribute__((weak));
extern void tmr3_isr(void) __attribute__((weak));
extern void tmr_isr(void) __attribute__((weak));

extern void crm_isr(void) __attribute__((weak));
extern void rtc_isr(void) __attribute__((weak));
extern void kbi4_isr(void) __attribute__((weak));
extern void kbi5_isr(void) __attribute__((weak));
Expand All @@ -438,4 +437,12 @@ extern void asm_isr(void) __attribute__((weak));

extern void i2c_isr(void) __attribute__((weak));

extern void spif_isr(void) __attribute__((weak));

extern void ssi_isr(void) __attribute__((weak));

extern void adc_isr(void) __attribute__((weak));

extern void spi_isr(void) __attribute__((weak));

#endif /* MC1322X_H */
45 changes: 45 additions & 0 deletions cpu/mc1322x/isr.c
@@ -0,0 +1,45 @@
/*
* isr.c - mc1322x specific isr
* Copyright (C) 2013 Thomas Eichinger <thomas.eichinger@fu-berlin.de>
*
* This source code is licensed under the GNU Lesser General Public License,
* Version 2. See the file LICENSE for more details.
*
* This file is part of RIOT.
*/

#include "mc1322x.h"

#define MAX_IRQ_INDEX 10

static void (*isr_funcs[11])(void) = {
asm_isr,
uart1_isr,
uart2_isr,
crm_isr,
i2c_isr,
tmr_isr,
spif_isr,
maca_isr,
ssi_isr,
adc_isr,
spi_isr
};

void register_isr(uint8_t interrupt, void (*isr)(void)) {
if (interrupt <= MAX_IRQ_INDEX) {
isr_funcs[interrupt] = isr;
}
}

void isr(void)
{
/* pending interrupt? */
while (ITC->NIPEND) {
/* get interrupt source, range 0-10 */
/* call corresponding ISR */
if (isr_funcs[ITC->NIVECTOR]) {
(isr_funcs[ITC->NIVECTOR])();
}
}
}

0 comments on commit 6d2ed29

Please sign in to comment.