Low Level Serial Control in TinyOS


It’s been awhile since my last TinyOS post, but a new project required me to return to programming motes.  In this case, we needed to send ASCII characters over the serial port to the PC, bypassing the default TinyOS serial stack.

The TinyOS serial stack is designed to work with Active Messages so that packets received over the radio can be easily forwarded on to the PC.  To that end, the high-level serial and radio components provide the same interfaces.  The TinyOS serial stack has layers for packet formatting, error checking, and a read/write buffer.  However, for our project, we wanted to simplify the PC side so we didn’t have to use the TinyOS JNI libraries to receive TinyOS Active Message packets.  A simple program to read ASCII characters over the serial connection would suffice for our purposes — Minicom does this quite well and is easily installed on Ubuntu Linux and can be configured to read from attached USB devices.

The goal was to produce a TinyOS component that provided a command for transmitting ASCII character strings over the serial connection to a PC.  The  implementation is very similar to the Pulse Oximeter code I wrote for Atmel-based devices, however this time I targeted MSP430-based devices, such as the TelosB or Tmote Sky.  The implementation uses the Msp430Uart1C component for accessing the serial connection. This component provides the UartByte or UartStream interfaces for reading and writing and the Resource interface for gaining control of the UART. Msp430Uart1C also provides the Msp430UartConfigure interface for setting the baud rate.

The control flow for writing a character string is as follows: First, request the UART resource. Second, when the resource has been granted, call UartStream.send() to transmit the string. Lastly, when UartStream.sendDone() is signaled, signal the higher level application that the character string has been sent or an error message if something went wrong. In my SerialAscii module, I have the following command to send a character string:

  command error_t SerialAscii.sendAscii(char *str)
  {
    bufferLength = strlen(str);
    if(bufferLength > BUFFER_SIZE)
      return FAIL;
    memcpy(strBuffer,str,bufferLength);  // copy string into a buffer
    call Resource.request(); // request access to the UART
    return SUCCESS;
  }

I copy the string into a buffer to keep the application from modifying it before being transmitted. When the resource request is granted, I transmit the string:

  event void Resource.granted()
  {
    error_t result = call UartStream.send(strBuffer,bufferLength);
    if(result == FAIL)
      post sendDoneFailTask();  // return failure message to the user if something bad happened
  }

Lastly, when the string is sent, I release the resource and signal the higher level application:

  async event void UartStream.sendDone(uint8_t *buf, uint16_t len, error_t error)
  {
    // call Resource.release() in each of these tasks
    if(error == SUCCESS)
      post sendDoneSuccessTask(); // signal SerialAscii.sendAsciiDone(SUCCESS);
    else
      post sendDoneFailTask(); // signal SerialAscii.sendAsciiDone(FAIL);
  }

I’ve made my code available here. Let me know if you find any bugs or have any comments or suggestions.

, , , , ,

  1. No comments yet.
(will not be published)