Customizing the CEPC BSP in Windows Embedded Compact 7

Posted By David Campbell
Program Manager

As the Windows Embedded Compact v.Next launch approaches, we will soon be posting detailed information about the Compact OS and tools, both Platform Builder (used for Board Support Packages (BSPs) as well as drivers) and the use of Visual Studio itself for developing applications on top of Compact OS images. I’m looking forward to making more of the technical details of the release available, probably in small bits until we can go fully public, which will happen very soon.

In the meantime let’s take a detailed look at the CEPC BSP. Here’s a guest post by Doug Boling again with a great overview based on his recent webcast. (More details on Doug’s webcast series are provided at the end of the article.)

The CEPC board support package (BSP) in Windows Embedded Compact 7 is one of the frequently used BSPs in Platform Builder. Unfortunately it is also one of the more difficult to customize. It may seem strange to customize a BSP that runs on a generic PC chassis but when used on a production embedded system, some form of customization such as splash screens or subtle changes in hardware is almost always necessary.

The difficulty in customizing the CEPC BSP comes from its file structure. Before I can explain the problem, I need to discuss the architecture of a standard Windows Embedded Compact BSP

BSP 101

The structure of a Windows Embedded Compact BSP, with one exception, hasn’t changed much since Windows CE 1.0 was released in 1996. The directory layout is generally consistent across BSPs of all CPU architectures. This allows developers to use their knowledge of one BSP when working on another. It also allows developers to fairly easily port a BSP from one version of Windows CE/Compact to the next.

The BSP directory structure looks like the following

Wince700\Platform\

                {BSPName}\                                                                       Root of BSP Tree

                                Catalog\                                                               Used by PB for catalog management

                                Files\                                                                     Contains non-compliable (*.reg, *.bib)  files

                                Src\                                                                        Contains all source code for BSP

                                                Bootloader\                                       Boot loader files (sometimes renamed)

                                                Drivers\                                                                Contains the driver source for each platform

specific driver

                                                                Driver1 PDD                        Generic Driver 1

                                                                Driver2 PDD                        Generic Driver 2

                                                                (continued…)                     As many drivers as in the platform

                                                inc\                                                        Contains BSP specific include files

                                                KITL\                                                      Contains KITL support code

                                                OAL\                                                      Contains OAL (OEM Abstraction Layer) code

                                                                OALEXE                                                Contains SOURCES file to build OAL

                                                                OALLIB                                  Contains source code for OAL

A screen capture of a typical BSP (the NE1TB) in Platform Builder 7 is shown below. Notice that there are a few more directories in this BSP. The CeSysgen folder is generated during a build. The Misc directory contains tools specific for this BSP.

image

Notice that in the NE1TB\Src\oal\oallib folder, shown on the right above, that there are a number of source files. Each of these source file names are intentionally chosen to be consistent across most BSPs. The init.c file contains the OEMInit routine as well as other routines specific to initialization. The intr.c file contains the interrupt handler routines for the OAL. By keeping the source code filenames consistent, also helps when moving from one BSP to another or from one version of Windows Embedded Compact to another.

The BSP Common Directory

Unfortunately, not all the source code is in the NE1TB directory structure shown above. As part of the “Production Quality Driver Initiative” in Windows CE 5. Code considered “common” across multiple BSPs was moved from the individual BSP trees to the WinceXXX\Platform\Common directory. This directory structure is frankly too complex to show in this document as it has to contain a variety of like-named routines each customized to a subset of the BSPs, across all supported CPU architectures provided in Platform Builder.

While combining common code into a single place is theoretically good “Software Engineering” practice, it is problematic when working on embedded systems where code frequently needs to be customized. The common code can’t be customized in place as any changes would be reflected in all BSPs that used the modified code. Therefore the code to be changed must first be found and then moved into the BSP directory tree before being modified. You may be asking, what does this have to do with the CEPC BSP?

[David: While there is some copying required, arguably confusing, the code that is being copied is reference code intended to accelerate development. Rather than starting from scratch, there is reference code that can be copied and modified for your platform – or, if no modification is needed, can be used as is. So while there is come knowledge involved to understand this process – and thanks to Doug here for explaining, overall the development of quality BSPs should be easier as a result. Or at least that was the intent. ]

The CEPC Board Support Package

The CEPC BSP takes “common code” to an extreme. Notice in the screen capture below that the oallib directory in CEPC is almost empty. Of the two source files, only one contains any executing code and that one contains only one routine. The drivers directory is empty and there is again only a single file in the KITL directory with any code.

image

This design makes modifying the CEPC BSP an exercise in finding code in the common tree, moving it to the CEPC tree and changing the build scheme. This is all before you get around to actually writing the code that changes the behavior of the system.

