RKH
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Porting
rkh_bunner.jpg

Prev: Home
Next: Configuration

This section describes how to adapt the RKH to various platforms, which is a process called porting. RKH contains a clearly defined abstraction layer, which encapsulates all the platform-specific code and cleanly separates it from platform-neutral code.

Porting RKH implies to create the a few platform-dependent files, rhhport.h, rkhport.c, which frequently defines the interrupt locking method, the critical section management, among other things. The RKH directories and files are described in detail in Installation section. The next sections listed below describes the aspects to be considered to port RKH:


This section includes:



Platform-dependent files

Please, see RKH portable directory section.



Data types definitions

Please, see RKH portable directory section.



ROM allocator

For declaring an object that its value will not be changed and that will be stored in ROM, must be defined in rkhport.h the RKHROM macro.

Example:

#define RKHROM const



Blocking mechanism

RKH works in conjunction with a traditional OS/RTOS?

YES:
The RKH framework can work with virtually any traditional OS/RTOS. Combined with a conventional RTOS, RKH takes full advantage of the multitasking capabilities of the RTOS by executing each active object (SMA) in a separate task or thread.

Example for x86, VC08, and win32 with scheduler emulation

#define RKH_EQ_TYPE RKH_RQ_T
#define RKH_OSSIGNAL_TYPE HANDLE
#define RKH_THREAD_TYPE HANDLE
#define RKH_SMA_BLOCK( sma ) \
RKH_ASSERT( ((RKH_SMA_T*)(sma))->equeue.qty != 0 )
#define RKH_SMA_READY( rg, sma ) \
RKH_RDY_INSERT( (rg), ((RKH_SMA_T*)(sma))->romrkh->prio ); \
(void)SetEvent( sma_is_rdy )
#define RKH_SMA_UNREADY( rg, sma ) \
RKH_RDY_REM( (rg), ((RKH_SMA_T*)(sma))->romrkh->prio )
#define RKH_WAIT_FOR_EVENTS() \
((void)WaitForSingleObject( sma_is_rdy, (DWORD)INFINITE))
void
rkh_fwk_init( void )
{
InitializeCriticalSection( &csection );
sma_is_rdy = CreateEvent( NULL, FALSE, FALSE, NULL );
}
void
{
rui8_t prio;
RKH_SMA_T *sma;
RKH_HOOK_START();
running = 1;
while( running )
{
RKH_ENTER_CRITICAL( dummy );
if( RKH_RDY_ISNOT_EMPTY( rkhrg ) )
{
RKH_RDY_FIND_HIGHEST( rkhrg, prio );
RKH_EXIT_CRITICAL( dummy );
sma = rkh_sptbl[ prio ];
e = rkh_sma_get( sma );
rkh_sm_dispatch( (RKH_SM_T *)sma, e );
RKH_FWK_GC( e );
}
else
}
CloseHandle( sma_is_rdy );
DeleteCriticalSection( &csection );
}
void
rkh_fwk_exit( void )
{
}
void
rkh_sma_activate( RKH_SMA_T *sma, const RKH_EVT_T **qs, RKH_RQNE_T qsize,
void *stks, rui32_t stksize )
{
( void )stks;
( void )stksize;
rkh_rq_init( &sma->equeue, (const void **)qs, qsize, sma );
rkh_sm_init( (RKH_SM_T *)sma );
}
void
{
}

NO:



Priority mechanism

If RKH works in conjunction with a traditional OS/RTOS, RKH provides its own priority mechanism?

YES:

NO:
Nothing to do.



Event queue

If RKH works in conjunction with a traditional OS/RTOS, are implemented the event queues with a message queue of the underlying OS/RTOS?

YES:

Generic example

void
{
RKH_SR_ALLOC();
RKH_HOOK_SIGNAL( e );
RKH_ENTER_CRITICAL_();
if( RKH_CAST_EVT( e )->pool != 0 )
++RKH_CAST_EVT( e )->nref;
RKH_EXIT_CRITICAL_();
os_post_fifo_message( &sma->equeue, e );
RKH_TR_SMA_FIFO( sma, e );
}
void
{
RKH_SR_ALLOC();
RKH_HOOK_SIGNAL( e );
RKH_ENTER_CRITICAL_();
if( RKH_CAST_EVT( e )->pool != 0 )
++RKH_CAST_EVT( e )->nref;
RKH_EXIT_CRITICAL_();
os_post_lifo_message( &sma->equeue, e );
RKH_TR_SMA_LIFO( sma, e );
}
{
RKH_SR_ALLOC();
RKH_ENTER_CRITICAL_();
e = os_get_message( &sma->equeue );
RKH_ASSERT( e != ( RKH_EVT_T * )0 );
RKH_EXIT_CRITICAL_();
RKH_TR_SMA_GET( sma, e );
return e;
}

