This document describes the provided SOS framework. This is provided to make it easier for you to get started with the project. The source code itself should be reasonably well commented, and you should ensure that you understand the provided source code.
Although you are free to change the build system and layout of the project it is discouraged for the following reasons:
We have provided a fairly comprehensive build system for you, however you will need to edit the Makefile throughout your project as you add new libraries and applications. The Makefile itself is extensively commented, this documentation is meant to supplement those comments.
The Makefile basically does the following:
The list of libraries to build is held in the
variable. This is the variable you should change if you add a
library. To determine exactly which files are built into a
library the Makefile includes a library specific makefile called
subdir.mk. You will notice that each of the
provided libraries contains one of these files.
The subdir.mk defines some variables and a make target. For example the device library has the following subdir.mk:
LIBDEVICE_OBJS = lib/device/dev.o lib/libdevice.a: lib/libdevice.a($(LIBDEVICE_OBJS))
For any libraries you create you should replace DEVICE with the name of your library.
Executables are setup in a similar way to libraries. Instead of
LIBS variable you have an
variable. On top of this the subdir.mk must also tell the build
system which libraries to link against:
TTY_TEST_OBJ = tty_test/tty_test.o tty_test/ttyout.o TTY_TEST_LIBS = -ll4 -ll4e -lc
You should note that the
sos app is special, as
this is your privileged server. It is linked with different crt
code, and is inserted into your dit image differently. You
should always ensure that
sos is listed first in
Most of the code you will write will be in the
directory. Currently there is a very minimal operating system
implemented, which should help get you started.
The implementation has been kept very simple, (you wouldn't
want us to do all the fun bits would you!). The interesting
thing here is the startup procedure, which should be fairly easy
to follow in
main.c. On startup the following
init_thread) to finish initialisation.
You may be wondering why we spawn a separate thread to handle
most of the initialisation. The main reason for this is so that
we can keep things simple (no really!). In the
init_thread you may wish to execute some code that
waits for interrupts, or possibly waits to IPC to a user-level
program. Now both interrupts and user-level code rely on the IPC
loop being able to respond to IPC.
There are of course other ways you could structure your
start-up protocol and operating system so that this is not
required. For example, you may want to have a separate thread
for each interrupt handler. Or you may wish to restrict
init_thread so that is doesn't rely on user-level
code or interrupts. You are free to explore these ides in the
design of you system.
hardware.c handles setting up device
drivers and initialising hardware for you. It exports the single
hardware_init function, which you should ensure is
called on startup. It is unlikely that you will need to edit
this file, and you should expect patches to it as other device
drivers are released throughout the course.
So that you don't have to write everything from scratch we provide you with some libraries to get you going.
Each executable is linked with a piece of crt (C runtime) code
which does some basic initialisation and calls a program's
main entry point.
Two crts are provided, a crtK.S, and a crt0.S. crtK is used when linking against SOS. Your user programs will be linked against crt0.S.
If you need to execute any code that runs before or after the
main() function runs, you should add it to your
crt0.S file. (For example, you may have some IPC handshake on
startup, and another IPC message to tell the server to do a
process_delete on exit.)