Modifying the CEPC BSP

While almost all x86 systems have a very similar hardware configuration there can easily be one or two things the OEM must change in the OAL when bringing up Windows Embedded Compact. Before diving in and modifying the code in the CEPC BSP there are a few things to do.

While the CEPC BSP is a great generic platform for your x86 system, the odds are that your silicon vender; Intel, AMD, ICop or whoever, has a customized version of CEPC that would be a better starting point for your BSP. The vendors have already made specific modifications to take advantage of the specific hardware on their silicon. This typically includes changes to the cache management routines, timer, and the video driver. Frequently, the BSP will also include drivers for network adapters that may be present on some demo systems from the vendor. It’s always a good idea to check out those BSPs for additional drivers as well.

Also, never change the BSP directly. Leave the original CEPC, or vendor supplied BSP, intact and clone the BSP using the Platform Builder BSP Cloning tool. This tool can be accessed through the Tools | Platform Builder | Clone BSP menu item in Visual Studio. Cloning duplicates the entire directory structure of the BSP and allows you to name the new BSP something more appropriate for your specific hardware.

There are a few areas that are typically modified in a BSP to adapt it to customized hardware. In this post, I’m going to focus on modifications to the OAL layer. There are also the drivers to consider. I’ll leave that to another discussion. For now, let’s look at modifications to the OAL.

Modifying the OAL Code

The OAL, or OEM Abstraction Layer, is the code underneath the kernel that abstracts the basic hardware components such as the interrupt controller, timers, and real time clock. This code also includes the initialization code that runs before the kernel starts.

Doing this on a ‘typical’ BSP would simply involve changing a routine in the src\oal\oallib folder. However in the sparsely populated CEPC BSP, the code must first be found in the common directory, moved into the CEPC BSP directory tree, and the build files modified to include the newly moved code. Only then can the code be changed.

Finding code in the Platform\Common directory can be a bit of a challenge. The place to start the search is the SOURCES file in CEPC\src\oal\oalexe. This file contains the link information that is used to bring all the disparate lib files from other parts of the build tree in to make the OAL code. Below is a copy of the TARGETLIBS line in that SOURCES file.

image

There are two interesting aspects to TARGETLIBS. First are the directory tokens that begin each line in the listing. They indicate the general location of that library, and therefore the source code that created that library. The _COMMONOAKROOT token indicates that the code is in either the Public\Common\oak folder or is in the Private\winceos\coreos folder. Those libraries aren’t going to be typically modified but it’s nice to know where they are.

The _PLATLIB token indicates that the library was built in and located in the BSP directory tree. Unfortunately, in the CEPC BSP, only one library is in the BSP tree and that is the oallib library that contains very little code. The _PLATCOMMONLIB token indicates a library that is located in the Platform\Common tree. These are the libraries that we may need to move into the BSP directory tree for modification.

The other aspect of TARGETLIBS is the names of the libraries themselves. Fortunately, they provide a hint as to the code in those libraries. Some such as oal_intr_x86 (interrupt code) and oal_memory_x86 (memory code) are fairly obvious. Other names such as oal_other_x86 don’t provide much help. Regardless, that is what we have to work with at this point.

In the Wince700\Platform\Common tree, our code can mostly be found in the Wince700\Platform\Common\Src\x86\Common directory. A screenshot of that directory tree is shown below.

image

Notice that the names of these folders are quite similar to the library names in the SOURCES file. This provides us a one-to-one tie between the SOURCES file and the code in the common directory.

The other relevant directory is Wince700\Platform\Common\Src\soc\x86_ms_v1. In that directory, you will find the DMA routines but more importantly an include directory that contains some important .h files. Be sure to keep that directory in mind when hunting for critical structure definitions.

At this point, it’s just a matter of finding the specific routine we want to change and bringing it into the CEPC BSP. For example, let’s assume that the Real Time Clock (RTC) routines need to be changed in a fictional CEPC-based BSP. The relevant routines will be found in Wince700\Platform\Common\Src\x86\Common\rtc. The first step is to copy that folder from its current location to our BSP tree under src\oal. The new directory structure would look like the following.

image

Be careful not to move the directory instead of copying it. In Explorer, you’ll need to right click and drag instead of simply dragging the folder since a drag within a drive is an implied move.

Once the directory has been copied, the DIRS file within the CEPC\src\oal directory needs to be updated. The DIRS file originally looks like:

DIRS= oallib \

oalexe \

It needs to be modified to add a reference to the RTC directory. This reference must be before the reference to oalexe since building that directory depends on the RTC lib. The DIRS file should now look like:

DIRS= oallib \

