Bruce Eitman

Windows CE Musings

  Home  |   Contact  |   Syndication    |   Login
  91 Posts | 0 Stories | 91 Comments | 0 Trackbacks

News

Tag Cloud


Archives

Post Categories

Thursday, September 11, 2008 #

Michel Verhagen at GuruCE has just published a very nice blog post about Filtering Dat Files.

In the article, he shows how to use a batch file to remove lines from the Public DAT files during makeimg.  Note that this technique can be used to filter lines out of other file types as well, including bib and db files.

Tags: Makeimg, Dat Files
Copyright © 2008 – Bruce Eitman
All Rights Reserved

Tuesday, September 09, 2008 #

There isn’t any magic that occurs when you set a SYSGEN variable, or drag a component from the catalog into your project. I know that sometimes it sure seems like it, but if I know anything about computers I know that there isn’t any magic involved. Instead, there are some batch files, makefiles, and few applications that work together to define the OS that you want to build and then to build it. During the sysgen of your project, a file in your project (OSDesign or PBWorkspace) is used to convert SYSGEN variables into other environment variables used to define the build of your system.
Cesysgen.bat is in your project’s Misc folder. Maybe you have never even looked at the cesysgen.bat file, probably because you didn’t need to. I will go out on a limb here and make a statement without any scientific data to back it up: most projects never make changes to cesysgen.bat. In fact, my team doesn’t even keep it in version control for Windows CE 5.0 or 6.0 projects, instead we allow the build system to create the default one when needed.
Why would I discuss cesysgen.bat if most projects don’t modify it? For two reasons; knowing about it can provide some valuable information and if you do need to modify it you will be glad that you know about it.
First a little history, prior to Windows CE 5.0, cesysgen.bat was a monolithic file that would be copied into your project when the project was created. This approach had some created some problems for those of us who did need to modify our cesysgen.bat files. QFEs were the primary source of the problem. Anytime that a QFE was installed, the default cesysgen.bat file would be updated to solve problems or add new features, but my modified cesysgen.bat file would not be updated. No problem if you have one or two projects, but my team manages a large number of projects.
The engineers at Microsoft took a new approach starting with Windows CE 6.0. The cesysgen.bat file became a set of batch files located in Public\CEBase\Oak\Misc and the project contains a small cesysgen.bat file that calls on the set of files to do the work. This change means that the base set of batch files will be updated with QFE installs, but you can still change cesysgen.bat in your project.
Enough history, what does cesysgen.bat and do? Cesysgen.bat checks the SYSGEN variables that your project has set and verifies that dependent SYSGEN variables are set and sets other environment variables that will be used during the sysgen process. That sounds a lot like something that Microsoft would need to set up and that you should never need to change, but Windows CE is highly configurable. To make a very small OS image, you may need to modify environment variables to override the settings that Microsoft has determined are “correct."
I also find it useful to look at the cesysgen batch files to reverse engineer the process to figure out which SYSGEN variable I need to set. This is especially true when one of my customers knows which file they need in the OS image, but don’t know what I need to do to get the file into the OS image.    I can then search the bib files for the file to determine which environment variable needs to be set to include the file. Then searching the batch files I can find the SYSGEN variable that causes the environment variable to be set.                                                                                                                                                                 
Tags: Build.exe
Copyright © 2008 – Bruce Eitman
All Rights Reserved

Monday, September 08, 2008 #

