[Tinyos-beta-commits] CVS: tinyos-1.x/beta/Deluge/Deluge/TOSBoot/msp430 HPLUSART0M.nc, NONE, 1.1 ProgFlashM.nc, NONE, 1.1 hardware.h, NONE, 1.1 msp430hardware.h, NONE, 1.1

Jonathan Hui jwhui at users.sourceforge.net
Thu Apr 21 10:31:43 PDT 2005


Update of /cvsroot/tinyos/tinyos-1.x/beta/Deluge/Deluge/TOSBoot/msp430
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9078/msp430

Added Files:
	HPLUSART0M.nc ProgFlashM.nc hardware.h msp430hardware.h 
Log Message:
- Cleaned up bootloader for msp430. Reduces code size by more than
half and now sits at under 2K of code.



--- NEW FILE: HPLUSART0M.nc ---
/*
 * Copyright (c) 2004-2005, Technische Universitat Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - 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.
 * - Neither the name of the Technische Universitat Berlin 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 COPYRIGHT HOLDERS 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 COPYRIGHT 
 * OWNER 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.
 *
 * - Description ----------------------------------------------------------
 * Implementation of USART0 lowlevel functionality - stateless.
 * Setting a mode will by default disable USART-Interrupts.
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2005/04/21 17:31:41 $
 * @author: Jan Hauer (hauer at tkn.tu-berlin.de)
 * @author: Joe Polastre
 * ========================================================================
 */

