RKH
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, rkht.h, which frequently defines the interrupt locking method, the critical section management, data types, among other things.

Note
It is recommended to start from a similar and existing port, properly copying and modifying its files (rkhport.c, rkhport.h and rkht.h) according to your needs and platform in question.

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.

  1. Platform-dependent files
  2. Data types definitions
  3. ROM allocator
  4. Active Object execution
  5. Dynamic event support
  6. Hook functions
  7. Interrupt locking mechanism
  8. Critical section
  9. Trace facility
  10. A port file example
  11. Extras

Platform-dependent files

Create a directory into source/fwk/portable within its platform dependent-files (rkhport.c, rkhport.h and rkht.h). Please, see RKH portable directory section.


Data types definitions

Create the data type file. The RKH uses a set of integer quantities. That maybe machine or compiler dependent. These types must be defined in rkht.h file. The following listing shows the required data type definitions:

/* ------------------------------- Data types ------------------------------ */
/*
* The RKH uses a set of integer quantities. That maybe machine or
* compiler dependent.
*/
typedef signed char ri8_t; /* Denotes a signed integer type with a */
/* width of exactly 8 bits */
typedef signed short ri16_t; /* Denotes a signed integer type with a */
/* width of exactly 16 bits */
typedef signed long ri32_t; /* Denotes a signed integer type with a */
/* width of exactly 32 bits */
typedef unsigned char rui8_t; /* Denotes a unsigned integer type with */
/* a width of exactly 8 bits */
typedef unsigned short rui16_t; /* Denotes a unsigned integer type with */
/* a width of exactly 16 bits */
typedef unsigned long rui32_t; /* Denotes a unsigned integer type with */
/* a width of exactly 32 bits */
/*
* 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 unsigned int ruint;
typedef signed int rInt;
/*
* Boolean data type and constants.
*
* \note
* The true (RKH_TRUE) and false (RKH_FALSE) values as defined as macro
* definitions in \c rkhdef.h file.
*/
typedef unsigned int rbool_t;

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

Active Object execution

RKH works in conjunction with a traditional OS/RTOS? [ YES ] - [ NO ]


RKH works in conjunction with a traditional OS/RTOS?: YES
Is a multithreaded application? [ YES ] - [ NO ]


Is a multithreaded application?: 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.

  1. Define the macros RKH_CFGPORT_NATIVE_SCHEDULER_EN = RKH_DISABLED, RKH_CFGPORT_SMA_THREAD_EN = RKH_ENABLED, RKH_CFGPORT_REENTRANT_EN = RKH_ENABLED, within the rkhport.h file.
  2. Define the macros RKH_THREAD_TYPE, RKH_CFGPORT_SMA_STK_EN and RKH_THREAD_STK_TYPE in rkhport.h according to underlying OS/RTOS.
  3. Define the macro RKH_CFGPORT_SMA_STK_EN in rkhport.h according to OS/RTOS.
  4. Then, implement the platform-specific functions rkh_fwk_init(), rkh_fwk_enter(), rkh_fwk_exit(), rkh_sma_activate(), and rkh_sma_terminate() in rkhport.c, which are specified in source/fwk/inc/rkhfwk_sched.h and source/sma/inc/rkhsma.h respectively.

Example for ARM Cortex-M4 Kinetis, KDS, KSDK and uC/OS-III
Fragment of rkhport.h See source/portable/arm-cortex/ksdk_os/ucosiii/kds/rkhport.h

#define RKH_CFGPORT_NATIVE_SCHEDULER_EN RKH_DISABLED
#define RKH_CFGPORT_SMA_THREAD_EN RKH_ENABLED
#define RKH_CFGPORT_REENTRANT_EN RKH_ENABLED
#define RKH_THREAD_TYPE OS_TCB
#define RKH_THREAD_STK_TYPE rui8_t

Fragment of rkhport.c. See source/portable/arm-cortex/ksdk_os/ucosiii/kds/rkhport.c

