I wrote a driver for CE 3.0. In it I used the following API call:
This worked well on CE 3.0. I used this in an Interrupt Service Thread (IST) and did some measurements with an oscilloscope to ensure that the my IST was getting called soon after the interrupt was raised.
We moved to CE .NET 4.2 and I did some very basic (i.e. skimpy) testing of the driver. It worked. At the time we made the switch I was worried that I would be unable to hook the interrupt in the same way I had in CE 3.0 using
InterruptInitialise(). I did not worry about other issues. I assumed that
SetThreadPriority() worked the way that it had in CE 3.0
Boy, was I wrong!
Our CE .NET software started having problems as we pushed the software harder so we started looking at a number of design decisions, especially with regard to our driver. We hooked the scope back up and discovered the interrupt performance to be terrible. The IST was getting kicked off anywhere between 30 and 400 micro-seconds after the interrupt. The IST takes between 50 and 250 micro-seconds to do its work. And this interrupt goes off every 500 micro-seconds. I hadn’t changed the IST scheduling code form CE 3.0 to CE .NET 4.2 so I was getting worried. And then I noted the small print in the documentation for
SetThreadPriority() in the Ce .NET 4.2 documentation:
Note The priority levels zero through 7 that were available in earlier versions of Windows CE are now mapped to priority levels 248 through 255.
So that was it. My priority zero was being mapped to priority 248. No wonder the IST latency sucked so badly.
The answer is to use the
CeSetThreadPriority() API call. This does not remap the thread priorities. Making this switch reduced the worst case latency from 400 usec to 130 usec. Other changes and a rebalencing of the workload in the interrupts changed the IST execution time from 250 usec down to 150 usec. Performance is improved and more reliable.