Frequently asked Questions
- What do you
see XMK being used for?
-
How come XMK isn't in assembly? I don't see how you can argue
the "X" in XMK if you're not in assembly?
- What is "APL"?
-
What is the reason for having the XMK Scheduler package and the
APL package?
-
What is the difference between the "full" and "compact"
releases?
-
Why can't I get BENV to work with CYGWIN or MinGW/MSYS?
- What are "volatile registers"?
- How are
"thread context" and "interrupt context" defined?
- What is a
"thread switch" and when can it occur?
- What
are and how are the "_XMK_xxxx_STACK" macros defined?
The primary/initial target for XMK is to provide a RTOS for low-end 8Bit
microcontrollers. XMK can realistically run on a micro that has at least
512Bytes of RAM and 8K of ROM. From our research, there are no other preemptive
multitasking RTOSes than can fit in to this small of a platform and still be
useful. Caveat: our research has been limited to "free" RTOSes, and marketing
literature (read as: not very technical) for commercial RTOSes.
The secondary target for XMK is to scale up to higher-end platforms (read as:
>64K address space). The limiting factors for scaling-up XMK are:
1) It is statically linked with the user's application.
2) It does not support protected memory/MMUs, and does not support multiple
CPUs.
The short answer is, XMK is useful for embedded development projects that
require an non process architecture, priority based preemptive
multithreading on single CPU.
The majority of the XMK source code is written in C to be portable across
microcontrollers. XMK does resort to assembler for access to the
underlying hardware registers, and for speed and efficiency for implementing
context switches.
The major justifications for XMK's "eXtreme" moniker are:
1) Compared to other non-chip specific kernels, both commercial and open source,
XMK is one of the smallest if not the smallest.
2) For Microcontrollers that are C friendly, XMK's C source is almost as
efficient as assembler.
3) XMK's design is responsible for its minimal footprint, not the
implementation language. If another kernel design has defined a
Thread-Control-Block (TCB) to be 16 bytes, its going to have a larger footprint
than XMK which only has a 3 byte TCB, regardless of the implementation language.
Granted, the same kernel design written in pure assembler
is always going to be smaller than a C or C/ASM hybrid implementation.
APL is the Application Programming Layer. The XMK
Operating System is divided into two major sections and/or packages. The
first package is the XMK Scheduler. The XMK Scheduler is the thread
scheduler and provides basic kernel services and synchronization primitives.
Historically, the XMK Scheduler package is the original XMK system
before it expanded into a full featured RTOS. The second package is APL. APL provides framework interfaces such as
memory management, inter-thread communications, list and container management,
devices interfaces, networking, etc.
The primary reason for the two package/layer approach is the
designers of XMK decided that instead of creating XMK specific
services such as mailboxes, heaps, memory pools, lists, etc., that
these services should be part of a kernel independent library.
The APL and XMK Scheduler packages can be used separately since
neither package has any direct dependencies on each other.
The full releases contains not only the source tree, but a
large number of example projects as well as non-XMK board/chip
specific example projects. The full release contains:
The XMK source tree and documentation.
All of the XMK example projects (using BENV as the build
environment).
A Collection of board/chip specific non-XMK example projects
(using BENV as the build environment).
BENV - a
multiple host, multi-target build environment.
If you are new to XMK, it is recommended that you start with the
one of the compact releases, since it contains significantly fewer
files and is easier to navigate.
The compact releases contain only the source tree and a
very small set of example programs for a very small set of the
supported platforms. The idea to demonstrate XMK without
overwhelming the potential users. The Compact release was created
out of the confusion caused (and rightly so) by the sheer number of
files in the full releases. The compact releases uses only
traditional GNU Makefiles or vendor specific IDE project files.
The current version of BENV does not support from working within the CYGWIN
or MSYS environments. The problem is how these environments handle the
file system root/C drive issue. BENV support for CYGWIN and MSYS is
planned, but has not yet been completed.
However, if the compiler you are trying to use, will execute correctly from a
DOS prompt - you can use BENV - just define the Host Platform of your Toolset to
be "Windows"
Note: Even though BENV uses CYGWIN's BASH shell implementation for its Unix
emulation under Windows, the build engine still needs to be updated to support
CYGWIN/MSYS as a "Host Platform"
The volatile registers are the set of hardware registers that a
called function is not require to preserve when
called, i.e. the calling function always assumes that the
contents of the volatile registers will-be/can-be change when making
a function call. Which registers are volatile are compiler and
target specific. The compiler's Application Binary Interface (ABI)
defines the set of volatile registers.
Thread Context - The CPU is running normally, that is not running a
interrupt service routine. Each thread has its own call stack and its own copy
of the hardware registers. The current running thread and/or thread context has
access to the actual hardware registers and control of the CPU. All other
threads have the state of their hardware registers saved as part of their call
stack.
Interrupt Context - The CPU has is running one of its
interrupt/exception handling vectors, a.k.a running a interrupt service routine.
Thread Switch - The process of changing which thread is the current thread.
This involves saving the hardware register of the old thread and then
restore the hardware registers of the new thread.
A thread switch can only happen under three conditions:
1) The currently running thread voluntary gives up control, i.e. waits on a
semaphore to be signal, puts itself to sleep, etc.
2) The currently running thread readies another thread that has higher priority
than itself, i.e. signals a semaphore, releases a mutex that higher priority
thread is waiting on, etc.
3) An interrupt occurs and during the execution of the interrupt service routine
a thread is ready that has higher has higher priority than the current running
thread, i.e. signals a semaphore, sleep timer expires, etc.
These macros are used to calculate the amount of stack overhead that is
required by 1) the context registers; and 2) the XMK's calling sequence when
doing context switches from an ISR and/or from a thread. This overhead becomes
the absolute minimum size for a thread's stack. These macros are also compiler
specific because they depended on the compiler's ABI.
_XMK_1LEVEL_ISR_STACK - This is the size, in bytes, of the stack frame that
is generated when an interrupt occurs, i.e. what is pushed onto the stack by the
hardware and the prolog of the interrupt service routine. It includes: the
return address, the program status word, and the volatile hardware registers
_XMK_ISRHOOK_STACK - This is the amount of overhead, in bytes, required by
XMK's ISR stubs. Typically it is only the size of a 'return address' since the
XMK stub calls the applications ISR.
_XMK_ISR_SWITCH_GETNEXT - This is the amount of stack, in bytes, required by
XMK's function: Xmk_getNext(). Xmk_getNext() returns the thread handle of the
new thread when a context is performed. Typically this is only the size of a
'return address' since the function has no functions args, no local variables,
and has minimal code (i.e. all the work can be done using the volatile hardware
registers - this is all up to the compiler though).
_XMK_ISR_KERNEL_WAKEUP - This the amount of stack, in bytes, required by
XMK's function: Xmk_requestContextSwitch(). This method is called internally
when an ISR 'wakes-up' a thread. Typically this is only the size of a 'return
address' since the function has no functions args, no local variables, and has
minimal code (i.e. all the work can be done using the volatile hardware
registers - this is all up to the compiler though).
_XMK_GP_STACK - This is the size, in bytes, of the non-volatile
hardware registers.
|