Thursday, June 8, 2017

Building a 68000 Single Board Computer - The Newlib C Library



To protect it, I made a Lexan cover for the TS2 board, similar to what I did for the prototype. I mounted it using nylon standoffs and mounted the switches on the cover. I don't yet have the correct toggle switches, so the units here are temporary.




In order to run C programs of any complexity, you need a C run-time library to provide functions for things like input/output (e.g. printf) and string manipulation (e.g. strcmp). Since the TS2 is not running an operating system like Linux, this is not available.

A full C library is too large to run on a board like this with only 32K of RAM. Fortunately, there are some smaller alternative C run-time libraries available, mostly designed for embedded systems.

I spent some time looking at one of the popular ones, newlib. Designed for embedded systems, it supports the Motorola 68000 processor (usually referred to as m68k).

It is quite complex and documentation is sparse. I found and read a number of references. I found the easiest way to port it to the TS2 board was to start with the newlib code for another 68000-based single-board computer, copy it, and adapt it (As someone once said: "adopt, adapt, and improve").

Porting newlib involves creating at least some minimal functions for low-level input output and returning from the main() functions. These are in a part of newlib known as libgloss.

I won't cover all the details, but these were the files I needed to modify or create, all located in the libgloss/m68k/ direcytory of newlib:

Makefile.in - This is the make file which needed to be modified to add the new TS2 target platform.

crt0.S - This is the C run-time startup file. This only needed one minor change to work around a problem I encountered with atexit handling.

tutor.S - This file implements basic routines for character and string input and output and returning after main(). They are implemented in assembler and call the TUTOR ROMs routines via trap 14 with the exception of one routine which returns if a character is ready for input. It needed to talk directly to the UART hardware as TUTOR did not implement such a function. After executing main, controls returns to the TUTOR monitor.

tutor.h - This file defines some constants use by tutor.S, specifically the names of the TUTOR trap 14 functions.

ts2.ld - This is a linker script which defines the memory map to use when building for the TS2 board. You refer to this when linking your program with newlib.

The relevant files can all be found here.

The newlib directory contains a script which downloads the gcc and newlib source code, and then configures and builds gcc and newlib. It patches newlib with the files needed to support the TS2.

Also included is a sample program and make file which builds using the cross-compiler and newlib and runs on the TS2. It is a small C program I wrote some years ago to solve the "n queens" chess problem. It is very CPU and stack intensive program that can take a long time to run depending on the speed of the system and the size of the chessboard for the problem.

I ran it for a 5x5 board. The output is below:

TUTOR  1.3 > GO 804
PHYSICAL ADDRESS=00000804
Solving n queens problem for n = 5
+---------------+
| Q  .  .  .  . |
| .  .  Q  .  . |
| .  .  .  .  Q |
| .  Q  .  .  . |
| .  .  .  Q  . |
+---------------+
+---------------+
| Q  .  .  .  . |
| .  .  .  Q  . |
| .  Q  .  .  . |
| .  .  .  .  Q |
| .  .  Q  .  . |
+---------------+
+---------------+
| .  Q  .  .  . |
| .  .  .  Q  . |
| Q  .  .  .  . |
| .  .  Q  .  . |
| .  .  .  .  Q |
+---------------+
+---------------+
| .  Q  .  .  . |
| .  .  .  .  Q |
| .  .  Q  .  . |
| Q  .  .  .  . |
| .  .  .  Q  . |
+---------------+
+---------------+
| .  .  Q  .  . |
| Q  .  .  .  . |
| .  .  .  Q  . |
| .  Q  .  .  . |
| .  .  .  .  Q |
+---------------+
+---------------+
| .  .  Q  .  . |
| .  .  .  .  Q |
| .  Q  .  .  . |
| .  .  .  Q  . |
| Q  .  .  .  . |
+---------------+
+---------------+
| .  .  .  Q  . |
| Q  .  .  .  . |
| .  .  Q  .  . |
| .  .  .  .  Q |
| .  Q  .  .  . |
+---------------+
+---------------+
| .  .  .  Q  . |
| .  Q  .  .  . |
| .  .  .  .  Q |
| .  .  Q  .  . |
| Q  .  .  .  . |
+---------------+
+---------------+
| .  .  .  .  Q |
| .  Q  .  .  . |
| .  .  .  Q  . |
| Q  .  .  .  . |
| .  .  Q  .  . |
+---------------+
+---------------+
| .  .  .  .  Q |
| .  .  Q  .  . |
| Q  .  .  .  . |
| .  .  .  Q  . |
| .  Q  .  .  . |
+---------------+
Found 10 solutions after 53130 tries.
TUTOR  1.3 > 

This took about 2.5 minutes to find all the solutions. On a modern 64-bit computer running at a 2 GHz or so clock speed, the same program runs in negligeable time.

With newlib, I can now write C programs that use most of the common ANSI C library functions other than file i/o, threads, or other things lacking without a "real" operating system. The program also has to fit within the 32K RAM limit.

1 comment:

Unknown said...

Awesome blog! Working on a 68k project myself. Question: how do you handle exceptions/interrupts in this C environment? I need some vectored subroutines written, but unsure how to compile/link them in. Thanks.