posts - 20 , comments - 57 , trackbacks - 0

APIC and ACPI in Windows Embedded Compact 2013

APIC: Advanced Programmable Interrupt Controller

ACPI: Advanced Configuration & Power Interface

ACPICA: ACPI Component Architecture

I needed a timer. A timer with a granularity of < 1msec and not tied to the Windows CE 1msec kernel tick. I wanted to program the timer hardware, raise an interrupt and signal an event to trigger specific code in my application.

I used to do this with custom timer hardware in an FPGA design that resides on my Intel x86 based board (as a PCI device) and my own driver. Now I want to eliminate the FPGA so that I can use cheaper COTS (custom of the shelf) hardware.

The only experience I have with Windows CE is on Intel x86 compatible hardware, mainly with ICH4, ICH7 and NM10 chipsets. And yes, already since early 2000 most Intel chipsets (SouthBridge) include a timer, named HPET : High Precision Event Timer. That sounded promising, but further in depth studying and experiencing with the HPET timers revealed that not all features of the HPET can be used if the IRQ from the HPET is redirected to the (old) PIC interrupt controller. Darn! However all features are available when you use the (new) APIC interrupt controller. This is (was) a problem with the standard CEPC BSP for Windows CE 6/7/8 (and before). The CEPC BSP always uses the old 16 input interrupt controller (actually 2 cascaded 8259 PICs dated back from the 1980’s, but nowadays integrated in the Intel chipsets ICHx and NM10.  At least, with these embedded chipsets I am familiar with).

So if I wanted to use all features of the HPET’s, I needed to adapt the CEPC BSP that it can work with the newer APIC. (I don’t need to say that you first need to clone the CEPC and that you do your changes in the clone to keep the original CEPC source code for further reference, do I? You can find some tips and tricks on the GuruCE website on how that is best done. But I will keep referencing hereafter to the CEPC BSP for ease of sake)

My goal is to be able to use the HPET timers with all its features. I started reading many documents, datasheets, weblinks, books on how to program the Intel APIC interrupt controller.

There is LAPIC (Local APIC) and IOAPIC (InputOutput APIC) and even more xAPIC’s. LAPIC is the APIC located close (integrated) to the CPU. The IOAPIC is typically located in the SouthBridge and deals with all peripheral interrupts. When the IOAPIC processes an interrupt, it “talks” to the LAPIC that on its turn will “talk” to (one of) the CPU(s) that will handle the interrupt. You need to program the IOAPIC in your BSP.

In a multi-cpu design the LAPIC can be used to send IPI (InterProcessor Interrupts) between cpu’s. You might need to specify which cpu will handle the IOAPIC interrupts (I choose typically cpu0). IPI setup is done already in the CEPC BSP for Windows 7/8 due to its SMP support.

I learned that you cannot use the old PIC and new IOAPIC together. You choose one of them. The CEPC BSP uses the old PIC as it is still available for backwards compatibility on all modern Intel chipsets that accompanies the Intel cpu’s. And most BIOSes still support this.

Master 8259

IRQ0

Intel 8253 or Intel 8254 Programmable Interval Timer, aka the system timer

IRQ1

Intel 8042 keyboard controller

IRQ2

not assigned in PC/XT; cascaded to slave 8259 INT line in PC/AT

IRQ3

8250 UART serial ports 2 and 4

IRQ4

8250 UART serial ports 1 and 3

IRQ5

hard disk controller in PC/XT; Intel 8255 parallel ports 2 and 3 in PC/AT

IRQ6

Intel 82072A floppy disk controller

IRQ7

Intel 8255 parallel port 1 / spurious interrupt

Slave 8259 (PC/AT and later only)

IRQ8

real-time clock (RTC)

IRQ9

no common assignment, but 8-bit cards' IRQ2 line is routed to this interrupt.

IRQ10

no common assignment

IRQ11

no common assignment

IRQ12

Intel 8042 PS/2 mouse controller

IRQ13

math coprocessor

IRQ14

hard disk controller 1

IRQ15

hard disk controller 2

Table: default IRQ mapping on 8259

So why did Intel introduced than the IOAPIC? A few reasons are:

  • The IOAPIC has more interrupt inputs. Typically 24 or 32.
  • You can have more than 1 IOAPIC on your motherboard to even increase the number of interrupt lines
  • More interrupts give the board designer more freedom how to route the devices to the IOAPIC –> LAPIC -> CPU
  • You can easily reorganize the priority of the interrupts (which is handy for some devices, like USB that have a higher resource/performance need than e.g. an old RS232 port)
  • You don’t need to share interrupts, again for better performance

Most of the time these days you are interested in the PCI/PCI express interrupts. (what I tell about PCI most of the time also applies to PCI express. They are in many respects backwards compatible towards the software (driver)). I am not going to dive too deep in how PCI works, but every PCI device has the possibility to use 4 PCI interrupts INTA, INTB, INTC, INTD. Those 4 PCI interrupts are routed via a PCI router to the APIC(s). This router can be programmed separately (in fact that is a place where you can determine the PCI interrupt priority routing). Apart from the board layout routing which is determined by the board manufacturer.

Note that the HPET does not reside on the PCI bus, but still its interrupts need to be connected and routed to the IOAPIC.

I learned that in order to program the IOAPIC controller, you need information on how the interrupt lines on your motherboard are routed to the IOAPIC. With the old PIC, there was some agreement that particular IRQ lines were reserved for specific hardware and only a few PIC inputs remained available for the PCI interrupts. Most of the time all PCI interrupts ended up being shared with 1 or 2 of the 8259 input lines, leading to resource congestion.

Where do you find this “routing” information? There are a few mechanisms invented over time

  • PIR$ table
  • MP table
  • ACPI 
  • UEFI (supersedes ACPI)

Apart from UEFI, all other mechanisms are mostly available on modern Intel based motherboard architectures. ACPI is the most complete mechanism (of the first 3), it tells you much more about your motherboard hardware than just the PCI interrupt mapping. I learned then I needed to use ACPI for my IOAPIC BSP programming. Also the CEPC BSP already uses parts of ACPI (e.g. to query the available RAM), so in fact is already partly there.

My first attempt was to extend the existing ACPI code in the CEPC BSP. But “on the road” I learned that there is an Open Source library available designed specifically for using the ACPI mechanism and integrate it in an OS. Enter ACPICA. The ACPICA organization maintains this library. You can download it for free and it is already tailored (it builds) for desktop Windows and Unix/Linux. It took me some time to experiment with it and make it buildable for Windows CE, but now I can tell you how to use it in your Windows CE BSP. I did my porting for Windows CE 8, but it can easily be done also for earlier versions of Windows CE.

More about ACPI in my next article

Interesting links:

http://en.wikipedia.org/wiki/Advanced_Programmable_Interrupt_Controller
https://acpica.org/
http://www.acpi.info/
http://www.uefi.org/


Print | posted on Sunday, March 23, 2014 1:46 PM | Filed Under [ Windows CE Windows Embedded Compact Embedded RTOS APIC ACPI ACPICA ]

Feedback

No comments posted yet.
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 

Powered by: