bulat-icon  Articles  

[+]  Articles


Porting Windows CE 5.0 on PXA255 Based Platform

by Vinoth.R


The PXA255 processor is one of the popular xscale processor other then PXA270. Even though Intel is not promoting this product for the future use, there are many development boards as well as devices developed over this 200MHz chip. Microsoft has released the WindowsCE 4.20 BSP during the initial boom of this processor into the market. After the introduction of the PXA270 processor by Intel Microsoft did not put any effort to release WindowsCE BSP for the next release of its pioneer Mobile operating system like Windows CE 5.0.

This article introduces some easy as well interesting method to develop Windows CE 5.0 BSP for PXA255. Instead of having the conventional approach of porting PXA255 Windows CE 4.20 BSP to Windows CE 5.0 Our windows embedded development team has a different approach ie, take the PXA270 Windows CE 5.0 BSP and modify it for PXA255 processor.


The scope of this document is limited to Window ce BSP developing audience who are interested in developing PXA255 BSP for Windows CE 5.0 or even 6.0. We use Windows CE 5.0 BSP for Intel’s PXA270 Developers board as the reference BSP for our development. This BSP is commonly known as the Mainstone-III Windows CE 5.0 BSP. The user is expected to have the understanding of PXA255 processor register set and Mainstone III BSP architecture.

Porting the Cross Platform Low Level definitions (XLLP)

The Cross Platform Low Level functions are the processor initialization functions, and are closely bind to the processor. PXA270 has few features those are not available for the PXA255 processor. Most of the registers for the devices those are common for PXA255 and PXA270 have same register set and bit definition. So those features and its corresponding register set have to be removed from the BSP. For example PXA27x contains 120 GPIO where as PXA255 contains 85 GPIO pins, PXA255 doesn’t have the power I2C interface and it contains only 15 DMA channels etc. The register set is defined in a file located at
Step 1:
  Remove the following register definitions from the xlli_bulverde_defs.inc file.
Gpio Registers:
xlli_GPLR3_offset EQU (0x100)
xlli_GPDR3_offset EQU (0x10C)
xlli_GPSR3_offset EQU (0x118)
xlli_GPCR3_offset EQU (0x124)
xlli_GAFR3_L_offset EQU (0x06C)
xlli_GAFR3_U_offset EQU (0x070)

Power Manager:
xlli_PGSR3_offset EQU (0x2C)
xlli_PSLR_offset EQU (0x34); Power Manager Sleep Mode Config Register
xlli_PSTR_offset EQU (0x38); Power Manager Standby Mode Config Register
xlli_PSNR_offset EQU (0x3C); Power Manager Sense Mode Config Register
xlli_PVCR_offset EQU (0x40); Power Manager Voltage Change Control Register
xlli_PKWR_offset EQU (0x50); Power Manager Keyboard Wake-up Enable Register
xlli_PKSR_offset EQU (0x54); Power Manager Keyboard Edge-Detect Status Register
xlli_PI2DBR_offset EQU (0x188); Power I2C Data Buffer Register
xlli_PI2CR_offset EQU (0x190); Power I2C Control Register
xlli_PI2SR_offset EQU (0x198); Power I2C Status Register
xlli_PI2SAR_offset EQU (0x1A0); Power I2C Slave Address Register

Power Manager Register definition bit masks:
xlli_PCFR_SYSEN_EN EQU (0x20); SYS_EN pin
xlli_PCFR_DC_EN EQU (0x80); Deep-Sleep Mode

Memory Controller Registers:
xlli_ARB_CNTL_offset EQU (0x48) xlli_BSCNTR0_offset EQU (0x4C) xlli_BSCNTR1_offset EQU (0x50) xlli_LCDBSCNTR_offset EQU (0x54) xlli_BSCNTR2_offset EQU (0x5C) xlli_BSCNTR3_offset EQU (0x60)

Interrupt Controller:
xlli_ICHP_offset EQU (0x18); Interrupt Controller Highest Priority Register
xlli_ICMR2_offset EQU (0xA0); Interrupt Controller Mask Register 2
xlli_ICLR2_offset EQU (0xA4); Interrupt Controller Level Register 2
xlli_ICCR2_offset EQU (0xAC); Interrupt Controller Control Register 2