module HPLUSART0M {
  provides interface HPLUSARTControl as USARTControl;
  provides interface HPLUSARTFeedback as USARTData;
  provides interface HPLI2CInterrupt;
}
implementation
{
  MSP430REG_NORACE(ME1);
  MSP430REG_NORACE(IFG1);
  MSP430REG_NORACE(U0TCTL);

  uint16_t l_br;
  uint8_t l_mctl;
  uint8_t l_ssel;

/*
  TOSH_SIGNAL(UART0RX_VECTOR) {
    uint8_t temp = U0RXBUF;
    signal USARTData.rxDone(temp);
  }
  
  TOSH_SIGNAL(UART0TX_VECTOR) {
    if (call USARTControl.isI2C())
      signal HPLI2CInterrupt.fired();
    else
      signal USARTData.txDone();
  }
*/

  default async event void HPLI2CInterrupt.fired() { }
  
  async command bool USARTControl.isSPI() {
    bool _ret = FALSE;
//    atomic{
      if (ME1 & USPIE0)
	_ret = TRUE;
//    }
    return _ret;
  }
  
  async command bool USARTControl.isUART() {
    bool _ret = FALSE;
//    atomic {
      if ((ME1 & UTXE0) && (ME1 & URXE0) &&
          TOSH_IS_URXD0_MODFUNC() &&
          TOSH_IS_UTXD0_MODFUNC())
	_ret = TRUE;
//    }
    return _ret;
  }

  async command bool USARTControl.isUARTtx() {
    bool _ret = FALSE;
//    atomic {
      if ((ME1 & UTXE0) && 
          TOSH_IS_UTXD0_MODFUNC() &&
          TOSH_IS_URXD0_IOFUNC())
	_ret = TRUE;
//    }
    return _ret;
  }

  async command bool USARTControl.isUARTrx() {
    bool _ret = FALSE;
//    atomic {
      if ((ME1 & URXE0) && 
          TOSH_IS_URXD0_MODFUNC() &&
          TOSH_IS_UTXD0_IOFUNC())
	_ret = TRUE;
//    }
    return _ret;
  }
  
  async command bool USARTControl.isI2C() {
    bool _ret = FALSE;
#ifdef __msp430_have_usart0_with_i2c
//    atomic {
      if ((U0CTL & I2C) && (U0CTL & SYNC) && (U0CTL & I2CEN))
	_ret = TRUE;
//    }
#endif
    return _ret;
  }

  async command msp430_usartmode_t USARTControl.getMode() {
    if (call USARTControl.isUART())
      return USART_UART;
    else if (call USARTControl.isUARTrx())
      return USART_UART_RX;
    else if (call USARTControl.isUARTtx())
      return USART_UART_TX;
    else if (call USARTControl.isSPI())
      return USART_SPI;
    else if (call USARTControl.isI2C())
      return USART_I2C;
    else
      return USART_NONE;
  }

  /**
   * Sets the USART mode to one of the options from msp430_usartmode_t
   * defined in MSP430USART.h
   */
  async command void USARTControl.setMode(msp430_usartmode_t _mode) {
    switch (_mode) {
    case USART_UART:
      call USARTControl.setModeUART();
      break;
    case USART_UART_RX:
      call USARTControl.setModeUART_RX();
      break;
    case USART_UART_TX:
      call USARTControl.setModeUART_TX();
      break;
    case USART_SPI:
      call USARTControl.setModeSPI();
      break;
    case USART_I2C:
      call USARTControl.setModeI2C();
      break;
    default:
      break;
    }
  }

  async command void USARTControl.enableUART() {
      TOSH_SEL_UTXD0_MODFUNC();
      TOSH_SEL_URXD0_MODFUNC();
      ME1 |= (UTXE0 | URXE0);   // USART0 UART module enable
  }
  
  async command void USARTControl.disableUART() {
      ME1 &= ~(UTXE0 | URXE0);   // USART0 UART module enable
      TOSH_SEL_UTXD0_IOFUNC();
      TOSH_SEL_URXD0_IOFUNC();
  }

  async command void USARTControl.enableUARTTx() {
      TOSH_SEL_UTXD0_MODFUNC();
      ME1 |= UTXE0;   // USART0 UART Tx module enable
  }

  async command void USARTControl.disableUARTTx() {
      ME1 &= ~UTXE0;   // USART0 UART Tx module enable
      TOSH_SEL_UTXD0_IOFUNC();
  }

  async command void USARTControl.enableUARTRx() {
      TOSH_SEL_URXD0_MODFUNC();
      ME1 |= URXE0;   // USART0 UART Rx module enable
  }

  async command void USARTControl.disableUARTRx() {
      ME1 &= ~URXE0;  // USART0 UART Rx module disable
      TOSH_SEL_URXD0_IOFUNC();
  }

  async command void USARTControl.enableSPI() {
      TOSH_SEL_SIMO0_MODFUNC();
      TOSH_SEL_SOMI0_MODFUNC();
      TOSH_SEL_UCLK0_MODFUNC();
      ME1 |= USPIE0;   // USART0 SPI module enable
  }
  
  async command void USARTControl.disableSPI() {
      ME1 &= ~USPIE0;   // USART0 SPI module disable
      TOSH_SEL_SIMO0_IOFUNC();
      TOSH_SEL_SOMI0_IOFUNC();
      TOSH_SEL_UCLK0_IOFUNC();
  }
  
  async command void USARTControl.enableI2C() {
#ifdef __msp430_have_usart0_with_i2c   
    /*atomic*/ U0CTL |= I2C | I2CEN | SYNC;
#endif
  }

  async command void USARTControl.disableI2C() {
#ifdef __msp430_have_usart0_with_i2c
//    if (call USARTControl.isI2C())
    /*atomic*/ U0CTL &= ~(I2C | I2CEN | SYNC);
#endif
  }

  async command void USARTControl.setModeSPI() {
    // check if we are already in SPI mode
//    if (call USARTControl.getMode() == USART_SPI) 
//      return;
      
    call USARTControl.disableUART();
    call USARTControl.disableI2C();

//    atomic {
      TOSH_SEL_SIMO0_MODFUNC();
      TOSH_SEL_SOMI0_MODFUNC();
      TOSH_SEL_UCLK0_MODFUNC();

      IE1 &= ~(UTXIE0 | URXIE0);  // interrupt disable    

      U0CTL = SWRST;
      U0CTL |= CHAR | SYNC | MM;  // 8-bit char, SPI-mode, USART as master
      U0CTL &= ~(0x20); 

      U0TCTL = STC ;     // 3-pin
      U0TCTL |= CKPH;    // half-cycle delayed UCLK
/*
      if (l_ssel & 0x80) {
        U0TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
        U0TCTL |= (l_ssel & 0x7F); 
      }
      else {
*/
        U0TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
        U0TCTL |= SSEL_SMCLK; // use SMCLK, assuming 1MHz
//      }
/*
      if (l_br != 0) {
        U0BR0 = l_br & 0x0FF;
        U0BR1 = (l_br >> 8) & 0x0FF;
      }
      else {
*/
        U0BR0 = 0x02;   // as fast as possible
        U0BR1 = 0x00;
//      }
      U0MCTL = 0;

      ME1 &= ~(UTXE0 | URXE0); //USART UART module disable
      ME1 |= USPIE0;   // USART SPI module enable
      U0CTL &= ~SWRST;  

      IFG1 &= ~(UTXIFG0 | URXIFG0);
      IE1 &= ~(UTXIE0 | URXIE0);  // interrupt disabled    
//    }
    return;
  }
  
  void setUARTModeCommon() {
//    atomic {
      U0CTL = SWRST;  
      U0CTL |= CHAR;  // 8-bit char, UART-mode

      U0RCTL &= ~URXEIE;  // even erroneous characters trigger interrupts

      
      U0CTL = SWRST;
      U0CTL |= CHAR;  // 8-bit char, UART-mode

      if (l_ssel & 0x80) {
        U0TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
        U0TCTL |= (l_ssel & 0x7F); 
      }
      else {
        U0TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
        U0TCTL |= SSEL_ACLK; // use ACLK, assuming 32khz
      }

      if ((l_mctl != 0) || (l_br != 0)) {
        U0BR0 = l_br & 0x0FF;
        U0BR1 = (l_br >> 8) & 0x0FF;
        U0MCTL = l_mctl;
      }
      else {
        U0BR0 = 0x03;   // 9600 baud
        U0BR1 = 0x00;
        U0MCTL = 0x4A;
      }

      ME1 &= ~USPIE0;   // USART0 SPI module disable
      ME1 |= (UTXE0 | URXE0); //USART0 UART module enable;
      
      U0CTL &= ~SWRST;

      IFG1 &= ~(UTXIFG0 | URXIFG0);
      IE1 &= ~(UTXIE0 | URXIE0);  // interrupt disabled
//    }
    return;
  }
  
  async command void USARTControl.setModeUART_TX() {
    // check if we are already in UART mode
    if (call USARTControl.getMode() == USART_UART_TX) 
      return;

    call USARTControl.disableSPI();
    call USARTControl.disableI2C();
    call USARTControl.disableUART();

//    atomic {   
      TOSH_SEL_UTXD0_MODFUNC();     
      TOSH_SEL_URXD0_IOFUNC();    
//    }
    setUARTModeCommon();  
    return;
  }
  
  async command void USARTControl.setModeUART_RX() {
    // check if we are already in UART mode
    if (call USARTControl.getMode() == USART_UART_RX) 
      return;

    call USARTControl.disableSPI();
    call USARTControl.disableI2C();
    call USARTControl.disableUART();

//    atomic {
      TOSH_SEL_URXD0_MODFUNC(); 
      TOSH_SEL_UTXD0_IOFUNC(); 
//    }
    setUARTModeCommon(); 
    return;
  }

  async command void USARTControl.setModeUART() {
    // check if we are already in UART mode
    if (call USARTControl.getMode() == USART_UART) 
      return;

    call USARTControl.disableSPI();
    call USARTControl.disableI2C();
    call USARTControl.disableUART();

//    atomic {
      TOSH_SEL_UTXD0_MODFUNC();
      TOSH_SEL_URXD0_MODFUNC();
//    }
    setUARTModeCommon();
    return;
  }

  // i2c enable bit is not set by default
  async command void USARTControl.setModeI2C() {
#ifdef __msp430_have_usart0_with_i2c
    // check if we are already in I2C mode
    if (call USARTControl.getMode() == USART_I2C) 
      return;

    call USARTControl.disableUART();
    call USARTControl.disableSPI();

//    atomic {
      TOSH_MAKE_SIMO0_INPUT();
      TOSH_MAKE_UCLK0_INPUT();
      TOSH_SEL_SIMO0_MODFUNC();
      TOSH_SEL_UCLK0_MODFUNC();

      IE1 &= ~(UTXIE0 | URXIE0);  // interrupt disable    

      U0CTL = SWRST;
      U0CTL |= SYNC | I2C;  // 7-bit addr, I2C-mode, USART as master
      U0CTL &= ~I2CEN;

      U0CTL |= MST;

      I2CTCTL = I2CSSEL_2;        // use 1MHz SMCLK as the I2C reference

      I2CPSC = 0x00;              // I2C CLK runs at 1MHz/10 = 100kHz
      I2CSCLH = 0x03;
      I2CSCLL = 0x03;
      
      I2CIE = 0;                 // clear all I2C interrupt enables
      I2CIFG = 0;                // clear all I2C interrupt flags
//    }
#endif
    return;
  }
 
  async command void USARTControl.setClockSource(uint8_t source) {
//      atomic {
        l_ssel = source | 0x80;
        U0TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
        U0TCTL |= (l_ssel & 0x7F); 
//      }
  }

  async command void USARTControl.setClockRate(uint16_t baudrate, uint8_t mctl) {
//    atomic {
      l_br = baudrate;
      l_mctl = mctl;
      U0BR0 = baudrate & 0x0FF;
      U0BR1 = (baudrate >> 8) & 0x0FF;
      U0MCTL = mctl;
//    }
  }

  async command result_t USARTControl.isTxIntrPending(){
    if (IFG1 & UTXIFG0){
      IFG1 &= ~UTXIFG0;
      return SUCCESS;
    }
    return FAIL;
  }

  async command result_t USARTControl.isTxEmpty(){
    if (U0TCTL & TXEPT) {
      return SUCCESS;
    }
    return FAIL;
  }

  async command result_t USARTControl.isRxIntrPending(){
    if (IFG1 & URXIFG0){
      IFG1 &= ~URXIFG0;
      return SUCCESS;
    }
    return FAIL;
  }

  async command result_t USARTControl.disableRxIntr(){
    /*atomic*/ IE1 &= ~URXIE0;    
    return SUCCESS;
  }

  async command result_t USARTControl.disableTxIntr(){
    /*atomic*/ IE1 &= ~UTXIE0;  
    return SUCCESS;
  }

  async command result_t USARTControl.enableRxIntr(){
//    atomic {
      IFG1 &= ~URXIFG0;
      IE1 |= URXIE0;  
//    }
    return SUCCESS;
  }

  async command result_t USARTControl.enableTxIntr(){
//    atomic {
      IFG1 &= ~UTXIFG0;
      IE1 |= UTXIE0;
//    }
    return SUCCESS;
  }
  
  async command result_t USARTControl.tx(uint8_t data){
    /*atomic*/ U0TXBUF = data;
    return SUCCESS;
  }
  
  async command uint8_t USARTControl.rx(){
    uint8_t value;
    /*atomic*/ value = U0RXBUF;
    return value;
  }

  default async event result_t USARTData.txDone() { return SUCCESS; }

  default async event result_t USARTData.rxDone(uint8_t data) { return SUCCESS; }
}