rtc \

oalexe \

Of course, the \ is a line continuation character and must be the last character on the line.

The change to the DIRS file allows the RTC directory to be built, but another change is needed to have the OAL code link to the new version of the library. This change is in the previously discussed SOURCES file in CEPC\src\oal\oalexe. In that file, the line

$(_PLATCOMMONLIB)\$(_CPUINDPATH)\oal_rtc_x86.lib \

Needs to be changed to

$(_PLATLIB)\$(_CPUDEPPATH)\oal_rtc_x86.lib \

You also might want to change the name of the revised rtc library. To do this, you’ll need to modify the TARGETNAME line in the SOURCES file in CEPC\src\oal\rtc as well as update the name of the lib in the SOURCES file in CEPC\src\oal\oalexe. Changing the name ensures that any future developer will notice that you’ve created a new library with different code. It will also cause a build error if you forget to change the directory reference.

At this point, you can rebuild the OAL code. To fully build and link the changes into the OAL, either build the complete BSP using the Platform Builder menu item Build | Advanced Build Commands | Build Current BSP and Subprojects; or from the command line, build from the OAL directory, not from the RTC directory. Building from the RTC directory will only build the RTC library, not relink the OAL. To do that, you must build from the oal directory so that the oalexe directory can be built, which links all the libraries together to create the OAL.

Modifying IOCTL functionality

The RTC routines are directly called by the kernel. They are among the 12 mandatory and 20 or so optional routines that are directly called by the Windows Embedded Compact kernel. There are however another 20 or more routines that are called through the IOCTL interface. That is, the kernel calls the OAL’s OEMIoControl routine and it forwards the call to one of many routines depending on the IOCTL command.

Frequently, tuning the system is accomplished by changing one of the routines called by the IOCTL command or by adding a new IOCTL command handler to the OAL. To do this, either the OEMIoControl needs to be modified or (an easier strategy) the lookup table that is used by the OEMIoControl routine needs to be changed.

The lookup table that is used by the CEPC BSP is defined in the file globals.c in CEPC\src\oal\oallib. The code for that file that includes the table is shown below

const OAL_IOCTL_HANDLER g_oalIoCtlTable [] = {

     {IOCTL_HAL_QUERY_FORMAT_PARTITION, 0, x86IoCtlHalQueryFormatPartition },

#include <ioctl_tab.h>

};

Notice that the table g_oalIoCtlTable contains a local entry for the query format command and then an include of the file ioctl_tab.h. This file, ioctl_tab.h, located in platform\common\src\x86\inc and shouldn’t be confused with the ioctl.h file that is also in the platform\common tree but is used by other BSPs.

I recommend simply replacing the include line in globals.c with the contents of the ioctl_tab.h file. This way you can update the table as needed and the contents of the table will be in a convenient location, not hidden in some far away include directory. The result of adding the table would look like the following

image

Once the table has been included, it is simple to see what routines need to be modified to change the behavior of a given IOCTL command. At this point, changing the routine would be accomplished in the same method discussed above to change the RTC routines.

Modifying the CEPC Device Drivers

The CEPC device drivers are all located in the public side of the build tree at \wince700\public\common\oak\drivers. The drivers such as serial, keyboard and mouse, display, USB host controller, wave and so on are there.

As with the platform common code, the drivers should not be updated in place on the public side of the tree. Changing them there would affect all the other platforms in your system. Even if you only have one platform currently under development, at some point, you may be required to develop another, so any changes should be done on source code moved to the BSP directory.

Moving code from the Public tree to the BSP directory is beyond the scope of this blog post. I hope in the future to return to this topic. It is an interesting but quite technical topic that deserves its own discussion.

Fortunately, these drivers are very configurable using registry values. You can configure the base address of hardware, the physical interrupt values as well as many other parameters simply by changing their initialization values in the registry. These changes should be made in platform.reg under CEPC\files. The original configuration values for many of these drivers are located in common.reg in Public\common\oak\files. You should use common.reg as a guide but as with all files on the public side of the tree, it should not be modified. Instead, make the changes in platform.reg. Since the build system parses platform.reg after common.reg, any change made in platform.reg will override the original values set in common.reg.

As for this discussion, I’ve covered how you can move code from the platform\common tree into a BSP. This is obviously needed in the CEPC and CEPC-derived BSPs due to the almost total dependency on code from the platform\common tree. However all BSPs include libraries from the platform\common tree to some degree so these lessons apply there as well. The CEPC is an interesting BSP, but it takes a bit more knowledge to configure than most BSPs.

For more information, visit Doug’s website at www.bolingconsulting.com.

Doug and I both thank you for your time and for your interest in Windows Embedded Compact.