embedded software boot camp

Novel uses for RTC registers

Sunday, December 4th, 2011 by Nigel Jones

For obvious reasons, I usually write about things that are widely applicable. Today I’m going to deviate from this slightly and talk about the real time clock registers / RAM that are available on some (many?) ARM processors as well as I suspect a number of other architectures. An excerpt from the NXP data sheet is shown in the figure below.

NXP LPC17xx RTC registers

Of most interest is the column labeled ‘Reset Value’. You will notice that the values highlighted in red are ‘NC’. ‘NC’ means that the registers are unaffected by a reset condition. Furthermore, these particular registers may also be powered from an alternate power source such that they are also unaffected by loss of power. So why is this useful? Well I have found a couple of uses for them beyond the obvious and intended applications of maintaining date and time (for the RTC registers) and for providing non-volatile R/W storage for the General Purpose registers.

Communicating with the Bootstrap loader

Most embedded applications today contain a bootstrap loader (BSL). Although there are several ways of entering the BSL from the main application, the most common that I see is to force a watchdog reset, resulting in the CPU rebooting and starting up in the BSL. This technique is pretty good and I use it all the time. However I usually find it necessary for the main application to communicate some information to the BSL. For example, at a minimum the BSL needs to know that it has been intentionally entered for the purposes of performing a firmware update (as opposed to being entered as a result of a genuine watchdog failure). Under some circumstances I also need to pass other information to the BSL such as the port that initiated the update. In the past I have tended to pass this information via EEPROM. However with these registers available to me, I now use them for this task.

Debugging

If you are plagued with your system taking unexpected resets, then it’s a relatively trivial matter to write some debug code that writes context information to these registers. For example most RTOS provide mechanisms for calling user functions prior to performing a task switch. Within this function it’s trivial to write the task ID to one of these registers. Then it’s just a matter of putting a breakpoint on the entry into main() to discover which task was running when the reset occurred. Once you have it narrowed down to a task, you can then instrument functions in a similar manner.

I suspect I may find other uses for these registers in the future. Suffice to say I’d really like it if this feature became widespread across all processor families.

