CS444 Wed., Sept. 12

                Our Google group is set up, based on .forward email addresses

 

System setup for SAPCs

 

Each SAPC is (effectively) connected to the UNIX host “ulab” by a serial line from COM2 on the SAPC to (effectively) a serial port on ulab.  We call this the console line.  (Actually, there is a terminal concentrator involved.) When Tutor prints a prompt, those bytes are going out COM2 and are handled by the UNIX program “mtip” that we run on ulab.

 

mtip shuttles bytes back and forth between your stdin/stdout user i/o setup and the console line.  When you type a character during an mtip session, it goes via stdin to the mtip program, and from there out to COM2 of the connected SAPC.  If you type “~” or <esc>, the mtip escape character, mtip takes notice and then waits for the next character to see what to do, for example ~d (or <esc>d) for download.

 

Each SAPC numbered 5 or more has its COM1 separately connected to another serial port on ulab.  This connection is used by remote gdb to provide debugging.

 

When you type “~r” (or <esc>r) in mtip, the connected SAPC gets rebooted.  This works by first being interpreted by mtip, and then mtip runs another program that sends a command via a serial port on ulab to the “reset server”, a little machine that John Lentz built for this purpose.  It interprets the command and then generates a signal on a wire into the reset circuitry of the right SAPC, that is, a signal equivalent to pressing the reset button on the SAPC box.

 

 

Intro to hw1—

Problem 1—warmup for 2.  Just duplicate a given remgdb session –due Thurs, Sept.  21

Rest due following Oct 1--

Problem 2—UNIX gdb for hello-world problem

Problem 3--finishing an i/o library for the SAPC.

 

Intro to hw1—

 

Problem 3 (Part 2)--finishing an i/o library for the SAPC.

 

As a library, it implements certain useful functions for apps.  Its API is in io_public.h:

void ioinit(void);

int read(int dev, char *buf, int nchar);

int write(int dev, char *buf, int nchar);

also “control”

 

Read and write look very much like the same-named UNIX system calls, except for “dev” instead of “fd”.  The dev parameter is the device number, for the io library. Here dev can be TTY0 (value 0, standing for COM1) or TTY1 (value 1, standing for COM2).  See tty_public.h for the following:

 

#define TTY0 0

#define TTY1 1

 

In class, we looked briefly at the provided test program testio.c, to get the idea that it calls into the library using the API quoted above.

In "write(ldev, buf, nchar)", seen in testio.c, ldev is TTY0 or TTY1. These numbers are defined in the header file tty_public.h provided with the hw1 project files.  These device numbers are special to hw1, hw2, etc.

 

testio.c is the test program calling through the API.  After making sure it’s talking to the user over a serial line, device ldev, it does ioinit() and then write(ldev, “hi!\n”, 4) as a first test.  As delivered, output works but without using interrupts.  Your job is to reimplement it with interrupts.

 

kprintf. Note the use of kprintf instead of printf in testio.c and elsewhere. Kprintf (for kernel printf, currently called printk in Linux sources) first turns off all interrupts then executes printf with the same arguments as it was called with, and then restores interrupts to their previous state.  This means that if execution reaches the kprintf code it will definitely print out the message, even if interrupts are enabled in the program.  That is a great help for debugging, since it’s important to know where execution is in the code. So be sure to use kprintf instead of printf for debugging hw1 code.

Recall from CS341 that the SAPC device numbers COM1 (value 1) and COM2 (value 2) are in a system of numbers set up in $pcinc/sysapi.h, which is included from $pcinc/stdio.h, and thus is in effect in any program with “#include <stdio.h>” or equivalent.

 

Note: you should have the environment pcinc defined for you by the ulab module, so if you can run mtip, you can also use $pcinc, for example by doing "cd $pcinc"  or "ls $pcinc" or "more $pcinc/stdio.h".  To see what it stands for, do "echo $pcinc".  It's just a directory in the UNIX filesystem.  Similarly $pcex stands for the file path to the SAPC examples directory.

 

The "system defined" (via stdio.h for SAPC) devices:

 

#define CONSOLE 100

#define KBMON 0   <---keyboard + monitor (we can’t use this via mtip)

#define COM1 1

#define COM2 2

 