Recently, there have been a few questions in the newsgroups about the serial debug port. The questions were along the lines of:
·         Which COM port do I use for debug output?
·         How do I change the COM port that is used for debug output?
These are actually quite common questions, so I thought I would address these. Every CPU and/or UART is different so I won’t give you a how to lesson, but I will provide you with enough information to look inside your BSP to figure it out for yourself.
First, let’s address the term COM port. COM is a special name used in device drivers to indicate that the driver is manageable through special COM APIs for controlling the communications through a UART. The term doesn’t apply to the debug serial port because:
1.       No device driver. The serial debug port must be available before the device manager is even running. The serial debug port is available in the single threaded bootloader and is available early in the kernel initialization.
2.       No run time API support for baud rate, parity, stop bit…
3.       The debug serial port is not manageable by the COM APIs.
Getting the Serial Debug Port Started
On the most base level, the serial debug port can be initialized and written to in the assembly code that starts your bootloader. This is not the focus of this article, but I mention it because you may need to delve into the assembly code to change the serial debug port.
Talking C though, the serial debug port is initialized in OEMInitDebugSerial(). OEMInitDebugSerial() should initialize the UART. It should set the baud rate, parity and stop bits, may need to turn on power to external hardware and may need to start a clock to run the UART. OEMInitDebugSerial() may select different UARTs or even disable the serial output depending on platform specific features.
Outputting on the Serial Debug Port
OEMWriteDebugString() and OEMWriteDebugByte() provide the functionality of outputting on the serial debug port. OEMWriteDebugByte () usually implements putting a byte on the output FIFO of the UART and OEMWriteDebugString () usually processes a string and calls OEMWriteDebugByte () for each character to be output.
Reading Input on the Serial Debug Port
OEMReadDebugByte() implements reading a byte from the UART input FIFO. OEMReadDebugByte() is non-blocking, so if a character isn’t available or an error occurs it returns with a status code of either OEM_DEBUG_COM_ERROR, OEM_DEBUG_READ_NODATA. I have provided a code sample of reading from the serial debug port in Windows CE: Using the debug serial port for input.
Answering the Questions
How would you answer the questions about the serial debug port? Every BSP is different, so I the only concrete advice that I can give is to look for the serial debug port functions in your code. But in more generic terms, these functions are often implemented in both the bootloader and the OAL or Kernel, so you may need to look in both. The functions are sometimes implemented in a file named debug.c. If you look at CEPC, you will find that it actually has three implementations of these functions in eboot, sboot and the kernel uses an implementation in Platform\Common.
Copyright © 2008 – Bruce Eitman
All Rights Reserved

This weekend I received an email from one of my blog’s readers asking my how to search for content on my blog. To be honest, my first reaction was to wonder why someone would ask me such a silly question. But then I thought on it and realize that I didn’t know the answer, but I was pretty sure that Google could do it. For the few of you that watched the video that Microsoft produced where I answered some questions that were asked of me off camera, I said that the most important tools that a Platform Builder developer needs are good search tools.   So let’s look at some:
Searching my Blog for Information
Most of you are currently using Google. I know that because I can see how you found my blog if you click on a link to one of my pages.   In the last week Google has represented about 98% of the search engines used by you. So you are familiar with the Google home page:
But
have you noticed the text next to the search box? One of the choices is Advanced Search:
Clicking on Advanced Search links to a page that allows you to narrow down your search results, like to view results only from my blog.
Last
week one of my readers noticed that I referred to the _FLATRELEASEDIR and asked what the _FLATRELEASEDIR is. So let’s use the Advance Search on Google to see if we can find more information about the _FLATRELEASEDIR. Start by entering _FLATRELEASEDIR in the Find web pages that have... all of these words text field. If you were to search now you would find thousands of pages, but of course you really want to know what I have to say about the _FLATRELEASEDIR, so enter geekswithblogs.net/bruceeitman in the Search within a site or domain  box:
Now we have results from my blog showing the 18 pages (not counting this one) that have references to the _FLATRELEASEDIR:
<results.jpg>
Searching within Platform Builder
If you are going to do much with Platform Builder, then you should have a good tool for searching all of the source code available within the build tree. There is just too much information available in the source code to not be able to find it with ease. If you have looked at Profile: Software Development Tools then you already know that my software engineering roots include UNIX, where I learned to use grep to get answers. Grep is a powerful tool, but the results can be cumbersome, so I now use Examine32 which works like grep, but has a simple GUI to aid in creating the search and using the results. I am not necessarily promoting Examine32, I don’t have any ties to it, but I am promoting owning and using good search tools.
Copyright © 2008 – Bruce Eitman
All Rights Reserved

Wednesday, September 03, 2008 #

Windows CE provides several ways to synchronize threads and access to data by multiple threads. These include the synchronization objects that are typical for a multithreaded operating system: mutex, semaphores, events and critical sections. These synchronization objects may be overkill for protecting access to a single variable. The Interlocked functions can be used to control access to a single 32 bit variable.
The interlocked functions are:
Function Name
Action
InterlockedCompareExchange
Compares two values and writes a third value if they are equal
InterlockedCompareExchangePointer
Compares two values and writes a third value if they are equal
InterlockedDecrement
Decrements a value
InterlockedExchange
Writes a new value to a location
InterlockedExchangeAdd
Adds a value to a location
InterlockedExhangePointer
Writes a new value to a location
InterlockedIncrement
Increments a value
IntelockedTestExchange
Compares two values and writes a third value if they are equal
 
