Hello, kernel! Part 2

Now that you have your project structure, let’s take a look at the tools we will use to create our final image.

Compiler

As discussed earlier, I use the arm-none-eabi-* compiler. This is a “tool chain” which means if you followed my download instructions, you will have a variety of different programs that all start with that prefix. This tool chain includes a C Compiler, C++ Compiler, Assembly Compiler, Dis-assembler, and a few other things. So how the heck do we get access to all that neat stuff? Well, it’s pretty complicated and well documented. To setup your environment, I recommend following some of this tutorial: http://hertaville.com/2012/09/28/development-environment-raspberry-pi-cross-compiler/

NOTE: That post shows you how to install a different tool chain than I use. You can try it if you want, but the important thing to glean from that site is the PATH setup instructions for pointing your local PATH variable to the compiler bin directory. Please note you’ll have to do this for the root user as well – if you plan on compiling under root.

I’m going to assume you have the compiler setup and configured properly. So how do we actually use it? Well, let’s start by creating a program! Now I don’t intend to teach you assembly language, but I do want to show you the basics of how to use the compiler. Plus, the entry point for our kernel has to be assembly. So you will learn a tiny bit about it. Let’s start by creating a new  file called init.asm within our /project/kernel/ directory. I’ll post a screenshot of my code and step you through it.

code

Okay, that is technically assembly but it doesn’t look too scary.

  • .global – This is basically defining a function that we plan to implement later on which can be linked by the compiler and called from other files. I don’t think it actually has to be global, in this case, but I wanted to show you the code anyway.
  • _start: – This line defines what we call a “label”. Labels are basically functions.
  • MOV sp,#0x8000 – In assembly, there are many “global” variables that you have access to. sp means “stack pointer”, I believe. What this line of code does is specify a location in memory where the stack memory will start to be allocated. It is pretty much required to be the first thing in your program.
  • b hang – This is two things. First, ‘b’ means ‘branch’ (essentially “call function”). There are multiple ways to call a function and I am not entirely sure of the difference between them. ‘bx’ means “branch and then return”, I think. So ‘b’ probably means you’re going away but you aren’t planning on returning!
  • hang: – Again, this just defines a new function called ‘hang’.
  • b hang – Again, this just calls the function ‘hang’ thus putting us in an infinite loop.

And that’s it! So now that we have a lovely program, how do we compile it specifically for the raspberry pi? Well, before we jump ahead of ourself, let’s take a look at some of the tools that our tool chain provides us.

Tools

Here is a list of some really useful commands and their descriptions:

arm-none-eabi-objump

This utility is capable of disassembling the output of your compiled files (amongst many other things). Use the -D flag to tell it to disassemble.

arm-none-eabi-objcopy

This utility is used to copy binary files (and possibly preform transformations on them in the process). We use it to copy our linked program into an IMG file.

arm-none-eabi-as

This is the assembler. We will be using it to compile the bootstrap.S file into a common format that can eventually be linked with C/C++.

arm-none-eabi-gcc

This is the C compiler. There are a number of flags we’ll be talking about later which we will be using during our compilation. NOTE: if you change that last part to g++ it comes a C++ compiler. All the same command line switches are the same.

arm-none-eabi-ld

And finally our linker! This is what takes all of the compiled binaries that we’ve developed and merges them into one output. There are some very important command line switches we need to learn about to properly use this one. So I’ll be explaining those in the next section.

The BUILD Script

Technically you’re supposed to use makefiles, but I prefer bash scripting. So let me show you a possible build.sh script looks like and we will go over some of the options.

#!/bin/sh
compiler=arm-none-eabi
code=../code
boot=../boot

# First let's compile our assembly file.
$compiler-as $code/init.asm -o $code/init.o

# Then let's call the linker to generate a binary output.
$compiler-ld $code/init.asm -o $code/kernel.elf

# Then let's dump some debug info to disk.
$compiler-objdump -D $code/init.o > $code/init.disassembled.asm
$compiler-objdump -D $code/kernel.elf > $code/kernel.disassembled.asm

# Lastly let's copy our binary into an img format.
$compiler-objcopy $code/kernel.elf -O binary $boot/kernel.img

echo "Finished compiling!"

Using the script above, your program should be compiled, disassembled, linked, converted to an IMG file, and then copied to the boot directory! If you just move all the files in that boot directory onto a FAT32 formatted SD Card (or just call that make image script we made in the other post) and you’ll be good! Give it a whirl.

DISCLAIMER: I wrote this code by hand without testing it. I will be doing some tests later (at which point I’ll remove this disclaimer). So be aware that I may have made a mistake somewhere. Feel free to post questions as they arise.

Advertisements
Tagged with: , , , , , ,
Posted in Beginner, Introduction
4 comments on “Hello, kernel! Part 2
  1. christian says:

    line 10 in buil.sh i think must be $code/init.o 🙂

  2. When the linker is called, should we not be passing the output of the compiler to it?
    This line:
    $compiler-ld $code/init.asm -o $code/kernel.elf

    I believe instead of .asm, it should be .o

  3. Unkown says:

    Bx is “branch and change instruction set if needed”, b is a simple branch. Both set the lr(link register, the adress to continue at when finished), so you can return from the function. Technical background is that most current ARMs support the thumb instruction set which contains less instructions but is only 16bit/instruction instead of 32bit which is important in really small scape embedded systems (low rom space, ram only delivering 16bit/request)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: