u-boot select boot partition based on GPIO state

5.7k views Asked by At

I'm developing a recovery mechanism on a embedded system. I want to boot into recovery mode if user pressed a GPIO button. Recovery mode means selecting different kernel and root partition than usual. I got stuck on using gpio value in conditional command. If I write if gpio input 20; then cmd; fi cmd will always run because gpio returns error status not the value of GPIO. How can I get the value?

Is it feasible to use U-Boot commands to implement boot selection (I need to blink LEDs for 15s and if the user presses the button for at least 5s then switch to recovery). Would it be easier to implement this logic in C code? If so where to look and are there any examples?

In general providing recovery system seems like a common task for an embedded engineer. What are the best practices in this scenario? What is the most common way of implementing this? I could not find any help or guidelines on the web.

1

There are 1 answers

2
jcc273 On BEST ANSWER

Recovery may depend on what your system has available to you, and how robust you need to be. Remember to always keep everything you can read-only and seperated it from stuff that is writeable. Keep writeable stuff in a different partition in your NAND or wherever. Your method described above will get you back and running if the kernel/FS is bad. Which may be all you need. If you ever plan on allowing the updating of U-Boot itself then you may also want to consider the possibility of U-Boot getting corrupt when rewritten and have a way to recover.

Alot of the embedded processor's have a boot order defined by pins you pull one way or the other on start. A favorite method of mine is to connect a button to one of these that user can hold on power up to change the boot order (say from NAND to SD) and boot from another device that can then restore the system.

For your situation above it is definitely possible to check a gpio, flash an LED etc. from U-Boot. You can use U-Boot commands:

if gpio input 63; then 
    gpio toggle 52; "
    sleep 1; 
    gpio toggle 52; 
    sleep 1;
fi;

Or you can do it directly in the U-Boot C Code somewhere if you prefer, such as in your own U-Boot Command that would be compiled with U-Boot:

gpio_request(GPIO_LED2, "ind_led2");
gpio_request(GPIO_LED3, "ind_led3");
while(1) {
    gpio_direction_output(GPIO_LED1, 1);
    gpio_direction_output(GPIO_LED2, 0);
    gpio_direction_output(GPIO_LED3, 1);
    udelay (500000);        //Wait 500ms
    gpio_direction_output(GPIO_LED1, 0);
    gpio_direction_output(GPIO_LED2, 1);
    gpio_direction_output(GPIO_LED3, 0);
    udelay (500000);        //Wait 500ms
}

If you are getting errors running gpio commands from U-Boot make sure you have the gpio command stuff enabled, with the following in your config file:

#define CONFIG_CMD_GPIO

If it still doesn't work then make sure U-Boot has drivers for GPIO on your part (which i can't imagine it doesn't).