From f4f84ffca47715e09d6b4d9dfc25bc3d21b40ad0 Mon Sep 17 00:00:00 2001 From: Niclas Finne Date: Fri, 23 Sep 2011 15:01:13 +0200 Subject: [PATCH] Updated SPI config for faster SPI, split msp430/clock/spi into separate versions for MSP430/MSP430X --- cpu/msp430/Makefile.msp430 | 6 +- cpu/msp430/cc2520-arch.c | 6 +- cpu/msp430/{ => f1xxx}/clock.c | 115 ++------- cpu/msp430/{ => f1xxx}/msp430.c | 46 +--- cpu/msp430/{ => f1xxx}/rtimer-arch.c | 41 +-- cpu/msp430/{ => f1xxx}/spi.c | 0 cpu/msp430/{ => f1xxx}/spix.c | 82 +++--- cpu/msp430/f5xxx/clock.c | 229 +++++++++++++++++ cpu/msp430/f5xxx/msp430.c | 238 ++++++++++++++++++ cpu/msp430/f5xxx/rtimer-arch.c | 107 ++++++++ {platform/wismote => cpu/msp430/f5xxx}/spix.c | 35 ++- cpu/msp430/rtimer-arch.h | 4 + platform/wismote/contiki-wismote-main.c | 2 - platform/wismote/platform-conf.h | 3 +- 14 files changed, 677 insertions(+), 237 deletions(-) rename cpu/msp430/{ => f1xxx}/clock.c (71%) rename cpu/msp430/{ => f1xxx}/msp430.c (91%) rename cpu/msp430/{ => f1xxx}/rtimer-arch.c (84%) rename cpu/msp430/{ => f1xxx}/spi.c (100%) rename cpu/msp430/{ => f1xxx}/spix.c (63%) create mode 100644 cpu/msp430/f5xxx/clock.c create mode 100644 cpu/msp430/f5xxx/msp430.c create mode 100644 cpu/msp430/f5xxx/rtimer-arch.c rename {platform/wismote => cpu/msp430/f5xxx}/spix.c (62%) diff --git a/cpu/msp430/Makefile.msp430 b/cpu/msp430/Makefile.msp430 index 328089406..73dc45d98 100644 --- a/cpu/msp430/Makefile.msp430 +++ b/cpu/msp430/Makefile.msp430 @@ -11,7 +11,11 @@ CONTIKI_CPU=$(CONTIKI)/cpu/msp430 ### Define the source files we have in the MSP430 port -CONTIKI_CPU_DIRS = . dev +ifneq (,$(findstring msp430x5,$(MCU))) +CONTIKI_CPU_DIRS = ${addprefix f5xxx/,. dev} . dev +else +CONTIKI_CPU_DIRS = ${addprefix f1xxx/,. dev} . dev +endif MSP430 = msp430.c flash.c clock.c leds.c leds-arch.c \ watchdog.c lpm.c mtarch.c rtimer-arch.c diff --git a/cpu/msp430/cc2520-arch.c b/cpu/msp430/cc2520-arch.c index be73a9ab5..f6613dade 100644 --- a/cpu/msp430/cc2520-arch.c +++ b/cpu/msp430/cc2520-arch.c @@ -73,8 +73,10 @@ cc2520_arch_init(void) CC2520_VREG_PORT(DIR) |= BV(CC2520_VREG_PIN); CC2520_RESET_PORT(DIR) |= BV(CC2520_RESET_PIN); - P1DIR &= ~(BV(CC2520_FIFOP_PIN) | BV(CC2520_FIFO_PIN) | BV(CC2520_CCA_PIN)); - P2DIR &= ~(BV(CC2520_SFD_PIN)); + CC2520_FIFOP_PORT(DIR) &= ~(BV(CC2520_FIFOP_PIN)); + CC2520_FIFO_PORT(DIR) &= ~(BV(CC2520_FIFO_PIN)); + CC2520_CCA_PORT(DIR) &= ~(BV(CC2520_CCA_PIN)); + CC2520_SFD_PORT(DIR) &= ~(BV(CC2520_SFD_PIN)); #if CONF_SFD_TIMESTAMPS cc2520_arch_sfd_init(); diff --git a/cpu/msp430/clock.c b/cpu/msp430/f1xxx/clock.c similarity index 71% rename from cpu/msp430/clock.c rename to cpu/msp430/f1xxx/clock.c index 556fb6e82..5686f3fe9 100644 --- a/cpu/msp430/clock.c +++ b/cpu/msp430/f1xxx/clock.c @@ -27,11 +27,8 @@ * SUCH DAMAGE. * * This file is part of the Contiki operating system. - * - * @(#)$Id: clock.c,v 1.26 2010/12/16 22:50:21 adamdunkels Exp $ */ - #include "contiki.h" #include "sys/energest.h" #include "sys/clock.h" @@ -49,60 +46,6 @@ static volatile clock_time_t count = 0; /* last_tar is used for calculating clock_fine */ static volatile uint16_t last_tar = 0; /*---------------------------------------------------------------------------*/ -#if CONTIKI_TARGET_WISMOTE -#ifdef __IAR_SYSTEMS_ICC__ -#pragma vector=TIMER1_A1_VECTOR -__interrupt void -#else -interrupt(TIMER1_A1_VECTOR) -#endif -timera1 (void) -{ - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - watchdog_start(); - - if(TA1IV == 2) { //CCR1 - - // HW timer bug fix: Interrupt handler called before TR==CCR. - // Occurrs when timer state is toggled between STOP and CONT. - while(TA1CTL & MC1 && TA1CCR1 - TA1R == 1); - - // Make sure interrupt time is futures - do { - TA1CCR1 += INTERVAL; - ++count; - - /* Make sure the CLOCK_CONF_SECOND is a power of two, to ensure - that the modulo operation below becomes a logical and and not - an expensive divide. Algorithm from Wikipedia: - http://en.wikipedia.org/wiki/Power_of_two */ -#if (CLOCK_CONF_SECOND & (CLOCK_CONF_SECOND - 1)) != 0 -#error CLOCK_CONF_SECOND must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...). -#error Change CLOCK_CONF_SECOND in contiki-conf.h. -#endif - if(count % CLOCK_CONF_SECOND == 0) { - ++seconds; - energest_flush(); - } - } while((TA1CCR1 - TA1R) > INTERVAL); - - last_tar = TA1R; - - if(etimer_pending() && - (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { - etimer_request_poll(); - LPM4_EXIT; - } - - } - /*if(process_nevents() >= 0) { - LPM4_EXIT; - }*/ - watchdog_stop(); - ENERGEST_OFF(ENERGEST_TYPE_IRQ); -} -#else #ifdef __IAR_SYSTEMS_ICC__ #pragma vector=TIMERA1_VECTOR __interrupt void @@ -118,7 +61,7 @@ timera1 (void) if(TAIV == 2) { /* HW timer bug fix: Interrupt handler called before TR==CCR. - * Occurrs when timer state is toggled between STOP and CONT. */ + * Occurs when timer state is toggled between STOP and CONT. */ while(TACTL & MC1 && TACCR1 - TAR == 1); /* Make sure interrupt time is future */ @@ -154,10 +97,9 @@ timera1 (void) }*/ watchdog_stop(); - + ENERGEST_OFF(ENERGEST_TYPE_IRQ); } -#endif /*---------------------------------------------------------------------------*/ clock_time_t clock_time(void) @@ -173,13 +115,8 @@ clock_time(void) void clock_set(clock_time_t clock, clock_time_t fclock) { -#if CONTIKI_TARGET_WISMOTE - TA1R = fclock; - TA1CCR1 = fclock + INTERVAL; -#else TAR = fclock; TACCR1 = fclock + INTERVAL; -#endif count = clock; } /*---------------------------------------------------------------------------*/ @@ -196,42 +133,14 @@ clock_fine(void) /* Assign last_tar to local varible that can not be changed by interrupt */ t = last_tar; /* perform calc based on t, TAR will not be changed during interrupt */ -#if CONTIKI_TARGET_WISMOTE - return (unsigned short) (TA1R - t); -#else return (unsigned short) (TAR - t); -#endif } /*---------------------------------------------------------------------------*/ void clock_init(void) { dint(); -#if CONTIKI_TARGET_WISMOTE - /* Select SMCLK (2.4576MHz), clear TAR */ - //TA1CTL = TASSEL1 | TACLR | ID_3; - /* Select ACLK clock, divide*/ - /* TA1CTL = TASSEL0 | TACLR | ID_1; */ - -#if INTERVAL==32768/CLOCK_SECOND - TA1CTL = TASSEL0 | TACLR; -#elif INTERVAL==16384/CLOCK_SECOND - TA1CTL = TASSEL0 | TACLR | ID_1; -#else -#error NEED TO UPDATE clock.c to match interval! -#endif - - /* Initialize ccr1 to create the X ms interval. */ - /* CCR1 interrupt enabled, interrupt occurs when timer equals CCR1. */ - TA1CCTL1 = CCIE; - - /* Interrupt after X ms. */ - TA1CCR1 = INTERVAL; - - /* Start Timer_A in continuous mode. */ - TA1CTL |= MC1; -#else /* Select SMCLK (2.4576MHz), clear TAR */ /* TACTL = TASSEL1 | TACLR | ID_3; */ @@ -250,7 +159,7 @@ clock_init(void) #endif /* Initialize ccr1 to create the X ms interval. */ - /* CCR1 interrupt enabled, interrupt occurs when timer equals CCR1. */ + /* CCR1 interrupt enabled, interrupt occurs when timer equals CCR. */ TACCTL1 = CCIE; /* Interrupt after X ms. */ @@ -258,7 +167,7 @@ clock_init(void) /* Start Timer_A in continuous mode. */ TACTL |= MC1; -#endif + count = 0; /* Enable interrupts. */ @@ -293,7 +202,10 @@ clock_wait(int i) void clock_set_seconds(unsigned long sec) { - + int s; + s = splhigh(); + seconds = sec; + splx(s); } /*---------------------------------------------------------------------------*/ unsigned long @@ -310,10 +222,11 @@ clock_seconds(void) rtimer_clock_t clock_counter(void) { -#if CONTIKI_TARGET_WISMOTE - return TA1R; -#else - return TAR; -#endif + rtimer_clock_t t1, t2; + do { + t1 = TAR; + t2 = TAR; + } while(t1 != t2); + return t1; } /*---------------------------------------------------------------------------*/ diff --git a/cpu/msp430/msp430.c b/cpu/msp430/f1xxx/msp430.c similarity index 91% rename from cpu/msp430/msp430.c rename to cpu/msp430/f1xxx/msp430.c index 26c816461..eb0ca5515 100644 --- a/cpu/msp430/msp430.c +++ b/cpu/msp430/f1xxx/msp430.c @@ -28,18 +28,18 @@ * * This file is part of the Contiki operating system. */ + #include "contiki.h" #include "dev/watchdog.h" -#if DCOSYNCH_CONF_ENABLED /* dco_required set to 1 will cause the CPU not to go into sleep modes where the DCO clock stopped */ int msp430_dco_required; -#endif /* DCOSYNCH_CONF_ENABLED */ #if defined(__MSP430__) && defined(__GNUC__) #define asmv(arg) __asm__ __volatile__(arg) #endif + /*---------------------------------------------------------------------------*/ #if defined(__MSP430__) && defined(__GNUC__) && MSP430_MEMCPY_WORKAROUND void * @@ -71,27 +71,6 @@ w_memset(void *out, int value, size_t n) void msp430_init_dco(void) { -#ifdef __MSP430X__ - -#ifdef __IAR_SYSTEMS_ICC__ - __bis_SR_register(SCG0); -#else - asmv("bis %0, r2" : : "i" (SCG0)); -#endif - - UCSCTL0 = 0x0000; - UCSCTL1 = DCORSEL_4; - - UCSCTL2 = MSP430_CPU_SPEED / 32768; - UCSCTL4 = 0x33; /* instead of 0x44 that is DCO/2 */ - -#ifdef __IAR_SYSTEMS_ICC__ - __bic_SR_register(SCG0); -#else - asmv("bic %0, r2" : : "i" (SCG0)); -#endif - -#else /* This code taken from the FU Berlin sources and reformatted. */ #define DELTA ((MSP430_CPU_SPEED) / (32768 / 8)) @@ -109,8 +88,8 @@ msp430_init_dco(void) asm("nop"); } - CCTL2 = CCIS0 + CM0 + CAP; // Define CCR2, CAP, ACLK - TACTL = TASSEL1 + TACLR + MC1; // SMCLK, continous mode + CCTL2 = CCIS0 + CM0 + CAP; /* Define CCR2, CAP, ACLK */ + TACTL = TASSEL1 + TACLR + MC1; /* SMCLK, continous mode */ while(1) { @@ -141,15 +120,13 @@ msp430_init_dco(void) TACTL = 0; /* Stop Timer_A */ BCSCTL1 &= ~(DIVA1 + DIVA0); /* remove /8 divisor from ACLK again */ - -#endif } /*---------------------------------------------------------------------------*/ - static void init_ports(void) { /* Turn everything off, device drivers enable what is needed. */ + /* All configured for digital I/O */ #ifdef P1SEL P1SEL = 0; @@ -227,21 +204,17 @@ static char *cur_break = (char *)&_end; void msp430_add_lpm_req(int req) { -#if DCOSYNCH_CONF_ENABLED if(req <= MSP430_REQUIRE_LPM1) { msp430_dco_required++; } -#endif /* DCOSYNCH_CONF_ENABLED */ } void msp430_remove_lpm_req(int req) { -#if DCOSYNCH_CONF_ENABLED if(req <= MSP430_REQUIRE_LPM1) { msp430_dco_required--; } -#endif /* DCOSYNCH_CONF_ENABLED */ } void @@ -258,14 +231,11 @@ msp430_cpu_init(void) } #endif -#if DCOSYNCH_CONF_ENABLED msp430_dco_required = 0; -#endif /* DCOSYNCH_CONF_ENABLED */ } /*---------------------------------------------------------------------------*/ #define STACK_EXTRA 32 -#define asmv(arg) __asm__ __volatile__(arg) /* * Allocate memory from the heap. Check that we don't collide with the @@ -357,13 +327,13 @@ msp430_sync_dco(void) { /* start the timer */ TBCTL |= MC1; - // wait for next Capture + /* wait for next Capture */ TBCCTL6 &= ~CCIFG; while(!(TBCCTL6 & CCIFG)); last = TBCCR6; TBCCTL6 &= ~CCIFG; - // wait for next Capture - and calculate difference + /* wait for next Capture - and calculate difference */ while(!(TBCCTL6 & CCIFG)); diff = TBCCR6 - last; @@ -381,7 +351,7 @@ msp430_sync_dco(void) { if(DCOCTL == 0xFF) { /* Did DCO role under? */ BCSCTL1--; } - } else if (DELTA_2 > diff) { + } else if(DELTA_2 > diff) { DCOCTL++; if(DCOCTL == 0x00) { /* Did DCO role over? */ BCSCTL1++; diff --git a/cpu/msp430/rtimer-arch.c b/cpu/msp430/f1xxx/rtimer-arch.c similarity index 84% rename from cpu/msp430/rtimer-arch.c rename to cpu/msp430/f1xxx/rtimer-arch.c index 50e6a2c76..9584ee4e7 100644 --- a/cpu/msp430/rtimer-arch.c +++ b/cpu/msp430/f1xxx/rtimer-arch.c @@ -39,6 +39,7 @@ */ #include "contiki.h" + #include "sys/energest.h" #include "sys/rtimer.h" #include "sys/process.h" @@ -53,32 +54,8 @@ #endif /*---------------------------------------------------------------------------*/ -#if CONTIKI_TARGET_WISMOTE #ifdef __IAR_SYSTEMS_ICC__ -#pragma vector=TIMER1_A0_VECTOR -__interrupt void -#else -interrupt(TIMER1_A0_VECTOR) -#endif -timera0 (void) -{ - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - watchdog_start(); - - rtimer_run_next(); - - if(process_nevents() > 0) { - LPM4_EXIT; - } - - watchdog_stop(); - - ENERGEST_OFF(ENERGEST_TYPE_IRQ); -} -#else -#ifdef __IAR_SYSTEMS_ICC__ -#pragma vector=TIMER1_A0_VECTOR +#pragma vector=TIMERA0_VECTOR __interrupt void #else interrupt(TIMERA0_VECTOR) @@ -99,7 +76,6 @@ timera0 (void) ENERGEST_OFF(ENERGEST_TYPE_IRQ); } -#endif /*---------------------------------------------------------------------------*/ void rtimer_arch_init(void) @@ -107,11 +83,7 @@ rtimer_arch_init(void) dint(); /* CCR0 interrupt enabled, interrupt occurs when timer equals CCR0. */ -#if CONTIKI_TARGET_WISMOTE - TA1CCTL0 = CCIE; -#else TACCTL0 = CCIE; -#endif /* Enable interrupts. */ eint(); @@ -122,13 +94,8 @@ rtimer_arch_now(void) { rtimer_clock_t t1, t2; do { -#if CONTIKI_TARGET_WISMOTE - t1 = TA1R; - t2 = TA1R; -#else t1 = TAR; t2 = TAR; -#endif } while(t1 != t2); return t1; } @@ -138,10 +105,6 @@ rtimer_arch_schedule(rtimer_clock_t t) { PRINTF("rtimer_arch_schedule time %u\n", t); -#if CONTIKI_TARGET_WISMOTE - TA1CCR0 = t; -#else TACCR0 = t; -#endif } /*---------------------------------------------------------------------------*/ diff --git a/cpu/msp430/spi.c b/cpu/msp430/f1xxx/spi.c similarity index 100% rename from cpu/msp430/spi.c rename to cpu/msp430/f1xxx/spi.c diff --git a/cpu/msp430/spix.c b/cpu/msp430/f1xxx/spix.c similarity index 63% rename from cpu/msp430/spix.c rename to cpu/msp430/f1xxx/spix.c index 5e55d788b..0641b72ba 100644 --- a/cpu/msp430/spix.c +++ b/cpu/msp430/f1xxx/spix.c @@ -1,38 +1,39 @@ /* * Copyright (c) 2006, Swedish Institute of Computer Science - * All rights reserved. + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * * @(#)$Id: spix.c,v 1.1 2010/08/24 16:23:20 joxe Exp $ */ #include "contiki.h" + /* * This is SPI initialization code for the MSP430X architecture. - * + * */ unsigned char spi_busy = 0; @@ -47,29 +48,30 @@ spi_init(void) //if (spi_inited) //return; - // Initalize ports for communication with SPI units. + // Initalize ports for communication with SPI units. - UCB0CTL1 |= UCSWRST; //reset usci - UCB0CTL1 |= UCSSEL_2; //smclk while usci is reset - UCB0CTL0 = ( UCMSB | UCMST | UCSYNC | UCCKPL); // MSB-first 8-bit, Master, Synchronous, 3 pin SPI master, no ste, watch-out for clock-phase UCCKPH + UCB0CTL1 |= UCSWRST; //reset usci + UCB0CTL1 |= UCSSEL_2; //smclk while usci is reset + UCB0CTL0 = ( UCMSB | UCMST | UCSYNC | UCCKPL); // MSB-first 8-bit, Master, Synchronous, 3 pin SPI master, no ste, watch-out for clock-phase UCCKPH - UCB0BR1 = 0x00; - UCB0BR0 = 0x02; + UCB0BR1 = 0x00; + UCB0BR0 = 0x02; -// UCB0MCTL = 0; // Dont need modulation control. +// UCB0MCTL = 0; // Dont need modulation control. - P3SEL |= BV(SCK) | BV(MOSI) | BV(MISO); // Select Peripheral functionality - P3DIR |= BV(SCK) | BV(MISO); // Configure as outputs(SIMO,CLK). + P3SEL |= BV(SCK) | BV(MOSI) | BV(MISO); // Select Peripheral functionality + P3DIR |= BV(SCK) | BV(MISO); // Configure as outputs(SIMO,CLK). - //ME1 |= USPIE0; // Module enable ME1 --> U0ME? xxx/bg - - // Clear pending interrupts before enable!!! + //ME1 |= USPIE0; // Module enable ME1 --> U0ME? xxx/bg + + // Clear pending interrupts before enable!!! IFG2 &= ~UCB0RXIFG; IFG2 &= ~UCB0TXIFG; - UCB0CTL1 &= ~UCSWRST; // Remove RESET before enabling interrupts - //Enable UCB0 Interrupts + /* UCB0IE &= ~UCRXIFG; */ + /* UCB0IE &= ~UCTXIFG; */ + UCB0CTL1 &= ~UCSWRST; // Remove RESET before enabling interrupts + + //Enable UCB0 Interrupts //IE2 |= UCB0TXIE; // Enable USCI_B0 TX Interrupts //IE2 |= UCB0RXIE; // Enable USCI_B0 RX Interrupts } - - diff --git a/cpu/msp430/f5xxx/clock.c b/cpu/msp430/f5xxx/clock.c new file mode 100644 index 000000000..403799311 --- /dev/null +++ b/cpu/msp430/f5xxx/clock.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +#include "contiki.h" +#include "sys/energest.h" +#include "sys/clock.h" +#include "sys/etimer.h" +#include "rtimer-arch.h" +#include "dev/watchdog.h" + +#define INTERVAL (RTIMER_ARCH_SECOND / CLOCK_SECOND) + +#define MAX_TICKS (~((clock_time_t)0) / 2) + +static volatile unsigned long seconds; + +static volatile clock_time_t count = 0; +/* last_tar is used for calculating clock_fine, last_ccr might be better? */ +static volatile uint16_t last_tar = 0; +/*---------------------------------------------------------------------------*/ +#ifdef __IAR_SYSTEMS_ICC__ +#pragma vector=TIMER1_A1_VECTOR +__interrupt void +#else +interrupt(TIMER1_A1_VECTOR) +#endif +timera1 (void) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + /* watchdog_start(); */ + + if(TA1IV == 2) { + + /* HW timer bug fix: Interrupt handler called before TR==CCR. + * Occurs when timer state is toggled between STOP and CONT. */ + while(TA1CTL & MC1 && TA1CCR1 - TA1R == 1); + + /* Make sure interrupt time is future */ + do { + TA1CCR1 += INTERVAL; + ++count; + + /* Make sure the CLOCK_CONF_SECOND is a power of two, to ensure + that the modulo operation below becomes a logical and and not + an expensive divide. Algorithm from Wikipedia: + http://en.wikipedia.org/wiki/Power_of_two */ +#if (CLOCK_CONF_SECOND & (CLOCK_CONF_SECOND - 1)) != 0 +#error CLOCK_CONF_SECOND must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...). +#error Change CLOCK_CONF_SECOND in contiki-conf.h. +#endif + if(count % CLOCK_CONF_SECOND == 0) { + ++seconds; + energest_flush(); + } + } while((TA1CCR1 - TA1R) > INTERVAL); + + last_tar = TA1R; + + if(etimer_pending() && + (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { + etimer_request_poll(); + LPM4_EXIT; + } + + } + /* if(process_nevents() >= 0) { + LPM4_EXIT; + }*/ + + /* watchdog_stop(); */ + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +clock_time_t +clock_time(void) +{ + clock_time_t t1, t2; + do { + t1 = count; + t2 = count; + } while(t1 != t2); + return t1; +} +/*---------------------------------------------------------------------------*/ +void +clock_set(clock_time_t clock, clock_time_t fclock) +{ + TA1R = fclock; + TA1CCR1 = fclock + INTERVAL; + count = clock; +} +/*---------------------------------------------------------------------------*/ +int +clock_fine_max(void) +{ + return INTERVAL; +} +/*---------------------------------------------------------------------------*/ +unsigned short +clock_fine(void) +{ + unsigned short t; + /* Assign last_tar to local varible that can not be changed by interrupt */ + t = last_tar; + /* perform calc based on t, TAR will not be changed during interrupt */ + return (unsigned short) (TA1R - t); +} +/*---------------------------------------------------------------------------*/ +void +clock_init(void) +{ + dint(); + + /* Select SMCLK (2.4576MHz), clear TAR */ + /* TACTL = TASSEL1 | TACLR | ID_3; */ + + /* Select ACLK 32768Hz clock, divide by 2 */ +/* TA1CTL = TASSEL0 | TACLR | ID_1; */ + +#if INTERVAL==32768/CLOCK_SECOND + TA1CTL = TASSEL0 | TACLR; +#elif INTERVAL==16384/CLOCK_SECOND + TA1CTL = TASSEL0 | TACLR | ID_1; +#else +#error NEED TO UPDATE clock.c to match interval! +#endif + + /* Initialize ccr1 to create the X ms interval. */ + /* CCR1 interrupt enabled, interrupt occurs when timer equals CCR1. */ + TA1CCTL1 = CCIE; + + /* Interrupt after X ms. */ + TA1CCR1 = INTERVAL; + + /* Start Timer_A in continuous mode. */ + TA1CTL |= MC1; + + count = 0; + + /* Enable interrupts. */ + eint(); + +} +/*---------------------------------------------------------------------------*/ +/** + * Delay the CPU for a multiple of 2.83 us. + */ +void +clock_delay(unsigned int i) +{ + while(i--) { + asm("nop"); + } +} +/*---------------------------------------------------------------------------*/ +/** + * Wait for a multiple of 10 ms. + * + */ +void +clock_wait(int i) +{ + clock_time_t start; + + start = clock_time(); + while(clock_time() - start < (clock_time_t)i); +} +/*---------------------------------------------------------------------------*/ +void +clock_set_seconds(unsigned long sec) +{ + int s; + s = splhigh(); + seconds = sec; + splx(s); +} +/*---------------------------------------------------------------------------*/ +unsigned long +clock_seconds(void) +{ + unsigned long t1, t2; + do { + t1 = seconds; + t2 = seconds; + } while(t1 != t2); + return t1; +} +/*---------------------------------------------------------------------------*/ +rtimer_clock_t +clock_counter(void) +{ + rtimer_clock_t t1, t2; + do { + t1 = TA1R; + t2 = TA1R; + } while(t1 != t2); + return t1; +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/msp430/f5xxx/msp430.c b/cpu/msp430/f5xxx/msp430.c new file mode 100644 index 000000000..cc678ee36 --- /dev/null +++ b/cpu/msp430/f5xxx/msp430.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ +#include "contiki.h" +#include "dev/watchdog.h" + +/* dco_required set to 1 will cause the CPU not to go into + sleep modes where the DCO clock stopped */ +int msp430_dco_required; + +#if defined(__MSP430__) && defined(__GNUC__) +#define asmv(arg) __asm__ __volatile__(arg) +#endif +/*---------------------------------------------------------------------------*/ +void +msp430_init_dco(void) +{ +#ifdef __IAR_SYSTEMS_ICC__ + __bis_SR_register(SCG0); +#else + asmv("bis %0, r2" : : "i" (SCG0)); +#endif + + UCSCTL0 = 0x0000; + UCSCTL1 = DCORSEL_4; + + UCSCTL2 = MSP430_CPU_SPEED / 32768; + UCSCTL4 = 0x33; /* instead of 0x44 that is DCO/2 */ + +#ifdef __IAR_SYSTEMS_ICC__ + __bic_SR_register(SCG0); +#else + asmv("bic %0, r2" : : "i" (SCG0)); +#endif +} +/*---------------------------------------------------------------------------*/ + +static void +init_ports(void) +{ + /* Turn everything off, device drivers enable what is needed. */ + /* All configured for digital I/O */ +#ifdef P1SEL + P1SEL = 0; +#endif +#ifdef P2SEL + P2SEL = 0; +#endif +#ifdef P3SEL + P3SEL = 0; +#endif +#ifdef P4SEL + P4SEL = 0; +#endif +#ifdef P5SEL + P5SEL = 0; +#endif +#ifdef P6SEL + P6SEL = 0; +#endif + + /* All available inputs */ +#ifdef P1DIR + P1DIR = 0; + P1OUT = 0; +#endif +#ifdef P2DIR + P2DIR = 0; + P2OUT = 0; +#endif +#ifdef P3DIR + P3DIR = 0; + P3OUT = 0; +#endif +#ifdef P4DIR + P4DIR = 0; + P4OUT = 0; +#endif + +#ifdef P5DIR + P5DIR = 0; + P5OUT = 0; +#endif + +#ifdef P6DIR + P6DIR = 0; + P6OUT = 0; +#endif + +#ifdef P7DIR + P7DIR = 0; + P7OUT = 0; +#endif + +#ifdef P8DIR + P8DIR = 0; + P8OUT = 0; +#endif + + P1IE = 0; + P2IE = 0; +} +/*---------------------------------------------------------------------------*/ +/* msp430-ld may align _end incorrectly. Workaround in cpu_init. */ +#if defined(__MSP430__) && defined(__GNUC__) +extern int _end; /* Not in sys/unistd.h */ +static char *cur_break = (char *)&_end; +#endif + +/*---------------------------------------------------------------------------*/ +/* add/remove_lpm_req - for requiring a specific LPM mode. currently Contiki */ +/* jumps to LPM3 to save power, but DMA will not work if DCO is not clocked */ +/* so some modules might need to enter their LPM requirements */ +/* NOTE: currently only works with LPM1 (e.g. DCO) requirements. */ +/*---------------------------------------------------------------------------*/ +void +msp430_add_lpm_req(int req) +{ + if(req <= MSP430_REQUIRE_LPM1) { + msp430_dco_required++; + } +} + +void +msp430_remove_lpm_req(int req) +{ + if(req <= MSP430_REQUIRE_LPM1) { + msp430_dco_required--; + } +} + +void +msp430_cpu_init(void) +{ + dint(); + watchdog_init(); + init_ports(); + msp430_init_dco(); + eint(); +#if defined(__MSP430__) && defined(__GNUC__) + if((uintptr_t)cur_break & 1) { /* Workaround for msp430-ld bug! */ + cur_break++; + } +#endif + + msp430_dco_required = 0; +} +/*---------------------------------------------------------------------------*/ + +#define STACK_EXTRA 32 + +/* + * Allocate memory from the heap. Check that we don't collide with the + * stack right now (some other routine might later). A watchdog might + * be used to check if cur_break and the stack pointer meet during + * runtime. + */ +#if defined(__MSP430__) && defined(__GNUC__) +void * +sbrk(int incr) +{ + char *stack_pointer; + + asmv("mov r1, %0" : "=r" (stack_pointer)); + stack_pointer -= STACK_EXTRA; + if(incr > (stack_pointer - cur_break)) + return (void *)-1; /* ENOMEM */ + + void *old_break = cur_break; + cur_break += incr; + /* + * If the stack was never here then [old_break .. cur_break] should + * be filled with zeros. + */ + return old_break; +} +#endif +/*---------------------------------------------------------------------------*/ +/* + * Mask all interrupts that can be masked. + */ +int +splhigh_(void) +{ + int sr; + /* Clear the GIE (General Interrupt Enable) flag. */ +#ifdef __IAR_SYSTEMS_ICC__ + sr = __get_SR_register(); + __bic_SR_register(GIE); +#else + asmv("mov r2, %0" : "=r" (sr)); + asmv("bic %0, r2" : : "i" (GIE)); +#endif + return sr & GIE; /* Ignore other sr bits. */ +} +/*---------------------------------------------------------------------------*/ +#ifdef __IAR_SYSTEMS_ICC__ +int __low_level_init(void) +{ + /* turn off watchdog so that C-init will run */ + WDTCTL = WDTPW + WDTHOLD; + /* + * Return value: + * + * 1 - Perform data segment initialization. + * 0 - Skip data segment initialization. + */ + return 1; +} +#endif +/*---------------------------------------------------------------------------*/ diff --git a/cpu/msp430/f5xxx/rtimer-arch.c b/cpu/msp430/f5xxx/rtimer-arch.c new file mode 100644 index 000000000..910d76b9c --- /dev/null +++ b/cpu/msp430/f5xxx/rtimer-arch.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * MSP430-specific rtimer code for MSP430X + * \author + * Adam Dunkels + */ + +#include "contiki.h" +#include "sys/energest.h" +#include "sys/rtimer.h" +#include "sys/process.h" +#include "dev/watchdog.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*---------------------------------------------------------------------------*/ +#ifdef __IAR_SYSTEMS_ICC__ +#pragma vector=TIMER1_A0_VECTOR +__interrupt void +#else +interrupt(TIMER1_A0_VECTOR) +#endif +timera0 (void) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + watchdog_start(); + + rtimer_run_next(); + + if(process_nevents() > 0) { + LPM4_EXIT; + } + + watchdog_stop(); + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +void +rtimer_arch_init(void) +{ + dint(); + + /* CCR0 interrupt enabled, interrupt occurs when timer equals CCR0. */ + TA1CCTL0 = CCIE; + + /* Enable interrupts. */ + eint(); +} +/*---------------------------------------------------------------------------*/ +rtimer_clock_t +rtimer_arch_now(void) +{ + rtimer_clock_t t1, t2; + do { + t1 = TA1R; + t2 = TA1R; + } while(t1 != t2); + return t1; +} +/*---------------------------------------------------------------------------*/ +void +rtimer_arch_schedule(rtimer_clock_t t) +{ + PRINTF("rtimer_arch_schedule time %u\n", t); + + TA1CCR0 = t; +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/wismote/spix.c b/cpu/msp430/f5xxx/spix.c similarity index 62% rename from platform/wismote/spix.c rename to cpu/msp430/f5xxx/spix.c index df0670b2b..b92ca0ec7 100644 --- a/platform/wismote/spix.c +++ b/cpu/msp430/f5xxx/spix.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Swedish Institute of Computer Science. + * Copyright (c) 2011, Swedish Institute of Computer Science * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,19 +42,28 @@ unsigned char spi_busy = 0; void spi_init(void) { - UCB0CTL1 |= UCSWRST; // Put state machine in reset - UCB0CTL1 = UCSSEL0 | UCSSEL1; // Select ACLK - UCB0CTL0 |= UCCKPH | UCSYNC | UCMSB | UCMST; // 3-pin, 8-bit SPI master, rising edge capture + // Initialize ports for communication with SPI units. - // 16 bit baud rate register - UCB0BR0 = 0x00; // MSB => 0 - UCB0BR1 = 0x08; // LSB => SMCLK / (UCxxBR0 + UCxxBR1 × 256) + UCB0CTL1 |= UCSWRST; //reset usci + UCB0CTL1 |= UCSSEL_2; //smclk while usci is reset + UCB0CTL0 = ( UCMSB | UCMST | UCSYNC | UCCKPL); // MSB-first 8-bit, Master, Synchronous, 3 pin SPI master, no ste, watch-out for clock-phase UCCKPH - // Set MOSI and SCLK as OUT and MISO as IN ports - P3SEL |= ( BIT1 + BIT2 + BIT3 ); // Port3 = SPI peripheral - P3DIR |= ( BIT1 + BIT3 ); // MOSI and SCLK as Output - P3DIR &= ~BIT2; // Don't forget to configure MISO as Input - P3DIR |= BIT0; + UCB0BR1 = 0x00; + UCB0BR0 = 0x02; - UCB0CTL1 &= ~UCSWRST; // Initialize USCI state machine +// UCB0MCTL = 0; // Dont need modulation control. + + P3SEL |= BV(SCK) | BV(MOSI) | BV(MISO); // Select Peripheral functionality + P3DIR |= BV(SCK) | BV(MISO); // Configure as outputs(SIMO,CLK). + + //ME1 |= USPIE0; // Module enable ME1 --> U0ME? xxx/bg + + // Clear pending interrupts before enable!!! + UCB0IE &= ~UCRXIFG; + UCB0IE &= ~UCTXIFG; + UCB0CTL1 &= ~UCSWRST; // Remove RESET before enabling interrupts + + //Enable UCB0 Interrupts + //IE2 |= UCB0TXIE; // Enable USCI_B0 TX Interrupts + //IE2 |= UCB0RXIE; // Enable USCI_B0 RX Interrupts } diff --git a/cpu/msp430/rtimer-arch.h b/cpu/msp430/rtimer-arch.h index d90d1e437..9faca1589 100644 --- a/cpu/msp430/rtimer-arch.h +++ b/cpu/msp430/rtimer-arch.h @@ -43,7 +43,11 @@ #include "sys/rtimer.h" +#ifdef RTIMER_CONF_SECOND +#define RTIMER_ARCH_SECOND RTIMER_CONF_SECOND +#else #define RTIMER_ARCH_SECOND (4096U*8) +#endif rtimer_clock_t rtimer_arch_now(void); diff --git a/platform/wismote/contiki-wismote-main.c b/platform/wismote/contiki-wismote-main.c index ab8cef083..f7a456f88 100644 --- a/platform/wismote/contiki-wismote-main.c +++ b/platform/wismote/contiki-wismote-main.c @@ -450,8 +450,6 @@ main(int argc, char **argv) ENERGEST_ON(ENERGEST_TYPE_CPU); } } - - return 0; } /*---------------------------------------------------------------------------*/ #if LOG_CONF_ENABLED diff --git a/platform/wismote/platform-conf.h b/platform/wismote/platform-conf.h index 91d154a94..e5b8b481c 100644 --- a/platform/wismote/platform-conf.h +++ b/platform/wismote/platform-conf.h @@ -46,10 +46,11 @@ #define PLATFORM_HAS_BUTTON 1 /* CPU target speed in Hz */ -#define F_CPU 16000000uL /*2457600uL*/ +#define F_CPU 16000000uL /* Our clock resolution, this is the same as Unix HZ. */ #define CLOCK_CONF_SECOND 128UL +#define RTIMER_CONF_SECOND (4096U*8) #define BAUD2UBR(baud) ((F_CPU/baud))