diff --git a/cpu/arm_common/bootloader.c b/cpu/arm_common/bootloader.c index 14813ae8bb..57707d4205 100644 --- a/cpu/arm_common/bootloader.c +++ b/cpu/arm_common/bootloader.c @@ -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(); diff --git a/cpu/arm_common/common.s b/cpu/arm_common/common.s index 66646adef4..d8bd1310f0 100644 --- a/cpu/arm_common/common.s +++ b/cpu/arm_common/common.s @@ -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 */ diff --git a/cpu/mc1322x/cpu.c b/cpu/mc1322x/cpu.c index 93f90d3a95..c937b107ed 100644 --- a/cpu/mc1322x/cpu.c +++ b/cpu/mc1322x/cpu.c @@ -1,6 +1,7 @@ /* * cpu.c - MC1322X architecture common support functions * Copyright (C) 2013 Oliver Hahm + * Copyright (C) 2013 Thomas Eichinger * * This source code is licensed under the GNU Lesser General Public License, * Version 2. See the file LICENSE for more details. @@ -10,7 +11,9 @@ */ #include "mc1322x.h" +#include "cpu.h" #include "lpm.h" +#include "arm_cpu.h" __attribute__((naked,noreturn)) void arm_reset(void) { @@ -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); +} diff --git a/cpu/mc1322x/hwtimer_cpu.c b/cpu/mc1322x/hwtimer_cpu.c index 4f53f4d42a..6107426d96 100644 --- a/cpu/mc1322x/hwtimer_cpu.c +++ b/cpu/mc1322x/hwtimer_cpu.c @@ -11,15 +11,48 @@ #include #include "mc1322x.h" +#include "cpu.h" #include "hwtimer_arch.h" #include "irq.h" +#include + /* 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 */ @@ -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) { @@ -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(); } /*---------------------------------------------------------------------------*/ @@ -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<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<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<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<SCTRLbits.TCFIE = 1; /* enable interrupts when TCF is one - do we need both?*/ - /* restor status register */ + /* restore status register */ restoreIRQ(cpsr); } diff --git a/cpu/mc1322x/include/cpu.h b/cpu/mc1322x/include/cpu.h index f37db452d5..82b307bf4a 100644 --- a/cpu/mc1322x/include/cpu.h +++ b/cpu/mc1322x/include/cpu.h @@ -15,10 +15,18 @@ #ifndef CPU_H #define CPU_H -#include +/** + * @defgroup mc1322x Freescale mc1322x + * @ingroup cpu + * @{ + */ + +#include #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 */ diff --git a/cpu/mc1322x/include/mc1322x.h b/cpu/mc1322x/include/mc1322x.h index 20409bf445..d8c7c74e0d 100644 --- a/cpu/mc1322x/include/mc1322x.h +++ b/cpu/mc1322x/include/mc1322x.h @@ -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)); @@ -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 */ diff --git a/cpu/mc1322x/isr.c b/cpu/mc1322x/isr.c new file mode 100644 index 0000000000..5023ecef5b --- /dev/null +++ b/cpu/mc1322x/isr.c @@ -0,0 +1,45 @@ +/* + * isr.c - mc1322x specific isr + * Copyright (C) 2013 Thomas Eichinger + * + * 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])(); + } + } +} diff --git a/cpu/mc1322x/startup.s b/cpu/mc1322x/startup.s index 30edd9a37c..c454a6cd80 100644 --- a/cpu/mc1322x/startup.s +++ b/cpu/mc1322x/startup.s @@ -33,7 +33,7 @@ * */ - + /* The following lincence is for all parts of this code done by Martin Thomas. Code from others used here may have other license terms. @@ -57,56 +57,63 @@ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - + +/* + * startup.s - mc1322x specific startup code + * Copyright (C) 2013 Thomas Eichinger + * + * 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. + */ + /* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs (program status registers) */ -.set MODE_USR, 0x10 /* Normal User Mode */ -.set MODE_FIQ, 0x11 /* FIQ Processing Fast Interrupts Mode */ -.set MODE_IRQ, 0x12 /* IRQ Processing Standard Interrupts Mode */ -.set MODE_SVC, 0x13 /* Supervisor Processing Software Interrupts Mode */ -.set MODE_ABT, 0x17 /* Abort Processing memory Faults Mode */ -.set MODE_UND, 0x1B /* Undefined Processing Undefined Instructions Mode */ -.set MODE_SYS, 0x1F /* System Running Priviledged Operating System Tasks Mode */ +.set USR_MODE, 0x10 /* Normal User Mode */ +.set FIQ_MODE, 0x11 /* FIQ Processing Fast Interrupts Mode */ +.set IRQ_MODE, 0x12 /* IRQ Processing Standard Interrupts Mode */ +.set SVC_MODE, 0x13 /* Supervisor Processing Software Interrupts Mode */ +.set ABT_MODE, 0x17 /* Abort Processing memory Faults Mode */ +.set UND_MODE, 0x1B /* Undefined Processing Undefined Instructions Mode */ +.set SYS_MODE, 0x1F /* System Running Priviledged Operating System Tasks Mode */ -.set I_BIT, 0x80 /* when I bit is set, IRQ is disabled (program status registers) */ -.set F_BIT, 0x40 /* when F bit is set, FIQ is disabled (program status registers) */ +.set IRQ_DISABLE, 0x80 /* when I bit is set, IRQ is disabled (program status registers) */ +.set FIQ_DISABLE, 0x40 /* when F bit is set, FIQ is disabled (program status registers) */ - .section .startup - + .section .startup + .set _rom_data_init, 0x108d0 .global _startup .func _startup _startup: b _begin /* reset - _start */ - ldr PC, Undef_Addr /* Undefined Instruction */ - ldr PC, SWI_Addr /* Software Interrupt */ - ldr PC, PAbt_Addr /* Prefetch Abort */ - ldr PC, DAbt_Addr /* Data Abort */ - nop /* Reserved Vector (holds Philips ISP checksum) */ - - /* see page 71 of "Insiders Guide to the Philips ARM7-Based Microcontrollers" by Trevor Martin */ - /* ldr PC, [PC,#-0x0120] /* Interrupt Request Interrupt (load from VIC) */ - ldr PC, IRQ_Addr /* Interrupt Request Interrupt (load from VIC) */ - ldr r0, =__fiq_handler /* Fast Interrupt Request Interrupt */ + ldr PC, Undef_Addr /* Undefined Instruction */ + ldr PC, SWI_Addr /* Software Interrupt */ + ldr PC, PAbt_Addr /* Prefetch Abort */ + ldr PC, DAbt_Addr /* Data Abort */ + ldr PC, _not_used + ldr PC, IRQ_Addr /* Interrupt Request Interrupt (load from VIC) */ + ldr PC, _fiq - /* these vectors are used for rom patching */ + /* these vectors are used for rom patching */ .org 0x20 .code 16 _RPTV_0_START: - bx lr /* do nothing */ + bx lr /* do nothing */ .org 0x60 _RPTV_1_START: - bx lr /* do nothing */ + bx lr /* do nothing */ .org 0xa0 _RPTV_2_START: - bx lr /* do nothing */ + bx lr /* do nothing */ .org 0xe0 _RPTV_3_START: - bx lr /* do nothing */ + bx lr /* do nothing */ .org 0x120 ROM_var_start: .word 0 @@ -114,40 +121,40 @@ ROM_var_start: .word 0 ROM_var_end: .word 0 .code 32 -.align -_begin: - /* FIQ mode stack */ - msr CPSR_c, #(MODE_FIQ | I_BIT | F_BIT) - ldr sp, =__fiq_stack_top__ /* set the FIQ stack pointer */ +.align +_begin: + /* FIQ mode stack */ + msr CPSR_c, #(FIQ_MODE | IRQ_DISABLE | FIQ_DISABLE) + ldr sp, =__fiq_stack_top__ /* set the FIQ stack pointer */ - /* IRQ mode stack */ - msr CPSR_c, #(MODE_IRQ | I_BIT | F_BIT) - ldr sp, =__irq_stack_top__ /* set the IRQ stack pointer */ + /* IRQ mode stack */ + msr CPSR_c, #(IRQ_MODE | IRQ_DISABLE | FIQ_DISABLE) + ldr sp, =__irq_stack_top__ /* set the IRQ stack pointer */ - /* Supervisor mode stack */ - msr CPSR_c, #(MODE_SVC | I_BIT | F_BIT) - ldr sp, =__svc_stack_top__ /* set the SVC stack pointer */ + /* Supervisor mode stack */ + msr CPSR_c, #(SVC_MODE | IRQ_DISABLE | FIQ_DISABLE) + ldr sp, =__svc_stack_top__ /* set the SVC stack pointer */ - /* Undefined mode stack */ - msr CPSR_c, #(MODE_UND | I_BIT | F_BIT) - ldr sp, =__und_stack_top__ /* set the UND stack pointer */ + /* Undefined mode stack */ + msr CPSR_c, #(UND_MODE | IRQ_DISABLE | FIQ_DISABLE) + ldr sp, =__und_stack_top__ /* set the UND stack pointer */ - /* Abort mode stack */ - msr CPSR_c, #(MODE_ABT | I_BIT | F_BIT) - ldr sp, =__abt_stack_top__ /* set the ABT stack pointer */ + /* Abort mode stack */ + msr CPSR_c, #(ABT_MODE | IRQ_DISABLE | FIQ_DISABLE) + ldr sp, =__abt_stack_top__ /* set the ABT stack pointer */ - /* System mode stack */ - msr CPSR_c, #(MODE_SYS | I_BIT | F_BIT) - ldr sp, =__sys_stack_top__ /* set the SYS stack pointer */ + /* System mode stack */ + msr CPSR_c, #(SYS_MODE | IRQ_DISABLE | FIQ_DISABLE) + ldr sp, =__sys_stack_top__ /* set the SYS stack pointer */ - /* call the rom_data_init function in ROM */ - /* initializes ROM_var space defined by ROM_var_start and ROM_var_end */ - /* this area is used by ROM functions (e.g. nvm_read) */ - ldr r12,=_rom_data_init - mov lr,pc - bx r12 + /* call the rom_data_init function in ROM */ + /* initializes ROM_var space defined by ROM_var_start and ROM_var_end */ + /* this area is used by ROM functions (e.g. nvm_read) */ + ldr r12,=_rom_data_init + mov lr,pc + bx r12 - msr CPSR_c, #(MODE_SYS) + msr CPSR_c, #(SYS_MODE) /* Clear BSS */ clear_bss: @@ -160,17 +167,18 @@ clbss_l: cmp r0, r1 blt clbss_l - b main + bl bootloader + b kernel_init /* Exception vector handlers branching table */ -Undef_Addr: .word UNDEF_Routine /* defined in main.c */ -SWI_Addr: .word ctx_switch /* defined in main.c */ -PAbt_Addr: .word PABT_Routine /* defined in main.c */ -DAbt_Addr: .word DABT_Routine /* defined in main.c */ -IRQ_Addr: .word arm_irq_handler /* defined in main.c */ -__fiq_handler: .word __fiq /* FIQ */ - -__fiq: b . /* FIQ */ +Undef_Addr: .word UNDEF_Routine +SWI_Addr: .word ctx_switch +PAbt_Addr: .word PABT_Routine +DAbt_Addr: .word DABT_Routine +_not_used: .word not_used +IRQ_Addr: .word arm_irq_handler +_fiq: .word fiq + .balignl 16, 0xdeadbeef /* * These are defined in the board-specific linker script. @@ -179,6 +187,17 @@ __fiq: b . /* FIQ */ _bss_start: .word __bss_start - .globl _bss_end + .globl _bss_end _bss_end: .word _end + +.align 5 +not_used: + + .align 5 +/*irq: +// +// .align 5*/ +fiq: + + .align 5