CONSOLE is the current console, where the Tutor prompt shows up, and where the user is typing.  It is possible to run Tutor with console KBMON, COM1, or COM2, depending on what device the user types the first carriage return on at bootup time.  So by using CONSOLE, for example by fprintf(CONSOLE, “hi”); or equivalently printf(“hi”), we can talk to our user regardless of which way they are using our code. CONSOLE is the logical console, like stdout in UNIX.  All output via CONSOLE is sent to remote gdb as well as to the Tutor console.

 

When we use mtip, the Tutor console line is COM2.  So fprintf(CONSOLE, “hi”) and fprintf(COM2, “hi”) both output directly to the user.  You can put fprintf(COM1, “hi”) in your program, and it will work, but you won’t see the resulting output on COM1 (unless you remember a trick we used in CS341 mp5.)  (If you’re using remote gdb, you’ll be messing around with its protocol connection, to its great detriment.)

Even simpler, we can just put "printf("hi")" to write to the console.

 

SAPC Support Library

Uses device numbers: COM1, COM2, CONSOLE, etc., #define’d via stdio.h for SAPC

#include <stdio.h>    includes special stdio.h for SAPC, in $pcinc.  How does this work?  via compiler flag “–I <include-path>” in makefile

 

In the SAPC library, also arranged for access in the makefile:

  1. Standard C library calls, also available on UNIX, Windows, no modification:  printf, scanf, getchar, putchar, strcpy, strcmp, …
  2. C library calls, with device numbers instead of FILE *’s:  fprintf, fgets, …
  3. Special SAPC functions: sys_get_console_dev(), other sys_ functions, kprintf for debugging

 

Note that kprintf and some other functions in the SAPC library are utilizing the fact that our SAPC code is running in kernel mode, not user mode as is normal for C applications.  In user mode, we cannot turn off the interrupt system, as is done in kprintf!

 

In some cases we want to make sure we’re talking to the user over a serial line.  We can ask Tutor what the current console device is by using the call “sys_get_console_dev()”.  You’ll see this called in echo.c and hw1’s testio.c.

 

hw1: In problem 3, you write code suitable for an i/o library layered on top of SAPC library.

 

As a library, it implements certain useful functions for apps.  Its API is in io_public.h:

void ioinit(void)

int read(int dev, char *buf, int nchar);

int write(int dev, char *buf, int nchar);

also “control”

 

Read and write look very much like the same-named UNIX system calls, except for “dev” instead of “fd”.  The dev parameter is the device number, for the io library. Here dev can be TTY0 (value 0, standing for COM1) or TTY1 (value 1, standing for COM2

 

Look at the API again.  This can be called a “device-independent” i/o library because the interface is generic, not specific to any particular device.  The actual device in use can be determined at runtime, for example, by asking the user for a device number.

 

The edits you need to make are all in tty.c, in ttyread and ttywrite and the interrupt handler.  A call to read ends up at ttyread and a call to write at ttywrite.  I’ll let you trace out how this happens.  Look at io.c and ioconf.c.  This shows how device independent i/o systems work—the device number specifies which device-specific function to actually execute.  Here the device-specific functions are ttyread and ttywrite, and the bundle of tty-functions in tty.c is called the tty driver, or serial port driver.

 

C Objects, a quick intro/review.

 

Here the Queue ADT in C is provided in the queue subdirectory, along with a unit test testqueue.c.  queue.h defines the Queue API and the Queue type.

 

You know how to do objects in Java, what about in C?  Recall the Chip object in CS341.  Also the Cmd object for tutor.

 

Example: Rectangle objects

 

struct rect {

     int x1, y1, x2, y2;

};

struct rect *recp;

 

recp->x1 = 10;

 

Watch out!, there’s no (validly-allocated) memory pointed to by recp!  This is a garbage pointer, a pointer that points nowhere good.  Using it usually causes segmentation violations on UNIX and similar exceptions on Windows.  But on SAPC, all user memory is writable, so it may quietly work to damage some memory.

 

Normally under UNIX or Windows, we could malloc space for the Rectangle, but we have no malloc in the SAPC library.  Anyway, malloc is quite expensive in CPU, and we can easily avoid using it.  Just set up whole objects like this:

 

struct rect rect;

 

Now we can put

 

rect.x1 = 10;

 

      As a Java programmer, you’re used to “Rectangle rect;” meaning rect is a ref to a Rectangle, but in C, rect is the whole object, more like int x; in C or Java.

            To make a rectangle pointer, we have to use * in the type: “struct rect *rp;” defines rp to be a struct rect pointer.