--- NEW FILE: ProgFlashM.nc ---
// $Id: ProgFlashM.nc,v 1.1 2005/04/21 17:31:41 jwhui Exp $

/*									tab:4
 *
 *
 * "Copyright (c) 2000-2004 The Regents of the University  of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 */

/**
 * @author Jonathan Hui <jwhui at cs.berkeley.edu>
 */

module ProgFlashM {
  provides {
    interface TOSBootProgFlash as ProgFlash;
  }
}

implementation {

  command result_t ProgFlash.write(uint32_t addr, uint8_t* buf, uint16_t len) {

    volatile uint16_t *flashAddr = (uint16_t*)(uint16_t)addr;
    uint16_t *wordBuf = (uint16_t*)buf;
    uint16_t i = 0;
    
    FCTL2 = FWKEY + FSSEL1 + FN2;
    FCTL3 = FWKEY;
    FCTL1 = FWKEY + ERASE;
    *flashAddr = 0;
    FCTL1 = FWKEY + WRT;
    if (addr == (BL_MSP_RESET_ADDR/BL_INT_PAGE_SIZE)*BL_INT_PAGE_SIZE)
      *(uint16_t*)BL_MSP_RESET_ADDR = BOOTLOADER_START;
    for (i = 0; i < len / sizeof(uint16_t); i++) {
      if ((uint16_t)flashAddr != BL_MSP_RESET_ADDR)
	*flashAddr++ = wordBuf[i];
    }
    FCTL1 = FWKEY;
    FCTL3 = FWKEY + LOCK;

    return SUCCESS;

  }

}