These functions all perform atomic actions on the data, meaning that they perform the action without a context switch during the function handling. The functions work by calling into the kernel which then causes an exception. The action is then handled within the exception handler. The functions change a value that is pointed to by a pointer that is passed in. The pointer must point to a 32 bit value that is 32 bit aligned except for x86 processors (for a discussion on what happens if the pointer is not 32 bit aligned see: Platform Builder: Data Misalignment).
A few examples:
// Global data
DWORD Data = 0;
 
void Foo()
{
    DWORD Result;
    Result = InterlockedIncrement( &Data ); // Result will contain the original value of Data
    Result = InterlockedCompareExchange( &Data, 3, 1 ); // if Data == 1 then Result will be 1 and Data will be set to 3
    Result = InterlockedExhangeAdd( &Data, 6 ); // Result contains the original value of Data and Data will contain Data += 6      
}
 
The Interlocked functions provide a safe and convenient way to write to a variable from multiple threads. I say convenient because these functions don’t require the overhead of other synchronization methods when managing small amounts of data.   If on the other hand, you need to manage changing multiple values, the other synchronization methods may be a better choice.
 
Copyright © 2008 – Bruce Eitman
All Rights Reserved

I ran into a problem today with data misalignment. The problem would have taken a lot of time to find if I wasn’t already familiar with the problem (kicking myself now.)
I was porting an existing driver into an old platform to update the platform. So I know that the driver works, but when it started it would data abort. This particular driver is quite large and complex, so a simple read of the code would not be possible in a reasonable amount of time. I have some experience with tracking the cause of a data abort (Windows CE: Finding the cause of a Data Abort.) But this data abort was occurring in Coredll.dll, so I knew that it was because of something that the driver was passing into a function.
Thinking back on what I had done to port the driver into this platform here is what I did:
1.        Copy the driver into the platform
2.       Added some members to a data structure in a header file already in the platform
I know that the driver is well tested, but let’s review the data structure:
#pragma pack(1)
typedef struct _MYSTRUCT {
    BYTE var1;
    BYTE var2;
    DWORD var4;
    BYTE var5;
   DWORD NewVar1;
   DWORD NewVar2;
   DWORD NewVar3;
} MYSTRUCT; 
#pragma pack()
If you look at it closely, you may already have seen my problem. Of course depending on my driver code, this structure could be perfectly acceptable, but knowing my driver it is not. My driver increments NewVar1 using InterlockedIncrement() and decrements it using InterlockedDecrement(). If you aren’t familiar with these functions, these functions take as their parameter a pointer to a 32 bit location. InterlockedIncrment() then effectively does *ptr++ which when I pass in the address of NewVar1 is dereferencing a location that is not 32 bit aligned, which for the ARM processors that I work with causes an exception.
The alignment is not a problem when accessing the structure directly. If I had the following code:
MYSTRUCT *Ptr;
//Allocate some memory for Ptr…
Ptr->NewVar1++;
This would compile and run okay, although some extra assembly code would be generated to handle the alignment for me. The problem also would not exist if the structure wasn’t wrapped with the pragma pack, which tells the compiler not to add any padding to the structure to align the members.
The problem comes from passing the address of NewVar1 into another function.
The solution for my problem is to cause NewVar1 to be aligned by adding an extra byte before it in the definition.
Go to Summary of When Things Go Wrong
Tags: Data Abort
Copyright © 2008 – Bruce Eitman
All Rights Reserved

Tuesday, August 26, 2008 #

 Windows Embedded CE 6.0 Fundamentals by Stanislav Pavlov and Pavel Belevsky is one of the first books about developing a Windows CE device using Platform Builder availabe in several years.
