Docs

You are here:
Initializing and running the connection

The connection structure

The first thing when working with the RCM library is to initialize and open a connection with an RCM radio module. The connection is represented by RCMConnection structure which encapsulates all the data related to the connection. A single RCMConnection is a central point of all the library API.

The connection structure is usually defined by the user. Each instance represents a single RCM radio module (usually there is only one in the system).

// Structure representing the connection with the RCM radio module

Once we have the connection structure, we can start using the RCM library API.

Opening the connection

The very first thing we want to do is to open the connection. We do that through a call to RCM_Open, however there are several concepts we need to grasp before we do that. Most of them have to do with the underlying libraries that are designed with portability in mind. Let's list and briefly discuss them:

The IODevice object

Internally, the RCM library relies on HALFRED(tm) hardware abstraction layer, which, among others, introduces a concept of IODevices - abstraction of peripherals that can read and write data (I/O). One example of such device will be a serial communication port through which we communicate with a RCM radio module. The HALFRED library port provides these objects or means of constructing them. We're going to need one in order to communicate with a RCM radio module. For the purpose of this tutorial let's assume that the port we're going to use is called USART1.

SCOM frame buffer

The RCM library relies on SCOM communication protocol when it comes to delivering and receiving information to and from a RCM radio module. The underlying SCOM library implementation is designed in a portable way, which among other implies that it should be adaptable to a range of hardware platforms, including small 8-bit microcontrollers. On such platforms it is often strongly encouraged NOT to use any dynamic memory allocation. Thus, by default the SCOM library requires the user to define a memory pool of a chosen size, called SCOM frame buffer, that the SCOM library can use to queue incoming and outgoing SCOM packets. The SCOM library also delivers a convenient macro for doing so called SCOM_DECLARE_FRAME_BUFFER, that we can use to construct a frame buffer. Here's an example:

// Declare a structure named frameBuffer, that will fit 5 outgoing and 10 incoming SCOM packets
SCOM_DECLARE_FRAME_BUFFER(frameBuffer, 5, 10);

It is worth to note, that on platforms that do not have stringent heap memory usage barriers, we can use different macro, called SCOM_DECLARE_FRAME_BUFFER_USING_HEAP, and declare frame buffer without upper limits (other than heap memory availability) on the number of frames it can fit:

// Declare a structure named frameBuffer, that will fit infinite SCOM packets
SCOM_DECLARE_FRAME_BUFFER_USING_HEAP(frameBufferInHeap);

In order to open a RCMConnection we are going to need such frame buffer. Let's assume that it is the one from the first example called frameBuffer

RCM message buffer

The RCM library follows the same principles as SCOM implementation. As the library handles RCM messages it also needs space to hold them. This space will be called message buffer, and the user is expected to provide one of it's choosen size. Again, we have a convenient macro to do so called RCM_DECLARE_MESSAGE_BUFFER:

// Declare a structure named messageBuffer that can fit 10 RCM messages
RCM_DECLARE_MESSAGE_BUFFER(messageBuffer, 10);

Similar to SCOM, we have the RCM_DECLARE_MESSAGE_BUFFER_USING_HEAP macro to declare frame buffer without upper limits on the number of messages it can fit (other that heap memory availability):

// Declare a structure named messageBufferInHeap that can fit unlimited number of RCM messages
RCM_DECLARE_MESSAGE_BUFFER_USING_HEAP(messageBufferInHeap);

For further purposes we will use the first approach - our message buffer will be called messageBuffer.

Clock provider

The RCM library as well as the underling SCOM protocol implementation deals with real-time communication. Thus we need to deliver the information about time in a most portable manner. To do so, the RCM library expects the user to deliver a function, that will return current time in ms. We will call that function clockProvider.

Finally we can construct a working code:

#include "rcm.h"
// Structure holding information about the connection
static RCMConnection rcm;
// Declare a structure named frameBuffer, that will fit 5 outgoing and 10 incoming SCOM packets
static SCOM_DECLARE_FRAME_BUFFER(frameBuffer, 5, 10);
// Declare a structure named messageBuffer that can fit 10 RCM messages
static RCM_DECLARE_MESSAGE_BUFFER(messageBuffer, 10);
int rcm_init_example(IODevice iodevice)
{
// try to open the connection using specified IODevice
if (RCM_RESULT_OK == RCM_Open(&rcm, iodevice, &frameBuffer, &messageBuffer, OS_GetSystemTime)) {
// ... do something with the RCM module (read on!)
// finally close the connection
RCM_Close(&rcm);
// all OK
return 0;
} else {
// error
return 1;
}
}

Note, that in the above example the RCM_Close function is used to close a previously opened connection and free all resources taken for that purpose.

Running the connection

Opening the connection does not make it operational yet. Due to library design choices related to portability, the RCM library expects the user to periodically run two functions:

Both of these functions should be called periodically, with a rate acceptable to maintain a short response capability - around 10-50ms is a good approximation. Usually the functions can be called in a main loop or inside an operatin system thread.

The RCM library can make full use of an operating system. On target platforms covered by HALFRED operating system abstraction layer this is done automatically. On such platforms the user can simply call RCM_Run to start all threads necessary to run the connection. A complementary RCM_Stop is used to stop these threads

  • usually prior to closing the connection.

At any given time the user can poll the connection state using RCM_GetConnectionState function.

The following example shows a typical pattern when working on an operating system supported by HALFRED abstraction layer:

#include "rcm.h"
// Structure holding information about the connection
static RCMConnection rcm;
// Declare a structure named frameBuffer, that will fit infinite SCOM packets
static SCOM_DECLARE_FRAME_BUFFER_USING_HEAP(frameBufferInHeap);
// Declare a structure named messageBufferInHeap that can fit unlimited number of RCM messages
static RCM_DECLARE_MESSAGE_BUFFER_USING_HEAP(messageBufferInHeap);
int rcm_run_example(IODevice iodevice)
{
int result = 0;
OSTime startTime;
// get current time
startTime = OS_GetSystemTime();
// try to open the connection using specified IODevice
if (RCM_RESULT_OK == RCM_Open(&rcm, iodevice, &frameBufferInHeap, &messageBufferInHeap, OS_GetSystemTime)) {
// connection opened, run it
if (RCM_RESULT_OK == RCM_Run(&rcm)) {
// threads run successfully
while (0 == result) {
// ... do something with the RCM module (read on!)
// check connection
if (RCM_RESULT_OK != RCM_GetConnectionState(&rcm)) {
// connection broke down (hardware error?)
// exit with error code
result = 2;
}
// check timeout
if (OS_GetSystemTime() - startTime > 5000) {
// timeout
break;
}
}
// stop the RCM threads
RCM_Stop(&rcm);
} else {
// error
result = 2;
}
// finally close the connection
RCM_Close(&rcm);
} else {
// error
result = 1;
}
return result;
}
Go to Top