]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/lib/net/blip/PrintfUART.h
Merge TinyOS 2.1.1 into master.
[tinyos-2.x.git] / tos / lib / net / blip / PrintfUART.h
diff --git a/tos/lib/net/blip/PrintfUART.h b/tos/lib/net/blip/PrintfUART.h
new file mode 100644 (file)
index 0000000..2d7e39f
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * "Copyright (c) 2008 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."
+ *
+ */
+/*                          
+ * Copyright (c) 2005
+ *     The President and Fellows of Harvard College.
+ *
+ * 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 University 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 UNIVERSITY 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 UNIVERSITY 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.
+ */
+
+/* 
+ * Writes printf like output to the UART.  
+ * This works only on the AVR and MSP430 Microcontrollers!
+ * <p>
+ * Note: For AVR we explicitly place the print statements in ROM; for
+ * MSP430 this is done by default!  For AVR, if we don't place it
+ * explicitely in ROM, the statements will go in RAM, which will
+ * quickly cause a descent size program to run out of RAM.  By default
+ * it doesn't disable the interupts; disabling the interupts when
+ * writing to the UART, slows down/makes the mote quite unresponsive,
+ * and can lead to problems!  If you wish to disable all printfs to
+ * the UART, then comment the flag: <code>PRINTFUART_ENABLED</code>.
+
+ * <p> <pre>
+ * How to use:
+ *   // (0) In your Makefile, define PRINTFUART_ENABLED
+ *   CFLAGS += -DPRINTFUART_ENABLED
+ *   // (1) Call printfUART_init() from your initialization function 
+ *   //     to initialize the UART
+ *   printfUART_init();
+ *   // (2) Set your UART client to the correct baud rate.  Look at 
+ *   //     the comments in printfUART_init(), to figure out what 
+ *   //     baud to use for your particular mote
+ *
+ *   // (3) Send printf statements like this:
+ *   printfUART("Hello World, we are in year= %u\n", 2004);
+ *   printfUART("Printing uint32_t variable, value= %lu\n", 4294967295);
+ *
+ * Examples and caveats:
+ *   // (1) - Must use curly braces in single section statements.  
+ *            (Look in the app.c to see why -- hint: it's a macro)
+ *   if (x < 3)
+ *       {printfUART("The value of x is %i\n", x);}
+ *   // (2) - Otherwise it more or less works like regular printf
+ *   printfUART("\nThe value of x=%u, and y=%u\n", x, y); 
+ * </pre>
+ * <pre>URL: http://www.eecs.harvard.edu/~konrad/projects/motetrack</pre>
+ * @author Konrad Lorincz
+ * @version 2.0, January 5, 2005
+ */
+#ifndef PRINTFUART_H
+#define PRINTFUART_H
+#include <stdarg.h>
+#include <stdio.h>
+
+// -------------------------------------------------------------------
+#ifdef PRINTFUART_ENABLED
+    #define DEBUGBUF_SIZE 256
+    char debugbuf[DEBUGBUF_SIZE];
+    char debugbufROMtoRAM[DEBUGBUF_SIZE];
+
+    #if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)
+        #define printfUART(__format...) {                          \
+            static const char strROM[] PROGMEM = __format;         \
+            strcpy_P((char*) &debugbufROMtoRAM, (PGM_P) &strROM);  \
+            sprintf(debugbuf, debugbufROMtoRAM);                   \
+            writedebug();                                          \
+        }   
+    #else  // assume MSP430 architecture (e.g. TelosA, TelosB, etc.)
+        #define printfUART(__format...) {      \
+            sprintf(debugbuf, __format);       \
+            writedebug();                      \
+        }  
+    #endif
+#else
+    #define printfUART(X, args...) dbg("printf", X, ## args)
+// #define printfUART(__format...) {}
+    void printfUART_init() {}
+#endif
+
+#define NOprintfUART(__format...)
+
+
+// -------------------------------------------------------------------
+#ifdef PRINTFUART_ENABLED
+
+/**
+ * Initialize the UART port.  Call this from your startup routine.
+ */
+#define printfUART_init() {atomic printfUART_init_private();}
+void printfUART_init_private()
+{
+    #if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2)
+        // 56K baud
+        outp(0,UBRR0H);
+        outp(15, UBRR0L);                              //set baud rate
+        outp((1<<U2X),UCSR0A);                         // Set UART double speed
+        outp(((1 << UCSZ1) | (1 << UCSZ0)) , UCSR0C);  // Set frame format: 8 data-bits, 1 stop-bit
+        inp(UDR0);
+        outp((1 << TXEN) ,UCSR0B);   // Enable uart reciever and transmitter
+
+    #else
+    #if defined(PLATFORM_MICA2DOT)  
+        // 19.2K baud
+        outp(0,UBRR0H);            // Set baudrate to 19.2 KBps
+        outp(12, UBRR0L);
+        outp(0,UCSR0A);            // Disable U2X and MPCM
+        outp(((1 << UCSZ1) | (1 << UCSZ0)) , UCSR0C);
+        inp(UDR0);
+        outp((1 << TXEN) ,UCSR0B);
+  
+    #else
+    #if defined(PLATFORM_IMOTE2)
+      //async command result_t UART.init() {
+        
+        /*** 
+           need to configure the ST UART pins for the correct functionality
+           
+           GPIO<46> = STDRXD = ALT2(in)
+           GPIO<47> = STDTXD = ALT1(out)
+        *********/
+        //atomic{
+          
+        //configure the GPIO Alt functions and directions
+        _GPIO_setaltfn(46,2);   // STD_RXD
+        _GPIO_setaltfn(47,1);   // STD_TXD
+        
+        _GPDR(46) &= ~_GPIO_bit(46);  // input
+        _GPDR(47) |= _GPIO_bit(47);   // output
+        
+        STLCR |=LCR_DLAB; //turn on DLAB so we can change the divisor
+        STDLL = 8;  //configure to 115200;
+        STDLH = 0;
+        STLCR &= ~(LCR_DLAB);  //turn off DLAB
+        
+        STLCR |= 0x3; //configure to 8 bits
+        
+        STMCR &= ~MCR_LOOP;
+        STMCR |= MCR_OUT2;
+        STIER |= IER_RAVIE;
+        STIER |= IER_TIE;
+        STIER |= IER_UUE; //enable the UART
+        
+        //STMCR |= MCR_AFE; //Auto flow control enabled;
+        //STMCR |= MCR_RTS;
+        
+        STFCR |= FCR_TRFIFOE; //enable the fifos
+        
+//        call Interrupt.allocate();
+//        call Interrupt.enable();
+        //configure all the interrupt stuff
+        //make sure that the interrupt causes an IRQ not an FIQ
+        // __REG(0x40D00008) &= ~(1<<21);
+        //configure the priority as IPR1
+        //__REG(0x40D00020) = (1<<31 | 21);
+        //unmask the interrupt
+        //__REG(0x40D00004) |= (1<<21);
+        
+        CKEN |= CKEN5_STUART; //enable the UART's clk    
+
+
+    #else  // assume TelosA, TelosB, etc.
+        // Variabel baud 
+        // To change the baud rate, see /tos/platform/msp430/msp430baudrates.h
+        uint8_t source = SSEL_SMCLK;
+        uint16_t baudrate = 0x0012; // UBR_SMCLK_57600=0x0012
+        uint8_t mctl = 0x84;        // UMCTL_SMCLK_57600=0x84
+        //uint16_t baudrate = 0x0009; // UBR_SMCLK_115200=0x0009
+        //uint8_t mctl = 0x10;        // UMCTL_SMCLK_115200=0x10
+
+
+        uint16_t l_br = 0;
+        uint8_t l_mctl = 0;
+        uint8_t l_ssel = 0;
+
+        TOSH_SEL_UTXD1_MODFUNC();
+        TOSH_SEL_URXD1_MODFUNC();
+
+
+        UCTL1 = SWRST;  
+        UCTL1 |= CHAR;  // 8-bit char, UART-mode
+    
+        U1RCTL &= ~URXEIE;  // even erroneous characters trigger interrupts
+
+        UCTL1 = SWRST;
+        UCTL1 |= CHAR;  // 8-bit char, UART-mode
+
+        if (l_ssel & 0x80) {
+            U1TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
+            U1TCTL |= (l_ssel & 0x7F); 
+        }
+        else {
+            U1TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
+            U1TCTL |= SSEL_ACLK; // use ACLK, assuming 32khz
+        }
+
+        if ((l_mctl != 0) || (l_br != 0)) {
+            U1BR0 = l_br & 0x0FF;
+            U1BR1 = (l_br >> 8) & 0x0FF;
+            U1MCTL = l_mctl;
+        }
+        else {
+            U1BR0 = 0x03;   // 9600 baud
+            U1BR1 = 0x00;
+            U1MCTL = 0x4A;
+        }
+      
+        ME2 &= ~USPIE1;   // USART1 SPI module disable
+        ME2 |= (UTXE1 | URXE1);   // USART1 UART module enable
+      
+        U1CTL &= ~SWRST;
+    
+        IFG2 &= ~(UTXIFG1 | URXIFG1);
+        IE2 &= ~(UTXIE1 | URXIE1);  // interrupt disabled
+
+   
+
+        //async command void USARTControl.setClockSource(uint8_t source) {
+        //    atomic {
+                l_ssel = source | 0x80;
+                U1TCTL &= ~(SSEL_0 | SSEL_1 | SSEL_2 | SSEL_3);
+                U1TCTL |= (l_ssel & 0x7F); 
+                //    }
+                //}
+                //async command void USARTControl.setClockRate(uint16_t baudrate, uint8_t mctl) {
+                //atomic {
+                l_br = baudrate;
+                l_mctl = mctl;
+                U1BR0 = baudrate & 0x0FF;
+                U1BR1 = (baudrate >> 8) & 0x0FF;
+                U1MCTL = mctl;
+                //}
+                //}
+
+                //async command result_t USARTControl.enableRxIntr(){
+                //atomic {
+                IFG2 &= ~URXIFG1;
+                IE2 |= URXIE1;
+                //}
+                //return SUCCESS;
+                //}
+
+                //async command result_t USARTControl.enableTxIntr(){
+                //atomic {
+                IFG2 &= ~UTXIFG1;
+                IE2 |= UTXIE1;
+                //}
+                //return SUCCESS;
+                //}     
+
+    #endif
+    #endif
+    #endif
+}
+
+#if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)
+#else
+#if defined(PLATFORM_IMOTE2)
+#else // assume AVR architecture (e.g. TelosA, TelosB)
+    bool isTxIntrPending()
+    {
+        if (U1TCTL & TXEPT) {
+            return TRUE;
+        }
+        return FALSE;
+    }
+#endif
+#endif
+
+/**
+ * Outputs a char to the UART.
+ */
+void UARTPutChar(char c)
+{
+    if (c == '\n')
+        UARTPutChar('\r');
+
+
+    #if defined(PLATFORM_MICAZ) || defined(PLATFORM_MICA2) || defined(PLATFORM_MICA2DOT)
+        loop_until_bit_is_set(UCSR0A, UDRE);
+        outb(UDR0,c);
+
+    #else
+    #if defined(PLATFORM_IMOTE2)
+        STTHR = c;    
+
+    #else // assume AVR architecture (e.g. TelosA, TelosB)
+        U1TXBUF = c;  
+        while( !isTxIntrPending() )  
+            continue;
+    #endif
+    #endif
+}
+
+/**
+ * Outputs the entire debugbuf to the UART, or until it encounters '\0'.
+ */
+void writedebug()
+{
+    uint16_t i = 0;
+    
+    while (debugbuf[i] != '\0' && i < DEBUGBUF_SIZE)
+        UARTPutChar(debugbuf[i++]);
+}
+
+#endif  // PRINTFUART_ENABLED
+// -------------------------------------------------------------------
+
+#if 0
+// --------------------------------------------------------------
+#define assertUART(x) if (!(x)) { __assertUART(__FILE__, __LINE__); }
+void __assertUART(const char* file, int line)
+{
+    printfUART("ASSERT FAILED: file= %s, lineNbr= %i\n", file, line);
+    // for some reason, CLR means on
+    TOSH_MAKE_RED_LED_OUTPUT();
+    TOSH_MAKE_YELLOW_LED_OUTPUT();
+    TOSH_MAKE_GREEN_LED_OUTPUT();
+    TOSH_CLR_RED_LED_PIN();
+    TOSH_CLR_YELLOW_LED_PIN();
+    TOSH_CLR_GREEN_LED_PIN();
+    exit(1);
+}
+// --------------------------------------------------------------
+#endif
+
+#endif  // PRINTFUART_H
+