NO:

If the application code uses the RKH native scheduler, are implemented the event queues with the native queues RKH_RQ_T?

YES:

NO:



Dynamic event support

Is required events with arguments?

NO:

YES:
If RKH works in conjunction with a traditional OS/RTOS, is implemented the dynamic memory support with a internal module of the underlying OS/RTOS?

YES:

Generic example

#define RKH_DYNE_TYPE RKH_MP_T
#define RKH_DYNE_INIT( mp, sstart, ssize, esize ) \
rkh_mp_init( (mp),sstart,(rui16_t)ssize,(RKH_MPBS_T)esize )
#define RKH_DYNE_GET_ESIZE( mp ) \
( (mp)->bsize )
#define RKH_DYNE_GET( mp, e ) \
( (e) = (RKH_EVT_T*)rkh_mp_get( (mp) ) )
#define RKH_DYNE_PUT( mp, e ) \
( rkh_mp_put( (mp), e ) )

NO:

If the application code uses the RKH native scheduler, is implemented the dynamic memory support with the native fixed-size memory block pool RKH_MP_T?

YES:

NO:



Hook functions

A RKH port cannot and should not define all the functions that it calls, because this would render the port too inflexible. The functions that RKH calls but doesn't actually implement are referred to as callback or hook functions. All these functions in RKH are easily indentifiable by the "_hook_" key word used in the function name, rkh_hook_dispatch(), rkh_hook_signal(), rkh_hook_timeout(), rkh_hook_start(), rkh_hook_exit(), and rkh_hook_idle(). Please, see RKH_CFG_HOOK_DISPATCH_EN, RKH_CFG_HOOK_SIGNAL_EN, RKH_CFG_HOOK_TIMEOUT_EN, RKH_CFG_HOOK_START_EN, and RKH_CFG_HOOK_EXIT_EN options from the rkhcfg.h.

Type value
Boolean
Range value
Default configuration:
RKH_DISABLED
Type value
Boolean
Range value
Default configuration:
RKH_DISABLED
void rkh_hook_timeout( const void *t )
Type value
Boolean
Range value
Default configuration:
RKH_DISABLED
void rkh_hook_start( void )
Type value
Boolean
Range value
Default configuration:
RKH_DISABLED
void rkh_hook_exit( void )
Type value
Boolean
Range value
Default configuration:
RKH_DISABLED
void rkh_hook_idle( void )

This makes the idle hook function an ideal place to put the processor into a low power state - providing an automatic power saving whenever there is no processing to be performed.

Note
The rkh_hook_idle() callback is called with interrupts locked, because the determination of the idle condition might change by any interrupt posting an event. This function must internally unlock interrupts, ideally atomically with putting the CPU to the power-saving mode.
Usage
void
rkh_hook_idle( void ) // NOTE: entered with interrupts DISABLED
{
RKH_ENA_INTERRUPT(); // must at least enable interrupts
...
}



Interrupt locking mechanism

Example for HCS08 CW6.3 from C:

#define RKH_DIS_INTERRUPT() DisableInterrupts
#define RKH_ENA_INTERRUPT() EnableInterrupts

Please, see Installation section about RKH port directory and files.



Critical section



Trace facility

When using the trace facility must be defined in rkhport.h the following configurations:

#define RKH_CFGPORT_TRC_SIZEOF_PTR 32u
#define RKH_CFGPORT_TRC_SIZEOF_FUN_PTR 32u
#define RKH_CFGPORT_TRC_SIZEOF_TSTAMP 32u

A RKH port cannot and should not define all the functions that it calls, because this would render the port too inflexible. Therefore, the application-specific functions rkh_trc_open(), rkh_trc_close(), rkh_trc_flush(), and rkh_trc_getts() are application provided typically in the board support package (bsp.c).


void rkh_trc_open( void )

This function is application-specific and the user needs to define it. At a minimum, this function must initialize and/or configure the trace stream by calling rkh_trc_init() and RKH_TRC_SEND_CFG() respectively.

