Archive for arm linux

TFTP Boot using u-boot

Posted in Arm stuffs, Unix/Linux with tags , , , , , , , , , , , on January 16, 2013 by UnixmanLinuxboy

I was fiddling around with my newly purchased Beaglebone and wanted to get my hands dirty with kernel hacking and stuff. Since beaglebone is hard-wired to boot off an SD card I found it tedious to shuttle the card between my development laptop and the board.
===================
Enter TFTP boot.
===================
This is a very handy way of booting when you need to recompile your kernel repeatedly and inserting/removing the card from/to board becomes a tedious process. For those who wanted to try out this fantastic way of booting, here is my short howto:

Before I begin, here is snapshot of my development platform:
Host machine: am64 lubuntu 12.10
Tftp software: tftp-hpa 5.2 [client and server]
U-boot: 2013.01-dirty

===========================================================
To install, run: sudo apt-get install tftpd-hpa tftp-hpa
===========================================================

Before we begin, we need to configure the tftpd’s configuration file so edit:
————————————————–

sudo vim /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="your-ftp-root-directory"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"

————————————————–
After that restart the daemon: sudo service tftpd restart
Now that the server has been setup in our host machine, we may now concentrate on the target system.
Note: The SD card containing MLO and u-boot should always be present in the beaglebone’s slot.
Power up the board and and get to the u-boot prompt:
———————————————————————————————————-

U-Boot 2013.01-dirty (Jan 16 2013 - 15:36:41)
I2C: ready
DRAM: 256 MiB
WARNING: Caches not enabled
NAND: No NAND device found!!!
0 MiB
MMC: OMAP SD/MMC: 0, OMAP SD/MMC: 1
*** Warning - readenv() failed, using default environment

musb-hdrc: ConfigData=0xde (UTMI-8, dyn FIFOs, bulk combine, bulk split, HB-ISO Rx, HB-ISO Tx, SoftConn)
musb-hdrc: MHDRC RTL version 2.0
musb-hdrc: setup fifo_mode 4
musb-hdrc: 28/31 max ep, 16384/16384 memory
USB Peripheral mode controller at 47401000 using PIO, IRQ 0
musb-hdrc: ConfigData=0xde (UTMI-8, dyn FIFOs, bulk combine, bulk split, HB-ISO Rx, HB-ISO Tx, SoftConn)
musb-hdrc: MHDRC RTL version 2.0
musb-hdrc: setup fifo_mode 4
musb-hdrc: 28/31 max ep, 16384/16384 memory
USB Host mode controller at 47401800 using PIO, IRQ 0
Net: cpsw, usb_ether
Hit any key to stop autoboot: 0
U-Boot#

———————————————————————————————————-
Make sure that ethernet cable is plugged into the board and a dhcp server is running in either your host machine or your router.
———————————————————————————————————-

U-Boot# setenv autoload no
U-Boot# dhcp
link up on port 0, speed 100, full duplex
BOOTP broadcast 1
DHCP client bound to address 192.168.1.11

———————————————————————————————————-
Next will be configuring the server-ip [our host machine’s IP], kernel’s command line and the load address
———————————————————————————————————-

