In this post I’ll explain how to debrick the CORE 9G25 on a Linux machine. This post is the second in a series of series posts. I highly recommend to read the previous post before continuing. In that post I explained how the boot process works, how the update procedure works and the layout of the NAND. This post will be about debricking the NAND using SAM-BA on a Linux machine.
In the previous post I explained that the ROM code of the CPU contains a program called SAM Boot Agent (SAM-BA). This program can be used to reflash the NAND.
In order to interact with this program in ROM from your Linux machine you need a tool. This tool is also called SAM-BA and you can download it from Microchip’s website. For this post I used SAM-BA 3.2.1. If I refer to SAM-BA in this post I mean the Linux program unless stated otherwise.
SAM-BA comes with little programs, called applets, to interact with external
flash or memory. SAM-BA supports different pieces of hardware. The applets
available depends on the board. You can list all supported boards by running
sam-ba -d <board> -a help.
$ ./sam-ba -b sam9xx5-ek -a help No port option on command-line, using 'serial'. Known applets: lowlevel, extram, sdmmc, serialflash, nandflash
An applet can be loaded using the
-a flag and most applets will print an help
text if you run the applet with the
help parameter. Below you find the
documentation of the
$ ./sam-ba -b sam9xx5-ek -a nandflash:help Syntax: nandflash:[<ioset>]:[<bus_width>]:[<header>] Parameters: ioset I/O set bus_width NAND bus width (8/16) header NAND header value Examples: nandflash use default board settings nandflash:2:8:0xc0098da5 use fully custom settings (IOSET2, 8-bit bus, header is 0xc0098da5) nandflash:::0xc0098da5 use default board settings but force header to 0xc0098da5 For information on NAND header values, please refer to SAM9xx5 datasheet section "10.4.4 Detailed Memory Boot Procedures".
Most applets can be used in conjunction with zero or more commands using the
-c flag. To read the first 1024 (or 0x400 hexadecimal) bytes of the NAND, for
example, you can use the
read command like below.
$ ./sam-ba -p serial -b sam9xx5-ek -a nandflash -c read:file.bin:0x0:0x400
All supported commands of an applet can be listed by issueing the
command. The next snippet shows the command that implemented by the
$ ./sam-ba -b sam9xx5-ek -a nandflash -c help No port option on command-line, using 'serial'. * erase - erase all or part of the memory Syntax: erase:[<addr>]:[<length>] Examples: erase erase all erase:4096 erase from 4096 to end erase:0x1000:0x10000 erase from 0x1000 to 0x11000 erase::0x1000 erase from 0 to 0x1000 * read - read from memory to a file Syntax: read:<filename>:[<addr>]:[<length>] Examples: read:firmware.bin read all to firmware.bin read:firmware.bin:0x1000 read from 0x1000 to end into firmware.bin read:firmware.bin:0x1000:1024 read 1024 bytes from 0x1000 into firmware.bin read:firmware.bin::1024 read 1024 bytes from start of memory into firmware.bin * verify - verify memory from a file Syntax: verify:<filename>:[<addr>] Examples: verify:firmware.bin verify that start of memory matches firmware.bin verify:firmware.bin:0x1000 verify that memory at offset 0x1000 matches firmware.bin * verifyboot - verify boot program from a file Syntax: verifyboot:<filename> Example: verify:firmware.bin verify that start of memory matches boot program firmware.bin * write - write to memory from a file Syntax: write:<filename>:[<addr>] Examples: write:firmware.bin write firmware.bin to start of memory write:firmware.bin:0x1000 write firmware.bin at offset 0x1000 * writeboot - write boot program to memory from a file Syntax: writeboot:<filename> Example: writeboot:firmware.bin write firmware.bin as boot program at start of memory
Connect your Linux machine to the serial debug port of the device. I’ve used this USB-to-serial cable.
Before I continue I often use Minicom to validate if the serial connection is
working. Start Minicom and configure the serial port with the settings below.
You can open the settings menu by pressing
Ctrl-a and then
o (the letter,
not the number).
- baudrate: 115200
- parity: none
- bytesize: 8
- stopbits: 1
Reboot the CPU. When you see human readable data in Minicom the serial port has been configured correctly. You probably should at least see the string “romboot”.
If you don’t see anything, you probably need to switch your Rx and Tx lines.
When Minicom prints garbage it’s likely that the settings on either end of the serial line doesn’t match. You probably have to change Minicom’s configuration.
Boot from ROM
If your serial connection has been set up it’s time to fix debrick the NAND. The ROM of the AT91SAM9G25 contains a program which is also called SAM-BA, SAM-BA on your Linux machine interacts with SAM-BA on the ROM via the serial connection.
In order to boot from ROM the BMS pin must be
1. The BMS pin can be brought
1 by shortening the marked 2 islands on the picture below.
Before you continue make sure that you’ve closed Minicom! Only 1 program at the time can use serial line.
Enable the BMS pin while rebooting the device; the device will boot SAM-BA program that is from ROM.
Now bring the BMS pin back to
0. This is important! I took me 2 days to
discover that the BMS pin must set back to
0 in order to execute most of the
Validate that SAM-BA detects the serial port by running:
$ ./sam-ba --port help Known ports: serial, j-link
Before you can write anything to the NAND flash the RAM must be initialized.
This can be done by using the
$ ./sam-ba -p serial -b sam9xx5-ek -a extram Opening serial port 'ttyUSB0' Connection opened. Compatible device detected: SAM9G25. Connection closed.
Now it’s time to to use the
nandflash applet. Before writing a segment of the
NAND you should erase the existing content. This can be done using the
command. Then you can write a file to the NAND. You can use the either the
writeboot or the
write command. The first command is for writing
a bootloader to the first segment of the NAND. The latter is for writing other
The command in the next snippet loads the
nandflash applet, erases the first
0x40000 bytes from the NAND and then uses the
writeboot command to write the
at91sam9x5ek-nandflashboot-uboot-3.5.3.bin to the NAND. No offset is
given, so AT91Bootstrap is written to address
The next snippet shows to write AT91Bootstrap to the NAND using the
$ ./sam-ba -p serial -b sam9xx5-ek -a nandflash -c erase:0x0:0x40000 -c writeboot:at91sam9x5ek-nandflashboot-uboot-3.5.3.bin Opening serial port 'ttyUSB0' Connection opened. Compatible device detected: SAM9X25. Detected memory size is 268435456 bytes. Page size is 2048 bytes. Buffer is 131072 bytes (64 pages) at address 0x2000a000. NAND header value is 0xc0c00405. Supported erase block sizes: 128KB Executing command 'erase:0x0:0x40000' Erased 131072 bytes at address 0x00000000 (50.00%) Erased 131072 bytes at address 0x00020000 (100.00%) Executing command 'writeboot:at91sam9x5ek-nandflashboot-uboot-3.5.3.bin' Prepended NAND header prefix (0xc0c00405) Appending 1776 bytes of padding to fill the last written page Wrote 16384 bytes at address 0x00000000 (100.00%) Connection closed.
This next snippet shows how U-Boot is written to the NAND. Again, the
applet is loaded and a segment of the NAND is cleared. This time the segment
has an offset of
0x40000 bytes and it’s size is
0x80000 bytes. The file
u-boot.bin is written to the NAND with using that same offset of
bytes. The offset and size of the segment corresponds with the numbers found in
the output of the update that is part of the previous post.
$ ./sam-ba -p serial -b sam9xx5-ek -a nandflash -c erase:0x40000:0x80000 -c write:u-boot.bin:0x40000 Opening serial port 'ttyUSB0' Connection opened. Compatible device detected: SAM9G25. Detected memory size is 268435456 bytes. Page size is 2048 bytes. Buffer is 131072 bytes (64 pages) at address 0x2000a000. NAND header value is 0xc0c00405. Supported erase block sizes: 128KB Executing command 'erase:0x40000:0x80000' Erased 131072 bytes at address 0x00040000 (25.00%) Erased 131072 bytes at address 0x00060000 (50.00%) Erased 131072 bytes at address 0x00080000 (75.00%) Erased 131072 bytes at address 0x000a0000 (100.00%) Executing command 'write:u-boot.bin:0x40000' Appending 940 bytes of padding to fill the last written page Wrote 131072 bytes at address 0x00040000 (29.63%) Wrote 131072 bytes at address 0x00060000 (59.26%) Wrote 131072 bytes at address 0x00080000 (88.89%) Wrote 49152 bytes at address 0x000a0000 (100.00%) Connection closed.
Now you only have to write the device tree, Linux kernel and root filesystem and your CORE 9G25 is working again.
It took me days to figure it all out, but in the end the debrick procedure of the CORE 9G25 turned out to be quite simple. I learned a lot while figuring it out and writing these posts. I hope you learned something too. And I hopefully saved you a little bit of time.