14 Responses to “Novel uses for RTC registers”

  1. Anonymous says:

    What a gloriously embedded-geeky post.

    And how many times have I passed the same way!

    I have some pretty comprehensive stuff for the MSP430 which allows you to know where you left your blanket when the processor restarts.

    The “most obvious” candidate for this treatment is the alarm registers in a std. RTC – but I would always be wary that some BIOS nurd thought they ought to be zeroed.

  2. Martin says:

    To switch from App to BSL with some info I am using this procedure:
    1. prepare HW to switch to BSL,
    2. indicate intention for BSL to keep running by something that is not usual like zeroing the StackPtr register,
    3. enter info for BSL in register or RAM,
    4. jump to BSL which then starts from scratch like after reset, gets the info, init StackPtr, init HW, ….

    I don’t use reset for CPU. I think reset should occur when SW (or HW) fails.
    BSL and App are considered to be 2 independent applications that can be switched between.

    I am interested why would you wear out eeprom just to switch to BSL. It seems to me like it have some sense but I don’t see one.

    Here is one use for these battery backedup registers in RTC:
    – preserve coulomb counter state in BatteryMgmt App.

    • Nigel Jones says:

      I like the reset approach because it guarantees a known HW configuration. In your approach you have to write code that ensures the HW configuration – which is fine right up until someone enables a new peripheral and forgets to update the BSL entry code. As for wearing out EEPROM: EEPROM today typically has 100,000 guaranteed erase cycles. Even on a really bad day I don’t come close to needing to update my code that many times :-).

  3. Anonymous says:

    I have done a similar “hack” on Freescale HCS08/HCS12 MCUs. Apparently they maintain a stable supply voltage to the RAM cells during watchdog reset, so I just reserve a chunk of memory in RAM which the compiler isn’t allowed to fiddle with. If the reset source is power-on, then I clear this chunk of memory. If the reset source is the watch dog, then I check whether there is data in that memory or not. If there is data, the program should enter “bootloader mode”. If there isn’t, ignore it and run as usual.

    This is quite undocumented however, and probably not something that should be used 🙂 But I have done stress tests on the Freescale MCU where I just reset it, and check the integrity of the RAM cells with a CRC16 upon reset. Works just fine in 100% of the cases. You didn’t hear it from me.

    • Nigel Jones says:

      I’ve done the same in the past. Like you I was a little (OK – a lot) concerned that I was relying on undocumented behavior. However, provided you can beat the linker into submission and provided someone doesn’t do a destructive RAM test on reset you should be OK.

  4. Daryl says:

    Why don’t processors have an instruction or register that causes a commanded (and immediate without having to wait for the watchdog or reprogram the watchdog) reset for a reason other then watchdog and reports itself as such in the reset causes register enumerated such as:

    enum ResetCauses {
    RESET_CAUSE_POR, ///< power on reset
    RESET_CAUSE_EXT, ///< external reset pin
    RESET_CAUSE_WDT, ///< watchdog timer reset
    RESET_CAUSE_COMMANDED, ///< commanded reset

    };

    I found that waiting for the watchdog is not always what I want and if I reprogram the watchdog to something short it will cause infinite resets if your app doesn't make it to reprogramming it back in time, perhaps due to oscillator startup time or other c_init delays.

    Really, how hard is it to include a register which when you write to it performs an immediate reset?

    • Daryl says:

      To add to that idea it would be nice if this commanded reset register also contained a few extra bits to indicate a user defined reason value. So if you reset and see it was commanded you can also read the reason enumeration. Essentially a byte of non-volatile ram that is preserved across resets.

    • tol says:

      The need for a software initiated reset is common in most systems and I am sure that many people have wondered the same thing like you- and so have I. But if time is your issue, you don’t actually have to wait for your watchdog to time out for a reset, you can actually trigger it there and then with – for example – a password violation when writting to the watchdog regs, or flash etc.

      • Nigel Jones says:

        Really? I can’t say I have ever tried that; it does sound interesting though.

      • Daryl says:

        Clever, except again this is using some ‘trick’ to achieve what should be a basic feature for any MCU, to be able to command a reset intentionally that the processor recognizes as an intentional reset with user enumerated cause. Really, let’s just keep this obvious and to the point. You want to reset and you get a byte to tell yourself why. Justification for such a simple thing should be obvious to any chip designer. I mean what percent of embedded code out there uses a watchdog reset to do something that really should be done using a facility like this? >90 for sure.

  5. Great post. I had to do something similar on our i.MX31 design. We were having a problem where after a power down, if you waited between .5 and 2 seconds before powering up, the MX31 would lock up.

    Eventually I traced it back to the first AVIC access. The AVIC requires the processor to be in a privileged mode or else it would error out, and at that point our bootloader wasn’t awake enough to handle the error appropriately, so it just looked like it locked up.

    Our boot loader absolutely placed the ARM core into a priv. mode, but to confirm I wrote a couple of test functions. One set of functions managed two mini-counters in registers preserved by the PMIC ( it was tied to a backup battery). One counter incremented before the AVIC accesses, the second counter incremented after the AVIC accesses. So that way I could bracket the failure point.

    The second set of functions created what I called a mini-queue within one register. The priv. mode bit was in the last 8 bits of the CPSR register. I would take the previous value of the “queue “(a 24 bit register), shift it over 8 bits, and OR in the last 8 bits of the CPSR. This way I could see the status of the CPSR the last three times I booted.

    Long story short, the CPSR was set to the correct value. It turned out that due to a long discharge on the DDR memory power rail (~.6V between the .5 to 2 second window), the AVIC was not receiving the proper CPSR mode status. We replaced a decoupling cap on the DDR rail with a 1k resistor (basically a pulldown) and the problem was never seen again.

    Freescale and I could never root cause the reason for the failure, but I suspect that a silicon designer had inadvertantly used the DDR supply for a flop between the processor and the AVIC, which latched up when the power supply dropped to .6 and came back to 1.8v.

    I can post code if anyone is interested.

Leave a Reply to Martin

You must be logged in to post a comment.