C Microkernel Realtime eXecutive
Realtime Operating System for Cortex-M based microcontrollers
 
Loading...
Searching...
No Matches
Communication abstraction

Description

Communication abstraction offers transport-independent way of communication.

Abstract mechanisms offered here cover one-way communication either as a producer or as a consumer and two-way communication. These mechanisms internally use CMRX RPC interfaces, thus actual implementation of communication interfaces is fully up to provider / consumer.

Main advantage of abstract communication interfaces is, that it is possible to change communication channel without need of changing higher layers of the software. This improves portability and reusability of the code.

You can use communication abstraction in a following way:

Depending on if your communication is uni- or bi-directional and what direction the data flows, choose from one of three interfaces offered here: ComSink, ComSource or ComChannel. Each of these provides pre-defined virtual method table and very lean "virtual" class, which only publishes virtual method table itself. Therefore you are free to provide your own data members and means of how any of these interfaces is implemented.

Next, create your own interface using virtual method table of previously chosen interface, such as:

struct MySourceImplementation {
const struct ComSourceVMT * vtable;
unsigned int my_member;
unsigned short my_member_two;
};
Methods implemented by the interface of class ComSource.
Definition: com.h:142

Next, if you create instance of this interface, you need to initialize the vtable of your interface. You can do it such as:

// declare, which class will actually be accessible from within methods
#define CLASS struct MySourceImplementation
// prototypes of methods of interface implementations
static int my_source_read(SELF, uint8_t * data, unsigned max_len);
static bool my_source_ready(SELF);
static void my_source_set_notify(SELF, struct ComNotification * listener, uint32_t signal);
// map methods into slots of interface vtable
static VTABLE struct ComSourceVMT my_source_vtable = {
&my_source_read,
&my_source_ready,
&my_source_set_notify
};
// create interface instance
static struct MySourceImplementation instance = {
&my_source_vtable,
1,
2
};
#define VTABLE
Definition: application.h:21
__SYSCALL int signal(int signo, void(*sighandler)(uint32_t))
Register function as current thread signal handler.
Definition: signal.c:7
Definition: com.h:130

As you can see, You don't need to provide your own declaration of virtual method table. All you need to do is to provide your own methods to be filled into vtable of chosen interface. Another advantage of this approach is that you can pass instance of MySourceImplementation class whenever, when ComSource is expected. This will work transparently. Methods you've provided will have access to full details of class MySourceImplementation, while caller will simply treat your class as if it was generic ComSource class.

Data Structures

struct  ComNotificationVMT
 Interface of notification callback. More...
 
struct  ComNotification
 
struct  ComSourceVMT
 Methods implemented by the interface of class ComSource. More...
 
struct  ComSource
 Source - read end of simplex channel. More...
 
struct  ComSinkVMT
 Methods implemented by the interface of class ComSink. More...
 
struct  ComSink
 Sink - write end of simplex channel. More...
 
struct  ComChannelVMT
 Methods implemented by the interface of class ComChannel. More...
 
struct  ComChannel
 Channel - bidirectional communication channel. More...
 

Macros

#define COM_NOTIFICATION(name, argname)
 Helper macro for definition of notification callbacks.
 

Functions

int foo (int bar)
 

Macro Definition Documentation

◆ COM_NOTIFICATION

#define COM_NOTIFICATION (   name,
  argname 
)
Value:
static int __ ## name ## _handler(SELF, uint32_t argname);\
\
static VTABLE struct ComNotificationVMT name ## _vmt = {\
&__ ## name ## _handler\
};\
\
static struct ComNotification name = {\
& name ## _vmt,\
0xFF\
};\
\
static int __ ## name ## _handler(SELF, uint32_t argname)
Interface of notification callback.
Definition: com.h:125

Helper macro for definition of notification callbacks.

This macro defines all the stuff required for notification callback implementation. It defines virtual method table owned by the module and prototypes one method of this virtual method table. User can start defining body of this method directly after using macro.

Typical usage of this macro is:

static uint32_t notified_channel;
COM_NOTIFICATION(my_notification, channel)
{
notified_channel = channel;
...wake up or start thread which handles notification...
}
....
// channel initialization code:
rpc_call(&channel, set_notify, &my_notification, channel_id);
#define rpc_call(service_instance, method_name,...)
User-visible way to perform remote procedure call.
Definition: rpc.h:113
#define COM_NOTIFICATION(name, argname)
Helper macro for definition of notification callbacks.
Definition: com.h:105
Parameters
namename of interface instance usable in call to set_notify RPC call
argnamename of argument usable in body of notification handler

Function Documentation

◆ foo()

int foo ( int  bar)