void
{
osa_status_t status;
tick_cnt = RKH_TICKS_RATE;
status = OSA_Init();
OS_AppTimeTickHookPtr = rkh_isr_tick;
OS_AppIdleTaskHookPtr = idle_thread_function;
RKH_ENSURE(status == kStatus_OSA_Success);
}
void
{
osa_status_t status;
RKH_HOOK_START(); /* RKH start-up callback */
RKH_TR_FWK_OBJ(&rkh_isr_tick);
status = OSA_Start(); /* uC/OS-III start the multitasking */
RKH_TRC_CLOSE(); /* cleanup the trace session */
RKH_ENSURE(status == kStatus_OSA_Success); /* NEVER supposed to come */
/* back to this point */
}
void
{
RKH_HOOK_EXIT(); /* RKH cleanup callback */
}
void
void *stks, rui32_t stksize)
{
msg_queue_handler_t qh;
osa_status_t status;
task_handler_t th;
RKH_REQUIRE(qs != (const RKH_EVT_T **)0);
sma->equeue.msgs = (void *)qs;
qh = OSA_MsgQCreate(&sma->equeue, /* event message queue object */
(uint16_t)qsize, /* max. size of message queue */
/* allocate pointers */
(uint16_t)(sizeof(RKH_EVT_T *) / sizeof(uint32_t)));
RKH_ENSURE(qh != (msg_queue_handler_t)0);
th = &sma->thread;
status = OSA_TaskCreate(thread_function, /* function */
"uc_task", /* name */
(uint16_t)stksize, /* stack size */
(task_stack_t *)stks, /* stack base (low memory) */
(uint16_t)RKH_GET_PRIO(sma), /* priority */
sma, /* function argument */
false, /* usage of float register */
&th); /* task object */
RKH_ENSURE(status == kStatus_OSA_Success);
sma->running = (rbool_t)1;
}
void
{
osa_status_t status;
sma->running = (rbool_t)0;
status = OSA_MsgQDestroy(&sma->equeue);
RKH_ENSURE(status == kStatus_OSA_Success);
}

[ NEXT ]


Is a multithreaded application?: NO
It's frequently used for single thread applications that uses its own cooperative and non-preemptive scheduler, where RKH provides its own priority mechanism.

  1. Define the macros RKH_CFGPORT_NATIVE_SCHEDULER_EN = RKH_DISABLED, RKH_CFGPORT_SMA_THREAD_EN = RKH_DISABLED, RKH_CFGPORT_REENTRANT_EN = RKH_DISABLED, RKH_CFGPORT_SMA_STK_EN = RKH_DISABLED, within the rkhport.h file.
  2. Include the source/sma/inc/rkhsma_prio.h in rkhport.c.
  3. Implement the functions rkh_sma_block(), rkh_sma_setReady(), and rkh_sma_setUnready(), which are specified in source/sma/inc/rkhsma_sync.h, using the functions provided by source/sma/inc/rkhsma_prio.h

Example for Windows single-thread scheduling
Fragment of rkhport.c. See source/portable/80x86/win32_st/vc/rkhport.c

void
{
RKH_ASSERT(me->equeue.qty != 0);
}
void
{
SetEvent(sma_is_rdy);
}
void
{
}

[ NEXT ]


Are implemented the event queues with a message queue of the underlying OS/RTOS? [ YES ] - [ NO ]


Are implemented the event queues with a message queue of the underlying OS/RTOS?: YES

  1. Define the macro RKH_CFGPORT_NATIVE_EQUEUE_EN = RKH_DISABLED in rkhport.h
  2. Define the macro RKH_EQ_TYPE in rkhport.h according to OS/RTOS.
  3. Then, implement the platform-specific functions rkh_sma_post_fifo(), rkh_sma_post_lifo() and rkh_sma_get(), which are specified in source/sma/inc/rkhsma.h. All these functions are frequently placed in rkhport.c file.
  4. Define RKH_CFGPORT_SMA_THREAD_DATA_EN = RKH_DISABLED
  5. Define the macro RKH_CFGPORT_SMA_QSTO_EN in rkhport.h according to OS/RTOS.

Example for ARM Cortex-M4 Kinetis, KDS, KSDK and uC/OS-III
Fragment of rkhport.h See source/portable/arm-cortex/ksdk_os/ucosiii/kds/rkhport.h

#define RKH_EQ_TYPE msg_queue_t

Example for ARM Cortex-M4 Kinetis, KDS, KSDK and uC/OS-III
Fragment of rkhport.c See source/portable/arm-cortex/ksdk_os/ucosiii/kds/rkhport.c

