Skip to content

VELOOS Example 1

The previous post gave a brief introduction to VELOOS design idea. VELOOS assumes that an application is decomposed on PDOs (Process Data Objects). This post describes by example features provided by VELOOS for implementing PDO.

Self-triggering PDO

Design idea: Implement a PDO sending a message to itself. On every message received toggle a pin.
Value: Provides a simple example of PDO implementation.
Implements a metric for measuring/estimating system throughput.

Implementing a PDO for VELOOS requires three steps:

  • Declaring a class
  • Implementing message handler and initializer
  • Instantiating an object

Declaring a class

Class declaration sections starts with VOS_Classes macro and ends with beginning of any other section. As with regular MP ASM sections, there is no explicit ‘section end’ therefore it is important to properly delimit class declaration sections. A source file may have only one class declaration sections (MP ASM constraints).

Within class declaration section, a class is declared VOS_mClass macro. The macro should be preceded with a class name – a valid MP ASM label. This macro generates the class’s dispatch table. It accepts two labels as parameters: message handler and initialization handler. These labels should be known in this module (e.g. defined in the same module or imported with extern directive).


VOS_Classes                                ; Class definitions begin
MyClass VOS_mClass MyHandler, MyInit       ; MyClass implementes MyHandler and MyInit methods
 
    code
MyInit
    ...
    return
 
MyHandler
    ...
    return

Instantiating an object

Object instantiation section begins with VOS_Objects macro and ends with beginning of any other section. It accepts two parameters – class name and object data. Object data can be any 8-bit value. System does not make any assumption on it, it just loads this value to system variable This. Class name must be a label of a previously declared class. It should be known in this module.


 
VOS_Objects                        ; Object registry begins
MyObject
 VOS_mPersistentObject MyClass, 0  ; Instance of MyClass constructed with object data == 0
 

Objects can be instantiated in the same unit where class implemented or in a different unit. In latter case, class name should be exported with globaldirective.

Note on Class Reenterability

A reenterable class allows instantiating several objects. From the system point of view all classes are reenterable. Whether a particular class is reenterable or no depends on its design and implementation and it is up to developer to make such decision. To make a class reenterable, all resources it uses must be allocated by means of object data. PDO implemented in this example is not
reenterable.

Implementing a message handler

Message handler is a subroutine, called by the OS when it finds a message addressed to this object or a broadcast message. On handler entrance This is loaded with object data and FSR is pointing to the message ID, so that the handler may compare INDF to a (set of) message ID(s) known to PDO. A PDO should process only know messages and ignore all others. Once the message is recognized, PDO may increment FSR and access message data (if necessary). In this example message has no custom data.

Implementing an initializer

Initializer is a subroutine, called by the OS on start-up (power up and reset events). On its entrance This is loaded with object data. Initializer is called for every instantiated object, therefore Initializer should prepare all registers or periphery used by this particular instance. If there is a need of some initialization code executed for all instances PDO should implement a boot handler.

Sending a message

VELOOS provides few macros for sending messages. Each of those macro “allocates” space for a new message, places acceptor handle, message ID, sender handle (in the last location). When it completes, FSR is pointing to custom data location,
so that PDO may put message data if necessary.

Macro Parameters Description
VOS_mPostMessage obj_to – accepter handle
msg_id – message ID
Posts a message to a statically defined object. Both message ID and acceptor are defined at build time
VOS_mBroadcastMsg msg_id – message ID Posts a broadcast message. Message ID defined at build
time
VOS_mPostMsgIndir obj_ptr  file containing accepter handle
msg_id  message ID
Posts a message to an object using handle stored in a file, e.g. Acceptor is defined at run time while message ID at build time
VOS_mPostMsgDyn obj_ptr  file containing accepter handle
msg_file  file containing message ID
Posts a message to an object using handle stored in a file and message ID stored in another file. Both acceptor and message ID are defined at run time

In this example only one form is used:

    VOS_mPostMessage MyObject, 2   ; post message to MyObject
 

Implementing a boot handler

