Writing driver for PolyORB-HI-C

Jump to: navigation, search


In TASTE, implementing a driver consists in providing high-level functions that interacts with the OS-specific driver. In TASTE, the driver would consist of wrapper code that initializes, configures and access the driver with specific RTOS/BSP primitives. It consists of:

  • A data configuration type (expressed in ASN.1)
  • An initialisation function
  • A poller function (to poll the data for incoming data)
  • A sender function (to send data through the device)

Driver configuration type

The driver configuration type is defined in an ASN.1 file in PolyORB-HI-C. It already contains ASN data types for 1553, SpaceWire, Serial and Ethernet drivers. In case you need to add a new driver configuration data type, you should introduce your new type in PolyORB-HI-C. This data type is then reused by the TASTE toolchain to configure the driver.

In PolyORB-HI-C, the data types related to the driver configuration are located in the directory src/drivers/configuration.

Driver specification in AADL

The driver is then specified using AADL components (see below). It consists first on a device component that contains the following subcomponents :

  1. Deployment::Driver_Name: Name of the driver in TASTE
  2. Device_Driver: subcomponent that contains the implementation of the driver (see below)
  3. Initialize_Entrypoint: subprogram that initialize the driver
  4. Provided_Virtual_Bus_Class: list of buses that can communicate when using this driver.

The Device_Driver sub-component is an abstract AADL component that describe the resources required to run the device driver. In this example, this sub-component has the type spacewire_rasta and contains two sub-components:

  1. A poller component (receiver_rasta_spacewire) to poll the device for incoming data
  2. A sender component (sender) that is a subprogram to send data with the device over a network
  thread spacewire_poller
  end spacewire_poller;

  thread implementation spacewire_poller.rasta
          mycall : {
            pspg : subprogram spg_spacewire_poller_rasta;
     Period => 1000ms;
     Dispatch_Protocol => Periodic;
  end spacewire_poller.rasta;

  subprogram spg_spacewire_poller_rasta
          Source_Language => C;
          Source_Name => "__po_hi_c_driver_spacewire_rasta_poller";
  end spg_spacewire_poller_rasta;

  subprogram spg_spacewire_sender_rasta
          Source_Language => C;
          Source_Name => "__po_hi_c_driver_spacewire_rasta_sender";
  end spg_spacewire_sender_rasta;

  subprogram spg_spacewire_init_rasta
        Source_Language => C;
        Source_Name => "__po_hi_c_driver_spacewire_rasta_init";
  end spg_spacewire_init_rasta;

  abstract spacewire_driver
     Deployment::Version  => "0.1beta";
     Deployment::Help     => "Write your ASN.1 configuration here";
     Deployment::Configuration_Type => classifier (ocarina_drivers::configuration_type_spacewire);
  end spacewire_driver;

  abstract implementation spacewire_driver.rasta
     receiver_rasta_spacewire : thread spacewire_poller.rasta;
     sender                   : subprogram spg_spacewire_sender_rasta;
  end spacewire_driver.rasta;

  device rasta_spacewire
    link : requires bus access ocarina_buses::spacewire.generic;
  end rasta_spacewire;

  device implementation rasta_spacewire.pohic
    Deployment::Driver_Name       => "spacewire_rasta";
    Device_Driver                 => classifier (ocarina_drivers_rasta_spacewire::spacewire_driver.rasta);
    Initialize_Entrypoint         => classifier (ocarina_drivers_rasta_spacewire::spg_spacewire_init_rasta);
    Provided_Virtual_Bus_Class    => (classifier (ocarina_buses::pohi.c));
  end rasta_spacewire.pohic;

Implementing the driver

Then, you need to implement the driver itself. It consists in writing code specified in the driver specification (AADL model). This code will call the driver primitives implemented in the underlying operating system. For example, for the SpaceWire driver described earlier, this consist of writing three functions:

  • void __po_hi_c_driver_spacewire_rasta_poller (const __po_hi_device_id dev_id): Poll the device. The argument corresponds to the device index on the system (as a system may have several collocated devices)
  • void __po_hi_c_driver_spacewire_rasta_init (__po_hi_device_id id): initialize the device. As for the poller function, the argument corresponds to the device index on the system.
  • int __po_hi_c_driver_spacewire_rasta_sender (const __po_hi_task_id task_id, const __po_hi_port_t port): sends a data on the network. The first argument is the task identifier that is sending the data while the second is the source port of this task. As a task may have several communication ports, it should specify which one is used. Then, by using the communication service of PolyORB-HI-C, the developer can call appropriate functions to retrive the destination ports and remote devices. This function shall return 0 in case of error. For examples about the communication services, it is recommanded to look the code of existing drivers and have a look at PolyORB-HI-C functions in the include/ directory of the sources.

Driver implementation examples/templates

The directory src/drivers of PolyORB-HI-C contains a lot of existing drivers. You can read the code in order to learn the driver mechanisms of PolyORB-HI-C and start writing your own driver.

Getting support

If you want to get support about driver design and implementation in TASTE, you can contact the TASTE user community.