Clock Registers:
xlli_CCSR_offset EQU (0x0C); Core Clock Status Register
xlli_CCCR_A_Bit_Mask EQU (0x1 « 25); "A" bit is bit 25 in CCCR

OS Timer Registers:
xlli_OSCR4_offset EQU (0x40); OS Timer Count Register 4
xlli_OSCR5_offset EQU (0x44); OS Timer Count Register 5
xlli_OSCR6_offset EQU (0x48); OS Timer Count Register 6
xlli_OSCR7_offset EQU (0x4C); OS Timer Count Register 7
xlli_OSCR8_offset EQU (0x50); OS Timer Count Register 8
xlli_OSCR9_offset EQU (0x54); OS Timer Count Register 9
xlli_OSCR10_offset EQU (0x58); OS Timer Count Register 10
xlli_OSCR11_offset EQU (0x5C); OS Timer Count Register 11

xlli_OSMR4_offset EQU (0x80); OS Timer Match Register 4
xlli_OSMR5_offset EQU (0x84); OS Timer Match Register 5
xlli_OSMR6_offset EQU (0x88); OS Timer Match Register 6
xlli_OSMR7_offset EQU (0x8C); OS Timer Match Register 7
xlli_OSMR8_offset EQU (0x90); OS Timer Match Register 8
xlli_OSMR9_offset EQU (0x94); OS Timer Match Register 9
xlli_OSMR10_offset EQU (0x98); OS Timer Match Register 10
xlli_OSMR11_offset EQU (0x9C); OS Timer Match Register 11

xlli_OMCR4_offset EQU (0xC0); OS Timer Match Control Register 4
xlli_OMCR5_offset EQU (0xC4); OS Timer Match Control Register 5
xlli_OMCR6_offset EQU (0xC8); OS Timer Match Control Register 6
xlli_OMCR7_offset EQU (0xCC); OS Timer Match Control Register 7
xlli_OMCR8_offset EQU (0xD0); OS Timer Match Control Register 8
xlli_OMCR9_offset EQU (0xD4); OS Timer Match Control Register 9
xlli_OMCR10_offset EQU (0xD8); OS Timer Match Control Register 10
xlli_OMCR11_offset EQU (0xDC); OS Timer Match Control Register 11

RTC Registers:
xlli_RDCR_offset EQU (0x10); RTC Day Counter Register
xlli_RYCR_offset EQU (0x14); RTC Year Counter Register
xlli_RDAR1_offset EQU (0x18); RTC Day Alarm Register 1
xlli_RYAR1_offset EQU (0x1C); RTC Year Alarm Register 2
xlli_RDAR2_offset EQU (0x20); RTC Day Alarm Register 2
xlli_RYAR2_offset EQU (0x24); RTC Year Alarm Register 2
xlli_SWCR_offset EQU (0x28); Stopwatch Counter Register
xlli_SWAR1_offset EQU (0x2C); Stopwatch Alarm Register 1
xlli_SWAR2_offset EQU (0x30); Stopwatch Alarm Register 2
xlli_PICR_offset EQU (0x34); Periodic Interrupt Counter Register
xlli_PIAR_offset EQU (0x38); Periodic Interrupt Alarm Register

Oscillator controller bit definitions:
xlli_OSCC_TOUT_EN EQU (0x04); Timekeeping Output enable
xlli_OSCC_PIO_EN EQU (0x08); Processor Oscillator Output Enable
xlli_OSCC_CRI EQU (0x10); Processor Oscillator Output Enable
Step 2:

Change the GPIO registers value and SDRAM register values based on new Platform (All values are defined in the wince500/(platform)/src/common/xllp/inc/xlli_ (Platform) _defs.inc).

Also if you have any board specific registers you can represent the values in this file and remove the GPIO registers values which are irrelevant to PXA255 processor. The above two files are used by the Startup code of both the EBOOT and KERNEL.
Step 3:
  Remove all the register definitions which are not part of the PXA255 processors device specific register set. These registers are defined in the header files in the directory, wince500/platform/src/common/xllp/inc. Each header file name is of the format xlli_(device).h. The register set is represented as structure that contains all the registers related to devices. Also the bit definitions for of each of those registers are defined in the same header file. Remove the registers and also the bit definitions which are not relevant to PXA255.

