views:

76

answers:

3

I need to implement the following feature for my device running embedde linux on a 200mhz MIPS cpu: 1) if a reset button is pressed and held for less then a second - proceed with reboot 2) if a reset button is pressed and held for at least 3 sec. - restore the system's configuration with default values from NVRAM and then reboot.

I'm thinking of two ways: 1) a daemon that constantly polls the button's state with proper timings via GPIO ioctls (likely too big overhead, lots of context switching ?) 2) simple char driver polling the button, measuring timings and reporting the state, for example, via /proc to user space where daemon or a shell script can check and do what's required.

And for both cases I have no idea how to measure the time :( What would you suggest/recommend?

+2  A: 

You have to implement those in hardware. The purpose of the "restore defaults from NVRAM" is to restore a so-called "bricked" device.

For example, what if an NVRAM seting is modified (cosmic ray?) such that the device cannot boot? In that case, your proposed button-polling daemon will never execute.

For the one-second held reboot, use an RC (resistor + capacitor) circuit to "debounce" the button press. Select an RC time constant which is appropriate for the one second delay. Use a comparator watching the RC voltage to signal the RESET pin on the MIPS cpu.

For the three-second press functionality (restore NVRAM defaults), you have to do something more complicated, probably.

One possibility is to put a tiny PIC microcontroller into the reset circuit, but only use a microcontroller with fuse (non-erasable) ROM, not NVRAM.

An easier possibility is to have a ROM containing defaults on the same circuit and bus as the NVRAM. A J/K flip-flop latch can become part of your reset circuitry. You'll also need a three-second-tuned RC circuit and comparator. On sub-three-second presses, the flip-flop should latch a 0 output and on three-second-plus presses, the 2nd RC circuit should trigger the comparator after 3 seconds and present a 1 to the J/K latch, which will toggle its output.

The flip-flop output Q will store the single bit telling your circuit whether this reset cycle was subsequent to a three-second push. If so, that output Q is driving the chip select to the NVRAM and Q* is driving the chip select to ROM. (I assume chip select is negative logic on both NVRAM and ROM chips.)

Then when your CPU boots, it will fetch the settings from either the NVRAM or the ROM, depending on the chip select line.

Your boot code can detect that it booted with ROM chip select, and can later reset the J/K flip-flop with a GPIO line. Then the CPU will be able to write good values back into the NVRAM. That unbricks the device, hopefully.

You want to use ROM that is not erasable or reusable. That kind of ROM is the most resistant to static electricity, power supply trouble, and radiation. Radiation is much more present than we generally realize, and the amount of cosmic ray flux is multiplied by taking a device onboard an airliner, for example.

Heath Hunnicutt
+1  A: 

I am not familiar with the MIPS processor and the GPIO/interrupt capabilities of the pin that you could be using but a possible methodology could be as follows.

  1. Configure the input pin as an interrupt input.
  2. When the interrupt fires disable the interrupt and start a short 100ms-ish timer
  3. When the timer triggers check that the button is still pressed (for debounce). If it is not then re-enable the GPIO interrupt and restart, otherwise set the timer to re-trigger after the 3 second timeout.
  4. When the timer triggers this time then if the button is not pressed then do your reboot otherwise reset the system configuration and reboot.

If the pin cannot provide an interrupt then step 1 will be a polling task to look at the input.

The time between the reset button being pressed and the full reset process being run will always be 3 seconds from a debounced button press. In a reset situation this may not be important particularly if as part of step 3 you make it apparent to the user that a reset sequence has started - blank the display for example.

Ian
A: 

If you want to do this in software, you need to put this in kernel (interrupt) code, rather than in a shell script or daemon. The better approach would be to put this in hardware.

In my experience, the likely reason for resetting the device will be bad user code which has locked or bricked the processor. If the issue is a corruption of memory due to RF energy or something of that nature, you may require hardware or an external (hardened) processor to reflash the device and fix the problem.

In the bad-user-code case, processor interrupts and kernel code should continue to run, while user code may be completely stalled. If you can poll the pin from an interrupt, you stand a much better chance of actually getting the reset you expect. Also, this enables you to do event-driven programming, rather than constantly polling the pin.

One other approach (not to the specs you listed, but a popular method for achieving the same goal) would be to have the startup routines check a GPIO line, and hold a button down when you want to re-initialize the device. On most embedded Linux devices which I've seen, the "Reset" button is wired to a dedicated reset pin on the microcontroller, and not to a GPIO pin. You may have to go with this route, unless you want to start cutting traces.

reemrevnivek