As the name states, this book contains the fundamentals of developing using Platform Builder.  It does not venture into too many details though, so this is a book for beginners, not beginning programmers, but beginners with Platform Builder.
This book is fairly short at 230 pages, as technical books go, so reading it doesn't take long and can be worth the time.
This book's success is a a discussion of the architecture of Windows CE.  This is especially helpful becuase of the major changes to the Windows CE architecture in version 6.0.  This includes a discussion of how processes are managed, kernel and user mode drivers and virtual memory.
The book falls short though in details, and maybe that is appropriate for a fundamentals book.  It would have been good to have provided some source code examples to explain some of the material better.  There are also some topics which are covered better in Platform Builder Help.
Overall, if you are new to Platform Builder or need information about the changes to the Windows CE architecture, this is a good book to read.
 
 
Copyright © 2008 – Bruce Eitman
All Rights Reserved

Saturday, August 23, 2008 #

Sources.cmn is a build configuration system file that allows you to set common variables. This can be useful if more than one directory in the build tree need the a variable set to the same value because it can reduce your maintenance efforts. 
Each build tree can use one sources.cmn file.  When build.exe runs, it will determine the root of the build tree by looking for the top most folder with a Dirs file. Build.exe then sets BUILDROOT to the top most folder with a Dirs files.  Makefile.def in Public\Common\OAK\Misc will include $(BUILDROOT)\sources.cmn if it exists.
Some of the variables that are commonly set in sources.cmn include CDEFINES, ADEFINES and INCLUDES.
CDEFINES and ADEFINES are used to set macros that are common to multiple build folders. These might include RAM and ROM sizes, but might also include OEM and CPU specific macros.
The include path, INCLUDES, can be set in sources.cmn which is very helpful, especially if and when you change the directory structure.
 The Platform directory tree should have WINCEOEM set to 1, so sources.cmn is a good place to do this rather than setting it in each sources file.
Note: Starting with Windows CE 5.0, sources.cmn is no longer really an option. It is required because sources.cmn needs to at least set _COMMONPUBROOT, _ISVINCPATH, and _OEMINCPATH. These were set by build.exe in prior versions.
For more on sources files take a look at: Platform Builder: Sources Files and Platform Builder: Sources Files 2 
 
 
Copyright © 2008 – Bruce Eitman
All Rights Reserved

Friday, August 22, 2008 #

I was looking over my original post about sources files (Platform Builder: Sources Files) today and it occurred to me that there is room to improve. That post provided basic information to create a sources file that will build a driver.  The following are other things that you can do within a sources file:
Set CFLAGS and AFLAGS
CFLAGS and AFLAGS cannot be set in a sources file. Instead, you will need to set CDEFINES and ADEFINES to set compiler and assembler command line flags.
Set CDEFINES, LDEFINES and ADEFINES
These variables are used to change the command line parameters to the compiler (CDEFINES), assembler (ADEFINES) and linker (LDEFINES). 
As with all variables in a sources file the way to set the variable is <VAR NAME>=<DATA>. So, using CDEFINES for an example:
CDEFINES=-DMY_MACRO –DOTHER_MACRO=5
Which causes the compiler command line to define MY_MACRO and to define OTHER_MACRO=5. The –D is the compiler command line flag to define a macro. But wait, setting CDEFINES this way will cause any previous settings to be lost. This is exactly why we cannot use CFLAGS and AFLAGS, it is set this way in makefile.def. So a better way to set a variable is:
CDEFINES=$(CDEFINES) -DMY_MACRO –DOTHER_MACRO=5
By doing so, we are setting CDEFINES equal to the current value in CDEFINES plus defining MY_MACRO and OTHER_MACRO=5.
Skip Building
You can skip building a directory in the build tree by checking the component environment variable and setting SKIPBUILD. SKIPBUILD tells build to skip building the directory.
!if "$(BSP_NOTHISDRIVER)" == "1"
SKIPBUILD=1
!endif
This checks to see if the environment variable BSP_NOTHISDRIVER is set to “1”. If it is then sets SKIPBUILD=1. For those of us that don’t like variable with “NO” in them, you can use:
!if "$( BSP_THISDRIVER)" == ""
SKIPBUILD=1
!endif
This checks to see if BSP_THISDRIVER is not set. If it is not then sets SKIPBUILD=1.
Build Something Before or After Building the Directory
WINCETARGETFILE0 can be used to tell the build system to build a target before building the current directory. WINCETARGFILES tells the build system to build a target after building the current directory.    I have given an example of using WINCETARGETFILES in Windows CE Platform Builder: Automatically putting files in the SDK during build so let’s look at WINCETARGETFILE0.
In this example, I have a DLL that is built in a different directory tree and want to extend the DLL by adding some new functions. The original DLL is built in two directories, one that creates a LIB file and the other that links the LIB to create a DLL.  In this directory there is source code that adds some functions and a def file that exports the functions. For maintainability, I want to use the def file from the original DLL folder, but extend it to add new definitions. To do this, use WINCETARGETFILE0 set equal to DEFFILE:
WINCETARGETFILE0=$(DEFFILE)
Create or edit makefile.inc in the same folder as the sources file. Add a target to makefile.inc and build instructions. In this case the target is $(DEFFILE) and the instructions will copy the original def file to this directory and append the contents of Custome.def to it:
$(DEFFILE): Custom.def                               
xcopy ..\Original\BuildDll\Original.def .
                type Custom.def >> Original.def