--- NEW FILE: hardware.h ---
#ifndef _H_hardware_h
#define _H_hardware_h

#include "msp430hardware.h"
#include "MSP430ADC12.h"

#include "CC2420Const.h"

#include "AM.h"

// LEDs
TOSH_ASSIGN_PIN(RED_LED, 5, 4);
TOSH_ASSIGN_PIN(GREEN_LED, 5, 5);
TOSH_ASSIGN_PIN(YELLOW_LED, 5, 6);

// CC2420 RADIO #defines
TOSH_ASSIGN_PIN(RADIO_CSN, 4, 2);
TOSH_ASSIGN_PIN(RADIO_VREF, 4, 5);
TOSH_ASSIGN_PIN(RADIO_RESET, 4, 6);
TOSH_ASSIGN_PIN(RADIO_FIFOP, 1, 0);
TOSH_ASSIGN_PIN(RADIO_SFD, 4, 1);
TOSH_ASSIGN_PIN(RADIO_GIO0, 1, 3);
TOSH_ASSIGN_PIN(RADIO_FIFO, 1, 3);
TOSH_ASSIGN_PIN(RADIO_GIO1, 1, 4);
TOSH_ASSIGN_PIN(RADIO_CCA, 1, 4);

TOSH_ASSIGN_PIN(CC_FIFOP, 1, 0);
TOSH_ASSIGN_PIN(CC_FIFO, 1, 3);
TOSH_ASSIGN_PIN(CC_SFD, 4, 1);
TOSH_ASSIGN_PIN(CC_VREN, 4, 5);
TOSH_ASSIGN_PIN(CC_RSTN, 4, 6);