For example, to remove the GPIO registers which are not available in the PXA255, comment out the lines in the file wince500/(platform)/src/common/xllp/inc/xllp_gpio.h as shown below.
typedef struct


// Commented by econ for PXA255 Gpio configuration (pxa255 is having 85 GPIO)

// XLLP_VUINT32_T GAFR3_L; /* Alt. Function Select Reg.[ 96:111] */
// XLLP_VUINT32_T GAFR3_U; /* Alt. Function Select Reg.[112:120] */
// XLLP_VUINT32_T RESERVED1[35]; /* addr. offset 0x074-0x0fc */
// XLLP_VUINT32_T GPLR3; /* Level Detect Reg. Bank 3 */
// XLLP_VUINT32_T RESERVED2[2]; /* addr. offset 0x104-0x108 */
// XLLP_VUINT32_T GPDR3; /* Data Direction Reg. Bank 3 */
// XLLP_VUINT32_T RESERVED3[2]; /* addr. offset 0x110-0x114 */
// XLLP_VUINT32_T GPSR3; /* Pin Output Set Reg. Bank 3 */
// XLLP_VUINT32_T RESERVED4[2]; /* addr. offset 0x11c-0x120 */
// XLLP_VUINT32_T GPCR3; /* Pin Output Clr Reg. Bank 3 */
// XLLP_VUINT32_T RESERVED5[2]; /* addr. offset 0x128-0x12c */
// XLLP_VUINT32_T GRER3; /* Ris. Edge Detect Enable Reg. Bank 3 */
// XLLP_VUINT32_T RESERVED6[2]; /* addr. offset 0x134-0x138 */
// XLLP_VUINT32_T GFER3; /* Fal. Edge Detect Enable Reg. Bank 3 */
// XLLP_VUINT32_T RESERVED7[2]; /* addr. offset 0x140-0x144 */
// XLLP_VUINT32_T GEDR3; /* Edge Detect Status Reg. Bank 3 */


Follow the same instructions for the remaining device files in the same directory.

1) Since PXA255 CCLKCFG register contains only F and T bit definitions and there is no B and H bits, related operations has to be removed from the file.
wince500/(platform)/src/common/xllp/src /xlli_lowlev_init.s file.

2) The CCCR register for PXA255 and PXA27x is different. There is no ‘A’ bit on PXA255, so remove the xlli_mem_Topt, xlli_mem_restart subroutines from the xlli_lowlev_init.s file. In the xlli_setClocks routine, the CCLKCFG Turbo mode bit and Fast bus Mode bit can be assigned directly to the CCCR register.

3) Change the MDREFR K1DB2 bit value according to the memory clock frequency.

4) I2C interface is a dedicated interface in PXA255 instead of GPIO alternating functions PXA270 and also there is no power I2C interface in PXA255. So remove the header file declarations in the corresponding device header file.


Porting the Kernel

There is no much difference in the processor dependent kernel source of the BSP. But there are two important units which are highly depended to processor, the Interrupt Unit and RTC. The interrupt architecture bit different in PXA255 and PXA270.

1) For PXA27x processor ICHP (Interrupt Higher priority register) is used for detecting the interrupt and for PXA255 processor ICIP (Interrupt Pending Register) is used. So the OEMInterruptHandler() has to be changed. Do the following changes in the OEMIntyerrupthandler().

In PXA270 the IRQ values are defined as IDs that can be understandable by the ICHP section of the processor. But in PXA255 interrupt are detected with ICIP register bits. So the OEMInterruptHandler() has to be rewritten in a from as given below. Since the Interrupt priority array g_intPriorities used by OEMIntyerrupthandler() ICHP remove it from the int.c file.

ULONG OEMInterruptHandler(ULONG ra)
  UINT32 sysIntr = SYSINTR_NOP;

  if (!g_pICReg || !g_pOSTRegs || !g_pGPIORegs ) {
  irq = (g_pICReg->icip);
  if (irq & 0)
   // System timer interrupt?
  if (irq & PXA_IRQ_OSMR0)
    // The rest is up to the timer interrupt handler.
    sysIntr = OALTimerIntrHandler();
  else if (irq & PXA_IRQ_STUART)
    CLRREG32(&g_pICReg->icmr, PXA_IRQ_STUART);
  else if (irq & PXA_IRQ_FFUART)
    CLRREG32(&g_pICReg->icmr, PXA_IRQ_FFUART);

2) PXA255 RTC contains only the RTTR, RTAR, RCNR, RTSR register so day, month, year calculation are done by software or External RTC.
The following are the RTC functions are used by the kernel which needs to be rewritten for PXA255.
UINT32 code, VOID *pInpBuffer, UINT32 inpSize, VOID *pOutBuffer,
UINT32 outSize, UINT32 *pOutSize)