Note
This function is internal to RKH and the user application should not call it. Instead, use RKH_TRC_OPEN() macro.
See also
rkhtrc.h file.
Usage
#define BSP_SIZEOF_TS 32u
#define BSP_TS_RATE_HZ CLOCK_PER_SEC
void
rkh_trc_open( void )
{
FTBIN_OPEN();
TCP_TRACE_OPEN();
RKH_TRC_SEND_CFG( BSP_SIZEOF_TS, BSP_TS_RATE_HZ );
if(( idle_thread = CreateThread( NULL, 1024,
&idle_thread_function, (void *)0,
CREATE_SUSPENDED, NULL )) == (HANDLE)0 )
fprintf( stderr, "Cannot create the thread: [%d]
line from %s "
"file\n", __LINE__, __FILE__ );
}


void rkh_trc_close( void )

This function is application-specific and the user needs to define it.

Note
This function is internal to RKH and the user application should not call it. Instead, use RKH_TRC_CLOSE() macro.
See also
rkhtrc.h file.
Usage
void
{
fclose( fdbg );
}


void rkh_trc_flush( void )

This function is application-specific and the user needs to define it. When the RKH trace an event, all the information related to it has to be stored somewhere before it can be retrieved, in order to be analyzed. This place is a trace stream. Frequently, events traced are stored in the stream until it is flushed.

Note
This function is internal to RKH and the user application should not call it. Instead, use RKH_TRC_FLUSH() macro.
See also
rkhtrc.h file.
Usage
void
{
rui8_t *blk;
TRCQTY_T nbytes;
RKH_SR_ALLOC();
FOREVER
{
nbytes = (TRCQTY_T)1024;
RKH_ENTER_CRITICAL_();
blk = rkh_trc_get_block( &nbytes );
RKH_EXIT_CRITICAL_();
if((blk != (rui8_t *)0))
{
FTBIN_FLUSH( blk, nbytes );
TCP_TRACE_SEND_BLOCK( blk, nbytes );
}
else
break;
}
}

void rkh_trc_getts( void )
This function is application-specific and the user needs to define it. The data returned is defined in compile-time by means of RKH_SIZEOF_TSTAMP.
Returns
Timestamp (RKH_TS_T data type).
See also
rkhtrc.h file.
Usage
{
return ( RKH_TS_T )clock();
}


A port file example.

"rkhport.h" for x86, VC08, and win32 with scheduler emulation (\source\portable\80x86\win32_st\vc08)

/*
* file: rkhport.h - Visual Studio 2008 port
* Last updated for version: 1.0.00
* Date of the last update: Feb 27, 2012
* Copyright (C) 2010 Leandro Francucci. All rights reserved.
* RKH is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* RKH is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with RKH, see copying.txt file.
* Contact information:
* RKH web site: http://sourceforge.net/projects/rkh-reactivesys/
* e-mail: francuccilea@gmail.com
*/
/*
* rkhport.h
*/
#ifndef __RKHPORT_H__
#define __RKHPORT_H__
#include <windows.h>
#include "rkhtype.h"
#include "rkhrq.h"
#include "rkhmp.h"
#include "rkhrdy.h"
extern CRITICAL_SECTION csection;
extern HANDLE sma_is_rdy;
extern RKH_RG_T rkhrg;
const char *rkh_get_port_version( void );
const char *rkh_get_port_desc( void );
#define RKH_CFGPORT_SMA_THREAD_EN 0
#define RKH_CFGPORT_SMA_THREAD_DATA_EN 0
#define RKH_CFGPORT_NATIVE_SCHEDULER_EN 0
#define RKH_CFGPORT_NATIVE_EQUEUE_EN 1
#define RKH_CFGPORT_NATIVE_DYN_EVT_EN 1
#define RKH_CFGPORT_REENTRANT_EN 0
#define RKH_CFGPORT_TRC_SIZEOF_PTR 32
#define RKH_CFGPORT_TRC_SIZEOF_FUN_PTR 32
#define RKH_CFGPORT_TRC_SIZEOF_TSTAMP 32u
#define RKH_CFGPORT_SMA_QSTO_EN RKH_ENABLED
#define RKH_CFGPORT_SMA_STK_EN RKH_ENABLED
/*
* Declaring an object RKHROM announces that its value will
* not be changed and it will be stored in ROM.
*/
#define RKHROM const
#define RKH_DIS_INTERRUPT()
#define RKH_ENA_INTERRUPT()
//#define RKH_CPUSR_TYPE
#define RKH_ENTER_CRITICAL( dummy ) EnterCriticalSection( &csection )
#define RKH_EXIT_CRITICAL( dummy ) LeaveCriticalSection( &csection )
#define RKH_EQ_TYPE RKH_RQ_T
#define RKH_OSSIGNAL_TYPE HANDLE
#define RKH_THREAD_TYPE HANDLE
#define RKH_SMA_BLOCK( sma ) \
RKH_ASSERT( ((RKH_SMA_T*)(sma))->equeue.qty != 0 )
#define RKH_SMA_READY( rg, sma ) \
RKH_RDY_INSERT( (rg), ((RKH_SMA_T*)(sma))->romrkh->prio ); \
(void)SetEvent( sma_is_rdy ); \
#define RKH_SMA_UNREADY( rg, sma ) \
RKH_RDY_REM( (rg), ((RKH_SMA_T*)(sma))->romrkh->prio )
#define RKH_WAIT_FOR_EVENTS() \
((void)WaitForSingleObject( sma_is_rdy, (DWORD)INFINITE))
#endif

