21

I already found the Baking Pi tutorials, but they only use assembly language. I followed the first lessons, but I am already wondering how to use C instead. I mean, there is a reason they invented higher-level languages. I tried just compiling the C code to an object (.o) file, compiling

.section .init
.globl _start
_start:

bl main

loop$:
b loop$

to another object file and linking them together and so obtaining kernel.img. I then replaced the already present kernel with my own, but it doesn't execute the C code. The C code I wrote should just turn on the OK LED and then return (then comes loop$: b loop$). But the OK LED flashes randomly a few times and then just stays off. Here's my C code:

int main(int argc, char ** argv) {
    volatile unsigned *gpioAddr = (volatile unsigned *)0x20200000;
    *(gpioAddr + 4) = 1 << 18;
    *(gpioAddr + 40) = 1 << 16;
    return 0;
}

How do I use C for operating system development on a Raspberry Pi?

I doubt it is an error in the code (although I'm just a hobbyist). I'm aware setting up C may be complicated, but I'm not the first one doing this. AFAIK, all the currently dominant OSes are mainly written in C, so there has to be an article explaining the process. I would be very happy with a list of steps too, so I can google for those steps and perhaps ask a question a little less broad.

Note: the ARM assembly equivalent of the above C code works just fine. It turns on the LED (after a bit of blinking). I think (hope) that indicates my Raspberry Pi is fine.

Peter Mortensen
  • 2,004
  • 2
  • 15
  • 18
11684
  • 465
  • 1
  • 3
  • 13
  • 1
    C was designed to be portable assembly language for Unix. Linux is written in C, you can save quite a bit of time by looking at how it is done. – Thorbjørn Ravn Andersen Jul 27 '13 at 22:27
  • 1
    @ThorbjørnRavnAndersen I think I'm not up to reading the source of Linux. Linux is far more complex than what I want know, thus obscuring the for me interesting pieces. – 11684 Aug 25 '13 at 15:48
  • Perhaps I misunderstood what you meant by "operating system development" on the Pi. Modern operating systems are quite complex. – Thorbjørn Ravn Andersen Aug 25 '13 at 20:23
  • I wasn't planning on writing an OS as complex as Linux. I want to site up a few LEDs and buttons and make a chess computer. Perhaps the software in a chess computer isn't called an operating system, but that's what I meant. @ThorbjørnRavnAndersen – 11684 Aug 26 '13 at 06:01
  • A Pi is powerful enough to run a modern programming language so you don't have to use C or assembly programming. Chess has received lot of attention from programmers so there are existing solutions for both engine and board which is easily glued together with the Chess Engine Connection Protocol - http://www.gnu.org/software/xboard/engine-intf.html - I suggest you open a new question specifically for finding out how you can use existing parts to get to the things you find fun. – Thorbjørn Ravn Andersen Aug 26 '13 at 06:10
  • 1
    Um, 'wire up' a few LEDs. – 11684 Aug 26 '13 at 06:49
  • 1
    Thank you, but I want to do most things myself. It's a learning project. – 11684 Aug 26 '13 at 06:51
  • Great. Have fun :) Note that if you stick with the de-facto API's for the various components you can get something up and running quickly and then rewrite each component in your own time and still have something running the whole time. – Thorbjørn Ravn Andersen Aug 26 '13 at 07:20
  • 1
    I Must admit I never saw a question any where before on how to write an OS. And there are some interesting answers. It is just crazy... – Piotr Kula Sep 13 '13 at 13:24
  • I respect the desire to write in C. Taking the time to learn assembly will illuminate the underpinnings of the computer. As a language, its mechanics are incredibly simple and easy to grasp. – James M. Lay May 02 '15 at 19:35

5 Answers5

14

I wrote a very simple kernel years ago, and ran it on a 386. I haven't done bare metal programming in years, but in broad terms you need to write some assembler code that will:

  • disable interrupts during the boot process
  • if the Pi has a memory controller, you'll need to set that up
  • set up a timer tick
  • configure the interrupt controller
  • set up a stack so that you can execute C code

Setting up the stack is easy - find some memory that's not being used, and load that address into which ever register is used as the stack pointer.

In your C code you need to init OS data structures like a memory pools and thread tables. You won't be able to use C library functions - you'll need to write that stuff yourself.

If you want to write a simple multitasking os, you'll need to write some assembler routines to save CPU registers on the stack, and load a different set of register values from another thread's stack. And you'll need to write an API to create different threads.

Steve
  • 1,431
  • 10
  • 8
  • 1
    Hard to choose between this answer and Georges Dupéron's. I accepted this one and gave the other an upvote. – 11684 Sep 17 '13 at 17:39
13

I haven't looked at your code in depth, but it seems to me you're on the right track. Make sure that:

  • The _start symbol is indeed the one used when compiling & linking your assembly file and your C file (and that main() isn't used instead)
  • When calling main(), you need to use the C calling convention:
    • push on the stack the address of the instruction following your call (the return address, which will be used by the return statement in C)
    • push the arguments for the function. In your case you can push two 32-bit values (8 bytes in total), but to make things simpler you could also remove the arguments and just have int main() { ... }
    • maybe reserve some space on the stack for the return value
    • I can't remember in what order these things should be pushed
    • To know what the C function expects exactly, disassemble it (objdump -S main.o) and look at how it manipulates the stack.
  • If you don't respect the calling convention, then the assembly code generated by the C compiler might tamper with the return address on the stack, and in your case you didn't even push a return address, so the return instruction will jump somewhere random, instead of going to loop$.

The OSDev wiki will be a very useful ressource -- it's mainly concerned with x86 development but most information is still applicable to the raspberry pi.

Some more raspberry-pi osdev specific resources:

Suzanne Soy
  • 249
  • 1
  • 5
2

Try this instead:

http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/

Also, the x86 experience is a bit different. It may be applicable to general ARM bare metal OS programming. But for Pi, sorry it is the gpu start first and set up quite a bit before your OS (?) code.

Dennis Ng
  • 121
  • 2
2

The main problem you might encounter is the C libraries and prologue code. It's started before your own code starts executing and sets up the stack, the heap and does plenty of other helpful things. However, when you're trying to program for bare metal you don't have any OS running below you and you'd better to avoid calling these functions. In order to do that you need modified versions of C libraries and/or some global symbols defined or replaced with your own. This process is a bit involving, that's why 'Baking Pi' people chose to use assembly for their tutorials.

lenik
  • 11,541
  • 1
  • 30
  • 37
  • Thank you for answering my question (and sorry for responding so late). But (surprise!) I bought my pi to learn about just that, the bit involving low level processes (I'd rather not do that on an expensive desktop with the risk of destroying personal files/mails/photos). Could you please add how I set up the stack, or an article/tutorial/some resource explaining that? (And what else I might need to run C). – 11684 Aug 05 '13 at 07:24
1

s-matyukevich/raspberry-pi-os

https://github.com/s-matyukevich/raspberry-pi-os

This awesome repo does both the C bootstraping, and goes into pretty complex topics.

Furthermore, it looks into how the Linux kernel does things, and annotates Linux kernel code.

Have a look at the first tutorial for a minimalistic setup: https://github.com/s-matyukevich/raspberry-pi-os/tree/43f682d406c8fc08736ca3edd08a1c8e477c72b0/src/lesson01/src

I highly recommend it.