Building a RAM based Tiny Kern



The Tiny Kernel configuration is designed to provide functionality for the smallest possible Windows CE–based device. The only sysgen variable needed for Tiny Kernel is SYSGEN_SHELL. Due to its small size, the Tiny Kernel configuration is designed for devices that do not require many driver functions such as display, audio, or networking. Additional features and drivers can be added after the Tiny Kernel configuration is working.

There are three major components for Tiny Kernel: CE kernel, OAL and KITL. The CE kernel is common for all CE devices. A BSP developer only needs to implement the OAL and KITL.

Adding OEM Adaptation Layer


An OEM adaptation layer (OAL) is a layer of code that resides between the Windows CE kernel and the hardware of your target device. It facilitates communication between your operating system (OS) and your target device and includes code to handle interrupts, timers, generic I/O control codes (IOCTLs), and so on.

Creating the OAL is a complex task. The easiest way to create an OAL is to copy the OAL implementation from a working OS design, and then modify it to suit the specific requirements of your hardware platform.

To aid you in developing the OAL, Microsoft provides the platform common code, which is located in \platform\common directory. This directory contains the common code for supported CPUs in a layered way.

\platform\common\src\common directory contains the generic OAL implementation independent of any CPU type.

\platform\common\src\arm, \platform\common\src\mips, \platform\common\src\shx and \platform\common\src\x86 directories contain OAL code for those four different CPU architectures. Subdirectories may contain code for certain CPU versions of those architectures.

\platform\common\src\soc directory contains OAL and driver code for certain system-on-chip and chipset implementations. The OAL code is under \platform\common\src\soc\<CPU name>\oal.

If a platform\common implementation works for your board, you can directly link to static libraries built in the above directories. Or you can use the closest CPU type as a reference design for your new BSP. These libraries help shorten the time during development and test phases.

These are steps to develop an OAL.


1. Create a hardware platform directory and a subdirectory for the OAL on your development workstation.

The following example shows the basic naming convention for a hardware platform called 'MyPlatform'.

* Hardware platform directory: %_WINCEROOT%\Platform\MyPlatform
* OAL directory: %_WINCEROOT%\Platform\MyPlatform\Src\OAL

2. Implement the StartUp function for the OAL.

In general, StartUp initializes the CPU core, including the SDRAM controller, memory management unit (MMU), and caches. The function performs this in preparation for running the CE kernel. Parts of this code can be shared with your hardware platform's boot loader. For more details, see Startup Process.

3. Create stubbed versions of required OAL functions. For more details, see Stubbed OAL. After this, you can build your oal.exe. At this point, the kernel image is not yet very useful, but if you successfully create the resulting oal.exe image this establishes the OAL framework and verifies that the build-related files are configured properly.

4. Implement the following CPU-specific functions and global variables:

For ARM-based hardware platforms only:

* OEMAddressTable
* OEMARMCacheMode
* OEMDataAbortHandler

For MIPS-based hardware platforms only:

* OEMTLBSize
* CacheErrorHandler
* CacheErrorHandler

For x86-based hardware platforms only:

* OEMAddressTable
* OEMNMIHandler

For SHx-based hardware platforms only:

* SH4CacheLines

The code for these functions may already be implemented in the SOC library for your chipset. If so, you can link to the SOC library instead of creating your own.

5. Implement the OEMCacheRangeFlush function.

The code can be linked to the SOC library if your chipset is already implemented in SOC.

6. Implement the following serial debug functions. These are the same routines used by the boot loader so you can share the code with the OAL.

* OEMInitDebugSerial
* OEMReadDebugByte
* OEMWriteDebugByte
* OEMWriteDebugString

7. Implement the OEMInit Function

During OEMInit, you must:

Initialize all hardware peripherals needed to support the hardware platform.

Initiate the debug KITL transport.

Set kernel variables that are required by the kernel to enable or alter functionality.

8. Implement the ISR

An interrupt service routine (ISR) is code that handles interrupt requests (IRQs) on your target device. The ISR is the core of the OAL and is responsible for locating an interrupt source, masking it, and returning a unique identifier to the CE kernel to indicate which driver needs to be used to handle the event.

When developing a Tiny Kernel image, the ISR only needs to focus on the timer tick interrupt. After Tiny Kernel is working, you can expand your ISR to handle other user peripherals such as keyboard, mouse, PCMCIA, and USB.

The following table shows the ISR management functions that allow the kernel to begin, service, and complete interrupt processing.

For all hardware platforms:

* OEMInterruptEnable
* OEMInterruptDisable
* OEMInterruptDone

For ARM-based hardware platforms only:

* OEMInterruptHandler
* OEMInterruptHandlerFIQ

For non-ARM hardware platforms:

* An interrupt service routine (ISR) that handles the 1-millisecond (ms) system tick interrupt

9. Implementing the System-Timer Functions

* OALTimerInit - This function initializes the system timer. It is typically called from OEMInit.
* OALTimerIntrHandler - This function implements the timer interrupt handler. OALTimerIntrHandler is called from the general interrupt handler for ARM-based hardware platforms, or it is used as an interrupt handler for MIPS-based hardware platforms. Each time the interrupt goes off, the ISR should reset the hardware and increment the variable CurMSec (usually by one millisecond).

10. Create a %_WINCEROOT%\Platform\MyPlatform\Files directory and create the following empty files in the new directory: Platform.bib, Platform.reg, Platform.db, and Platform.dat.

Copy and edit a Config.bib file from a similar hardware platform, and then specify the MEMORY and CONFIG section information for your hardware platform.

Config.bib should minimally specify the NK and RAM section address information. Romimage.exe uses this address information to know how to organize the OS to fit the hardware resources available on your development board.

Adding KITL Initialization Code

Kernel Independent Transport Layer (KITL) support enables a debug communications channel between the device and the development workstation through Platform Builder. It is essential for enabling kernel debugger support.

If the KITL connection occurs over an Ethernet connection, the Ethernet debug (EDBG) library used in the boot loader development process can be used. The EDBG library will be referenced and linked into the kitl.dll. For more information about KITL, see Kernel Independent Transport Layer.

These are steps to add KITL initialization code

  1. Initialize any PCI bridges and devices, and then enumerate, assign resources, and enable these.

2. Perform any other bus initialization required for the CPU in order to recognize the NIC.

3. KITL is initialized by calling KitlIoctl with the IOCTLKITLSTARTUP parameter, typically during the OEMInit phase of the boot process. KitlIoctl must be called before any debug services can be started. This function will call KitlInit in the kernel, which will call the OEMKitlInit function to perform hardware initialization.

4. Most of common kitl functions such as OEMKitlInit are already implemented in platform\common\src\common\kitl directory. There is a good chance that your platform can directly link to the common kitl library generated in the common kitl directory.

5. Some platform specific functions are still needed for your BSP. These functions should be implemented in platform\<hardware Platform Name>\src\kitl\kitl.c.

OEMKitlStartup – This function handles the start up sequence including reading bootloader arguments, setting kitl variables and creating a device name if bootloader didn’t do so.

OALGetTickCount – This function will read system timer or RTC to return a relative time in millisecond since the system start. The return value is normally used for KITL Ethernet timeout count.

OEMEthGetSecs – This function is similar to OALGetTickCount. The difference is it returns the relative time in seconds since system start.

6. After implementing the the BSP-specific KITL functions, include the common kitl library such as oalkitl.lib or oalkitl_pci.lib in your Platform\<Hardware Platform Name>\kitl sources file. The BSP-specific and common KITL code will be build in to kitl.dll.

After performing the above tasks, you can enable KITL in polling mode using the OALKITLFLAGS_POLL flag in your KITL initialization code. To use KITL in interrupt mode, you need to make sure KITL related interrupts are handled correctly and remove the polling flag.

At this point, the all basic component of the TinyKern image are prepared. Ensure that all appropriate hardware platform directories have dirs files and sources files. Then build an TinyKern image by entering "blddemo clean -q" in the command line. If the nk.bin is build successfully, you can try Downloading TinyKern and Validating TinyKern.




Go up to BSP Bringup
Go up to Big Book of BSP

Thank you for contributing to this BSP Wiki. To ensure your comments and concerns receive proper exposure, include bspwiki""@""microsoft"".""com when providing feedback or topical suggestions.




Microsoft Communities