"rkht.h" for x86, VC08, and win32 scheduler emulation (\source\portable\80x86\win32_st\vc08)

#ifndef __RKHT_H__
#define __RKHT_H__
/*
* Portable data types.
* The RKH uses a set of integer quantities. That maybe
* machine or compiler dependent.
* Note:
* The 'ruint' and 'rint' will normally be the natural size
* for a particular machine. These types designates an integer
* type that is usually fastest to operate with among all integer
* types.
*/
typedef signed char ri8_t;
typedef signed short ri16_t;
typedef signed long ri32_t;
typedef unsigned char rui8_t;
typedef unsigned short rui16_t;
typedef unsigned long rui32_t;
typedef unsigned int ruint;
typedef signed int rint;
#endif

"rkhport.c" for x86, VC08, and win32 with scheduler emulation (\source\portable\80x86\win32_st\vc08)

/*
* file: rkhport.c - Visual Studio 2008 port
* Last updated for version: 1.0.00
* Date of the last update: Feb 22, 2012
* Copyright (C) 2010 Leandro Francucci. All rights reserved.
* RKH is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* RKH is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with RKH, see copying.txt file.
* Contact information:
* RKH web site: http://sourceforge.net/projects/rkh-reactivesys/
* e-mail: francuccilea@gmail.com
*/
/*
* rkhport.c
*/
#include "rkh.h"
RKH_MODULE_NAME( rkhport )
RKH_MODULE_VERSION( rkhport, 1.00 )
RKH_MODULE_DESC( rkhport, "Windows 32-bits (single thread)" )
CRITICAL_SECTION csection; /* Win32 critical section */
HANDLE sma_is_rdy; /* Win32 event to signal when SMAs are ready */
RKH_RG_T rkhrg; /* ready group of SMAs */
extern rui8_t running;
const
char *
rkh_get_port_version( void )
{
}
const
char *
rkh_get_port_desc( void )
{
}
void
rkh_fwk_init( void )
{
InitializeCriticalSection( &csection );
sma_is_rdy = CreateEvent( NULL, FALSE, FALSE, NULL );
}
void
{
rui8_t prio;
RKH_SMA_T *sma;
RKH_HOOK_START();
running = 1;
while( running )
{
RKH_ENTER_CRITICAL( dummy );
if( RKH_RDY_ISNOT_EMPTY( rkhrg ) )
{
RKH_RDY_FIND_HIGHEST( rkhrg, prio );
RKH_EXIT_CRITICAL( dummy );
sma = rkh_sptbl[ prio ];
e = rkh_sma_get( sma );
rkh_sm_dispatch( (RKH_SM_T *)sma, e );
RKH_FWK_GC( e );
}
else
}
RKH_HOOK_EXIT();
CloseHandle( sma_is_rdy );
DeleteCriticalSection( &csection );
}
void
rkh_fwk_exit( void )
{
running = 0;
}
void
rkh_sma_activate( RKH_SMA_T *sma, const RKH_EVT_T **qs, RKH_RQNE_T qsize,
void *stks, rui32_t stksize )
{
( void )stks;
( void )stksize;
rkh_rq_init( &sma->equeue, (const void **)qs, qsize, sma );
rkh_sm_init( (RKH_SM_T *)sma );
}
void
{
}