SOS SOS Operating System by yxv76130


       SOS Operating System
        Updated by Andreas Savvides
                Nov 2, 2004
Chih-Chieh Han, Ram Rengaswamy, Roy Shea
      Eddie Kohler, and Mani Srivastava

         Based on initial tutorial by
     Sung Park and Andreas Savvides
    Electrical Engineering Departments
    University of California, Los Angeles
            September 17, 2004
         Recap: A Program without OS
int main(void)
   for (;;) {
          IO_Scan();               // bar-code scanner
          KBD_Scan();              // keyboard
          PRN_Print();             // printer
          LCD_Update();            // display
          RS232_Receive();         // serial port
          TIMER_Process();         // timer
   // should never ever get here
         Recap:Task Requirements

 Some tasks are periodic
  • Blink the LCD cursor once every second
 Tasks may not need to run at the same
 Some tasks may be event triggered
  • RS-232 receive only needs to execute of there is a
    character received
  • PRN_Print() only needs to execute when a receipt is
 Need a method to communicate between

              Event Driven Tasks &
              Task Communication

                Task 2

Task 1                    Task3_PutEvent()

                                                        Task 3

                  Task Event Queue

        Task Execution Frequency

 Different tasks may need to execute at
  different frequencies OR
 Task execution frequency may change during
  the lifetime of an application
 Example:
     You may not need to refresh the LCD
  every 1ms if the information to be displayed
  does not change
     You may not want to delay execution of
  other tasks too long
                   Software Timers

 Timers are needed to provide multitasking
  ability to your software
 Need to schedule a large number of periodic
  or single shot events
  •   Blinking cursor
  •   Flashing leds
  •   Be able to put your device to sleep after some idle time
  •   Timers in the implementation of communication protocols
 You could use hardware timers for some
  tasks BUT
  • There is a very limited number of hardware timers
    compared to the needs of an application

                 Designing a Software Timer
Tasks deposit their
events in a queue

                                                handler functions

      Handler for the hardware         Software timer process
    10ms timer check Delta Queue
         For expired timers        7
             Using A Software Timer

 The timer API function in SOS looks like
  int8_t ker_timer_start(sos_pid_t pid, uint8_t tid, uint8_t
  type, int32_t interval)

  int8_t ker_timer_stop(uint8_t pid, uint8_t tid)

pid – ID of the module(task) that creates the timer
         pid is unique to the whole OS
tid – ID of the timer within
         tid needs to be unique to a specific module
We will return to this in a few slides…

      SOS: Pseudo-Realtime (soft)

 Structure: OS functions and user
  defined Tasks
 Multi-tasking (Event-Driven)
  • Each tasks is a routine which processes events
    that are stored in event queues
 Supports Inter-task Communication
  • Implements a messaging model

      SOS: Pseudo-Realtime (soft)

 Instead of hard-realtime, SOS provides
  soft-realtime guarantee (best-effort)
 Tasks cannot be pre-emptied (by other
  • Tasks run one after the other
  • No shared memory protection required
 Cooperative task scheduling
  • Task posts messages to self or other tasks for
    further execution.

          Need for Reprogramming

 How do you update a deployed system of
  100s of nodes?
 Changing project needs, surfacing of new
  applications, repairing bugs needs
 Different attempts for reprogramming
  • XNP mechanism on MICA nodes
     Image stored on external flash rebooting the nodes
  • Could use differential patching
     Just update the part of the binary image that changed

              SOS Approach

Dynamic Loadable                   Dynamic Loadable
 Binary Modules                     Binary Modules

                   Static SOS Kernel

 Hardware             Module               Memory
Abstraction        Communication           Manager

SOS Functional Layout

                      SOS features

       Message Passing Communication
       Virtual Delta Timers
       Dynamic Memory Management (heap)
       Support Module Insertion
       Event driven Sensing Interface
       Cross Platform

       Memory footprint in Mica2
    •    FLASH size(Code): 17816 bytes (Total: 128Kbytes)
    •    RAM Size (Memory): 2697 bytes (Total: 4Kbytes)
    •    Includes hardware drivers, radio stack, and heap.
           Compared to tinyOS

 Notion of well-defined tasks
 Inter-task communication through the
  use of message queue
 More elaborate scheduling scheme
  where task has context
 Easier to debug
  • Minimum use of macros
  • Standard C language => JTAG friendly!

                    SOS Modules

   Each module is uniquely identified by its ID or pid.
   Module has private state.
   Modules can be loaded post-deployment.
   Each module is represented by a message handler
    and has following prototype.

    int8_t handler(void *private_state, Message *msg)

 Each module is a finite state machine that changes
  state based on messages.
 Return value follows errno.
    • SOS_OK for success. -EINVAL, -ENOMEM, etc for
                Inter-Module Communication

 Module A                Module B               Module A                           Module B

                                                       Indirect Function Call
                          Message                                      Module Function
                           Buffer                                       Pointer Table

Inter-Module Message Passing                   Inter-Module Function Calls

 Asynchronous communication                    Synchronous communication

                                                Kernel stores pointers to functions
 Messages dispatched by a two-level           registered by modules
priority scheduler
                                                Blocking calls with low latency
 Suited for services with long latency
                                                Type-safe runtime function binding

                 SOS Messaging

 Task scheduling
  • Send message to self
  • Schedule timer for later message delivery
 Inter-module asynchronous communication
  • Send message to other module
 Multi-level queues (currently Two)
  • High priority Message for timely response.
 Network capable (Currently NOT
  implemented on XYZ)
  • Same message format for both local message queue and
    radio send queue.
  • Receive queue is local message queue.

              SOS Messaging and Modules
                           2        Module A

          1                         Module B
               Msg Queue   4                   5   Send Queue

     Module is active when it is handling the message
     Message handling runs to completion and can only be
      interrupted by hardware interrupts.
     Module can send message to another module (3) or
      send message to the network (5).
     Message can come from both network (1) and local
      host (3).
  Modules and Memory Dependencies

 There are 2 main types of memory
  • Function dependencies – when a module needs
    to make a function call to another module
      SOS wraps a function call into a message
  • Data dependencies – arise when a module
    needs to store data to memory
      SOS provides heap memory. Upon a
       message arrival, SOS is passed the message
       along with a pointer to the module’s state
       maintained by SOS
     int8_t app_handler(void* state, Message *msg)
              Network Capable Messages
   typedef struct {
       sos_pid_t did;           //       destination module ID
       sos_pid_t sid;           //       source module ID
       uint16_t daddr;          //       destination node
       uint16_t saddr;          //       source node
       uint8_t type;            //       message type
       uint8_t len;             //       message length
       uint8_t *data;           //       payload
       uint8_t flag;            //       options
   } Message;

 Messages are best-effort                 Messages are filtered when
by default.                               received.
    No senddone and Low priority             CRC Check and Non-
                                               promiscuous mode
    Can be changed via flag in
                                              Can turn off filter in runtime
              SOS Messaging API
// send message over net        // send message
int8_t post_net(                int8_t post(Message *msg);
  sos_pid_t did,                // short message struct
  sos_pid_t sid,                typedef struct {
  uint8_t type,
                                  uint8_t byte;
  uint8_t length,
                                  uint16_t word;
  void *data,
                                } MsgParam;
  uint8_t flag,
  uint16_t daddr);              // send short message
// send long message            int8_t post_short(
int8_t post_long(                 sos_pid_t did,
  sos_pid_t did,                  sos_pid_t sid,
  sos_pid_t sid,                  uint8_t type,
  uint8_t type,                   uint8_t byte,
  uint8_t length,                 uint16_t word,
  void *data,                     uint8_t flag);
  uint8_t flag);
      Messaging Example: Ping_pong
enum {
enum {
typedef uint8_t ball_t;
typedef struct {
    ball_t next_seq;
} player_t;

      Messaging Example: Ping_pong
int8_t player(void *state, Message *msg){
  player_t *s = (player_t*)state;

 switch (msg->type){
   case MSG_INIT:
     //! initialize the state
     s->next_seq = 0;
     //! start with short ball
     if(msg->did == PLAYER1_PID) {
       post_short(PLAYER2_PID, PLAYER1_PID,
                  MSG_SHORT_BALL, s->next_seq, 0, 0);
     return SOS_OK;

   Messaging Example: Ping_pong
   MsgParam *p = (MsgParam*)(msg->data);
   s->next_seq = p->byte + 1;
   DEBUG("%d get short ball %d\n", msg->did, p-
   if(p->byte % 2) {
     post_short(msg->sid, msg->did,
                MSG_SHORT_BALL, s->next_seq, 0, 0);
   } else {
     post_net(msg->sid, msg->did,
              MSG_LONG_BALL, sizeof(ball_t),
              &(s->next_seq), 0, ker_id());
   return SOS_OK;
  Messaging Example: Ping_pong
  ball_t *b = (ball_t*)(msg->data);
  s->next_seq = (*b) + 1;
  DEBUG("%d get long ball %d\n", msg->did, *b);
  if((*b) % 2) {
    post_long(msg->sid, msg->did,
               MSG_LONG_BALL, sizeof(ball_t),
               &(s->next_seq), 0);
  } else {
    Message m;
    m.did = msg->sid; m.sid = msg->did;
    m.daddr = ker_id(); m.saddr = ker_id();
    m.type = MSG_SHORT_BALL;m.len = sizeof(ball_t); = &(s->next_seq); m.flag = 0;
  return SOS_OK;      26
          Messaging Example: Ping_pong
        return -EINVAL;

void sos_start(void){
                    sizeof(player_t), player);
                    sizeof(player_t), player);

                         Message Types
//                                                msg discription
enum {
    MSG_INIT             = (KER_MSG_START + 0), //!< initialization
    MSG_DEBUG            = (KER_MSG_START + 1), //!< debug info request
    MSG_TIMER_TIMEOUT    = (KER_MSG_START + 2), //!< timeout timer id
    MSG_PKT_SENDDONE     = (KER_MSG_START + 3), //!< send done
    MSG_DATA_READY       = (KER_MSG_START + 4), //!< sensor data ready
    MSG_TIMER3_TIMEOUT   = (KER_MSG_START + 5), //!< Timer 3 timeout
    MSG_FINAL            = (KER_MSG_START + 6), //!< process kill
    MSG_FROM_USER        = (KER_MSG_START + 7), //!< user input (gw only)
    MSG_GET_DATA         = (KER_MSG_START + 8), //!< sensor get data
    MSG_SEND_PACKET         = (KER_MSG_START + 9), //!< send packet
    //! XXX probably not a good idea to put I2C stuff here
    MSG_I2C_SENDSTARTDONE = (KER_MSG_START + 10), //!< I2C send Start done
    MSG_I2C_SENDENDDONE   = (KER_MSG_START + 11), //!< I2C send End done
    MSG_I2C_READDONE      = (KER_MSG_START + 12), //!< I2C Read Done
    MSG_I2C_WRITEDONE     = (KER_MSG_START + 13), //!< I2C Write Done
    //! MAXIMUM is 31 for now
//! PLEASE add name string to kernel/message.c

Applications can create their own messages, that
  need to be added here – include/message_types.h

             Synchronous Communication

                                         Module can register
                                          function for low latency
Module A                Module B
                                          blocking call (1).

                 3                       Modules which need such
                                          function can subscribe it by
  2                         1
                                          getting function pointer
      Module Function                     pointer (i.e. **func) (2).
       Pointer Table
                                         When service is needed,
                                          module dereferences the
                                          function pointer pointer (3).
     Synchronous Communcation API
typedef int8_t (*fn_ptr_t)(void);
// register function
int8_t ker_register_fn(
        sos_pid_t pid,     // function   owner
        uint8_t fid,       // function   id
        char *prototype,   // function   prototype
        fn_ptr_t func);    // function
// subscribe function
fn_ptr_t* ker_get_handle(
        sos_pid_t req_pid, // function   owner
        uint8_t req_fid,   // function   id
        char* prototype)   // function   prototype

                   Memory Management
 Modules need memory to store state information
 Problems with static memory allocation
   •   Worst case memory allocation – every variable is global
   •   Single packet in the radio stack – can lead to race conditions

 Problems with general purpose memory allocation
   •   Non-deterministic execution delay
   •   Suffers from external fragmentation

 Use fixed-partition dynamic memory allocation
   •   Memory allocated in blocks of fixed sizes
   •   Constant allocation time
   •   Low overhead

 Memory management features
   •   Guard bytes for run-time memory over-flow checks
   •   Semi-auto ownership tracking of memory blocks
   •   Automatic free-up upon completion of usage
              SOS Memory API
// allocate memory to id
void *ker_malloc(uint16_t size, sos_pid_t id);

// de-allocate memory
void ker_free(void* ptr);

     Messaging and Dynamic Memory

 Messaging is asynchronous operation. Attaching
  dynamic memory in post() results transfer of
   • Bit Flag is used to tell SOS kernel the existence of dynamic
   • SOS_MSG_DYM_ALLOC -- data is dynamically allocated
   • SOS_MSG_FREE_ON_FAIL -- free memory when post fail.
 Dynamically allocated message payload will be
  automatically freed after module handling.
   • This is the default. You can change it by return
     SOS_TAKEN instead of SOS_OK to take the memory.
   • Message header belongs to the kernel, and it will be
     recycled. If you need them, make a deep copy.
 Asynchronous Module Kernel Interaction
                              Module A
           System Call                    System Messages

              System                                High Priority
            Jump Table       SOS Kernel                Message

HW Specific API                               Interrupt

 Kernel provides system services and access to hardware
 Kernel jump table re-directs system calls from modules to kernel
 Hardware interrupts and messages from the kernel to modules
  are dispatched through a high priority message buffer
    • Low latency
    • Concurrency safe operation
 Schedule Message with Software Timer
                            Module A
         Timer syscall                    Timer Messages

             System                                High Priority
           Jump Table      SOS Kernel                 Message

  Timer API                                   Interrupt
                           Delta Timer

 Two priority: high and low.
   • Normal timer has high priority while slow timer is not.
 Two types: periodic and one shot

                 SOS Timer API
enum {
  TIMER_REPEAT          =   0,    //   high priority, periodic
  TIMER_ONE_SHOT        =   1,    //   high priority, one shot
  SLOW_TIMER_REPEAT     =   2,    //   low priority, periodic
  SLOW_TIMER_ONE_SHOT   =   3,    //   low priority, one shot

int8_t ker_timer_start(
  sos_pid_t pid,                  //   module id
  uint8_t tid,                    //   timer id
  uint8_t type,                   //   timer type
  int32_t interval                //   binary interval
int8_t ker_timer_stop(
  sos_pid_t pid,                  // module id
  uint8_t tid                     // timer id
               Timer Example: Blink
#include <sos.h>
#define MY_ID DFLT_APP_ID0
int8_t blink(void *state, Message *msg)
  switch (msg->type) {
    case MSG_INIT:            //!< initial message from SOS
      //! 256 ticks is 250 milliseconds
      ker_timer_start(MY_ID, 0, TIMER_REPEAT, 256);
      return SOS_OK;
    case MSG_TIMER_TIMEOUT: //!< timeout message arrived
      return SOS_OK;
    default: return -EINVAL;
void sos_start()
  ker_register(MY_ID, 0, blink);
}                            37
                            Sensor Manager
                                      Enables sharing of sensor data
   Module A          Module B          between multiple modules
Periodic                    Polled
Access     Data             Access    Presents a uniform data access API
                                       to many diverse sensors
           Manager                    Underlying device specific drivers
                                       register with the sensor manager
     Request         Data

                                      Device specific sensor drivers control
           Data Policy                     • Calibration
                                           • Data interpolation

                                      Sensor drivers are loadable
  Sensor 1           Sensor 2              • Enables post-deployment configuration
                                             of sensors
                                      38   • Enables hot-swapping of sensors on a
                                             running node
                   SOS Directory Layout
sos/apps        Application directory
    blank_sos   Application with just SOS core
    blink       Blink application
    sender      Periodic packet sending
    ping_pong   ping-pong example

sos/dev         Device specific directory
    mica2       mica2 hardware device drivers
    micaz       micaz hardware device drivers
    gw          Gateway(PC) hardware device drivers
    sim         Simulated hardware device drivers
    xyz         XYZ device driver
    template    sample hardware template

sos/doc         SOS Documentation directory

sos/include     Include files
    modules     include files for loadable modules

sos/kernel      Portable kernel

sos/modules     Loadable module directory
    gw          Modules for Gateway(PC) class device
    mc          Modules for microcontroller class device
              CVS Access

% export CVSROOT=
% export CVS_RSH=ssh
% cvs co sos
  password = „anon‟
% echo “happy hacking”

   Michael Melkonian, “Get by Without an RTOS”, Embedded Systems
    Programming Mag, vol 3. No. 10 Sept., 2000
   Jack W. Crenshaw, “Mea Culpa (Is RTOS needed?)”,
   Karl Fogel, “Open Source Development with CVS”,
   CVS FAQ,


To top