• PicŪ Basic


  • P-RTOS Real Time Operating System for PDS

    Downloads: P_RTOS all files download


    P-RTOS is a real time operating system provides a programming environment which allows routines to appear to run concurrently with each other. Such multitasking can make better use of the processor's resources when compared with the more conventional in line programming.

    Consider DelayMS to adjust the timing of an operation; with a real time operating system this need not be wasted CPU time as the processor can be released to do other tasks. P-RTOS uses a co-operative scheduler to effect multitasking. This means that, outside interrupts, your application must specifically Yield back to the operating system rather than the OS determining when to resume control.

    P-RTOS has been designed and written in Proton PICŪ Basic and provides real time services which can be used directly by your application. The OS takes the form of include files which you reference in your main program to use these services.

    A new approach to programming

    Programming in a P-RTOS environment requires your design to be more event driven with functions broken down into a set of tasks triggered by events. An event can be anything from a timer completing to a character appearing on a serial port.

    The links at the top of this article will take you to downloads of the P-RTOS manual, the source code and a demonstration program.

    A Real Life Example

    Part of the demo program includes a function to drive 4 R/C type servos and is a good real life example of the sort of techniques you will need to use.

    For the purposes of the demo, P-RTOS has been configured to use Timer1 as a basic 10 mSec timing source, referred to as an OSTick. This is the minimum period to which P-RTOS can resolve time. You could reduce this period further but given the same processor clock rate the shorter the tick period the greater the overhead P-RTOS will incur.

    For those unfamiliar with R/C servo operation the position of the servo is determined by the width of the pulse on its input which typically varies between 1mS and 2mS long, 0 to FSD. This must be repeated at a repetition rate of 50Hz or every 20mS to hold the servos in that position. In this example P-RTOS can only resolve down to 10mS so we need another way to generate the individual server pulses. For this we use Timer3. With the background set, let us look at a code extract for the servo driver and explain how it all works.

    There are 3 routines involved in this function; ServoDrv, ServoTmr and ServoISR and they co-operate with each other through the operating system.

    Code:
    ServoTmr: 
       OSStartTask T_ServoDrv                   ' Start the Servo driver.     
    Return
    The ServoTmr starts everything off. It is triggered by a cyclic timer, an OS resource which calls the routine at a set rate. In this example the OS calls the ServoTmr routine every 20mS or 2 OS Ticks. This gives us our basic update rate for the servos. The ServoTmr routine simply starts the Task ServoDrv and returns to the OS. The OS runs the ServoDrv task immediately there are no higher priority tasks waiting to run.

    The desired position of each of the 4 servos is held in a word array (ServoPositions). The 4 servo outputs are allocated to bits 0 to 3 of PortB. The ServoDrv Task sets up a mask to the first Servo, gets the first servo position, loads and starts Timer3, sets the port bit high, and Yields back to the OS (OS_WaitBinSem) to wait for the Timer3 to complete. See the first part of the ServoDrv below.

    Code:
    ServoDrv:
    Repeat
      SetMsk = 00001                              ' set mask initial value
      ClrMsk = ~ SetMsk                           ' set Clear mask initial value
      idx = 0                                     ' and index to first servo position
      Repeat
    Tw = ServoPositions[idx]                   ' Get Servo position
    WriteTimer3 Tw                             ' Set Servo pulse width
        StartTimer3                                ' Start Pulse Timer
        PORTB = PORTB | SetMsk                     ' Write to the port to set pulse high
        OS_WaitBinSem E_ServoDrv,1                 ' Wait on server pulse timeout
    ....
    The ServoISR is triggered by the interrupt generated by Timer3 when it completes. ServoISR stops Timer3, sets the port bit back to 0 and Signals an Event (OSQueue_Event) to the OS.

    Code:
    ServoISR:
      If PIR2.1 = 0 Then GoTo OSUSER_ISR_RTN      ' if Timer3 Interrupt Flag not set skip
      CloseTimer3                                 ' it's this ISR's interrupt so stop timer
      PORTB = PORTB & ClrMsk                      ' clear pulse to low
      OSQueue_Event E_ServoDrv | OSBINSEMEVNT     ' queue the event (Signal timeout for servo)
      Clear PIR2.1   
    GoTo OSUSER_ISR_RTN                           ' return to Main interrupt handler
    The ServoDrv Task has been waiting this Event and resumes from where it left off, incrementing on to the next servo. It continues in this sequence until all the servos have been serviced when ServoDrv stops and returns to the OS. See whole ServoDrv task below:

    Code:
    ServoDrv:   
    Repeat
      SetMsk = 00001                              ' set mask initial value
      ClrMsk = ~ SetMsk                           ' set Clear mask initial value
    idx = 0                                     ' and index to first servo position
    Repeat
        Tw = ServoPositions[idx]                  ' Get Servo position
        WriteTimer3 Tw                            ' Set Servo pulse width
        StartTimer3                               ' Start Pulse Timer
        PORTB = PORTB | SetMsk                    ' Write to the port to set pulse high
        OS_WaitBinSem E_ServoDrv,1                ' Wait on server pulse timeout
        If OSTimedOut = True Then SvError
        SetMsk = SetMsk <<1                       ' Update Set Bit Mask
        ClrMsk = ~ SetMsk                         ' Update Clear Bit mask
        Inc idx                                   ' on to next servo
      Until idx > 3                               ' until all servos serviced
    SvError:
      OS_Stop                                     ' stop and wait to be re triggered.
    Forever
    This whole sequence is restarted when ServoTmr runs next.

    This should give you a flavour of what you can do with P-RTOS. There is an important difference between Cyclic Timers and Tasks. Cyclic Timers call standard routines which must end with a Return. Tasks on the other hand never return but simply loop forever. To return to the OS from a task you must call one of the OS's yield services. In P-RTOS all yielding services start with OS_, and can only be called from a Task.


    The demo program contains much more, including a function to set the servo positions from a terminal so you can see the pulse widths increasing and decreasing. Also included are demonstrations of each of the major services provided by the OS. You can run this program in ISIS using the DSN file provided.
    This article was originally published in forum thread: P-RTOS Real Time Operating System for PDS started by johngb View original post
  • Recent Activity

    towlerg-21522

    Mysterious PORTB problem

    Thread Starter: xldaedalus

    I'm using Proton+ to develop firmware for a product with switches. The MCU is an 18F26K22. Most of the switches reside on PORTB. I am NOT using a...

    towlerg Today, 15:45 Go to last post
    tumbleweed-20435

    PIC18F1330 PLL problem

    Thread Starter: rcurl

    I'm just starting out on a new project that uses a PIC18F1330. I haven't used this specific chip before, so I began by trying to blink an LED just...

    tumbleweed Today, 18:02 Go to last post
    towlerg-21522

    Pic16f18877 oread

    Thread Starter: evoortman

    Hi, On a PIC16F18877 the OREAD command doesn't seem to work. The code is working on a PIC16F1939. Both controllers use 32MHz int osc. If i...

    towlerg Today, 15:59 Go to last post