User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

[Guide] Beginning Bare Metal on Raspi

Tue Jul 10, 2012 8:14 pm

Hi,

I just wanted to start a thread about some links and guides to start bare metal programming on raspberry pi to give you a head start.

First of all some links which helped me alot to get a "feeling" for arm cpus. !
-----------------------
https://github.com/dwelch67/raspberrypi/
From here you should grab the bootloader 4 and have a look at the other sources.
]https://gitorious.org/lambdapi/lambdapi
LambdaPi very interessting for most people to get a bit started on bare metal
http://balau82.wordpress.com/2010/02/28 ... sing-qemu/
Explanation of LD scripts and all to compile a bare metal.
http://wiki.osdev.org/ARM_Overview
An overview of the CPU we are talking about. OSDev is the site for the best infos on coding an Operating System. And another Info for you: Did you know the ARM Cpu cant divide nor make modulo? :)
-----------------------

What you need to code bare metal (Windows):
- Windows ->
Cygwin
http://www.cygwin.com/
Cross Compiler
https://launchpad.net/gcc-arm-embedded
Something for the UART like this:
http://www.ebay.de/itm/USB-2-0-to-UART- ... 2c65c24878
The bootloader 4 from the link above.
+ Editor (Notepad+, ...)
------------------------
Our first code:

Linker script: (raspi.ld) (can be used for any purpose), the ENTRY(xxxx) is the starting point for your code.

Code: Select all

ENTRY(asm_start)

MEMORY
{
	ram : ORIGIN = 0x8000, LENGTH = 0x10000000
}

SECTIONS
{
	.text : {
		*(.text)
	} > ram
	
	.data : { *(.data) } > ram
	__bss_start__ = .;
	.bss : { *(.bss) } > ram
	__bss_end__ = .;	
}
and now for the code itself:

Code: Select all

.text

.global asm_start
.global exc_stack
.global supervisor_sp

asm_start:

	# initialize Stack pointer for exception modes
	mrs r4, cpsr
	bic r4, r4, #0x1f

	#FIQ Mode
	orr r3, r4, #0x11
	msr cpsr_c, r3
	ldr sp, =exc_stack

	#IRQ Mode
	orr r3, r4, #0x12
	msr cpsr_c, r3
	ldr sp, =exc_stack

	#ABORT Mode
	orr r3, r4, #0x17
	msr cpsr_c, r3
	ldr sp, =exc_stack

	#UNDEFINED Mode
	orr r3, r4, #0x1b
	msr cpsr_c, r3
	ldr sp, =exc_stack

	# switch to supervisor mode
	orr r3, r4, #0x13
	msr cpsr_c, r3
	
	ldr sp, =temp_stack
	
	#
	# Create the first stack frame.
	#
	mov fp, #0
	mov ip, sp
	push {fp, ip, lr, pc}
	sub fp, ip, #4

	bl not_main

.globl dummy
dummy:
    bx lr

	
	.space 0x100
temp_stack:

	.space 1024
exc_stack:

supervisor_sp:
	.space 4
This is the only assembler file you would need. it creates stack for all levels of the cpu and jumps then into your c code (not_main()). If you return from your C-Code the dummy is there to endless loop the cpu.

Code: Select all

__attribute__((no_instrument_function))  void not_main(void)
{
	UINT32 sel = READ32(GPFSEL1);
	sel &= ~(0b111 << 18);
	sel |= (0b001 << 18);
	WRITE32(GPFSEL1,sel);
  
	while(1) 
	{
		WRITE32(GPCLR0, 1<<16);
		for (int i = 0; i < 0x100000; i++) ;
		WRITE32(GPSET0, 1<<16);
		for (int i = 0; i < 0x100000; i++) ;
	}
} 
This code does nothing more than let your OK Led on your Raspi blink.

and now the makefile (written by tufti, its real cool and does everything!!)

Code: Select all

