I've been blogged! - Embedded.com

I’ve been blogged!

GetTickCount keeps on tickin'. Before moving on, Jack responds to some of your comments.

I guess it had to happen: I made it into someone's blog. The comments were not favorable. Now I know how John Kerry must have felt. My public “blogging” (flogging by blog) was in response to my recent columns on the Windows system function, GetTickCount.1,2 I won't paraphrase what was said on the blogs; it's best you read for yourself:

Michael Hall's blog on Microsoft's web site: http://blogs.msdn.com/mikehall/archive/2005/01/28/362498.aspx

Sue Loh, Windows CE expert who works at Microsoft, also has her blog posted on Microsoft's web site:https://blogs.msdn.com/sloh/archive/2005/04/05/405724.aspx

I also received a ton of e-mail in response to the GetTickCount topic. Some folks felt I was entirely too biased against Microsoft. (They should see me when I'm really on a roll.) The main criticisms seem to fall into three categories:

  1. Readers said I was wrong when I said the GetTickCount counter started at 0xffffffff and counted down. That's what a reader told me but it doesn't seem to be true. My bad for not checking.
  2. Readers said I was confusing what classifies as a primitive function, such as GetTickCount, with what is a higher-level system function or application, such as Rpcss.exe. But I am not confused. I mentioned the bug in Rpcss.exe deliberately to illustrate that people seem to be doing something to turn a non-problem into a problem.
  3. Readers said I was overly critical of Microsoft and failed to light my incense with the appropriate level of reverence.

In my February column, I mentioned some of the GetTickCount-related problems that are documented on the Internet.1 I'm including those URLs in the endnotes for completeness.3″7

Noteworthy are these two causes from Microsoft:

  • This problem [in Rpcss.exe] occurs because a call to the GetTickCount timer function causes the function to overflow 49.7 days after the server is started.3
  • This problem [system hangs after 49.7 days] can occur because of a timing algorithm in the Vtdapi.vxd file.4

    These explanations agree nicely with the comments from reader Tom Cannon:

    I recently ran into [the GetTickCount problem] in a Windows 2000 Excel/VBA application. The event triggered runtime error 6 — overflow (if my memory serves me correctly). If activated, the debugger points to the named function.

    Tom and Microsoft seem to agree that there is something associated with an overflow condition as the timer rolls over. We can all agree that the rollover itself is no problem. At least, it shouldn't be. The references to Rpcss.exe and Vtdapi.vxd seem to show, however, that someone has managed to make it a problem. Which was sort of my original point.

    Look, I'm no Windows programmer, CE or otherwise. I don't claim to be, I have no ambition of being. I'm the wrong guy to dig into Microsoft code to find out what's going on (though WinCE expert Sue Loh nicely points out that I could see the code for a sample of the function, if I chose; more on this later in my discussion of the BSP). Consider this a plea to those of you out there who use WinCE and are willing to do some experimentation. I'm particularly concerned about this condition called “overflow.” Does the GetTickCount function trigger a runtime error, as Tom reports? If so, then it's broken. If not, we must look at how the calls to it are (mis)used. Does the operating system set a “sticky bit” error flag as the clock rolls over or not? If it does, it's broken. If not, what does Microsoft's phrase “causes the function to overflow” mean?

    Some folks have pointed out that the problem is probably in the board support package (BSP). This is the software that goes between WinCE and the hardware. Because Microsoft can't anticipate what's in the hardware, they can hardly be expected to write this interface software. So they assume a custom BSP to perform those low-level functions that talk to hardware. One of these functions is GetTickCount.

    Microsoft does supply a representative, plain vanilla BSP, but the OEM is expected to write his own version customized to work with the hardware (for you old-timers out there, remember the CP/M BIOS?)

    Sue and others say that if GetTickCount fails, it's probably because there's a bug in the BSP, put there by the OEM. Therefore not Microsoft's fault.

    Hey, guys, in my world, I am the OEM! We're not building cell phones here, where the units run into the millions. We tend to build one-off hardware, so if anyone is going to write a BSP with its GetTickCount function, guess who it's going to be?

    I can tell you one thing: if I ever do write the GetTickCount function for a WinCE BSP, it will dang well work without bringing the system down.

    How hard can it be?
    If there's one thing I've learned out of this experience, besides staying out of sight of the bloggers, it's this: even as simple an operation as bumping a counter can be fraught with pitfalls. Here's how.

    Imagine that you have a 16-bit single-board computer and the BSP to go with it. The hardware includes a crystal-controlled timer that puts out interrupts every millisecond. Your job, should you choose to accept it, is to write the interrupt service routine (ISR) that bumps a 32-bit counter called CurMSec each time the clock ticks. Seems pretty reasonable. In C, just include the single line:

    ++CurMSec;

    Now write the GetTickCount function:

    Unsigned int GetTickCount( ){	return CurMSec;}

    It seems simple enough. Yet there's plenty that can go wrong, already. The problem is, both the update of the counter and the fetch in GetTickCount absolutely must be atomic or appear so.

    Suppose the current value of the counter is:

    0023 ffff

    Suppose further that your 16-bit CPU is going to fetch the high word first. So you read 0023, as expected. Now, what happens if the clock ticks, and your ISR bumps the counter, before you've read the low word. The counter now reads:

    0024 0000

    But you've already fetched the high word. After you've fetched the low one, you have the value:

    0023 0000

    which is wrong. The clock appears to have run backwards, and you will get the wrong values for any interval you're trying to measure.

    The easiest way to avoid this kind of error is to disable interrupts while executing GetTickCount. I'm told that this is not done in Microsoft's sample BSP.

    You can accomplish the same thing by using the mutual exclusion (mutex) mechanism in the operating system. It strikes me as a roundabout way of doing things; you're ultimately going to end up deferring to the operating system, which is going to disable the interrupts itself as it does its tasking thing. So you get the same result with only 10 or 20 times the overhead, but hey: it's more elegant.

    Et tu, ISR?
    Until recently, I would have sworn that you wouldn't have to worry about similar things on the ISR side. Most CPUs disable interrupts anyhow, when an interrupt comes in. Even if they don't, the clock tick ISR will presumably have a high priority, so it won't get “interrupted” by GetTickCount.

    But fellow columnist Jack Ganssle set me straight on this one. He pointed out the obvious, that my idea was based on the assumption that the timer is incremented in software. This may not be the case. Many real-time CPU boards have built-in hardware timers. In this case, the clock-tick ISR won't actually bump the counter; it only copies the contents of the timer to the RAM variable CurMSec. As before, if you're not copying the word in a single 32-bit transfer, you're back in the soup. What's more, this time disabling interrupts, or using a mutex, is not going to help. The hardware timer is going to tick, interrupts or no interrupts.

    What if we don't have a RAM variable but just assign the name, CurMSec, to the hardware timer? Now we've eliminated the middleman—the RAM variable—but now GetTickCount has to do what the ISR would otherwise do (read the timer) so nothing has changed.

    As if all that weren't enough, many modern, real-time embedded systems these days have sleep modes (think cell phones). The CPU powers down for all but the most essential functions, to save power. The hardware clock presumably keeps ticking, but the CPU isn't paying attention until it's awakened. When it is, the software must somehow get CurMSec back into sync with the hardware clock.

    All in all, it would seem that there is more than enough opportunity to foul this deal up. And, judging from the reported problems, someone has.I won't be saying anything more about GetTickCount unless and until I get some genuine, hard data. If there's anyone out there willing to experiment with the function and find out just what “overflow” means in this context, please don't hesitate to contact me. If there's anyone at Microsoft who wants to weigh in, mi column es su column. Otherwise, we'll be moving on.

    On fear
    I mentioned, in my last column the notion, which I'm still in the process of formulating, that too many of us make our decisions—at least partly—on the basis of fear.2 Not fear of dying, fear of falling, or any of those “night terror” type fears. The kind of fear I'm talking about is simply fear that we might screw up.

    On that note, I have a cautionary tale.

    In my college days, my most cherished ride was a 1940 fastback, 2-door Ford sedan, complete with flathead V-8, dual exhausts, fender skirts, and lowered suspension. It was my pride and joy, until a minor prang (translation: in one door and out the other) sidelined it.

    Since major bodywork had to be done, and I couldn't afford to pay for it, I resolved to do the bodywork myself. While I was at it, I reasoned, I might as well “improve” the car. In my case that involved an act called sectioning. You cut the car clean in two in a horizontal plane, take a section out, drop the top half down, and weld it back together. It's like a chopped top, only more so. Definitely not an act for the faint-hearted.

    My ambition and confidence exceeded my abilities. Whereas one of the California craftsmen would take on such a job with delicacy, using fine tools with surgical precision, I attacked the thing with a cutting torch.

    After much work, the pieces all got back together, and the car even looked great—from a distance. Up close, there were all those grotty welds joining rough and warped edges. Someone had to make the panels smooth again. I decided to try it myself, starting with the smallest panel, the front quarter panel. Getting out a brand new body hammer and dolly, I proceeded to pound the panel back into shape.

    Now, sheet metal is a funny thing. The more you pound it, the thinner it gets. The thinner it gets, the greater its area, and therefore the more it wants to bulge. Body workers call this stretching . They also have a technique, called shrinking , to fix it. Shrinking involves more torch work.

    After hours of hammering, picking, pounding, my quarter panel looked not so much like a body panel, as a relief map of the Himalayas. Time to start shrinking.That's when I discovered that I didn't know how. Somehow, instead of shrinking, the bulges got more and more pronounced. No matter what I tried, things only got worse. In the end, I had to admit my failure as a body man and pay an expert to straighten the car out. It cost a fortune.

    Fast forward to 1985, when my beloved Kaypro computer got bent somewhat out of shape (my wife ran over it). Since the enclosure of the Kaypro was nothing more than a giant Bud Box (two pieces of sheet metal, bent to form a top and bottom), I thought that a good body man could make it all straight again. I removed all the delicate electronic bits and drove with my wife to a body shop specializing in custom work.

    The owner gave me an estimate, which ran well into three digits. When my wife practically fainted, he said, “Look, I can do the paint job for you, but why don't you try straightening the metal yourself? It won't be very hard.”

    What danced in my head that day was not visions of sugarplums, but visions of my beloved computer looking like my Ford quarter panel. I resisted mightily, insisting that I wanted the body man do the work. He kept trying to talk me into doing it, with my wife nodding vigorously in agreement.

    Finally, seeing that I was breaking out in cold sweats and turning ashen, he said, “Ok, I can see that the thought is making you tense. Why don't you go home and give it some thought.”

    On the way home my wife goes, “What the heck was that ?” That's when I realized that, all those years, I had been carrying around some unwanted baggage: the memory of my failure to get that Ford quarter panel smooth again.

    Making that attempt at bodywork, all those years ago, should have left me with, at most, a perfectly rational thought: “Jack doesn't know how to shrink metal; it's something he needs to learn.” But what I took from the experience was far more sweeping, and also wrong: “Jack can't do bodywork.” As in, never could, never will.

    No, it wasn't something I lost sleep over; it didn't occupy my daily thoughts. In fact, I had almost forgotten the incident. Even so, for over 30 years I had been harboring that feeling of failure. And not just failure, but inability. And it was keeping me from doing something I wanted to do.

    To make a long story short, I did do the bodywork on the Kaypro. I got the enclosure straight, and the computer was resplendent (still is) in its many coats of custom purple and white lacquer. But this experience left me wondering what other fears I was carrying around.

    Some of you may know that I once wrote a tutorial series on compiler construction. You probably don't know that this tutorial, too, came from exorcising another fear. For years, I had been fascinated by compiler theory, and longed to be able to write my own compiler. I had bought a dozen texts on the subject, but I was completely bumfuzzled by the odd terminology and notation of the books. With each new book, I hoped that the whole thing would finally come clear, but each time, my hopes were dashed. This only reinforced the notion, “Jack can't do compiler theory.”

    Identifying one's particular demons is the first step in exorcising them. Once I recognized my Fear of Compilers, I resolved to get rid of it once and for all. I picked out one of the texts and tore into it. I treated the exercise as though I were cramming for an exam, and I worked out all the end-of-chapter exercises on my now-resplendent Kaypro. By the end of the first chapter, I found myself thinking, “Wow, this isn't so hard after all.” By the end of the second, it was, “In fact, it's quite easy.” And after the third chapter, it was, “But it's a pity they didn't explain it better.” I never finished the book. I didn't need to. I had already got the idea and was ready to share what I knew. Hence the compiler tutorial.

    After those experiences, I thought I was done with unfounded fears forever. T'aint so. Those sneaky little suckers keep creeping back in when you aren't looking. Lately I've identified two new ones.

    One of my hobbies is antique electronics, as in, vacuum tube hi-fi amplifiers, speakers, and test gear. In another lifetime I built a bunch of Heathkits, and once had a (mono) system that was absolutely state-of-the-art. I still remember the sweet, sweet sound that system emitted. Over the last four or five years, I've been buying up similar components on eBay. I have one room stuffed full of them, and they're now overflowing into two others.

    But you know what? In all this time, I've never once actually hooked them up, put on a record, and played music through them. I just figured out why: I'm afraid I'll find that my memory is clouded by rose-colored headphones. I don't want to discover that the amplifiers, preamps, speakers, and turntables don't sound as good as I remember. I've gotta work on that.

    At home, I have no fewer than six working personal computers—four PC clones, an Apple, and a DEC Alpha. It's true, I recently had at least one hard drive crash on every single one of them, but I've replaced those hard drives and, in the process, increased my storage capacity to close to a terabyte.

    Today, only one of the six sits on my desk, and it doesn't have much in it; no backup files, no archive of articles, no applications beyond Microsoft Office. I do have Partition Magic installed (still my favorite app) and its companion Boot Magic. But the latter does little good, since I only have one operating system loaded (Win2000). I have grandiose plans of loading Linux (maybe two or three versions), old versions of Windows, many C++ and Java compilers, PSpice circuit analysis tools for my Heathkits, and so on and so on.

    But you know what? Since the community disk crash, I haven't done any of that. I mainly do one of two things: surf the web or play Freecell.

    You know why? I'm scared of the $#@$^& thing. Every time recently that I've tried to “improve” it by loading more software, I end up breaking the stupid thing. By this time, I am so frustrated with software (and hardware) that doesn't work reliably, Freecell is the only app I still trust.

    I've gotta work on that.

    No fear
    So what, you ask, does this have to do with you? Simply this. You think you don't have fears? Think again. You may be an Xtreme sportsman—the original No Fear type, with the T-shirt to prove it. You may spend your Saturday mornings deciding whether to go skydiving, motocrossing, rock climbing, or all three. But you say you don't have fears? Tell me again after you've read this equation.

    (1)

    Yep, that's right. Show the average person a math equation and suddenly his bravado melts away like ice cream in August. His face goes blank, his eyes get that doe-in-the-headlight look and, to paraphrase Maggie Thatcher, he “goes all wobbly.”

    Which brings us back to the Rosetta stone. In my next column, we're going to take that little gem apart, examine all the pieces, and put it back together again. We're going to understand it—inside out, upside down, and backwards. I'm not going to rest until I've explained it to you in a way that's impossible not to get.

    I must tell you, I think the derivation of the Rosetta stone equation is the ultimate in cool. We start with the Taylor series, as expressed in Equation 1 (yep, it's for real) and end up with the way-cool result:

    (2)

    If you can agree that Equation 2 looks a lot better than Equation 1, then you can see why I like it so.

    In retrospect, though, I realize that I've done two things wrong. First, I've spent so much time absorbed in the elegance of getting from Equation 1 to Equation 2, I didn't have time left to show you how to use the result. In fact, until recently, I had resolved to skip the derivation this time around and concentrate on how to use the result. One of my readers changed my mind on this, though. He wants to see the derivation, so I'm somehow going to have to do justice to both derivation and application.

    Second, the thought of starting at Equation 1 seems less and less like a good idea. After all, I just used it as the ultimate example of things that make people go all wobbly. Why in the world did I ever think you wouldn't? And clearly, if you don't get Equation 1, you're not going to believe what happens to it later. Now I see that I have to start way further back, to something that you can accept as fact. It's not going to be either easy or fast, but I think we'll all be better for the experience.

    See you then.

    Jack Crenshaw is a senior software engineer at Spectrum-Astro and the author of Math Toolkit for Real-Time Programming , from CMP Books. He holds a PhD in physics from Auburn University. E-mail him at .

    End notes

    1. Crenshaw, Jack. “Time to Re-Evaluate Windows CE?” Programmer's Toolbox, Embedded Systems Programming , February 2005, p.9.
    2. Crenshaw, Jack. “From Time, Wisdom,” Programmer's Toolbox, Embedded Systems Programming , April 2005, p.9.
    3. http://support.microsoft.com/default.aspx?scid=kb;en-us;823273
    4. http://support.microsoft.com/kb/q216641/
    5. http://support.microsoft.com/default.aspx?scid=kb;en-us;318152
    6. http://support.microsoft.com/kb/169847/EN-US/
    7. www.spectrum.ieee.org/WEBONLY/resource/nov04/1104nair.html
  • Leave a Reply

    This site uses Akismet to reduce spam. Learn how your comment data is processed.