// UART pins
TOSH_ASSIGN_PIN(SOMI0, 3, 2);
TOSH_ASSIGN_PIN(SIMO0, 3, 1);
TOSH_ASSIGN_PIN(UCLK0, 3, 3);
TOSH_ASSIGN_PIN(UTXD0, 3, 4);
TOSH_ASSIGN_PIN(URXD0, 3, 5);
TOSH_ASSIGN_PIN(UTXD1, 3, 6);
TOSH_ASSIGN_PIN(URXD1, 3, 7);
TOSH_ASSIGN_PIN(UCLK1, 5, 3);
TOSH_ASSIGN_PIN(SOMI1, 5, 2);
TOSH_ASSIGN_PIN(SIMO1, 5, 1);

// ADC
TOSH_ASSIGN_PIN(ADC0, 6, 0);
TOSH_ASSIGN_PIN(ADC1, 6, 1);
TOSH_ASSIGN_PIN(ADC2, 6, 2);
TOSH_ASSIGN_PIN(ADC3, 6, 3);
TOSH_ASSIGN_PIN(ADC4, 6, 4);
TOSH_ASSIGN_PIN(ADC5, 6, 5);
TOSH_ASSIGN_PIN(ADC6, 6, 6);
TOSH_ASSIGN_PIN(ADC7, 6, 7);

// HUMIDITY
TOSH_ASSIGN_PIN(HUM_SDA, 1, 5);
TOSH_ASSIGN_PIN(HUM_SCL, 1, 6);
TOSH_ASSIGN_PIN(HUM_PWR, 1, 7);

// GIO pins
TOSH_ASSIGN_PIN(GIO0, 2, 0);
TOSH_ASSIGN_PIN(GIO1, 2, 1);
TOSH_ASSIGN_PIN(GIO2, 2, 3);
TOSH_ASSIGN_PIN(GIO3, 2, 6);

// 1-Wire
TOSH_ASSIGN_PIN(ONEWIRE, 2, 4);

void HUMIDITY_MAKE_CLOCK_OUTPUT() { TOSH_MAKE_HUM_SCL_OUTPUT(); }
void HUMIDITY_MAKE_CLOCK_INPUT() { TOSH_MAKE_HUM_SCL_INPUT(); }
void HUMIDITY_CLEAR_CLOCK() { TOSH_CLR_HUM_SCL_PIN(); }
void HUMIDITY_SET_CLOCK() { TOSH_SET_HUM_SCL_PIN(); }
void HUMIDITY_MAKE_DATA_OUTPUT() { TOSH_MAKE_HUM_SDA_OUTPUT(); }
void HUMIDITY_MAKE_DATA_INPUT() { TOSH_MAKE_HUM_SDA_INPUT(); }
void HUMIDITY_CLEAR_DATA() { TOSH_CLR_HUM_SDA_PIN(); }
void HUMIDITY_SET_DATA() { TOSH_SET_HUM_SDA_PIN(); }
char HUMIDITY_GET_DATA() { return TOSH_READ_HUM_SDA_PIN(); }

#define HUMIDITY_TIMEOUT_MS          30
#define HUMIDITY_TIMEOUT_TRIES       20

enum {
  // Sensirion Humidity addresses and commands
  TOSH_HUMIDITY_ADDR = 5,
  TOSH_HUMIDTEMP_ADDR = 3,
  TOSH_HUMIDITY_RESET = 0x1E
};

// FLASH
TOSH_ASSIGN_PIN(FLASH_PWR, 4, 3);
TOSH_ASSIGN_PIN(FLASH_CS, 4, 4);
TOSH_ASSIGN_PIN(FLASH_HOLD, 4, 7);

// PROGRAMMING PINS (tri-state)
//TOSH_ASSIGN_PIN(TCK, );
TOSH_ASSIGN_PIN(PROG_RX, 1, 1);
TOSH_ASSIGN_PIN(PROG_TX, 2, 2);

// send a bit via bit-banging to the flash
void TOSH_FLASH_M25P_DP_bit(bool set) {
  if (set)
    TOSH_SET_SIMO0_PIN();
  else
    TOSH_CLR_SIMO0_PIN();
  TOSH_SET_UCLK0_PIN();
  TOSH_CLR_UCLK0_PIN();
}

// put the flash into deep sleep mode
// important to do this by default
void TOSH_FLASH_M25P_DP() {
  //  SIMO0, UCLK0
  TOSH_MAKE_SIMO0_OUTPUT();
  TOSH_MAKE_UCLK0_OUTPUT();
  TOSH_MAKE_FLASH_HOLD_OUTPUT();
  TOSH_MAKE_FLASH_CS_OUTPUT();
  TOSH_SET_FLASH_HOLD_PIN();
  TOSH_SET_FLASH_CS_PIN();

  TOSH_wait();

  // initiate sequence;
  TOSH_CLR_FLASH_CS_PIN();
  TOSH_CLR_UCLK0_PIN();
  
  TOSH_FLASH_M25P_DP_bit(TRUE);   // 0
  TOSH_FLASH_M25P_DP_bit(FALSE);  // 1
  TOSH_FLASH_M25P_DP_bit(TRUE);   // 2
  TOSH_FLASH_M25P_DP_bit(TRUE);   // 3
  TOSH_FLASH_M25P_DP_bit(TRUE);   // 4
  TOSH_FLASH_M25P_DP_bit(FALSE);  // 5
  TOSH_FLASH_M25P_DP_bit(FALSE);  // 6
  TOSH_FLASH_M25P_DP_bit(TRUE);   // 7

  TOSH_SET_FLASH_CS_PIN();

  TOSH_SET_SIMO0_PIN();
  TOSH_MAKE_SIMO0_INPUT();
  TOSH_MAKE_UCLK0_INPUT();
  TOSH_CLR_FLASH_HOLD_PIN();
}


// need to undef atomic inside header files or nesC ignores the directive
#undef atomic
void TOSH_SET_PIN_DIRECTIONS(void)
{
  // reset all of the ports to be input and using i/o functionality
  atomic
  {
  P1SEL = 0;
  P2SEL = 0;
  P3SEL = 0;
  P4SEL = 0;
  P5SEL = 0;
  P6SEL = 0;

  P1DIR = 0xe0;
  P1OUT = 0x00;
 
  P2DIR = 0x7b;
  P2OUT = 0x10;

  P3DIR = 0xf1;
  P3OUT = 0x00;

  P4DIR = 0xfd;
  P4OUT = 0xdd;

  P5DIR = 0xff;
  P5OUT = 0xff;

  P6DIR = 0xff;
  P6OUT = 0x00;

  P1IE = 0;
  P2IE = 0;

  // the commands above take care of the pin directions
  // there is no longer a need for explicit set pin
  // directions using the TOSH_SET/CLR macros

  // wait 10ms for the flash to startup
//  TOSH_uwait(1024*10);
  // Put the flash in deep sleep state
//  TOSH_FLASH_M25P_DP();

  }//atomic
}

#endif // _H_hardware_h


--- NEW FILE: msp430hardware.h ---
// $Id: msp430hardware.h,v 1.1 2005/04/21 17:31:41 jwhui Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

// @author Vlado Handziski <handzisk at tkn.tu-berlin.de>
// @author Joe Polastre <polastre at cs.berkeley.edu>
// @author Cory Sharp <cssharp at eecs.berkeley.edu>

#ifndef _H_msp430hardware_h
#define _H_msp430hardware_h

#include <io.h>
#include <signal.h>
#include "msp430regtypes.h"

// define platform constants that can be changed for different compilers
// these are all msp430-gcc specific (add as necessary)

#ifdef __msp430_headers_adc10_h
#define __msp430_have_adc10
#endif

#ifdef __msp430_headers_adc12_h
#define __msp430_have_adc12
#endif


// assign a default DEFAULT_BAUDRATE
#ifndef DEFAULT_BAUDRATE
#define DEFAULT_BAUDRATE 57600
#endif

// CPU memory-mapped register access will cause nesc to issue race condition
// warnings.  Race conditions are a significant conern when accessing CPU
// memory-mapped registers, because they can change even while interrupts
// are disabled.  This means that the standard nesc tools for resolving race
// conditions, atomic statements that disable interrupt handling, do not
// resolve CPU register race conditions.  So, CPU registers access must be
// treated seriously and carefully.

// The macro MSP430REG_NORACE allows individual modules to internally
// redeclare CPU registers as norace, eliminating nesc's race condition
// warnings for their access.  This macro should only be used after the
// specific CPU register use has been verified safe and correct.  Example
// use:
//
//    module MyLowLevelModule
//    {
//      // ...
//    }
//    implementation
//    {
//      MSP430REG_NORACE(TACCTL0);
//      // ...
//    }

#undef norace