U-Boot# setenv serverip 192.168.1.4
U-Boot# setenv bootfile uImage
U-Boot# setenv bootargs console=ttyO0,115200 root=/dev/mmcblk0p2 rw rootwait ip=dhcp
U-Boot# tftp 0x80200000 uImage
link up on port 0, speed 100, full duplex
Using cpsw device
TFTP from server 192.168.1.4; our IP address is 192.168.1.11
Filename 'uImage'.
Load address: 0x80200000
Loading: #################################################################
#####################################################T ############
##########################################T #######################
###################################T ########
146.5 KiB/s
done
Bytes transferred = 3484264 (352a68 hex)
U-Boot# bootm 0x80200000
## Booting kernel from Legacy Image at 80200000 ...
Image Name: Angstrom/3.2.28/beaglebone
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 3484200 Bytes = 3.3 MiB
Load Address: 80008000
Entry Point: 80008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Linux version 3.2.28 (koen@Angstrom-F16-vm-rpm) (gcc version 4.5.4 20120305 (prerelease) (GCC) ) #1 Tue Sep 11 13:08:30 CEST 2012
[ 0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=50c53c7d
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[ 0.000000] Machine: am335xevm

———————————————————————————————————-
And voila! It boots!!!!

A simple “bare-metal” program (ARM)

Posted in Arm stuffs with tags , , , , , , , , , , , , , , on June 16, 2012 by UnixmanLinuxboy

Caution: Here be dragons!
For those who feel like writing C code with nice and fancy algorithm, this is not for you. This is for them who wants to dig deeper at the core to see how things run and work.
A “bare-metal” program is simplest of all which does not need special services from underlying OS. It is capable enough to run on its own.

Without much ado, lets get it on, shall we?

This tutorial can be used on both real hardware and an emulator. I have used QEMU for this purpose.

Architecture to emulate: ARM926EJ-S
This is well supported by QEMU and has four UART
serial ports. The first serial port (UART0) works
as a terminal when we will use '-nographic' or
'-serial stdio' option in QMEU

Goal: This program will run inside QEMU emulator and will pass few characters to the UART0 which will, then be redirected by QEMU to the standard console.
Note: On real board (ARM926EJ-S) you have to connect to serial port (Minicom).

Required:
QEMU, ARM toolchain, little patience and willingness to learn.

Install QEMU on ubuntu:
sudo apt-get install qemu qemu-kvm-extras

Get ARM toolchain from:
ARM toolchain download link

Note: Do not download the installer (it sucks!)
Instead, get the .tar.gz archieve and unpack it your working directory
and set your PATH accordingly.
If you’re using login shell, modify the .bash_profile,
else modify .bashrc.
————————————————————————–

No interrupt handling and other fancy stuffs.

The code is well-explained and do contact me if you need more information.

The command to run the final binary in QEMU is:
qemu-system-arm -M versatilepb -m 128M -nographic -kernel output.bin

"-M versatilepb" specifies the machine type: Here we are using ARM9 versatile board.
"-nographic" mode tells to redirect UART0 messages to console.

Note: Without the option "-m 128M" QEMU crashes badly. A bug has been already filed regarding this.

Here we go!!!

File: simple-startup.s


/* ===========================================
Start up routines for bare-metal program
===========================================
*/

.global _Reset
_Reset:
B Reset_Handler /* Reset handler */
B Undefined /* Undefined mode handler */
B SWI /* Software interrupt */
B Prfetch_Abort /* Prefetch abort handler */
B Data_Abort /* Data abort handler */
B IRQ_Handler /* IRQ handler */
B FIQ_Handler /* FIQ handler */

Reset_Handler:
LDR sp, =stack_top /*set up env for C function */
BL simple_init
B .
Undefined: /* do nothing */
B .
SWI: /* do nothing */
B .
Prfetch_Abort: /* do nothing */
B .
Data_Abort: /* do nothing */
B .
IRQ_Handler: /* do nothing */
B .
FIQ_Handler: /* do nothing */
B .

File: simple-init.c


/*******************************************/
/* Simple Bare metal program init */
/*******************************************/

/* Note: QEMU model of PL011 serial port ignores the transmit
FIFO capabilities. When writing on a real SOC, the
"Transmit FIFO Full" flag must be checked in UARTFR register
before writing on the UART register*/

volatile unsigned int* const UART0 = (unsigned int*)0x0101F1000;

static void uart_print(const char *s)
{
while(*s != '') {
*UART0 = (unsigned int)(*s); /* send to UART */
s++;
}
}

/* Main entry point */
void simple_init()
{
uart_print("Welcome to Simple bare-metal program\n");
uart_print("If you're running in QEMU, press Ctrl+a\n");
uart_print("and then x to stop me...\n");
}

File: simple-linker.ld


/* Simple Bare metal program - linker script
*
* Note: This is written for QEMU
* QEMU loads the kernel address at 0x00010000
* The emulator starts at 0x00000000 and peripheral interrupts
* are disabled at startup.
*
* The code must be compiled and linked to be placed at
* 0x00010000
* IRQ handling can be ignored.
*
*/

ENTRY(_Reset)
SECTIONS
{
. = 0x10000;
.startup . : { simple-startup.o(.text) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
. = . + 0x1000; /* move by 4kbyte (our stack memory) */
stack_top = .;
}

Build commands:


arm-none-eabi-as -mcpu=arm926ej-s -g simple-startup.s -o simple-startup.o
arm-none-eabi-gcc -c -mcpu=arm926ej-s -g simple-init.c -o simple-init.o
arm-none-eabi-ld -T simple-linker.ld simple-init.o simple-startup.o -o output.elf
arm-none-eabi-objcopy -O binary output.elf output.bin

And here is the output:

sarbojit@Phrozen:~/timepass/assembly-fun$ qemu-system-arm -M versatilepb -m 128M -nographic -kernel output.bin
Welcome to Simple bare-metal program
If you’re running in QEMU, press Ctrl+a
and then x to stop me…
QEMU: Terminated
sarbojit@Phrozen:~/timepass/assembly-fun$

Inspired by:
http://balau82.wordpress.com/2010/02/28/hello-world-for-bare-metal-arm-using-qemu/