Updated SPI config for faster SPI, split msp430/clock/spi into separate versions for MSP430/MSP430X

This commit is contained in:
Niclas Finne 2011-09-23 15:01:13 +02:00
parent 09082f02fe
commit f4f84ffca4
14 changed files with 677 additions and 237 deletions

View file

@ -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

View file

@ -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();

View file

@ -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 */
@ -157,7 +100,6 @@ timera1 (void)
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;
}
/*---------------------------------------------------------------------------*/

View file

@ -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;

View file

@ -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
}
/*---------------------------------------------------------------------------*/

View file

@ -30,6 +30,7 @@
*/
#include "contiki.h"
/*
* This is SPI initialization code for the MSP430X architecture.
*
@ -66,10 +67,11 @@ spi_init(void)
// Clear pending interrupts before enable!!!
IFG2 &= ~UCB0RXIFG;
IFG2 &= ~UCB0TXIFG;
/* 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
}

229
cpu/msp430/f5xxx/clock.c Normal file
View file

@ -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;
}
/*---------------------------------------------------------------------------*/

238
cpu/msp430/f5xxx/msp430.c Normal file
View file

@ -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
/*---------------------------------------------------------------------------*/

View file

@ -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 <adam@sics.se>
*/
#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 <stdio.h>
#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;
}
/*---------------------------------------------------------------------------*/

View file

@ -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
}

View file

@ -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);

View file

@ -450,8 +450,6 @@ main(int argc, char **argv)
ENERGEST_ON(ENERGEST_TYPE_CPU);
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
#if LOG_CONF_ENABLED

View file

@ -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))