AM335x
Prepare card
To make sure everything will run without problem wipe all data on the MMC:
$ sudo dd if=/dev/zero of=/dev/sdx bs=1k count=1024
Format the disk:
$ sudo fdisk /dev/sdx << __EOF__ > n > > > > > w > __EOF__
Make ext4 filesystem
$ sudo mkfs.ext4 -F -O ^metadata_csum,^64bit /dev/sdx1
NOTE: You MUST replace /dev/sdx with your device, e.g. /dev/sdc.
Cross compiler
In this tutorial gcc 5.4.0 is used:
$ arm-linux-gnueabihf-gcc --version arm-linux-gnueabihf-gcc (Debian 5.4.0-6) 5.4.0 20160609 Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
On Ubutuntu/Debian run:
$ sudo apt-get install gcc-5-arm-linux-gnueabihf
Optionally download toolchain from here. For example:
$ wget https://releases.linaro.org/components/toolchain/binaries/latest-5/arm-linux-gnueabihf/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabihf.tar.xz $ tar -xf gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabihf.tar.xz -C /opt
Then export to PATH:
$ expot PATH=$PATH:/opt/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/bin/
U-Boot
Building U-Boot
Get sources with:
$ git clone git://git.denx.de/u-boot.git $ cd u-boot
The patch is built against specific commit, so reset repository:
$ git reset --hard b89dfcfd926b8224edd24608065eb9bb601c0d3b
Get and apply patch:
$ wget https://raw.githubusercontent.com/OLIMEX/OLINUXINO/master/SOFTWARE/AM335x/patches/0001-Add-support-for-AM335x-Olimex-boards.patch $ git apply 0001-Add-support-for-AM335x-Olimex-boards.patch
Build image, where <board_defconfig> is am335x_olimex_som_defconfig or am335x_olimex_som_nandboot_defconfig:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- <board_defconfig>
This will produce two files:
- MLO
- u-boot.img
Writing U-Boot
MMC
Insert your card and write MLO and u-boot.img:
$ sudo dd if=MLO of=/dev/sdx count=1 seek=1 bs=128k $ sudo dd if=u-boot.img of=/dev/sdx count=2 seek=1 bs=384k
NAND
In both cases below you will need bootable MMC card. Copy MLO and u-boot.img to root (/) directory of the card.
NOTE: U-boot must be built with am335x_olimex_som_nandboot_defconfig!
From u-boot console
Boot via MMC and press any key to stop autoboot:
U-Boot SPL 2016.09-rc2-00047-gb89dfcf-dirty (Sep 15 2016 - 15:46:19) Trying to boot from MMC1 U-Boot 2016.09-rc2-00047-gb89dfcf-dirty (Sep 15 2016 - 15:46:19 +0300) DRAM: 512 MiB NAND: 512 MiB MMC: OMAP SD/MMC: 0 Hit any key to stop autoboot: 0 =>
To see nand partitions run:
=> mtd device nand0 <nand.0>, # parts = 10 #: name size offset mask_flags 0: NAND.SPL 0x00020000 0x00000000 0 1: NAND.SPL.backup1 0x00020000 0x00020000 0 2: NAND.SPL.backup2 0x00020000 0x00040000 0 3: NAND.SPL.backup3 0x00020000 0x00060000 0 4: NAND.u-boot-spl-os 0x00040000 0x00080000 0 5: NAND.u-boot 0x00100000 0x000c0000 0 6: NAND.u-boot-env 0x00020000 0x001c0000 0 7: NAND.u-boot-env.backup10x00020000 0x001e0000 0 8: NAND.kernel 0x00800000 0x00200000 0 9: NAND.file-system 0x1f600000 0x00a00000 0
Erase the while chip:
=> nand erase.chip NAND erase.chip: device 0 whole chip Erasing at 0x1ffe0000 -- 100% complete. OK
Or you can erase single partition:
=> nand erase.part NAND.SPL NAND erase.part: device 0 offset 0x0, size 0x20000 Erasing at 0x0 -- 100% complete. OK
NOTE: Everytime before write operation mtd partitions MUST be erased!
Write MLO:
=> nand erase.part NAND.SPL NAND erase.part: device 0 offset 0x0, size 0x20000 Erasing at 0x0 -- 100% complete. OK => nand erase.part NAND.SPL.backup1 NAND erase.part: device 0 offset 0x20000, size 0x20000 Erasing at 0x20000 -- 100% complete. OK => nand erase.part NAND.SPL.backup2 NAND erase.part: device 0 offset 0x40000, size 0x20000 Erasing at 0x40000 -- 100% complete. OK => nand erase.part NAND.SPL.backup3 NAND erase.part: device 0 offset 0x60000, size 0x20000 Erasing at 0x60000 -- 100% complete. OK => => => load mmc 0 0x82000000 MLO 46044 bytes read in 32 ms (1.4 MiB/s) => => => nand write 0x82000000 NAND.SPL NAND write: device 0 offset 0x0, size 0x20000 131072 bytes written: OK => nand write 0x82000000 NAND.SPL.backup1 NAND write: device 0 offset 0x20000, size 0x20000 131072 bytes written: OK => nand write 0x82000000 NAND.SPL.backup2 NAND write: device 0 offset 0x40000, size 0x20000 131072 bytes written: OK => nand write 0x82000000 NAND.SPL.backup3 NAND write: device 0 offset 0x60000, size 0x20000 131072 bytes written: OK =>
Write u-boot.img:
=> nand erase.part NAND.u-boot NAND erase.part: device 0 offset 0xc0000, size 0x100000 Erasing at 0x1a0000 -- 100% complete. OK => => => load mmc 0 0x82000000 u-boot.img 347364 bytes read in 48 ms (6.9 MiB/s) => => => nand write 0x82000000 NAND.u-boot NAND write: device 0 offset 0xc0000, size 0x100000 1048576 bytes written: OK =>
From linux console
Boot board from MMC card. Make sure you have mtd-utils package, otherwise:
$ apt-get update $ apt-get install mtd-utils
You should see 10 mtd devices:
# cat /proc/mtd dev: size erasesize name mtd0: 00020000 00020000 "NAND.SPL" mtd1: 00020000 00020000 "NAND.SPL.backup1" mtd2: 00020000 00020000 "NAND.SPL.backup2" mtd3: 00020000 00020000 "NAND.SPL.backup3" mtd4: 00040000 00020000 "NAND.u-boot-spl-os" mtd5: 00100000 00020000 "NAND.u-boot" mtd6: 00020000 00020000 "NAND.u-boot-env" mtd7: 00020000 00020000 "NAND.u-boot-env.backup1" mtd8: 00800000 00020000 "NAND.kernel" mtd9: 1f600000 00020000 "NAND.file-system"
To erase partition use:
# flash_erase /dev/mtd0 0 0
To write MLO:
# flash_erase /dev/mtd0 0 0 # nandwrite -p /dev/mtd1 /MLO # flash_erase /dev/mtd1 0 0 # nandwrite -p /dev/mtd0 /MLO # flash_erase /dev/mtd2 0 0 # nandwrite -p /dev/mtd2 /MLO # flash_erase /dev/mtd3 0 0 # nandwrite -p /dev/mtd3 /MLO
To write u-boot.img:
# flash_erase /dev/mtd5 0 0 # nandwrite -p /dev/mtd5 /u-boot.img
Kernel
We are going to use kernel 4.4 from TI.
Getting the sources
Clone into repository:
$ git clone git://git.ti.com/ti-linux-kernel/ti-linux-kernel.git $ cd ti-linux-kernel
Get 4.4.y remote branch:
$ git checkout linux-4.4.y -b linux-4.4
Configure kernel
Make omap2plus default defconfig:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- omap2plus_defconfig
Make some modifications:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- omap2plus_defconfig
- Enable SPIDEV
Device Drivers ---> [*] SPI support ---> <M> User mode SPI device driver support
- Enable DRM
Device Drivers ---> Graphics support ---> <M> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) ---> <M> DRM Support for TI LCDC Display Controller [*] Support device tree blobs using TI LCDC Slave binding (NEW)
- Enable SHAM and AES
-*- Cryptographic API ---> [*] Hardware crypto devices ---> <M> Support for OMAP MD5/SHA1/SHA2 hw accelerator <M> Support for OMAP AES hw engine
Kernel build
Build kernel and modules:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules
Install modules to target directory:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=output modules_install
Patch kernel tree to get our device-tree blobs:
$ wget https://raw.githubusercontent.com/OLIMEX/OLINUXINO/master/SOFTWARE/AM335x/patches/0001-Add-support-for-OLIMEX-dtbs.patch $ git apply 0001-Add-support-for-OLIMEX-dtbs.patch
If patch fail, you can reset the tree:
$ git reset --hard 65fd19fc2bac06ae7e66cc3d6450c9d6dd034311
Build dtbs:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs
This will produce lot of .dtb files. The interesting ones are:
- am335x-olimex-som.dtb - The minimum configuration for AM335x-SOM to run.
- am335x-olimex-som-nand.dtb - Same as above, but with enabled nand.
- am335x-olimex-som-evb.dtb - Support for AM335x-SOM-EVB. Use this one, if there isn't intalled nand on AM335x-SOM
- am335x-olimex-som-evb-nand.dtb - Save above, without dual ethernet and enabled nand.
Kernel writing
Now when you have new kernel put it on the right location
MMC card
We assume that you already installed rootfs on the card. Mount card, if its not mounted yet:
$ sudo mount /dev/sdx1 /mnt
Copy zImage and device-tree blobs:
$ sudo cp arch/arm/boot/zImage /mnt/boot/ $ sudo cp arch/arm/boot/dts/am335x-olimex-som*.dtb /mnt/boot
NAND flash
Again you must boot from MMC and have zImage and dtbs stored in some folder.
From u-boot console
Write zImage:
=> nand erase.part NAND.kernel NAND erase.part: device 0 offset 0x200000, size 0x800000 Erasing at 0x9e0000 -- 100% complete. OK => => => load mmc 0 0x82000000 /boot/zImage 3667672 bytes read in 327 ms (10.7 MiB/s) => => => nand write 0x82000000 NAND.kernel NAND write: device 0 offset 0x200000, size 0x800000 8388608 bytes written: OK =>
Write device-tree blob:
=> nand erase.part NAND.u-boot-spl-os NAND erase.part: device 0 offset 0x80000, size 0x40000 Erasing at 0xa0000 -- 100% complete. OK => => => load mmc 0 0x82000000 /boot/am335x-olimex-som-evb-nand.dtb 37870 bytes read in 18 ms (2 MiB/s) => => => nand write 0x82000000 NAND.u-boot-spl-os NAND write: device 0 offset 0x80000, size 0x40000 262144 bytes written: OK =>
From linux console
To write zImage:
# flash_erase /dev/mtd8 0 0 # nandwrite -p /dev/mtd8 /boot/zImage
To write dtb:
# flash_erase /dev/mtd4 0 0 # nandwrite -p /dev/mtd4 /boot/am335x-olimex-som-evb-nand.dtb
File system
Install required tools:
$ sudo apt-get install qemu-user-static debootstrap binfmt-support
Make target directory:
$ mkdir rootfs $ sudo debootstrap --arch=armhf --foreign jessie rootfs
Copy qemu and resolvonf:
$ sudo cp /usr/bin/qemu-arm-static rootfs/usr/bin/ $ sudo cp /etc/resolv.conf rootfs/etc
Go into the new file system:
$ sudo chroot rootfs
Inside the new file system do:
# export LANG=C # /debootstrap/debootstrap --second-stage
Set apt sources.list:
# cat << __EOF__ > /etc/apt/sources.list #------------------------------------------------------------------------------# # OFFICIAL DEBIAN REPOS #------------------------------------------------------------------------------# ###### Debian Main Repos deb http://ftp.bg.debian.org/debian/ jessie main contrib non-free deb-src http://ftp.bg.debian.org/debian/ jessie main contrib non-free ###### Debian Update Repos deb http://security.debian.org/ jessie/updates main contrib non-free deb http://ftp.bg.debian.org/debian/ jessie-proposed-updates main contrib non-free deb-src http://security.debian.org/ jessie/updates main contrib non-free deb-src http://ftp.bg.debian.org/debian/ jessie-proposed-updates main contrib non-free __EOF__
Note: The list is generated using this tool, so feel free modify it.
Set hostname:
# echo "AM335x" > /etc/hostname
Install some packages:
# apt-get install locales dialog sudo openssh-client
Set locales:
# dpkg-reconfigure locales
Set root password:
# passwd
Add olimex user:
# adduser olimex
Make uEnv file:
# cat << __EOF__ > /uEnv.txt fdtfile=am335x-olimex-som-evb-nand.dtb optargs=loglevel=0 mtdoops.mtddev=omap2.nand __EOF__
Enable serial port on USB-OTG
Make script that initialize serial gadget:
# cat << __EOF__ > /usb/bin/usb_serial.sh #/bin/sh # variables and strings CONFIGS_DIR="/configs" MANUFACTURER="Olimex Ltd." # manufacturer attribute SERIAL=$(ifconfig eth0 | head -n1 | awk -F" " '{print $5}' | sed 's/://g') IDPRODUCT="0x003e" # hex product ID, issued by USB Group IDVENDOR="0x15ba" # hex vendor ID, assigned by USB Group PRODUCT="AM335x Serial Gadget" # cleartext product description CONFIG_NAME="Configuration 1" # name of this configuration UDC=musb-hdrc.0.auto # name of the UDC driver to use (found in /sys/class/udc/) # Load modules ! lsmod | grep "libcomposite" > /dev/null 2>&1 && modprobe libcomposite ! lsmod | grep "usb_f_acm" > /dev/null 2>&1 && modprobe usb_f_acm # Mount confgsfs [ ! -d $CONFIGS_DIR ] && mkdir $CONFIGS_DIR mount none $CONFIGS_DIR -t configfs # Create gadget mkdir -p $CONFIGS_DIR/usb_gadget/serial cd $CONFIGS_DIR/usb_gadget/serial # Set VID and PID echo $IDVENDOR > idVendor echo $IDPRODUCT > idProduct # Set strings mkdir strings/0x409 echo $SERIAL > strings/0x409/serialnumber echo $MANUFACTURER > strings/0x409/manufacturer echo $PRODUCT > strings/0x409/product # Create configuration mkdir configs/c.1 mkdir configs/c.1/strings/0x409 echo "120" > configs/c.1/MaxPower echo $CONFIG_NAME > configs/c.1/strings/0x409/configuration # Creating functions mkdir functions/acm.usb0 # Associate function with comfiguration ln -s functions/acm.usb0 configs/c.1 # Enable UDC echo $UDC > UDC __EOF__ # chmod +x /usb/bin/usb_serial.sh
Add startup service:
# cat << _EOF__ > /lib/systemd/system/usb-serial.service [Unit] Description=Serial console on USB-OTG ConditionPathExists=/sys/devices/platform/ocp/47400000.usb/47401300.usb-phy/ [email protected] [Service] Type=oneshot ExecStart=/bin/bash -c "/usr/bin/usb_serial.sh" RemainAfterExit=yes [Install] WantedBy=getty.target __EOF__
Enable login on ttyGS0:
# cp -v /lib/systemd/system/serial-getty\@.service # nano /lib/systemd/system/serial-getty\@ttyGS0.service
Add following in [Unit] section:
Requires=usb-serial.service # systemctl enable serial-getty\@ttyGS0.service
Write file system
First exit and make some cleanup:
# exit $ sudo rm rootfs/usr/bin/qemu-arm-static $ sudo rm rootfs/etc/resolv.conf
Copy kernel modules:
$ cp -r <kernel_dir>/output/* rootfs/
Write to MMC card
Mount the card and simply copy files:
# sudo mount /dev/sdx1 /mnt # sudo cp -rpf rootfs/* /mnt
Write to NAND
Since NAND is MTD device thera are some extra operations.
First check nand parameters. In u-boot console run:
=> ubi part NAND.file-system ubi0: attaching mtd1 ubi0: scanning is finished ubi0: empty MTD device detected ubi0: attached mtd1 (name "mtd=9", size 502 MiB) ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 129024 bytes ubi0: min./max. I/O unit sizes: 2048/2048, sub-page size 512 ubi0: VID header offset: 512 (aligned 512), data offset: 2048 ubi0: good PEBs: 4016, bad PEBs: 0, corrupted PEBs: 0 ubi0: user volume: 0, internal volumes: 1, max. volumes count: 128 ubi0: max/mean erase counter: 1/0, WL threshold: 4096, image sequence number: 0 ubi0: available PEBs: 3932, total reserved PEBs: 84, PEBs reserved for bad PEB handling: 80 => ubi info UBI: MTD device name: "mtd=9" UBI: MTD device size: 502 MiB UBI: physical eraseblock size: 131072 bytes (128 KiB) UBI: logical eraseblock size: 129024 bytes UBI: number of good PEBs: 4016 UBI: number of bad PEBs: 0 UBI: smallest flash I/O unit: 2048 UBI: VID header offset: 512 (aligned 512) UBI: data offset: 2048 UBI: max. allowed volumes: 128 UBI: wear-leveling threshold: 4096 UBI: number of internal volumes: 1 UBI: number of user volumes: 0 UBI: available PEBs: 3932 UBI: total number of reserved PEBs: 84 UBI: number of PEBs reserved for bad PEB handling: 80 UBI: max/mean erase counter: 1/0 =>
Make ubifs:
# sudo mkfs.ubifs -q -r ./rootfs -m 2048 -e 129024 -c 3932 -o rootfs.ubifs
This image canbe used in booted linux system. If you want to burn the file system from u-boot, then make ubi image:
# cat << __EOF__ > ubinize.cfg [rootfs_volume] mode=ubi image=rootfs.ubifs vol_id=1 vol_type=static vol_name=rootfs vol_alignment=1 vol_flags=autoresize __EOF__
Run ubinize:
# sudo ubinize -o rootfs.ubi -m 2048 -p $((128*1024)) -s 512 ubinize.cfg
Burn from u-boot console
This is very slow!
Copy rootfs.ubi to MMC card and do:
=> nand erase.part NAND.kernel NAND erase.part: device 0 offset 0xa00000, size 0x1f600000 Erasing at 0x1ffe0000 -- 100% complete. OK => => => load mmc 0 0x82000000 rootfs.ubi 232521728 bytes read in 58315 ms (3.8 MiB/s) => => => nand write 0x82000000 NAND.file-system
Burn from linux console
Format partition and update partition:
# ubiformat /dev/mtd9 # ubiattach -p /dev/mtd9 # ubimkvol /dev/ubi0 -N rootfs -m # ubiupdatevol /dev/ubi0_0 /rootfs.ubifs
FAQ
I've bricked my NAND
If you upload broken MLO or u-boot.img, it's possible for your board to stop booting. To fix you'll need MMC card. Insert it. Short the pins like it's showed on the image and power-up the board.
You will see some CCCCCC and then the board will boot from the MMC. You can use u-boot console to erase nand chip.
Changing display resolution
If you're using am335x-olimex-som-evb device-tree blob you can choose from 4 predefined resolutions:
- 480x272 - 4.3' lcd
- 800x480 - 7' lcd
- 800x600 - VGA output
- 1024x600 - 10' lcd
You can use 2 methods: recompilation of the device-tree file inside kernel tree or rebuilding on booted system
Recompilation in kernel tree
Go to your kernel tree and edit dts file, for example:
$ cd kernel $ nano arch/arm/boot/dts/am335x-som-olimex-evb.dts
Go to panel/display-timings section end edit native-mode to timings0,1,2 or 3:
panel { .... display-timings { native-mode = <&timings0>;
Save the file and run:
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs
Then put the dtb files in /boot directory of your MMC card