#define MSP430REG_NORACE_EXPAND(type,name,addr) \
norace static volatile type name asm(#addr)

#define MSP430REG_NORACE3(type,name,addr) \
MSP430REG_NORACE_EXPAND(type,name,addr)

// MSP430REG_NORACE and MSP430REG_NORACE2 presume naming conventions among
// type, name, and addr, which are defined in the local header
// msp430regtypes.h and mspgcc's header io.h and its children.

#define MSP430REG_NORACE2(rename,name) \
MSP430REG_NORACE3(TYPE_##name,rename,name##_)

#define MSP430REG_NORACE(name) \
MSP430REG_NORACE3(TYPE_##name,name,name##_)

// Avoid the type-punned pointer warnings from gcc 3.3, which are warning about
// creating potentially broken object code.  Union casts are the appropriate work
// around.  Unfortunately, they require a function definiton.
#define DEFINE_UNION_CAST(func_name,to_type,from_type) \
to_type func_name(from_type x) { union {from_type f; to_type t;} c = {f:x}; return c.t; }

// redefine ugly defines from msp-gcc
#ifndef DONT_REDEFINE_SR_FLAGS
#undef C
#undef Z
#undef N
#undef V
#undef GIE
#undef CPUOFF
#undef OSCOFF
#undef SCG0
#undef SCG1
#undef LPM0_bits
#undef LPM1_bits
#undef LPM2_bits
#undef LPM3_bits
#undef LPM4_bits
#define SR_C       0x0001
#define SR_Z       0x0002
#define SR_N       0x0004
#define SR_V       0x0100
#define SR_GIE     0x0008
#define SR_CPUOFF  0x0010
#define SR_OSCOFF  0x0020
#define SR_SCG0    0x0040
#define SR_SCG1    0x0080
#define LPM0_bits           SR_CPUOFF
#define LPM1_bits           SR_SCG0+SR_CPUOFF
#define LPM2_bits           SR_SCG1+SR_CPUOFF
#define LPM3_bits           SR_SCG1+SR_SCG0+SR_CPUOFF
#define LPM4_bits           SR_SCG1+SR_SCG0+SR_OSCOFF+SR_CPUOFF
#endif//DONT_REDEFINE_SR_FLAGS

#ifdef interrupt
#undef interrupt
#endif

#ifdef wakeup
#undef wakeup
#endif

#ifdef signal
#undef signal
#endif

// I2CBusy flag is not defined by current MSP430-GCC
#ifdef __msp430_have_usart0_with_i2c
#ifndef I2CBUSY
#define I2CBUSY   (0x01 << 5)
#endif
MSP430REG_NORACE2(U0CTLnr,U0CTL);
MSP430REG_NORACE2(I2CTCTLnr,I2CTCTL);
MSP430REG_NORACE2(I2CDCTLnr,I2CDCTL);
#endif

// The signal attribute has opposite meaning in msp430-gcc than in avr-gcc
#define TOSH_SIGNAL(signame) \
void sig_##signame() __attribute__((interrupt (signame), wakeup, C))

// TOSH_INTERRUPT allows nested interrupts
#define TOSH_INTERRUPT(signame) \
void isr_##signame() __attribute__((interrupt (signame), signal, wakeup, C))

inline void TOSH_wait(void)
{
  nop(); nop();
}

#define TOSH_CYCLE_TIME_NS 250

inline void TOSH_wait_250ns(void)
{
  // 4 MHz clock == 1 cycle per 250 ns
  nop();
}

inline void TOSH_uwait(uint16_t u) 
{ 
  uint16_t i;
  if (u < 500)
    for (i=2; i < u; i++) { 
      asm volatile("nop\n\t"
                   "nop\n\t"
                   "nop\n\t"
                   "nop\n\t"
                   ::);
    }
  else
    for (i=0; i < u; i++) { 
      asm volatile("nop\n\t"
                   "nop\n\t"
                   "nop\n\t"
                   "nop\n\t"
                   ::);
    }
  
} 

void __nesc_disable_interrupt()
{
  dint();
  nop();
}

void __nesc_enable_interrupt()
{
  eint();
}

bool are_interrupts_enabled()
{
  return ((READ_SR & SR_GIE) != 0);
}

typedef bool __nesc_atomic_t;

__nesc_atomic_t __nesc_atomic_start(void);
void __nesc_atomic_end(__nesc_atomic_t oldSreg);

#ifndef NESC_BUILD_BINARY

__nesc_atomic_t __nesc_atomic_start(void)
{
//  __nesc_atomic_t result = are_interrupts_enabled();
//  __nesc_disable_interrupt();
//  return result;
  return 0;
}

void __nesc_atomic_end( __nesc_atomic_t reenable_interrupts )
{
//  if( reenable_interrupts )
//    __nesc_enable_interrupt();
}

#endif

//Variable to keep track if Low Power Modes shoud not be used
norace bool LPMode_disabled = FALSE;

void LPMode_enable() {
  LPMode_disabled = FALSE;
}

void LPMode_disable() {
  LPMode_disabled = TRUE;
}

inline void TOSH_sleep() {
  // The LPM we can go down to depends on the clocks used. We never go
  // below LPM3, so ACLK is always enabled, also TimerB clock source
  // is assumed to be ACLK.
  // We check MSP430's TimerA, USART0/1, ADC12 peripheral modules if they
  // use MCLK or SMCLK and switch to the lowest LPM that keeps 
  // the required clock(s) running. 
  extern uint8_t TOSH_sched_full;
  extern volatile uint8_t TOSH_sched_free;
  __nesc_atomic_t fInterruptFlags;
  uint16_t LPMode_bits = 0;
  
  fInterruptFlags = __nesc_atomic_start(); 
  
  if ((LPMode_disabled) || (TOSH_sched_full != TOSH_sched_free)) {
    __nesc_atomic_end(fInterruptFlags);
    return;
  } else {
    LPMode_bits = LPM3_bits;
    // TimerA, USART0, USART1 check
    if ( (((TACCTL0 & CCIE) || (TACCTL1 & CCIE) || (TACCTL2 & CCIE))
         && ((TACTL & TASSEL_3) == TASSEL_2))
      || ((ME1 & (UTXE0 | URXE0)) && (U0TCTL & SSEL1))
      || ((ME2 & (UTXE1 | URXE1)) && (U1TCTL & SSEL1)) 
#ifdef __msp430_have_usart0_with_i2c
      // registers end in "nr" to prevent nesC race condition detection
      || ((U0CTLnr & I2CEN) && (I2CTCTLnr & SSEL1) &&
	  (I2CDCTLnr & I2CBUSY) && (U0CTLnr & SYNC) && (U0CTLnr & I2C))
#endif	
      )
      LPMode_bits = LPM1_bits;
#ifdef __msp430_have_adc12
    // ADC12 check  
    if (ADC12CTL1 & ADC12BUSY){
      if (!(ADC12CTL0 & MSC) && ((TACTL & TASSEL_3) == TASSEL_2))
         LPMode_bits = LPM1_bits; // TimerA for ADC12 
      else
        switch (ADC12CTL1 & ADC12SSEL_3){
          case ADC12SSEL_2: LPMode_bits = 0; break;
          case ADC12SSEL_3: LPMode_bits = LPM1_bits; break;
        }
    }
#endif
    LPMode_bits |= SR_GIE;
    __asm__ __volatile__( "bis  %0, r2" : : "m" ((uint16_t)LPMode_bits) );
  }
}

#define SET_FLAG(port, flag) ((port) |= (flag))
#define CLR_FLAG(port, flag) ((port) &= ~(flag))
#define READ_FLAG(port, flag) ((port) & (flag))

// TOSH_ASSIGN_PIN creates functions that are effectively marked as
// "norace".  This means race conditions that result from their use will not
// be detectde by nesc.

#define TOSH_ASSIGN_PIN_HEX(name, port, hex) \
void TOSH_SET_##name##_PIN() { MSP430REG_NORACE2(r,P##port##OUT); r |= hex; } \
void TOSH_CLR_##name##_PIN() { MSP430REG_NORACE2(r,P##port##OUT); r &= ~hex; } \
void TOSH_TOGGLE_##name##_PIN() { MSP430REG_NORACE2(r,P##port##OUT); r ^= hex; } \
uint8_t TOSH_READ_##name##_PIN() { MSP430REG_NORACE2(r,P##port##IN); return (r & hex); } \
void TOSH_MAKE_##name##_OUTPUT() { MSP430REG_NORACE2(r,P##port##DIR); r |= hex; } \
void TOSH_MAKE_##name##_INPUT() { MSP430REG_NORACE2(r,P##port##DIR); r &= ~hex; } \
void TOSH_SEL_##name##_MODFUNC() { MSP430REG_NORACE2(r,P##port##SEL); r |= hex; } \
void TOSH_SEL_##name##_IOFUNC() { MSP430REG_NORACE2(r,P##port##SEL); r &= ~hex; } \
bool TOSH_IS_##name##_MODFUNC() { MSP430REG_NORACE2(r,P##port##SEL); return (r & hex); } \
bool TOSH_IS_##name##_IOFUNC() { MSP430REG_NORACE2(r,P##port##SEL); return (r | ~hex); }

#define TOSH_ASSIGN_PIN(name, port, bit) \
TOSH_ASSIGN_PIN_HEX(name,port,(1<<(bit)))

#endif//_H_msp430hardware_h




More information about the Tinyos-beta-commits mailing list