Boot handler is a fragment of code executed by the system on start-up. It is not related with any class or object. A boot handler is implemented by placing code to VOS_BootHandlers section. Since an asm file may have only one occurrence of a section name there could be only one boot handler in a source asm file. However, application that consists of many files may have many boot handlers. Order of execution is not known and not fixed, therefore the code should not relay on any particular order. When boot handler is executed objects are not initialized


 
VOS_BootHandlers code              ; starts a section for the application boot handler
    banksel     ANSEL
    clrf        ANSEL              ; Turn all pints to digital

    clrf        ANSELH
    banksel    
OSCCON             ; Set Fosc = 8Mhz
    movlw       (.7 << IRCF0)
    movwf       OSCCON
    ; !!! NO RETURN ALLOWED !!!

Building the project

A VELOOS project, to be properly built, should include VELOOS kernel (vos.asm) and VELOOS specific instructions in the linker script for the target device. Unfortunately, MP LAB does not support multiple lkr files (it just takes the first one) therefore changes have to be made in a copy of a standard .lkr file distributed with MP LAB.

VELOOS can be configured (fine tuned) at build time. All configurable parameters are given in a separate inc file.

A package with sources for this example can be downloaded on this link. It includes the following files:

Example1.mcp MP LAP project file
main.asm Example1 application sources
pic.inc Processor-specific primitives, macros and includes
pic16.inc PIC16/PIC12 specific primitives
vos.asm VELOOS kernel
vos.inc VELOOS public interface
vos_cfg.inc VELOOS configuration file
16f690.lkr VELOOS specific linker script

Download Example1 Sources

Simulation results

Figure 1 shows Logic Analyzer trace (20000 IC = 10 ms). As it can be easily counted, this example processes 13 messages per millisecond with turnaround in about 150 IC. Any load on CPU will decrease this number (which will be illustrated in the next example). 150 IC per message can be considered as messaging overhead and should be accounted when designing time-critical applications.

  Example1. Logic Analyzer Trace
Figure 1

Application Source


 
;      License:   Licensed to public under the Open Software License
;                http://www.opensource.org/licenses/osl-3.0.php
 include "pic.inc"
 include "vos.inc"
 
;------------------------------------------------------------------------------
 __CONFIG _WDT_ON & _INTRC_OSC_NOCLKOUT & _CP_OFF & _PWRTE_ON & _MCLRE_ON & _FCMEN_OFF & _BOR_OFF & _IESO_OFF
;------------------------------------------------------------------------------
 
 constant mask = .2                        ; mask to be used for driving port (RA1)
 constant msgid = 040h                     ; message ID

 
VOS_Classes                                ; Class definitions begin
MyClass VOS_mClass MyHandler, MyInit       ; MyClass implementes MyHandler and MyInit methods
                                           ; Class definitions end with beginning of the next code section
VOS_Objects                                ; Object registry begins
MyObject
  VOS_mPersistentObject MyClass, mask      ; Instance of MyClass constructed with object data == mask
                                           ; Object registry ends with beginning of the code next section
;------------------------------------------------------------------------------

    code
MyInit                                     ; This was loaded with object data
    comf       This, W                     ; W := ~mask

    banksel     TRISA
    movwf      TRISA                       ; Prepare port for output
    VOS_mPostMessage MyObject, msgid       ; post message to itself
    return
;------------------------------------------------------------------------------
 
MyHandler                                  ; FSR points to message ID field, This is loaded with object data
    movlw       msgid
    xorwf       INDF, W                    ; if message.msg_id <> msgid
    skpz
    return                                 ; return
    movf        This, W
    banksel     PORTA
    xorwf       PORTA, F                   ; Toggle port
    VOS_mPostMessageMyObject, msgid        ; post message to itself
    return
;------------------------------------------------------------------------------
 
VOS_BootHandlers code                       ; starts a section for the application boot handler
    banksel     ANSEL
    clrf       ANSEL                        ; Turn all pints to digital
    clrf        ANSELH
    banksel    OSCCON                       ; Set Fosc = 8Mhz
    movlw       (.7 << IRCF0)
    movwf       OSCCON
    ; !!! NO RETURN ALLOWED !!!
;------------------------------------------------------------------------------
 
 end

3 Comments