AM335x

Revision as of 00:40, 22 September 2016 by StefanM (talk | contribs) (From linux console)

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:

$ 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 <patch name>
$ git apply <patch name>

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 9 mtd devices:

# ls -l /dev/mtd*
crw------- 1 root root 90,  0 Jan  1  1970 /dev/mtd0
crw------- 1 root root 90,  1 Jan  1  1970 /dev/mtd0ro
crw------- 1 root root 90,  2 Jan  1  1970 /dev/mtd1
crw------- 1 root root 90,  3 Jan  1  1970 /dev/mtd1ro
crw------- 1 root root 90,  4 Jan  1  1970 /dev/mtd2
crw------- 1 root root 90,  5 Jan  1  1970 /dev/mtd2ro
crw------- 1 root root 90,  6 Jan  1  1970 /dev/mtd3
crw------- 1 root root 90,  7 Jan  1  1970 /dev/mtd3ro
crw------- 1 root root 90,  8 Jan  1  1970 /dev/mtd4
crw------- 1 root root 90,  9 Jan  1  1970 /dev/mtd4ro
crw------- 1 root root 90, 10 Jan  1  1970 /dev/mtd5
crw------- 1 root root 90, 11 Jan  1  1970 /dev/mtd5ro
crw------- 1 root root 90, 12 Jan  1  1970 /dev/mtd6
crw------- 1 root root 90, 13 Jan  1  1970 /dev/mtd6ro
crw------- 1 root root 90, 14 Jan  1  1970 /dev/mtd7
crw------- 1 root root 90, 15 Jan  1  1970 /dev/mtd7ro
crw------- 1 root root 90, 16 Jan  1  1970 /dev/mtd8
crw------- 1 root root 90, 17 Jan  1  1970 /dev/mtd8ro
crw------- 1 root root 90, 18 Jan  1  1970 /dev/mtd9
crw------- 1 root root 90, 19 Jan  1  1970 /dev/mtd9ro
brw-rw---- 1 root disk 31,  0 Jan  1  1970 /dev/mtdblock0
brw-rw---- 1 root disk 31,  1 Jan  1  1970 /dev/mtdblock1
brw-rw---- 1 root disk 31,  2 Jan  1  1970 /dev/mtdblock2
brw-rw---- 1 root disk 31,  3 Jan  1  1970 /dev/mtdblock3
brw-rw---- 1 root disk 31,  4 Jan  1  1970 /dev/mtdblock4
brw-rw---- 1 root disk 31,  5 Jan  1  1970 /dev/mtdblock5
brw-rw---- 1 root disk 31,  6 Jan  1  1970 /dev/mtdblock6
brw-rw---- 1 root disk 31,  7 Jan  1  1970 /dev/mtdblock7
brw-rw---- 1 root disk 31,  8 Jan  1  1970 /dev/mtdblock8
brw-rw---- 1 root disk 31,  9 Jan  1  1970 /dev/mtdblock9

To erase partition use:

# flash_erase /dev/mtd0 0 0

To write MLO:

# flash_erase /dev/mtd0 0 0
Erasing 128 Kibyte @ 0 -- 100 % complete 
# nandwrite -p /dev/mtd1 /MLO
Writing data to block 0 at offset 0x0
# flash_erase /dev/mtd1 0 0
Erasing 128 Kibyte @ 0 -- 100 % complete 
# nandwrite -p /dev/mtd0 /MLO
Writing data to block 0 at offset 0x0
# flash_erase /dev/mtd2 0 0
Erasing 128 Kibyte @ 0 -- 100 % complete 
# nandwrite -p /dev/mtd2 /MLO
Writing data to block 0 at offset 0x0
# flash_erase /dev/mtd3 0 0
Erasing 128 Kibyte @ 0 -- 100 % complete 
# nandwrite -p /dev/mtd3 /MLO
Writing data to block 0 at offset 0x0

To write u-boot.img:

# flash_erase /dev/mtd5 0 0
Erasing 128 Kibyte @ e0000 -- 100 % complete
# nandwrite -p /dev/mtd5 /u-boot.img
Writing data to block 0 at offset 0x0
Writing data to block 1 at offset 0x20000
Writing data to block 2 at offset 0x40000

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:

$ 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.


File system

Debian 8

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

Set locales:

# dpkg-reconfigure locales


Set root password:

# passwd

Add olimex user:

# adduser olimex

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/
Before=serial-getty@ttyGS0.service

[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