void
{
osa_status_t status;
RKH_HOOK_SIGNAL(e);
RKH_ENTER_CRITICAL_();
RKH_INC_REF(e);
status = OSA_MsgQPut(&sma->equeue, /* event queue object */
(void *)&e); /* actual event posted */
RKH_ALLEGE(status == kStatus_OSA_Success);
RKH_TR_SMA_FIFO(sma, e, sender, e->pool, e->nref,
&sma->equeue.queue.MsgQ.NbrEntries, 0);
RKH_EXIT_CRITICAL_();
}
void
{
osa_status_t status;
RKH_HOOK_SIGNAL(e);
RKH_ENTER_CRITICAL_();
RKH_INC_REF(e);
status = OSA_MsgQPutLifo(&sma->equeue, /* event queue object */
(void *)&e); /* actual event posted */
RKH_ALLEGE(status == kStatus_OSA_Success);
RKH_TR_SMA_LIFO(sma, e, sender, e->pool, e->nref,
&sma->equeue.queue.MsgQ.NbrEntries, 0);
RKH_EXIT_CRITICAL_();
}
{
osa_status_t status;
status = OSA_MsgQGet(&sma->equeue, /* event queue object */
&e, /* received event message */
OSA_WAIT_FOREVER); /* wait indefinitely */
RKH_ENSURE(status == kStatus_OSA_Success);
/* To get the number of message currently in the queue and its */
/* minimum number of free elements is not a reliable manner in OSA */
/* Because the variables are obtained outside critical section could be */
/* a race condition */
/* Morever, OSA abstraction layer not implements the water mark in */
/* the queue */
RKH_TR_SMA_GET(sma, e, e->pool, e->nref,
&sma->equeue.queue.MsgQ.NbrEntries, 0);
return e;
}

[ NEXT ]


Are implemented the event queues with a message queue of the underlying OS/RTOS?: NO

  1. Define the macro RKH_CFGPORT_NATIVE_EQUEUE_EN = RKH_ENABLED in rkhport.h
  2. Define the macro RKH_CFG_QUE_EN = RKH_ENABLED in rkhcfg.h
  3. Implement the platform-specific functions rkh_sma_block(), rkh_sma_setReady(), and rkh_sma_setUnready() in rkhport.c according to underlying OS/RTOS, which are specified in source/sma/inc/rkhsma_sync.h file.
  4. Define RKH_CFGPORT_SMA_THREAD_DATA_EN = RKH_ENABLED and RKH_OSSIGNAL_TYPE according to underlying OS/RTOS
  5. Define the macro RKH_CFGPORT_SMA_QSTO_EN = RKH_ENABLED in rkhport.h

Example for Windows multithreaded application
Fragment of rkhport.h. See source/portable/80x86/win32_mt/vc/rkhport.h

#define RKH_OSSIGNAL_TYPE void*

Fragment of rkhport.c. See source/portable/80x86/win32_mt/vc/rkhport.c

void
{
while (me->equeue.qty == 0)
{
rkhport_exit_critical();
(void)WaitForSingleObject(me->os_signal, (DWORD)INFINITE);
rkhport_enter_critical();
}
}
void
{
(void)SetEvent(me->os_signal);
}
void
{
(void)me;
}

[ NEXT ]


RKH works in conjunction with a traditional OS/RTOS?: NO

  1. Define the macros RKH_CFGPORT_NATIVE_SCHEDULER_EN = RKH_ENABLED, RKH_CFGPORT_SMA_THREAD_EN = RKH_DISABLED, RKH_CFGPORT_SMA_THREAD_DATA_EN = RKH_DISABLED, RKH_CFGPORT_SMA_STK_EN = RKH_DISABLED, RKH_CFGPORT_REENTRANT_EN = RKH_DISABLED in the rkhport.h file.
  2. Define the macro RKH_EQ_TYPE = RKH_QUEUE_T in rkhport.h

[ NEXT ]


Are implemented the event queues with the native queues? [ YES ] - [ NO ]


Are implemented the event queues with the native queues?: YES

  1. Define the macro RKH_CFGPORT_NATIVE_EQUEUE_EN = RKH_ENABLED and RKH_CFG_QUE_EN = RKH_ENABLED in rkhport.h and rkhcfg.h respectively.
  2. Define the macro RKH_CFGPORT_SMA_QSTO_EN = RKH_ENABLED in rkhport.h

[ NEXT ]


Are implemented the event queues with the native queues?: NO

  1. Define the macro RKH_CFGPORT_NATIVE_EQUEUE_EN = RKH_DISABLED in rkhport.h
  2. Define the macro RKH_EQ_TYPE in rkhport.h according to external queue module.
  3. Then, implement the platform-specific functions rkh_sma_post_fifo(), rkh_sma_post_lifo() and rkh_sma_get(), which are specified in source/sma/inc/rkhsma.h. All these functions are frequently placed in rkhport.c file. See section YES of q3.
  4. Define the macro RKH_CFGPORT_SMA_QSTO_EN in rkhport.h according to external queue module..

[ NEXT ]


Dynamic event support

Is required events with arguments? [ YES ] - [ NO ]


Is required events with arguments?: 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 ] - [ NO ]


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

  1. Define the macro RKH_CFG_FWK_DYN_EVT_EN = RKH_ENABLED in rkhcfg.h
  2. Define the macro RKH_CFGPORT_NATIVE_DYN_EVT_EN = RKH_DISABLED in rkhport.h
  3. Then, implement the platform-specific functions rkh_evtPool_init(), rkh_evtPool_getPool(), rkh_evtPool_getBlockSize(), rkh_evtPool_get(), rkh_evtPool_put(), rkh_evtPool_getNumUsed(), rkh_evtPool_getNumMin() and rkh_evtPool_getNumBlock(), which are specified in source/fwk/inc/rkhfwk_evtpool.h. All these functions are frequently placed in rkhport.c file.

Example for memory partitions of uC/OS-III

/* ---------------------------- Local data types --------------------------- */
struct RKHEvtPool
{
OS_MEM memPool;
rui8_t used;
};
/* ---------------------------- Global variables --------------------------- */
/* ---------------------------- Local variables ---------------------------- */
static RKHEvtPool evtPools[RKH_CFG_FWK_MAX_EVT_POOL];
/* ----------------------- Local function prototypes ----------------------- */
/* ---------------------------- Local functions ---------------------------- */
/* ---------------------------- Global functions --------------------------- */
void
{
rInt i;
RKHEvtPool *ep;
for (i = 0, ep = evtPools; i < RKH_CFG_FWK_MAX_EVT_POOL; ++i, ++ep)
{
ep->used = 0;
}
}
RKHEvtPool *
rkh_evtPool_getPool(void *stoStart, rui16_t stoSize, RKH_ES_T evtSize)
{
rInt i;
RKHEvtPool *ep;
OS_ERR err;
for (i = 0, ep = evtPools; i < RKH_CFG_FWK_MAX_EVT_POOL; ++i, ++ep)
{
if (ep->used == 0)
{
OSMemCreate((OS_MEM *)ep,
(CPU_CHAR *)"ep",
stoStart,
(OS_MEM_QTY )(stoSize / evtSize),
(OS_MEM_SIZE)evtSize,
&err);
/* Check 'err' */
return ep;
}
}
return (RKHEvtPool *)0;
}
rui8_t
rkh_evtPool_getBlockSize(RKHEvtPool *const me)
{
RKH_REQUIRE(me != (RKHEvtPool *)0);
return (rui8_t)((OS_MEM *)me)->BlkSize;
}
rkh_evtPool_get(RKHEvtPool *const me)
{
OS_ERR err;
RKH_REQUIRE(me != (RKHEvtPool *)0);
return (RKH_EVT_T *)OSMemGet((OS_MEM *)me, &err);
}
void
rkh_evtPool_put(RKHEvtPool *const me, RKH_EVT_T *evt)
{
OS_ERR err;
RKH_REQUIRE(me != (RKHEvtPool *)0);
rkh_memPool_put((OS_MEM *)me, (void *)evt, &err);
}
rui8_t
rkh_evtPool_getNumUsed(RKHEvtPool *const me)
{
RKH_REQUIRE(me != (RKHEvtPool *)0);
return (rui8_t)(((OS_MEM *)me)->NbrMax - ((OS_MEM *)me)->NbrFree);
}
rui8_t
rkh_evtPool_getNumMin(RKHEvtPool *const me)
{
RKH_REQUIRE(me != (RKHEvtPool *)0);
return (rui8_t)0; /* This operation is not supported for Micrium */
}
rui8_t
rkh_evtPool_getNumBlock(RKHEvtPool *const me)
{
RKH_REQUIRE(me != (RKHEvtPool *)0);
return (rui8_t)((OS_MEM *)me)->NbrMax;
}

