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.
- Platform-dependent files
- Data types definitions
- ROM allocator
- Active Object execution
- Dynamic event support
- Hook functions
- Interrupt locking mechanism
- Critical section
- Trace facility
- A port file example
- 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:
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;
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:
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.
- 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.
- Define the macros RKH_THREAD_TYPE, RKH_CFGPORT_SMA_STK_EN and RKH_THREAD_STK_TYPE in
rkhport.h
according to underlying OS/RTOS.
- Define the macro RKH_CFGPORT_SMA_STK_EN in
rkhport.h
according to OS/RTOS.
- 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;
}
void
{
osa_status_t status;
RKH_HOOK_START();
status = OSA_Start();
}
void
{
RKH_HOOK_EXIT();
}
void
void *stks, rui32_t stksize)
{
msg_queue_handler_t qh;
osa_status_t status;
task_handler_t th;
sma->
equeue.msgs = (
void *)qs;
qh = OSA_MsgQCreate(&sma->
equeue,
(uint16_t)qsize,
(uint16_t)(
sizeof(
RKH_EVT_T *) /
sizeof(uint32_t)));
status = OSA_TaskCreate(thread_function,
"uc_task",
(uint16_t)stksize,
(task_stack_t *)stks,
sma,
false,
&th);
}
void
{
osa_status_t status;
status = OSA_MsgQDestroy(&sma->
equeue);
}
#define RKH_ENSURE(exp)
This macro checks the postcondition.
#define RKH_REQUIRE(exp)
This macro checks the precondition.
#define RKH_TRC_CLOSE()
Close the tracing session.
void rkh_sma_terminate(RKH_SMA_T *me)
Terminate a state machine application (SMA) as known as active object.
void rkh_sma_activate(RKH_SMA_T *me, const RKH_EVT_T **qSto, RKH_QUENE_T qSize, void *stkSto, rui32_t stkSize)
Initializes and activates a previously created state machine application (SMA) as known as active obj...
void rkh_fwk_exit(void)
Exit the RKH framework.
void rkh_fwk_init(void)
Initializes the RKH framework.
void rkh_fwk_enter(void)
RKH framework is started.
void rkh_sm_init(RKH_SM_T *me)
Inits a previously created state machine calling its initializing action.
#define RKH_TR_FWK_EN()
Initializes the RKH framework.
#define RKH_TR_FWK_OBJ(obj_)
Entry symbol table for memory object.
#define RKH_TR_FWK_EX()
Exit the RKH framework.
#define RKH_SR_ALLOC()
RKH need to disable interrupts in order to access critical sections of code, and re-enable interrupts...
rui8_t RKH_QUENE_T
This data type defines the maximum number of elements that any queue can contain.
void rkh_sma_register(RKH_SMA_T *me)
Registers a state machine application (SMA) as known as active object into the framework,...
#define RKH_GET_PRIO(_ao)
Retrieves the priority number of an registered active object (SMA).
Represents events without parameters.
Describes the state machine.
Describes the SMA (active object in UML).
rbool_t running
The Boolean loop variable determining if the thread routine of the SMA is running.
RKH_THREAD_TYPE thread
Virtual pointer.
RKH_EQ_TYPE equeue
Event queue of the SMA (a.k.a Active Object).
[ 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.
- 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.
- Include the
source/sma/inc/rkhsma_prio.h
in rkhport.c
.
- 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
{
}
void
{
SetEvent(sma_is_rdy);
}
void
{
}
#define RKH_ASSERT(exp)
The RKH_ASSERT() macro is used to check expressions that ought to be true as long as the program is r...
#define RKH_SMA_ACCESS_CONST(me_, member_)
Macro for accessing to members of state machine structure.
void rkh_smaPrio_setUnready(rui8_t prio)
Removing an active object from the ready list.
void rkh_smaPrio_setReady(rui8_t prio)
Making an active object ready-to-run inserting it into the ready list.
void rkh_sma_setUnready(RKH_SMA_T *const me)
Informs the underlying kernel that the active object's event queue is becoming empty....
void rkh_sma_block(RKH_SMA_T *const me)
Encapsulates the mechanism of blocking the native event queue.
void rkh_sma_setReady(RKH_SMA_T *const me)
Encapsulates the mechanism of signaling the thread waiting on the used native event queue....
[ 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
- Define the macro RKH_CFGPORT_NATIVE_EQUEUE_EN = RKH_DISABLED in
rkhport.h
- Define the macro RKH_EQ_TYPE in
rkhport.h
according to OS/RTOS.
- 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.
- Define RKH_CFGPORT_SMA_THREAD_DATA_EN = RKH_DISABLED
- 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,
(void *)&e);
&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,
(void *)&e);
&sma->
equeue.queue.MsgQ.NbrEntries, 0);
RKH_EXIT_CRITICAL_();
}
{
osa_status_t status;
status = OSA_MsgQGet(&sma->
equeue,
&e,
OSA_WAIT_FOREVER);
&sma->
equeue.queue.MsgQ.NbrEntries, 0);
return e;
}
#define RKH_ALLEGE(exp)
General purpose assertion that ALWAYS evaluates the exp argument and calls the RKH_ASSERT() macro if ...
void rkh_sma_post_lifo(RKH_SMA_T *me, const RKH_EVT_T *e, const void *const sender)
Send an event to a state machine application (SMA) as known as active object through a queue using th...
void rkh_sma_post_fifo(RKH_SMA_T *me, const RKH_EVT_T *e, const void *const sender)
Send an event to a state machine application (SMA) as known as active object through a queue using th...
RKH_EVT_T * rkh_sma_get(RKH_SMA_T *me)
Get an event from the event queue of an state machine application (SMA) as known as active object....
#define RKH_TR_SMA_FIFO(actObj_, evt_, sender_, poolID_, refCntr_, nElem_, nMin_)
Send an event to a state machine application (SMA) as known as active object through a queue using th...
#define RKH_TR_SMA_GET(actObj_, evt_, poolID_, refCntr_, nElem_, nMin_)
Get an event from the active object's queue.
#define RKH_TR_SMA_LIFO(actObj_, evt_, sender_, poolID_, refCntr_, nElem_, nMin_)
Send an event to a state machine application (SMA) as known as active object through a queue using th...
rui8_t nref
Attribute of dynamic events.
rui8_t pool
Attribute of dynamic events (0 for static event).
[ NEXT ]
Are implemented the event queues with a message queue of the underlying OS/RTOS?: NO
- Define the macro RKH_CFGPORT_NATIVE_EQUEUE_EN = RKH_ENABLED in
rkhport.h
- Define the macro RKH_CFG_QUE_EN = RKH_ENABLED in
rkhcfg.h
- 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.
- Define RKH_CFGPORT_SMA_THREAD_DATA_EN = RKH_ENABLED and RKH_OSSIGNAL_TYPE according to underlying OS/RTOS
- 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
{
{
rkhport_exit_critical();
(void)WaitForSingleObject(me->
os_signal, (DWORD)INFINITE);
rkhport_enter_critical();
}
}
void
{
}
void
{
(void)me;
}
RKH_OSSIGNAL_TYPE os_signal
OS-dependent object used to signal that an event has been queued.
[ NEXT ]
RKH works in conjunction with a traditional OS/RTOS?: NO
- 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.
- 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
- Define the macro RKH_CFGPORT_NATIVE_EQUEUE_EN = RKH_ENABLED and RKH_CFG_QUE_EN = RKH_ENABLED in
rkhport.h
and rkhcfg.h
respectively.
- Define the macro RKH_CFGPORT_SMA_QSTO_EN = RKH_ENABLED in
rkhport.h
[ NEXT ]
Are implemented the event queues with the native queues?: NO
- Define the macro RKH_CFGPORT_NATIVE_EQUEUE_EN = RKH_DISABLED in
rkhport.h
- Define the macro RKH_EQ_TYPE in
rkhport.h
according to external queue module.
- 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.
- 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
- Define the macro RKH_CFG_FWK_DYN_EVT_EN = RKH_ENABLED in
rkhcfg.h
- Define the macro RKH_CFGPORT_NATIVE_DYN_EVT_EN = RKH_DISABLED in
rkhport.h
- 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
struct RKHEvtPool
{
OS_MEM memPool;
rui8_t used;
};
void
{
rInt i;
RKHEvtPool *ep;
{
ep->used = 0;
}
}
RKHEvtPool *
{
rInt i;
RKHEvtPool *ep;
OS_ERR err;
{
if (ep->used == 0)
{
OSMemCreate((OS_MEM *)ep,
(CPU_CHAR *)"ep",
stoStart,
(OS_MEM_QTY )(stoSize / evtSize),
(OS_MEM_SIZE)evtSize,
&err);
return ep;
}
}
return (RKHEvtPool *)0;
}
rui8_t
{
return (rui8_t)((OS_MEM *)me)->BlkSize;
}
{
OS_ERR err;
return (
RKH_EVT_T *)OSMemGet((OS_MEM *)me, &err);
}
void
{
OS_ERR err;
}
rui8_t
{
return (rui8_t)(((OS_MEM *)me)->NbrMax - ((OS_MEM *)me)->NbrFree);
}
rui8_t
{
return (rui8_t)0;
}
rui8_t
{
return (rui8_t)((OS_MEM *)me)->NbrMax;
}
void rkh_memPool_put(RKH_MEMPOOL_T *mp, void *blk)
When the application is done with the memory block, it must be returned to the appropiate memory pool...
#define RKH_CFG_FWK_MAX_EVT_POOL
If the dynamic event support is enabled (see RKH_CFG_FWK_DYN_EVT_EN) then the RKH_CFG_FWK_MAX_EVT_POO...
void rkh_evtPool_init()
Encapsulates the initialization of event pool manager.
rui8_t rkh_evtPool_getBlockSize(RKHEvtPool *const me)
Encapsulates how RKH should obtain the block size of an event pool.
rui8_t rkh_evtPool_getNumMin(RKHEvtPool *const me)
Encapsulates how RKH should return the lowest number of free blocks ever present in the pool me....
RKH_EVT_T * rkh_evtPool_get(RKHEvtPool *const me)
Encapsulates how RKH should obtain an event evt from the event pool me.
rui8_t rkh_evtPool_getNumBlock(RKHEvtPool *const me)
Encapsulates how RKH should return the total number of blocks in the pool me.
rui8_t rkh_evtPool_getNumUsed(RKHEvtPool *const me)
Encapsulates how RKH should return the current number of memory blocks used in the pool me.
RKHEvtPool * rkh_evtPool_getPool(void *stoStart, rui16_t stoSize, RKH_ES_T evtSize)
Encapsulates the creation of an event pool.
void rkh_evtPool_put(RKHEvtPool *const me, RKH_EVT_T *evt)
Encapsulates how RKH should return an event evt to the event pool me.
[ NEXT ]
Is required events with arguments?: NO
- Define the macro RKH_CFG_FWK_DYN_EVT_EN = RKH_DISABLED in
rkhcfg.h
- 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
- Define the macro RKH_CFG_FWK_DYN_EVT_EN = RKH_ENABLED and RKH_CFG_MP_EN = RKH_ENABLED in
rkhcfg.h
- 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
- Define the macro RKH_CFG_FWK_DYN_EVT_EN = RKH_ENABLED and RKH_CFG_MP_EN = RKH_ENABLED in
rkhcfg.h
- 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
- Define the macro RKH_CFG_FWK_DYN_EVT_EN = RKH_ENABLED in
rkhcfg.h
- Define the macro RKH_CFGPORT_NATIVE_DYN_EVT_EN = RKH_DISABLED in
rkhport.h
- 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
.
void rkh_hook_dispatch(RKH_SMA_T *me, RKH_EVT_T *e)
When dispatching an event to a SMA the dispatch hook function will be executed.
- Type value Boolean
- Range value
- Default configuration: RKH_DISABLED
void rkh_hook_signal(RKH_EVT_T *e)
When the producer of an event directly posts the event to the event queue of the consumer SMA the rkh...
- Type value Boolean
- Range value
- Default configuration: RKH_DISABLED
void rkh_hook_timeout(const void *t)
If a timer expires the rkh_hook_timeout() function is called just before the assigned event is direct...
- Type value Boolean
- Range value
- Default configuration: RKH_DISABLED
void rkh_hook_start(void)
This hook function is called just before the RKH takes over control of the application.
- Type value Boolean
- Range value
- Default configuration: RKH_DISABLED
void rkh_hook_exit(void)
This hook function is called just before the RKH returns to the underlying OS/RTOS....
- Type value Boolean
- Range value
- Default configuration: RKH_DISABLED
void rkh_hook_idle(void)
An idle hook function will only get executed (with interrupts LOCKED) when there are no SMAs of highe...
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
{
...
}
#define RKH_ENA_INTERRUPT()
RKH need to disable interrupts in order to access critical sections of code, and re-enable interrupts...
void rkh_hook_timetick(void)
This function is called by rkh_tmr_tick(), which is assumed to be called from an ISR....
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_ENTER_CRITICAL(dummy) EnterCriticalSection(&csection)
#define RKH_EXIT_CRITICAL(dummy) LeaveCriticalSection(&csection)
Example for uC/OS-III and KSDK
#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:
- 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
- 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
- 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)
Open the tracing session.
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
{
FTBIN_OPEN();
TCP_TRACE_OPEN();
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__ );
}
#define RKH_TRC_SEND_CFG(ts_hz)
Send the trace facility configuration to host application software Trazer.
void rkh_trc_init(void)
Initializes the RKH's trace record service.
void rkh_trc_close(void)
Close the tracing session.
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 rkh_trc_flush(void)
Platform-dependent macro flushing the trace stream.
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_();
RKH_EXIT_CRITICAL_();
if((blk != (rui8_t *)0))
{
FTBIN_FLUSH( blk, nbytes );
TCP_TRACE_SEND_BLOCK( blk, nbytes );
}
else
break;
}
}
rui8_t * rkh_trc_get_block(TRCQTY_T *nget)
Retrieves a pointer to a contiguous block of data from the trace stream.
RKH_TS_T rkh_trc_getts(void)
Retrieves a timestamp to be placed in a trace event.
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
{
}
rui32_t RKH_TS_T
Defines the size of trace timestamp.
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
#ifndef __RKHPORT_H__
#define __RKHPORT_H__
#ifdef __cplusplus
extern "C" {
#endif
#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()
#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
const char *rkhport_get_version(void);
const char *rkhport_get_desc(void);
void rkhport_enter_critical(void);
void rkhport_exit_critical(void);
#ifdef __cplusplus
}
#endif
#endif
Specifies the interface of the fixed-size memory blocks facility.
Specifies the interface of the queue services.
Specifies the native priority mechanism for active object scheduling.
Defines the data types that uses RKH.
rkht.h for ARM Cortex-M3 and LPCXpresso
See source/portable/arm-cortex/rkhs/arm_cm3/codered/rkht.h
file
#ifndef __RKHT_H__
#define __RKHT_H__
#ifdef __cplusplus
extern "C" {
#endif
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;
#ifdef __cplusplus
}
#endif
#endif
rkhport.c for ARM Cortex-M3 and LPCXpresso
See source/portable/arm-cortex/rkhs/arm_cm3/codered/rkhport.c
file
#include "lpc17xx.h"
#include "bsp.h"
static ruint critical_nesting;
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"
);
}
#define RKH_MODULE_NAME(__fname)
This macro appears at the top of each C/C++ source file defining a name for that file.
RKH framwwork platform - independent interface.
#define RKH_MODULE_GET_DESC()
Get the module description.
#define RKH_MODULE_GET_VERSION()
Get the module version.
#define RKH_MODULE_DESC(__fname, __desc)
This macro appears at the top of each C/C++ source file defining the description string for that file...
#define RKH_MODULE_VERSION(__fname, __version)
This macro appears at the top of each C/C++ source file defining the version string for that file (mo...
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
const char *
rkhport_get_version(void)
{
}
const char *
rkhport_get_desc(void)
{
}