These functions has to be implemented in the \WINCE500\PLATFORM\(Platform name)\SRC\COMMON\RTC\rtc.c file

3) PXA255 OS Timer is running at the frequency of 3.86 MHz where as PXA27x OS Timer is Timer running at the frequency of 3.25 MHz. So the Ticks per Microseconds definitions need to be changed. These OS timer definitions are used by the kernel and are defined in the \WINCE500\PLATFORM\(Platform name)\SRC\Bsp_cfg.h file.

Also calculate the divisor value according to the OEMMintickdistance in the OEMInit () function of init.c file. Make the followings changes in the for OS Timer definitions in bsp_cfg.h.

#define OEM_CLOCK_FREQ 3686400 // 3.25M ticks/sec #define OEM_TICKS_1MS 3686 // 1ms in ticks #define RESCHED_PERIOD 1 // Reschedule period in ms #define RESCHED_INCREMENT (RESCHED_PERIOD * OEM_TICKS_1MS) #define OEM_TICK_COUNT_MARGIN 0

4) Libraries for the sources KERN, KERNKITL, KERNKITLPROF are the same which is already in the sources file used for PXA27x processor except oal_cache_pxa27x.lib. Instead of the oal_cache_pxa27x.lib use oal_cache_pxa250.lib for PXA255. The above three kernel related directories are under the following tree. \WINCE500\PLATFORM\(platform name) \SRC\KERNEL\
The sample KERN sources file changed for PXA255 is given below.


$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\mainstoneii_freq.lib \
$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\mainstoneii_io.lib \
$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\mainstoneii_dbgserial.lib \
$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\pxa27x_xllp.lib \
$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\oal_startup_pxa27x.lib \
$(_PLATCOMMONLIB)\$(_CPUINDPATH)\oal_cache_pxa250.lib \
$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\oal_intr_pxa27x.lib \
$(_PLATCOMMONLIB)\$(_CPUINDPATH)\oal_memory_pxa27x.lib \
$(_PLATCOMMONLIB)\$(_CPUINDPATH)\oal_timer_pxa27x.lib \
$(_PLATCOMMONLIB)\$(_CPUINDPATH)\oal_timer_idle_stub.lib \
$(_PLATCOMMONLIB)\$(_CPUINDPATH)\oal_abort_pxa27x.lib \
$(_PLATCOMMONLIB)\$(_CPUINDPATH)\oal_power_pxa27x.lib \
$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\oal_rtc_pxa27x.lib \
$(_PLATCOMMONLIB)\$(_CPUINDPATH)\oal_misc_pxa27x.lib \
$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\oal_serial.lib \
$(_PLATCOMMONLIB)\$(_CPUDEPPATH)\oal_ioctl.lib \
$(_PLATCOMMONLIB)\$(_CPUDEPPATH)\oal_kitl.lib \
$(_PLATCOMMONLIB)\$(_CPUDEPPATH)\oal_log.lib \
$(_PLATCOMMONLIB)\$(_CPUDEPPATH)\oal_other.lib \
$(_COMMONOAKROOT)\lib\$(_CPUDEPPATH)\vbridge.lib \
$(_COMMONOAKROOT)\lib\$(_CPUDEPPATH)\kitl.lib \

Porting the Drivers

All PXA255 drivers can be copied from
\WINCE500\PUBLIC\COMMON\OAK\CSP\ARM\INTEL\PXA25X\ folder to local platform.


KITL is one the important block in the BSP for doing any sort of debugging. Most of the handheld device may not have Ethernet port on the board; in that case KITL can be implemented over either USB or Serial Port.

But there is no PDD level serial KITL driver for the Mainstone BSP. But this can be easily ported from X86 CSP.

Porting 6.0 to any cards and any questions on this article, please write to sales@e-consystems.com with the subject Porting Windows CE 5.0. For Windows CE Driver development please write to sales@e-consystems.com with the subject of Windows CE driver Development.