[ NEXT ]


Is required events with arguments?: NO

  1. Define the macro RKH_CFG_FWK_DYN_EVT_EN = RKH_DISABLED in rkhcfg.h
  2. Define the macro RKH_CFGPORT_NATIVE_DYN_EVT_EN = RKH_DISABLED in rkhport.h

[ NEXT ]


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?: NO

  1. Define the macro RKH_CFG_FWK_DYN_EVT_EN = RKH_ENABLED and RKH_CFG_MP_EN = RKH_ENABLED in rkhcfg.h
  2. Define the macro RKH_CFGPORT_NATIVE_DYN_EVT_EN = RKH_ENABLED in rkhport.h

[ NEXT ]


If the application code uses dynamic memory allocation, it's implemented with the native fixed-size memory block pool? [ YES ] - [ NO ]


If the application code uses dynamic memory allocation, it's implemented with the native fixed-size memory block pool?: YES

  1. Define the macro RKH_CFG_FWK_DYN_EVT_EN = RKH_ENABLED and RKH_CFG_MP_EN = RKH_ENABLED in rkhcfg.h
  2. Define the macro RKH_CFGPORT_NATIVE_DYN_EVT_EN = RKH_ENABLED in rkhport.h

[ NEXT ]


If the application code uses dynamic memory allocation, it's implemented with the native fixed-size memory block pool?: NO

  1. Define the macro RKH_CFG_FWK_DYN_EVT_EN = RKH_ENABLED in rkhcfg.h
  2. Define the macro RKH_CFGPORT_NATIVE_DYN_EVT_EN = RKH_DISABLED in rkhport.h
  3. Then, implement the platform-specific functions rkh_evtPool_init(), rkh_evtPool_getPool() and rkh_evtPool_getBlockSize(), rkh_evtPool_get(), rkh_evtPool_put(), rkh_evtPool_getNumUsed(), rkh_evtPool_getNumMin() and rkh_evtPool_getNumBlock() which are specified in source/fwk/inc/rkhfwk_evtpool.h. All these functions are frequently placed in rkhport.c file.

[ NEXT ]


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, RKH_CFG_HOOK_EXIT_EN, RKH_CFG_HOOK_TIMETICK_EN, and RKH_CFG_HOOK_PUT_TRCEVT_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
...
}

Usually, the rkh_hook_timetick() allows to the application to extend the functionality of RKH, giving the port developer the opportunity to add code that will be called by rkh_tmr_tick(). Frequently, the rkh_hook_timetick() is called from the tick ISR and must not make any blocking calls and must execute as quickly as possible. When this is set the application must provide the hook function.

Type value Boolean
Range value
Default configuration: RKH_DISABLED

Interrupt locking mechanism

RKH need to disable interrupts in order to access critical sections of code, and re-enable interrupts when done. This allows RKH to protect critical code from being entered simultaneously. To hide the implementation method chosen by the processor, compiler, etc, RKH defines two macros to unconditionally disable and enable interrupts: RKH_DIS_INTERRUPT() and RKH_ENA_INTERRUPT() respectively. Obviously, they resides in rkhport.h file, which the user always need to provide.
Example for HCS08 CW6.3

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

Example for uC/OS-III and KSDK

#define RKH_DIS_INTERRUPT() INT_SYS_DisableIRQGlobal()
#define RKH_ENA_INTERRUPT() INT_SYS_EnableIRQGlobal()

Critical section

RKH need to disable interrupts in order to access critical sections of code, and re-enable interrupts when done. This allows RKH to protect critical code from being entered simultaneously from either multiple SMAs or ISRs. Every processor generally provide instructions to disable/enable interrupts and the C compiler must have a mechanism to perform these operations directly from C. Some compilers will allows to insert in-line assembly language statements in the C source code. This makes it quite easy to insert processor instructions to enable and disable interrupts. Other compilers will actually contain language extensions to enable and disable interrupts directly from C. To hide the implementation method chosen by the compiler manufacturer, RKH defines two macros to disable and enable interrupts: RKH_ENTER_CRITICAL() and RKH_EXIT_CRITICAL().

The RKH_ENTER_CRITICAL() macro saves the interrupt disable status onto the stack and then, disable interrupts. RKH_EXIT_CRITICAL() would simply be implemented by restoring the interrupt status from the stack. Using this scheme, if it's called a RKH service with either interrupts enabled or disabled then, the status would be preserved across the call. If calls a RKH service with interrupts disabled, is potentially extending the interrupt latency of application. The application can use RKH_ENTER_CRITICAL() and RKH_EXIT_CRITICAL() to also protect critical sections of code. As a general rule, should always call RKH services with interrupts enabled!.

Note
These macros are internal to RKH and the user application should not call it.

Example for x86, VC2008, and win32 single thread:

//#define RKH_CPUSR_TYPE
#define RKH_ENTER_CRITICAL(dummy) EnterCriticalSection(&csection)
#define RKH_EXIT_CRITICAL(dummy) LeaveCriticalSection(&csection)

Example for uC/OS-III and KSDK

//#define RKH_CPUSR_TYPE
#define RKH_ENTER_CRITICAL(dummy) \
OSA_EnterCritical(kCriticalDisableInt)
#define RKH_EXIT_CRITICAL(dummy) \
OSA_ExitCritical(kCriticalDisableInt)

Trace facility

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

  1. RKH_CFGPORT_TRC_SIZEOF_PTR
    Specify the size of void pointer. The valid values [in bits] are 16 or 32. Default is 32. See RKH_TRC_SYM() macro.
    Type value Integer
    Range value [8, 16, 32]
    Default configuration: 32
  2. RKH_CFGPORT_TRC_SIZEOF_PTR
    Specify the size of function pointer. The valid values [in bits] are 16 or 32. Default is 32. See RKH_TUSR_FUN() and RKH_TRC_FUN() macros.
    Type value Integer
    Range value [8, 16, 32]
    Default configuration: 32
  3. RKH_CFGPORT_TRC_SIZEOF_TSTAMP
    Specify the number of bytes (size) used by the trace record timestamp. The valid values [in bits] are 8, 16 or 32. Default is 16.
    Type value Integer
    Range value [8, 16, 32]
    Default configuration: 16

    Example for ARM Cortex
    #define RKH_CFGPORT_TRC_SIZEOF_PTR 32u
    #define RKH_CFGPORT_TRC_SIZEOF_FUN_PTR 32u
    #define RKH_CFGPORT_TRC_SIZEOF_TSTAMP 32u

Example for S08 of NXP

#define RKH_CFGPORT_TRC_SIZEOF_PTR 16u
#define RKH_CFGPORT_TRC_SIZEOF_FUN_PTR 16u
#define RKH_CFGPORT_TRC_SIZEOF_TSTAMP 16u

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, which are specified in source/trc/inc/rkhtrc_out.h, 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;
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 ARM Cortex-M3 and LPCXpresso, with native scheduler
See source/portable/arm-cortex/rkhs/arm_cm3/codered/rkhport.h file

/* --------------------------------- Module -------------------------------- */
#ifndef __RKHPORT_H__
#define __RKHPORT_H__
/* ----------------------------- Include files ----------------------------- */
#include "rkhtype.h"
#include "rkhqueue.h"
#include "rkhmempool.h"
#include "rkhsma_prio.h"
/* ---------------------- External C language linkage ---------------------- */
#ifdef __cplusplus
extern "C" {
#endif
/* --------------------------------- Macros -------------------------------- */
#define RKH_DIS_INTERRUPT() __asm volatile ("cpsid i")
#define RKH_ENA_INTERRUPT() __asm volatile ("cpsie i")
#define RKH_ENTER_CRITICAL( dummy ) rkhport_enter_critical()
#define RKH_EXIT_CRITICAL( dummy ) rkhport_exit_critical()
/* ------------------------------- Constants ------------------------------- */
#define KERNEL_IRQ_PRIO 6
#define HIGHEST_IRQ_PRI 5
#define RKH_CFGPORT_SMA_THREAD_EN RKH_DISABLED
#define RKH_CFGPORT_SMA_THREAD_DATA_EN RKH_DISABLED
#define RKH_CFGPORT_NATIVE_SCHEDULER_EN RKH_ENABLED
#define RKH_CFGPORT_NATIVE_EQUEUE_EN RKH_ENABLED
#define RKH_CFGPORT_NATIVE_DYN_EVT_EN RKH_ENABLED
#define RKH_CFGPORT_REENTRANT_EN RKH_DISABLED
#define RKH_CFGPORT_TRC_SIZEOF_PTR 32u
#define RKH_CFGPORT_TRC_SIZEOF_FUN_PTR 32u
#define RKH_CFGPORT_TRC_SIZEOF_TSTAMP 32u
#define RKH_CFGPORT_SMA_QSTO_EN RKH_ENABLED
#define RKH_CFGPORT_SMA_STK_EN RKH_DISABLED
#define RKHROM const
#define RKH_EQ_TYPE RKH_QUEUE_T
/* ------------------------------- Data types ------------------------------ */
/* -------------------------- External variables --------------------------- */
/* -------------------------- Function prototypes -------------------------- */
const char *rkhport_get_version(void);
const char *rkhport_get_desc(void);
void rkhport_enter_critical(void);
void rkhport_exit_critical(void);
/* -------------------- External C language linkage end -------------------- */
#ifdef __cplusplus
}
#endif
/* ------------------------------ Module end ------------------------------- */
#endif
/* ------------------------------ End of file ------------------------------ */