ARCH = arm-none-eabi
CC = ${ARCH}-gcc
CPP = ${ARCH}-g++
AS = ${ARCH}-as
LD = ${ARCH}-ld
AR = ${ARCH}-ar
OBJCOPY = ${ARCH}-objcopy

PLATFORM = raspi

# Release Version -> Optimize 
#CFLAGS = -O3 -std=gnu99 -Werror -D__$(PLATFORM)__ -DRASPBERRY_PI
#ASFLAGS =

CFLAGS = -O0 -g -std=gnu99 -Werror -D__$(PLATFORM)__ -DRASPBERRY_PI -fno-builtin 
ASFLAGS = -g

CFLAGS_FOR_TARGET = -mcpu=arm1176jzf-s
ASFLAGS_FOR_TARGET = -mcpu=arm1176jzf-s
LDFLAGS = -nostdlib -static --error-unresolved-symbols 


MODULES := raspi 
SRC_DIR := $(addprefix src/,$(MODULES))
INC_DIR := $(addsuffix /include,$(SRC_DIR))
BUILD_DIR := $(addsuffix /build,$(SRC_DIR))

ASRC     := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.s))
AOBJ     := $(ASRC:.s=.o)
CSRC     := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c))
COBJ     := $(CSRC:.c=.o)

INCLUDES := -Isrc $(addprefix -I,$(SRC_DIR) $(INC_DIR))

vpath %.c $(SRC_DIR)
vpath %.cpp $(SRC_DIR)
vpath %.s $(SRC_DIR)

%.o: %.c
	$(CC) $(CFLAGS_FOR_TARGET) $(INCLUDES) $(CFLAGS) -c -o $*.o $<

%.o: %.s
	$(AS) $(ASFLAGS_FOR_TARGET) $(INCLUDES) $(ASFLAGS) -o $*.o $<

OBJ = $(AOBJ) $(COBJ)

bin/kernel.img: bin/kernel.elf
	${OBJCOPY} -O binary $< [email protected]

bin/kernel.elf: raspi.ld $(OBJ) 
	${LD} ${LDFLAGS}  $(OBJ) -Map bin/kernel.map -o [email protected] -T raspi.ld

