Laboratory 7 (individual) -- I/O devices

Due February 23, 2018
35 points

Overview

In this lab, you will gain experience writing assembly-language programs
and interacting with I/O devices. This assignment is to be done
individually.

Each person will write a device driver and test
program for one of the following I/O devices: speaker, microphone,
PS/2 keyboard, USB mouse, touchscreen, LCD display, VGA monitor, SD card,
camera, serial send, serial receive. Each member of your team should
choose a different I/O device. I recommend one member write the device
driver for the serial send controller, because you can use this as
console to help debug future programs.

This handout also provides information about other I/O devices
(SDRAM, real-time clock, Fast Fourier Transform co-processor, PWM, SPI),
but these should not be chosen for this lab.

Device driver: A device driver handles the low-level
details of interacting with an I/O device. You will implement a device
driver for your I/O device as an E100 assembly-language function.

Test program: You will also write a small test program
that uses your I/O device. Your test program will be implemented in E100
assembly language and will call your device driver to handle the low-level
details of using the I/O device.

You should develop and debug your device driver and program initially on
ase100. You should then run your device driver and program on a
hardware E100 processor, which you will create by
adding I/O controllers to your E100 processor.

E100 I/O devices

E100 programs communicate with I/O devices by reading and writing to
variables provided by those devices. These variables are called device
registers. Each device register is assigned a memory address, and
E100 programs read and write a device register via normal instructions
(e.g., cp, bne) to its assigned address. This method for
accessing I/O device registers is called memory-mapped device
registers.

Some device registers can be read to determine their current value; for
example, cp switch 0x80000000 reads the current value of
SW[17:0]. Other device registers may be written to change their
value; for example, cp 0x80000001 tmp writes the value of
tmp to LED_RED[17:0].

The following table lists the I/O devices available for the E100, along
with the addresses (in hexadecimal) assigned to each device registers and
whether the register can be read or written. The links in the right
column of the table provide detailed information about the behavior of each
device and the test program that you should write for that device.

I/O device protocol

At first glance, it seems easy to send data to/from an I/O device. For
example, one could send a sample to the speaker simply by copying data
to the speaker_sample device register.
However, this is not quite enough to send a sequence of
values. One problem is that the speaker controller doesn't know when the
program has sent the next value to the speaker_sample device register.
Another problem is that the program doesn't know when the speaker
controller has read the last sample and is ready to receive the next
sample. These problems are addressed by an I/O device protocol.

A protocol is used to guide the interaction between two parties. In the
context of I/O devices, an I/O protocol is used to guide the interaction
between an E100 program and an I/O device. A protocol defines the steps
involved in the interaction and includes how each party knows when the
current step is complete. We will use a protocol to send commands to an
I/O device and receive the response from that device.

The part of an E100 program that implements the E100's side of an I/O
protocol is called a device driver.

The I/O protocol uses four types of signals to allow an E100 program to
send commands to a device and receive the response from that device.

command parameters: These signals carry the
data that the E100 program wants to send to the device as part of the
command. These signals are set by the E100 program.

command: The value of this signal is set by
the E100 program. When it is 1, it tells the device that the E100
program is done setting the command parameters and is ready for the
device to carry out the command.

response parameters: These signals carry the
data that the device wants to send to the E100 program as part of its
response. These signals are set by the device.

response: The value of this signal is set by the
device. When it is 1, it tells the E100 program that the device has
executed the command and is sending its response to that command.

The steps involved in sending data to an output device are:

command

response

Description

0

0

System is idle.

1

0

E100 program sets the command
parameters to describe the desired command,
then sets command
to 1 to ask the device to execute the command. After
setting command to 1, the E100
program waits for device to execute the command.

1

1

After the device executes the command, it
sets the response parameters for
the command, then sets response
to 1 to tell the E100 program that it has executed the
command and is sending back the response. After setting
response to 1, the device waits
for the E100 program to set command
to 0.

0

1

E100 program sets command
to 0 to tell the device that the program has seen the
device's response. After this state, the device sets
response back to 0, and the system
returns to the Idle state.

Pre-lab assignment

Your pre-lab assignment is to write, test, and debug your device driver and
test program. These tasks can be done by running the E100 assembler and
simulator, ase100. Debugging on ase100 is much easier
than debugging on the DE2-115 because you can control the execution of your
program and view its state as it executes.

Your test program and device drivers should be in separate files. Include
the device driver file in your test program by adding a line at the
end of your test program, such as:

#include driver.e

Most of your testing and debugging should occur before your lab section.
The lab section is meant for running final tests on the DE2-115 board and for
demonstrating your program to a lab instructor.

Incremental development

One of the surest ways to waste a lot of time when programming is to try to
write and test the entire program all at once. This is especially true
when you are trying a new task, language, or unfamiliar environment (such
as this lab!).

A better way to program is to write and test a little at a time. The less
familiar you are with the material, the smaller the piece you should write
and test. For example, since you are new to assembly-language programming,
you might write a program consisting of a single instruction (plus halt),
then run that program and verify that it changed memory and the IAR as you
expected.

For this lab, I strongly recommend you first write and test your device
driver before you write your full test program. To test
your device driver, write a trivial test program that initializes the input
parameters (if any), calls the device driver, displays the output
parameters (if any) to the hex digits, then halts. After this works,
write a second test program that calls your device driver twice (this
verifies that the first call to your device driver left things in
the right state).

After you verify that your device driver is correct, then write your test
program. Again, do this a little at a time. For example, if your test
program requires a loop, test one iteration of the loop before running
multiple iterations.

In-lab demonstration

Demonstrate your test program and device driver on the DE2-115 to a lab instructor.
After you've demonstrated your program, submit the final version of your
test program and device driver here.