AM335x recovery

From eLinux.org
Jump to: navigation, search


AM335x recovery

This page is how to recover ("unbrick") a broken/non-booting device that uses an AM335x processor. It should help you if you messed your boot configuration and doesn't boot any more the normal way ("bricked").

Booting scheme

The processor starts by executing rom code that is hard-wired into its processor. That code will in turn fetch and execute external code, typically a bootloader like u-boot. The peripherals(eMMC, microSD, NAND, etc) it tries to boot from and the order in which it does it is device dependent.

If it finds valid code, it will execute it, else it will continue looking for valid code on the next peripheral in the boot order.

What it consider valid is documented more formally in the technical reference manual of the AM335x.


Recovery image constraints

According to the technical reference manual: "The boot image is downloaded directly into internal RAM at the location 0x402F0400 on GP devices. The maximum size of downloaded image is 109 KB."

BeagleBone Green

If the 'USER' button isn't pressed, the device will try to boot from: eMMC -> microSD -> UART -> USB

If the 'USER' button is pressed, it will instead try this order: SPI -> microSD -> USB -> UART.

Since we want to recover a non-booting device, and that the device boots first on the eMMC, we want it not to try the eMMC as it could load non-working code from there.

So during recovery, we will have to press the 'USER' button to switch the order to:

SPI -> microSD -> USB -> UART.

MMC recovery

The Beagle Board Recovery MMC instructions might be a useful starting point. In the case where it doens't work, it might be a good idea to compare them with what is in the AM335x technical reference manual.

BeagleBone Green USB recovery

When booting from USB, the processor will be presented as an RNDIS peripheral. It will then try to get an IP address trough the BOOTP protocol, and finally fetch and execute the bootloader trough TFTP.

So we will need to setup a BOOTP and TFTP server, we will use a GNU/Linux computer and dnsmasq to do that.

To make the device expose an RNDIS interface:

  • Remove the MicroSD card if there is one
  • Make sure the device is powered off
  • Plug the USB cable to the device but not to the computer yet
  • Press the the 'USER' button, and keep pressing it
  • Plug the USB cable: This will power up the device
  • Release the 'USER' button

Now an RNDIS network interface will appear on the GNU/Linux computer. Unfortunately if we unplug the USB cable, the RNDIS network interface will disapear.

This isn't very convenient as we need to setup a BOOTP and TFTP server, and we can't make dnsmasq listen on a inexisting interface. We also might not want to listen on all interfaces not to interfer with the rest of the system.

To handle this issue we can create a bridge network interface with the following commands:

# ip link add name am335x type bridge
# ip link set dev am335x up

And then add the following content in /etc/udev/rules.d/01-beaglebonegreen.rules:

SUBSYSTEM=="net", ACTION=="add", ATTRS{idProduct}=="6141", ATTRS{idVendor}=="0451", RUN+="/usr/bin/ip link set dev $name master am335x", RUN+="/usr/bin/ip link set dev $name up"

This will make the RNDIS interface join the bridge when it appears under the GNU/Linux computer.

Now we can use dnsmasq to make a BOOTP and TFTP server.

Now we will create the dnsmasq.conf configuration file with the following content:

no-daemon
interface=am335x
except-interface=lo
bind-interfaces
enable-tftp
bootp-dynamic
dhcp-script=/bin/echo
# Settings you might want to change:
dhcp-range=192.168.4.2,192.168.4.255,12h
dhcp-option=121,192.168.4.1
# You must change, at least the tftp-root, to the directory where the code to load resides
dhcp-boot=start_am33xx_beaglebone_sram.pblx
tftp-root=/home/gnutoo/work/devices/seedstudio/beaglebone-green/barebox/images/

In the configuration file above:

  • We will tell the device to load and execute the file named start_am33xx_beaglebone_sram.pblx in /home/gnutoo/work/devices/seedstudio/beaglebone-green/barebox/images/. Change it to make it load the code you want.
  • We use the 192.168.4.1 IP address, you might need to change it if this IP range is already used in your local network.

Finally setup the network interface IP address and start dnsmasq:

# ip addr add 192.168.4.1/24 dev am335x
# dnsmasq --conf-file=./dnsmasq.conf

It is also a good idea to start tshark to see what is going on:

# tshark am335x

Now that everything is ready, we can start the device by:

  • Makeing sure the device is powered off
  • Pluging the USB cable to the device but not to the computer yet
  • Pressing the the 'USER' button, and keep pressing it
  • Pluging the USB cable: This will power up the device
  • Releasing the 'USER' button

The device will now configure itself trough BOOTP and start downloading the code.

Building a recovery image

Clone barebox:

$ git clone git://git.pengutronix.de/barebox

Copy the following configuration in .config:

CONFIG_ARCH_OMAP=y
CONFIG_OMAP_BUILD_IFT=y
CONFIG_OMAP_MULTI_BOARDS=y
CONFIG_MACH_BEAGLEBONE=y
CONFIG_THUMB2_BAREBOX=y
# CONFIG_LOCALVERSION_AUTO is not set
# CONFIG_MEMINFO is not set
CONFIG_MMU=y
CONFIG_TEXT_BASE=0x0
CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
CONFIG_RELOCATABLE=y
CONFIG_PROMPT="barebox> "
CONFIG_SHELL_SIMPLE=y
CONFIG_CMDLINE_EDITING=y
# CONFIG_TIMESTAMP is not set
CONFIG_BOOTM_INITRD=y
CONFIG_BOOTM_OFTREE=y
CONFIG_CONSOLE_SIMPLE=y
CONFIG_PBL_CONSOLE=y
CONFIG_PARTITION=y
# CONFIG_DEFAULT_ENVIRONMENT is not set
CONFIG_POLLER=y
# CONFIG_CMD_ARM_CPUINFO is not set
# CONFIG_CMD_DEVINFO is not set
# CONFIG_CMD_DRVINFO is not set
CONFIG_LONGHELP=y
# CONFIG_CMD_VERSION is not set
# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
# CONFIG_CMD_MOUNT is not set
# CONFIG_CMD_UMOUNT is not set
CONFIG_CMD_NV=y
CONFIG_CMD_GLOBAL=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
# CONFIG_CMD_CAT is not set
# CONFIG_CMD_CD is not set
# CONFIG_CMD_CP is not set
# CONFIG_CMD_MKDIR is not set
# CONFIG_CMD_PWD is not set
# CONFIG_CMD_RMDIR is not set
# CONFIG_CMD_FALSE is not set
# CONFIG_CMD_TRUE is not set
CONFIG_CMD_DHCP=y
CONFIG_CMD_TFTP=y
# CONFIG_CMD_CLEAR is not set
# CONFIG_CMD_ECHO is not set
# CONFIG_CMD_MD is not set
# CONFIG_CMD_MEMCMP is not set
# CONFIG_CMD_MEMCPY is not set
# CONFIG_CMD_MEMSET is not set
# CONFIG_CMD_MW is not set
CONFIG_CMD_DETECT=y
CONFIG_NET=y
CONFIG_OFDEVICE=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
CONFIG_DRIVER_NET_CPSW=y
CONFIG_SMSC_PHY=y
# CONFIG_SPI is not set
CONFIG_MTD=y
# CONFIG_MTD_WRITE is not set
# CONFIG_MTD_OOB_DEVICE is not set
CONFIG_PINCTRL_SINGLE=y
CONFIG_BUS_OMAP_GPMC=y
CONFIG_RESET_CONTROLLER=y
CONFIG_FS_TFTP=y

Setup the cross compiler:

$ export ARCH=arm
$ export CROSS_COMPILE=arm-none-eabi-

Note that the CROSS_COMPILE variable value (arm-none-eabi-) might change depending on the arm compiler you have installed.

Then compile it:

$ make

You then have an image in images/start_am33xx_beaglebone_sram.pblx

To use this image, connect an Ethernet cable between your laptop and the BeagleBone, and setup a DHCP and TFTP server again, similarly to what was done before, then copy it in the tftp root directory.

After making sure that the cross-compiler is setup correctly, as done previously, you can build again a full barebox image with:

make am335x_defconfig
make

The image will be available in images/barebox-am33xx-beaglebone.img Put that image in the tftp root directory and witin barebox run:

> dhcp

It will then obtain an IP address, this will look like that:

T DHCP client bound to address 192.168.4.125

Then download the full barebox:

> tftp barebox-am33xx-beaglebone.img

It will then show a progress bar like that:

	[#################################################################]

And finally execute the full barebox:

> bootm barebox-am33xx-beaglebone.img

At this point you can, for instance put some image in the tftp root directory and use the new barebox to write to it like that:

> dhcp
> tftp sd.img /dev/mmc1

You can easily create such image on your host computer with qemu-img:

$ qemu create -f raw sd.img 3G

And partition it as a normal micro-SD card:

$ fdisk sd.img

And then enable access to its partitions:

$ sudo kpartx -a sd.img

which will then appear in in paths like /dev/mapper/loop0p1 and /dev/mapper/loop0p2, that you can format as usual, for instance like that:

$ sudo mkfs.vfat -n BOOT /dev/mapper/loop0p1
$ sudo mkfs.ext4 /dev/mapper/loop0p2

And for instance if you want barebox, you can copy it in them:

$ sudo mkdir -p /mnt/boot
$ sudo mount /dev/mapper/loop0p1 /mnt/boot
$ cp images/barebox-am33xx-beaglebone-mlo.img /mnt/boot/MLO
$ cp images/barebox-am33xx-beaglebone.img /mnt/barebox.bin