So the new def file will be created before building this directory and the def file will be available when the DLL is linked.
Tell the Solution Explorer about files to Display
The Solutions Explorer window uses sources files to determine which files to display and how to display them.
 
SOURCES not only tells build.exe which files should be built in the directory, but tells the Solutions Explorer which files to list in the “Source files” folder. The following will cause serial.cpp to display in the Source Files folder:
SOURCES=serial.cpp
FILE_VIEW_ROOT_FOLDER tells the Solutions Explorer window to which files to show in the root folder of the directory. The following will cause sources and makefile to display in the root folder:
FILE_VIEW_ROOT_FOLDER=Sources Makefile
FILE_VIEW_RESOURCE_FOLDER tells the Solutions Explorer window which files to display in the “Resource files” folder.
FILE_VIEW_RESOURCE_FOLDER=serial.rc
FILE_VIEW_INCLUDES_FOLDER tells the Solutions Explorer windows which files to display in the “Include files” folder.
FILE_VIEW_INCLUDES_FOLDER=serial.h
FILE_VIEW_PARAMETER_FOLDER tells the Solutions Explorer window which files to display in the “Paramter files” folder.
FILE_VIEW_PARAMETER_FOLDER=serial.bib serial.reg
 
Go to Summary of Building Windows CE
 
Tags: ,
 
Copyright © 2008 – Bruce Eitman
All Rights Reserved
 

Thursday, August 21, 2008 #

Every once in a while I am asked about running batch files on Windows CE. My first response of course to ask why? But let’s assume that you are set on using a batch file. I know you probably think that batch files are easy to modify, but really I don’t think that they are and you may find that batch files for Windows CE aren’t that easy.
The first thing that you are going to need is a Command window, or DOS shell, to run your batch file in.   It is likely that your system doesn’t have one, but if you have control over the content of your Windows CE OS ROM image, you can add one using Platform Builder or as your OS team to add one.   If you don’t have one and don’t have control over the OS, then you will need to find one that you can use. I do have control over my OS, so I have never needed to look for one.
To demonstrate that batch files can run in Windows CE, and to check for some of the shortcomings, I created the following batch file:
@ECHO OFF
 
echo Running Batch.bat
 
set LOGOFILE="\Release\Logo.jpg"
set TESTFILE="\Release\Test.txt"
 
if EXIST %LOGOFILE% xcopy %LOGOFILE% \Windows
if EXIST %LOGOFILE% copy %LOGOFILE% \Windows
 
for /F %%i in (%TESTFILE%) Do (
                echo %%i
                )
 
CALL :ListDirs
 
Pushd \Windows
Dir /A:D
Popd
 
GOTO :EOF
 
:ListDirs
cd %1
for /F %%i in ('dir /A:D /B /S \Windows' ) Do (
                                Echo Dir %%i
                 )
GOTO :EOF
Careful, don’t think that everything in this file works. Some things do not work:
1.       Xcopy isn’t available, but copy is
2.       For loops aren’t suppprted, but if statements are
3.       Call is supported, but not to functions in the batch file
4.       Pushd and Popd aren’t supported, but cd is
I am sure that if I kept adding things to this batch file, I would have found more unsupported features that are supported in big Windows or DOS.
I think that it might be easier to write a simple application to do most of what you might want to do in a batch file. You can write an application that uses main() for Windows CE, and have for loops. But I am a C programmer so what is easy to me might not be so easy for you.
 
Copyright © 2008 – Bruce Eitman
All Rights Reserved