Archive for the Arm stuffs Category

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

Problem running U-Boot on QEMU for versatilepb (ARM729EJ-S) ?

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

Qemu is a good emulator to try out and understand system programming without a real hardware.
Versatilepb (arm926ej-s) is supported quite well by Qemu and this article describes to overcome a nasty U-Boot error which I encountered when compiling u-boot for versatilepb.

U-boot version used: u-boot-2012.04.tar.bz2

Compiled using:

make versatilepb_config ARCH=arm CROSS_COMPILE=arm-none-eabi-
make all ARM=arm CROSS_COMPILE=arm-none-eabi-

Running u-boot with QEMU:
qemu-system-arm -M versatilepb -m 128M -nographic -kernel ./u-boot.bin

And I am greeted with this:


qemu: fatal: Trying to execute code outside RAM or ROM at 0xffff07bc

R00=fffcbf64 R01=ffff0000 R02=00000000 R03=0101c08c
R04=ffff0000 R05=fffcbf64 R06=ffff0000 R07=00000000
R08=008fff78 R09=feff0000 R10=0101c08c R11=00000000
R12=fffcbfdc R13=fffcbf58 R14=ffff07bc R15=ffff07bc
PSR=600001d3 -ZC- A svc32
Aborted

Or

U-Boot 2012.04 (Jun 18 2012 - 17:54:11)

DRAM: 128 MiB
WARNING: Caches not enabled
Flash: ## Unknown flash on Bank 1 - Size = 0x00000000 = 0 MB
*** failed ***
### ERROR ### Please RESET the board ###
QEMU: Terminated

How to avoid this nasty error you ask?

Answer: Patch include/configs/versatile.h
Add this line

#define CONFIG_ARCH_VERSATILE_QEMU

just below

#ifndef __CONFIG_H
#define __CONFIG_H

Recompile and voila!!

Here is the output


U-Boot 2012.04 (Jun 18 2012 - 18:14:08)

DRAM: 128 MiB
WARNING: Caches not enabled
Using default environment

In: serial
Out: serial
Err: serial
Net: SMC91111-0
VersatilePB # help
? - alias for 'help'
base - print or set address offset
bdinfo - print Board Info structure
bootm - boot application image from memory
bootp - boot image via network using BOOTP/TFTP protocol
cmp - memory compare
cp - memory copy
crc32 - checksum calculation
dhcp - boot image via network using DHCP/TFTP protocol
env - environment handling commands
erase - erase FLASH memory
flinfo - print FLASH memory information
go - start application at address 'addr'
help - print command description/usage
iminfo - print header information for application image
loop - infinite loop on address range
md - memory display
mm - memory modify (auto-incrementing address)
mtest - simple RAM read/write test
mw - memory write (fill)
nm - memory modify (constant address)
ping - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
protect - enable or disable FLASH write protection
reset - Perform RESET of the CPU
setenv - set environment variables
tftpboot- boot image via network using TFTP protocol
version - print monitor, compiler and linker version
VersatilePB #

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/