AM335x

Revision as of 04:55, 22 September 2016 by StefanM (talk | contribs)

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 <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 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:

$ 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

Install modules:

$ sudo cp -r output/* /mnt


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

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/
[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