clean:
	rm -f bin/*.elf bin/*.img bin/*.map $(OBJ)
if you do the simple "make" you will get a kernel.img, which you can uplaod to the raspi with the bootloader/terminalprg and start watching.
NOTE: If you have more than one directory the make should compile, just add it to the "MODULES " with a blank in between: MODULES := raspi raspisourcecodeexample2

So with these three code snippets and the tools from above you should be ready to dig in to the bare metal programming. The makefile, the linkerscript and the asm part can be kept as they are.

ghans
Posts: 7873
Joined: Mon Dec 12, 2011 8:30 pm
Location: Germany

Re: [Guide] Beginning Bare Metal on Raspi

Thu Jul 12, 2012 4:15 pm

Could you put this into the Wiki ?
Perhaps i'll have a look ino bare metal coding someday...

ghans
• Don't like the board ? Missing features ? Change to the prosilver theme ! You can find it in your settings.
• Don't like to search the forum BEFORE posting 'cos it's useless ? Try googling : yoursearchtermshere site:raspberrypi.org

User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

Re: [Guide] Beginning Bare Metal on Raspi

Thu Jul 12, 2012 5:18 pm

Maybe sometime. First I would like to collect everything here in the forum. Otherwise you end up with infos on wiki, infos in the forum, infos in the github, infos in some blog.. and then it gets annoying and hard time to keep all updated.

ghans
Posts: 7873
Joined: Mon Dec 12, 2011 8:30 pm
Location: Germany

Re: [Guide] Beginning Bare Metal on Raspi

Thu Jul 12, 2012 5:22 pm

But what happens if you post wrong instructions ?
In a wiki , you could correct them.
That happened to me while following instructions in forums ... :(

ghans
• Don't like the board ? Missing features ? Change to the prosilver theme ! You can find it in your settings.
• Don't like to search the forum BEFORE posting 'cos it's useless ? Try googling : yoursearchtermshere site:raspberrypi.org

User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

Re: [Guide] Beginning Bare Metal on Raspi

Thu Jul 12, 2012 5:32 pm

i can update my post :) if you like, you can take the contents here and put it on the wiki. To be honest, i wrote the two guide to get the head clear of this USB thing :-P

rockhawk
Posts: 54
Joined: Thu Feb 09, 2012 9:24 pm
Contact: Website

Re: [Guide] Beginning Bare Metal on Raspi

Sun Jul 15, 2012 10:54 am

I followed Cycl0ne's instructions, and there were a few things I had to work out as I went along. I've put up a git repo with the right directory structure and instructions on how to get it all going here: https://github.com/MichaelBell/RasPi-bare

Hope that's helpful to someone!
Find Iridium Rising, our 3D space combat game, on the Pi Store!

User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

Re: [Guide] Beginning Bare Metal on Raspi

Sun Jul 15, 2012 3:27 pm

Thats really nice, but i forgot one file i noticed :)

types.h

Code: Select all

typedef void				VOID;
typedef void *				APTR;

typedef signed char			INT8;
typedef signed short		INT16;
typedef signed int			INT32;
typedef signed long long int	INT64;

typedef unsigned char		UINT8;
typedef unsigned short		UINT16;
typedef unsigned int		UINT32;
typedef unsigned long long int	UINT64;

typedef volatile signed char			VINT8;
typedef volatile signed short int		VINT16;
typedef volatile signed int				VINT32;
typedef volatile signed long long int	VINT64;

typedef volatile unsigned char			VUINT8;
typedef volatile unsigned short int		VUINT16;
typedef volatile unsigned int			VUINT32;
typedef volatile unsigned long long int	VUINT64;

#define READ32(addr) (*(VUINT32*)(addr))
#define READ16(addr) (*(VUINT16*)(addr))
#define READ8(addr) (*(VUINT8*)(addr))

#define WRITE32(addr,value) (*(VUINT32*)(addr) = (VUINT32)(value))
#define WRITE16(addr,value) (*(VUINT16*)(addr) = (VUINT16)(value))
#define WRITE8(addr,value) (*(VUINT8*)(addr) = (VUINT8)(value))
There you find the READ and WRITE function, no need for your PUT/GETs. Can be all done in C and makes code clearer.

One question form my side, have you got the link to libgcc.a working? Thats the only thing i couldnt get to work in my setup :-(

another nice option would be, that the .o files are stored in another subdir and not with the code.

rockhawk
Posts: 54
Joined: Thu Feb 09, 2012 9:24 pm
Contact: Website

Re: [Guide] Beginning Bare Metal on Raspi

Sun Jul 15, 2012 6:46 pm

Ah, that would've been handy - as you've seen I started my own version of that header file :)

I'm not completely convinced doing the reads/writes through C is better. Especially with the read macro, you could accidentally end up writing to something you were reading given those READ macros, which is impossible with a function call. But even with the WRITE macro, what happens if you do int x = WRITE32(addr, value); Might the compiler try to read from that memory address (which might not be allowed by the hardware)?

I haven't tried to do anything more complicated than blink LEDs yet, so I haven't tried to link in the standard library yet.
Find Iridium Rising, our 3D space combat game, on the Pi Store!

User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

Re: [Guide] Beginning Bare Metal on Raspi

Tue Jul 17, 2012 3:19 pm

Can you give me write access to the repo on github? i will change and add things, that might be interessting. :)

rockhawk
Posts: 54
Joined: Thu Feb 09, 2012 9:24 pm
Contact: Website

Re: [Guide] Beginning Bare Metal on Raspi

Tue Jul 17, 2012 6:17 pm

I think I want the repo to be about creating a sort of minimal project that doesn't have a particular purpose. Quite happy to get display driver and UART and similar code in there, but I want to try and present it as generic building blocks. Then ideally people can fork the repo and use it as the basis for a specific task.

If you're happy with that aim, then I'm happy to give you write access - what's your github username?
Find Iridium Rising, our 3D space combat game, on the Pi Store!

User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

Re: [Guide] Beginning Bare Metal on Raspi

Tue Jul 17, 2012 6:25 pm

Cycl0ne, no problem on that. Im one of your "Watchers" on github ^^

rockhawk
Posts: 54
Joined: Thu Feb 09, 2012 9:24 pm
Contact: Website

Re: [Guide] Beginning Bare Metal on Raspi

Tue Jul 17, 2012 7:16 pm

ok, got you - you should have access now!
Find Iridium Rising, our 3D space combat game, on the Pi Store!

User avatar
Beakster
Posts: 29
Joined: Mon Oct 24, 2011 6:03 pm

Re: [Guide] Beginning Bare Metal on Raspi

Wed Jul 25, 2012 12:04 am

Hey guys,

Great work on creating the project on github. I've just checked it out and built it. One thing I noticed was that it failed the first time saying:

Code: Select all

/opt/gcc-arm-none-eabi-4_6-2012q2/bin/arm-none-eabi-ld: cannot open map file bin/kernel.map: No such file or directory
make: *** [bin/kernel.elf] Error 1
I think this was because there was no bin directory as once I created one it seemed to work. So maybe we need to add something to the makefile to create bin if it isn't there.

User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

Re: [Guide] Beginning Bare Metal on Raspi

Wed Jul 25, 2012 1:26 am

hehe did it the other way round.. check ouit the git ;)

now a bin is there ;)

dwelch67
Posts: 955
Joined: Sat May 26, 2012 5:32 pm

Re: [Guide] Beginning Bare Metal on Raspi

Wed Jul 25, 2012 1:55 am

http://infocenter.arm.com

You should get the ARM ARM (ARM Architectural reference manual for the architecture in question) and the TRM (Technical Reference Manual) for the core in question. In this case it is an ARM1176 and I believe that is an ARMv6. What used to be the only ARM ARM, which is now the oldest one there is good to have as well esp for these 32 bit ARM instruction set cores.

User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

Re: [Guide] Beginning Bare Metal on Raspi

Wed Jul 25, 2012 6:06 am

is it allowed to put them into a git repo? i could make a folder Docs and put them there, with the BCM Manual. And yes its an ARMv6.

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: [Guide] Beginning Bare Metal on Raspi

Wed Jul 25, 2012 8:27 am

Nope, the ARM ARM is copyrighted ARM, and you have to be registered with ARM to get a copy.
License terms, fair use, I hope wrote:1. Subject to the provisions set out below, ARM hereby grants to you a perpetual, non-exclusive, nontransferable, royalty free, worldwide licence to use this ARM Architecture Reference Manual for the purposes of developing; (i) software applications or operating systems which are targeted to run on microprocessor cores distributed under licence from ARM; (ii) tools which are designed to develop software programs which are targeted to run on microprocessor cores distributed under licence from ARM; (iii) or having developed integrated circuits which incorporate a microprocessor core manufactured under licence from ARM.
2. Except as expressly licensed in Clause 1 you acquire no right, title or interest in the ARM Architecture Reference Manual, or any Intellectual Property therein. In no event shall the licences granted in Clause 1, be construed as granting you expressly or by implication, estoppel or otherwise, licences to any ARM technology other than the ARM Architecture Reference Manual. The licence grant in Clause 1 expressly excludes any rights for you to use or take into use any ARM patents. No right is granted to you under the provisions of Clause 1 to; (i) use the ARM Architecture Reference Manual for the purposes of developing or having developed microprocessor cores or models thereof which are compatible in whole or part with either or both the instructions or programmers’ models described in this ARM Architecture Reference Manual; or (ii) develop or have developed models of any microprocessor cores designed by or for ARM; or (iii) distribute in whole or in part this ARM Architecture Reference Manual to third parties, other than to your subcontractors for the purposes of having developed products in accordance with the licence grant in Clause 1 without the express written permission of ARM; or (iv) translate or have translated this ARM Architecture Reference Manual into any other languages.
Is that enough ARMs yet? No?

The one you want for the Pi is the ARM-v7AR ARM ("ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition", ARM reference ARM DDI 0406). The ARM-v7M ARM is no use. Anyone noticed how the three subfamilies of ARM are A, R & M?

Simon

dwelch67
Posts: 955
Joined: Sat May 26, 2012 5:32 pm

Re: [Guide] Beginning Bare Metal on Raspi

Thu Jul 26, 2012 12:47 am

That is cool I didnt notice the A R and M variants.

g7tnz
Posts: 9
Joined: Thu Dec 01, 2011 5:33 pm
Contact: Website

Re: [Guide] Beginning Bare Metal on Raspi

Fri Aug 03, 2012 4:41 pm

My thanks to many on this forum, and in particular: dwelch67, Cycl0ne and tufty. I have managed to begin a project aimed at control rather than an OS and put it up on GitHub at https://github.com/G7TNZ/RPi-kernel.

It has screen output, but no input device. In order to get to this point I had to know what variables were doing and so the project contains a package that flashes the status led (or any GPIO pin) in Morse for either the Hex or decimal contents of a variable. Until I got the framebuffer working it was the only way I could think of of getting any information about why the mailbox did not seem to be working.

The project is built without the standard libraries and as I hit the problem with no divide functions the project contains the assembler divide routines from Linux cleaned up so they build without extras.

I think it may be useful as a starter for anyone who wants to use the Raspi for hardware control or who want to learn from a fairly simple beginning.

I build the project using the Codesourcery toolchain, qemu and scratchbox2.

I have the same problem with no bin folder in the repository so pointers to a solution would be appreciated.

User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

Re: [Guide] Beginning Bare Metal on Raspi

Fri Aug 03, 2012 10:07 pm

just create a file calles: "dontdeletethis" and bin will be in your repo ;)

romell
Posts: 25
Joined: Mon Jul 23, 2012 6:57 pm

Re: [Guide] Beginning Bare Metal on Raspi

Fri Aug 03, 2012 10:47 pm

Cycl0ne wrote:just create a file calles: "dontdeletethis" and bin will be in your repo ;)
Or you could do a .gitignore with just:

Code: Select all

*
!.gitignore
It looks a little bit better and has the added benefit of making git ignore anything else in that folder :)

g7tnz
Posts: 9
Joined: Thu Dec 01, 2011 5:33 pm
Contact: Website

Re: [Guide] Beginning Bare Metal on Raspi

Sat Aug 04, 2012 6:47 pm

Thanks to both. I have succeeded in getting the directory pushed. I will note both methods for the future.

User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

Re: [Guide] Beginning Bare Metal on Raspi

Sat Aug 04, 2012 9:56 pm

This USB you have in your source, does it support OTG USB from Raspberry Pi?

g7tnz
Posts: 9
Joined: Thu Dec 01, 2011 5:33 pm
Contact: Website

Re: [Guide] Beginning Bare Metal on Raspi

Sat Aug 04, 2012 11:41 pm

I haven't got around to looking at the USB yet. That has been added preparatory to my trying to hack it. It is LPCUSB for LPC214 not the LAN9512. Since I added that I have realised that the Linux Source may be better to look at to understand the USB and to use as a basis for incorporating here.

User avatar
Cycl0ne
Posts: 102
Joined: Mon Jun 25, 2012 8:03 am

Re: [Guide] Beginning Bare Metal on Raspi

Sun Aug 05, 2012 6:38 am

Here is a stripped down linux usb raspberry pi port:
https://github.com/gonzoua/u-boot-pi/tree/rpi

to be exactly here:
https://github.com/gonzoua/u-boot-pi/tr ... s/usb/host

all files containing "dwc_*"

Problem is only: Ethernet works, Mass Storage works, Mouse might work, Keyboard hangs ;-) So someone has to look into it.

Return to “Bare metal, Assembly language”