X-Git-Url: https://oss.titaniummirror.com/gitweb/?p=tinyos-2.x.git;a=blobdiff_plain;f=tos%2Flib%2Fprintf%2FPrintfP.nc;h=a1a81f3beb6a05786d14f20b268ed2cffdadd126;hp=608c4ea726477681efe87623e00117d138238e6f;hb=32d57e66807cbea2aedfda37461a891b3168d422;hpb=ec0de8e1ac425b0f6855d46f737c2726cd82df88 diff --git a/tos/lib/printf/PrintfP.nc b/tos/lib/printf/PrintfP.nc index 608c4ea7..a1a81f3b 100644 --- a/tos/lib/printf/PrintfP.nc +++ b/tos/lib/printf/PrintfP.nc @@ -7,158 +7,177 @@ * 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 WASHINGTON UNIVERSITY IN ST. LOUIS 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 WASHINGTON + * IN NO EVENT SHALL WASHINGTON UNIVERSITY IN ST. LOUIS 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 WASHINGTON * UNIVERSITY IN ST. LOUIS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * WASHINGTON UNIVERSITY IN ST. LOUIS 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 WASHINGTON UNIVERSITY IN ST. LOUIS HAS NO + * ON AN "AS IS" BASIS, AND WASHINGTON UNIVERSITY IN ST. LOUIS HAS NO * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR * MODIFICATIONS." */ + + /* + * Copyright (c) 2007 Stanford University. + * 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 Stanford 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 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 STANFORD + * UNIVERSITY OR ITS 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 is the PrintfP component. It provides the printf service for printing + * data over the serial interface using the standard c-style printf command. + * Data printed using printf are buffered and only sent over the serial line after + * the buffer is half full or an explicit call to printfflush() is made. This + * buffer has a maximum size of 250 bytes at present. This component is wired + * to a shadowed MainC component so that printf statements can be made anywhere + * throughout your code, so long as you include the "printf.h" header file in + * every file you wish to use it. Take a look at the printf tutorial (lesson 15) + * for more details. * - * @author Kevin Klues (klueska@cs.wustl.edu) - * @version $Revision$ - * @date $Date$ + * The printf service is currently only available for msp430 based motes + * (i.e. telos, eyes) and atmega128x based motes (i.e. mica2, micaz, iris). On the + * atmega platforms, avr-libc version 1.4 or above must be used. + */ + +/** + * @author Kevin Klues + * @date September 18, 2007 */ #include "printf.h" #ifdef _H_atmega128hardware_H static int uart_putchar(char c, FILE *stream); -static FILE atm128_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); +static FILE atm128_stdout = + FDEV_SETUP_STREAM(TCAST(int (*)(char c, FILE *stream), uart_putchar), + NULL, _FDEV_SETUP_WRITE); #endif -module PrintfP { +module PrintfP @safe() { provides { - interface SplitControl as PrintfControl; - interface PrintfFlush; + interface Boot; } uses { - interface SplitControl as SerialControl; - interface Leds; + interface Boot as MainBoot; + interface SplitControl as SerialControl; + interface PrintfQueue as Queue; + interface AMSend; interface Packet; + interface Leds; } } implementation { - + enum { - S_STARTED, - S_STOPPED, - S_FLUSHING, + S_STOPPED, + S_STARTED, + S_FLUSHING, }; - + message_t printfMsg; - nx_uint8_t buffer[PRINTF_BUFFER_SIZE]; - norace nx_uint8_t* next_byte; uint8_t state = S_STOPPED; - uint8_t bytes_left_to_flush; - uint8_t length_to_send; - - task void retrySend() { - if(call AMSend.send(AM_BROADCAST_ADDR, &printfMsg, sizeof(PrintfMsg)) != SUCCESS) - post retrySend(); - } - - void sendNext() { - PrintfMsg* m = (PrintfMsg*)call Packet.getPayload(&printfMsg, NULL); - length_to_send = (bytes_left_to_flush < sizeof(PrintfMsg)) ? bytes_left_to_flush : sizeof(PrintfMsg); - memset(m->buffer, 0, sizeof(printfMsg)); - memcpy(m->buffer, (uint8_t*)next_byte, length_to_send); - if(call AMSend.send(AM_BROADCAST_ADDR, &printfMsg, sizeof(PrintfMsg)) != SUCCESS) - post retrySend(); - else { - bytes_left_to_flush -= length_to_send; - next_byte += length_to_send; - } - } - - command error_t PrintfControl.start() { - if(state == S_STOPPED) - return call SerialControl.start(); - return FAIL; - } - command error_t PrintfControl.stop() { - if(state == S_STARTED) - return call SerialControl.stop(); - return FAIL; + event void MainBoot.booted() { + call SerialControl.start(); } event void SerialControl.startDone(error_t error) { - if(error != SUCCESS) { - signal PrintfControl.startDone(error); - return; - } + if (state == S_STOPPED) { #ifdef _H_atmega128hardware_H - stdout = &atm128_stdout; + stdout = &atm128_stdout; #endif - atomic { - memset(buffer, 0, sizeof(buffer)); - next_byte = buffer; - bytes_left_to_flush = 0; - length_to_send = 0; - state = S_STARTED; + atomic state = S_STARTED; + signal Boot.booted(); } - signal PrintfControl.startDone(error); } event void SerialControl.stopDone(error_t error) { - if(error != SUCCESS) { - signal PrintfControl.stopDone(error); - return; - } atomic state = S_STOPPED; - signal PrintfControl.stopDone(error); } - command error_t PrintfFlush.flush() { - atomic { - if(state == S_STARTED && (next_byte > buffer)) { - state = S_FLUSHING; - bytes_left_to_flush = next_byte - buffer; - next_byte = buffer; - } - else return FAIL; - } - sendNext(); - return SUCCESS; + task void retrySend() { + if(call AMSend.send(AM_BROADCAST_ADDR, &printfMsg, sizeof(printf_msg_t)) != SUCCESS) + post retrySend(); + } + + void sendNext() { + int i; + printf_msg_t* m = (printf_msg_t*)call Packet.getPayload(&printfMsg, sizeof(printf_msg_t)); + uint16_t length_to_send = (call Queue.size() < sizeof(printf_msg_t)) ? call Queue.size() : sizeof(printf_msg_t); + memset(m->buffer, 0, sizeof(printf_msg_t)); + for(i=0; ibuffer[i] = call Queue.dequeue(); + if(call AMSend.send(AM_BROADCAST_ADDR, &printfMsg, sizeof(printf_msg_t)) != SUCCESS) + post retrySend(); + } + + int printfflush() @C() @spontaneous() { + atomic { + if(state == S_FLUSHING) + return SUCCESS; + if(call Queue.empty()) + return FAIL; + state = S_FLUSHING; + } + sendNext(); + return SUCCESS; } event void AMSend.sendDone(message_t* msg, error_t error) { - if(error == SUCCESS) { - if(bytes_left_to_flush > 0) - sendNext(); - else { - next_byte = buffer; - bytes_left_to_flush = 0; - length_to_send = 0; - atomic state = S_STARTED; - signal PrintfFlush.flushDone(error); - } - } - else post retrySend(); + if(error == SUCCESS) { + if(call Queue.size() > 0) + sendNext(); + else state = S_STARTED; + } + else post retrySend(); } -#ifdef _H_msp430hardware_h - int putchar(int c) __attribute__((noinline)) @C() @spontaneous() { -#endif #ifdef _H_atmega128hardware_H int uart_putchar(char c, FILE *stream) __attribute__((noinline)) @C() @spontaneous() { +#else +#ifdef __M16C62PHARDWARE_H__ + int lowlevel_putc(int c) __attribute__((noinline)) @C() @spontaneous() { +#else + int putchar(int c) __attribute__((noinline)) @C() @spontaneous() { +#endif #endif - atomic { - if(state == S_STARTED && ((next_byte-buffer+1) < PRINTF_BUFFER_SIZE)) { - *next_byte = c; - next_byte++; - return 0; - } - else return -1; - } + if((state == S_STARTED) && (call Queue.size() >= ((PRINTF_BUFFER_SIZE)/2))) { + state = S_FLUSHING; + sendNext(); + } + atomic { + if(call Queue.enqueue(c) == SUCCESS) + return 0; + else return -1; + } } }