rkht.h for ARM Cortex-M3 and LPCXpresso
See source/portable/arm-cortex/rkhs/arm_cm3/codered/rkht.h file

/* --------------------------------- Module -------------------------------- */
#ifndef __RKHT_H__
#define __RKHT_H__
/* ----------------------------- Include files ----------------------------- */
/* ---------------------- External C language linkage ---------------------- */
#ifdef __cplusplus
extern "C" {
#endif
/* --------------------------------- Macros -------------------------------- */
/* -------------------------------- Constants ------------------------------ */
/* ------------------------------- Data 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;
typedef unsigned int rbool_t;
/* -------------------------- External variables --------------------------- */
/* -------------------------- Function prototypes -------------------------- */
/* -------------------- External C language linkage end -------------------- */
#ifdef __cplusplus
}
#endif
/* ------------------------------ Module end ------------------------------- */
#endif
/* ------------------------------ File footer ------------------------------ */

rkhport.c for ARM Cortex-M3 and LPCXpresso
See source/portable/arm-cortex/rkhs/arm_cm3/codered/rkhport.c file

/* --------------------------------- Notes --------------------------------- */
/* ----------------------------- Include files ----------------------------- */
#include "rkh.h"
#include "lpc17xx.h"
#include "bsp.h"
/* ----------------------------- Local macros ------------------------------ */
/* ------------------------------- Constants ------------------------------- */
RKH_MODULE_VERSION(rkhport, 1.00)
RKH_MODULE_DESC(rkhport, "ARM Cortex-M, LPCXpresso")
/* ---------------------------- Local data types --------------------------- */
/* ---------------------------- Global variables --------------------------- */
/* ---------------------------- Local variables ---------------------------- */
static ruint critical_nesting;
/* ----------------------- Local function prototypes ----------------------- */
/* ---------------------------- Local functions ---------------------------- */
/* ---------------------------- Global functions --------------------------- */
const char *
rkhport_get_version(void)
{
}
const char *
rkhport_get_desc(void)
{
}
void
rkhport_enter_critical(void)
{
__asm volatile
(
" mov r0, %0 \n"
" msr basepri, r0 \n"
::"i" (((HIGHEST_IRQ_PRI << (8 - __NVIC_PRIO_BITS)) & 0xFF)) : "r0"
);
critical_nesting++;
}
void
rkhport_exit_critical(void)
{
critical_nesting--;
if (critical_nesting != 0)
{
return;
}
__asm volatile
(
" mov r0, #0 \n"
" msr basepri, r0 \n"
::: "r0"
);
}
/* ------------------------------ File footer ------------------------------ */

Extras

In rkhport.h
See source/portable/arm-cortex/rkhs/arm_cm3/codered/rkhport.h file

const char *rkhport_get_version(void);
const char *rkhport_get_desc(void);

In rkhport.c
See source/portable/arm-cortex/rkhs/arm_cm3/codered/rkhport.c file

RKH_MODULE_VERSION(rkhport, 1.00)
RKH_MODULE_DESC(rkhport, "ARM Cortex-M, LPCXpresso")
const char *
rkhport_get_version(void)
{
}
const char *
rkhport_get_desc(void)
{
}