Skip to content
Libre Computer

ECEC 201

Modern Computer: Von Neumann

This section of Advanced Programming for Engineers uses Das Frite. The course is C on a Linux system, and the board is that system, so a program's memory and execution are things you inspect on real hardware. The labs are a Von Neumann computer: a program in memory, a processor that runs it, and I/O on the header. The course stops before the boot ROM, device-tree source, and kernel drivers.

Each week has two lecture hours, a two-hour lab, and four homework hours.

In class is the lecture. The lab and the homework under it are different hand-ins. Read the module the week names, and stop where the week says to stop. Pin numbers are on the station sheet. These notes do not print a second pin list.

All four courses. Modules and labs: education.libre.computer.

Week 1

In class

The board is the course's Linux machine. On this section the boot media is a USB drive the TA images with the desktop imager. A SHA-256 check answers one question: the bytes on the drive are the bytes the course published. Compare it before you boot. Stop before any boot stage. Do not mark stages on the log.

Log in twice, on the serial console and over SSH, so you have a way in when the network is down. Then the loop the whole course uses: edit a C file, compile it on the board with warnings on, run it, and read every warning before you move on.

On the lab site: Module 0, First boot, is the flash and the login. Stop before annotating boot stages.

Lab

  1. Write the term image with the desktop imager and compare its SHA-256 with the published value before you boot.
  2. Log in on the serial console, then over SSH. Write a C program that prints its arguments, compile it on the board with `gcc -Wall -Wextra`, and run it. Second pass: add one line that draws a warning, read the warning, and remove the line.
  3. Assemble the lab hand-in: The checksum you compared, a screenshot of the console and SSH logins, and the C file with its compile command and output.

Hand in: The checksum you compared, a screenshot of the console and SSH logins, and the C file with its compile command and output.

Homework

Write the four shell commands that edit, compile with warnings, run, and commit a C file in your course repository, without running them. Turn in: Those four commands and one line on what each does.

Week 2

In class

A C type is a size in memory, and the size belongs to the system, not the language. This board is a 64-bit Arm Linux system. Print sizeof for each type and keep the table: you will use it every week after this one.

Signed and unsigned values wrap differently at their limits. Two's complement is why a signed value turns negative. Print both results in decimal and in hexadecimal, then let the undefined-behaviour sanitizer show you which of the two the language does not define.

On the lab site: Module 1, What a board is, names the SoC. This week grades C type sizes measured on that SoC.

Lab

  1. Write a program that prints `sizeof` for char, short, int, long, long long, float, double, and a pointer.
  2. Add one to a signed and to an unsigned 32-bit value at their limits, and print both results in decimal and hexadecimal. Second pass: compile with `-fsanitize=undefined`, run again, and record the line it reports.
  3. Assemble the lab hand-in: The program, its `sizeof` table, the two overflow results, and the sanitizer line.

Hand in: The program, its `sizeof` table, the two overflow results, and the sanitizer line.

Homework

Before running anything, predict the eight `sizeof` values and the two overflow results on paper. Turn in: The predictions, marked where the board disagreed.

Week 3

In class

A pointer is an address. An array is a run of addresses, one element after another. Adding one to a pointer steps by the size of the element, which is why the step is different for an int, a double, and a char.

Reading past the end of an array is the bug this week makes visible. The address sanitizer catches the read and names the line. Write down the step you expect for each array before the lab; the board either agrees or shows you why not.

On the lab site: the modules do not grade pointer arithmetic. This week does.

Lab

  1. Print the address of each element of an int array and of a double array, and the difference between neighbours.
  2. Walk each array with a pointer, then read one element past the end with `-fsanitize=address` on. Second pass: repeat with a char array and compare its step.
  3. Assemble the lab hand-in: The program, the address table for the three arrays, and the sanitizer report for the out-of-bounds read.

Hand in: The program, the address table for the three arrays, and the sanitizer report for the out-of-bounds read.

Homework

For each of the three arrays, write the step you expect between neighbouring addresses and why, before the lab. Turn in: The three steps and the reason for each.

Week 4

In class

A running program is a process, and a process has a map of its memory: text for the code, data and bss for globals, the heap for malloc, and the stack for locals. Linux prints that map in /proc/self/maps. Draw the five regions in address order before you run anything.

Print one address from each region and find it on the map from the same run. Run it again: some addresses move between runs, and the reason is the lecture's last point.

On the lab site: Module 5, Memory bring-up, covers the DRAM. This week grades one process's map of that memory.

Lab

  1. Print the address of a function, a global, a static variable, a `malloc` block, and a local variable.
  2. In the same run, print `/proc/self/maps` and mark the region each address falls in. Second pass: run it twice more and note which addresses move between runs.
  3. Assemble the lab hand-in: The program, the five addresses marked on the memory map, and one sentence on which addresses moved between runs and why.

Hand in: The program, the five addresses marked on the memory map, and one sentence on which addresses moved between runs and why.

Homework

From the lecture, draw the five regions of a process in address order before you run the program. Turn in: The drawing with each region named.

Week 5

In class

Memory you ask for with malloc is yours to give back with free. A linked list is the first structure where forgetting that costs something. Valgrind reports every block you did not free. A test is a program that checks your code and fails loudly: write one with assert that inserts, finds, and removes nodes, and run it under valgrind too.

A struct is laid out in memory with padding between members so each one is aligned. offsetof prints where each member starts. Compute the offsets by hand first, then reorder the members and watch the size change.

On the lab site: the modules do not grade heap use or struct layout. This week does.

Lab

  1. Build a linked list of structs from the lines of a text file, then free it, and write an `assert`-based test that inserts, finds, and removes nodes.
  2. Run the program and the test under valgrind until both report no leaks, and print `sizeof` and `offsetof` for each struct member. Second pass: reorder the members to remove padding, print the new size, and run the test again.
  3. Assemble the lab hand-in: The program and its test, the valgrind summary with no leaks, and the member offset table before and after reordering.

Hand in: The program and its test, the valgrind summary with no leaks, and the member offset table before and after reordering.

Homework

Compute each member's offset and the struct's total size by hand, with the alignment rule from the lecture. Turn in: The hand-computed offset table.

Week 6

In class

A C file becomes a running program in steps: the preprocessor, the compiler, the assembler, the linker, and the loader. Run each step by hand once and keep the file each one writes. A link error names a symbol; nm shows which file has it.

In 64-bit Arm assembly, a function's first arguments arrive in x0 and x1 and its result leaves in x0. In gdb, a recursive call is a stack of frames. Count how far the stack pointer moves for each frame.

On the lab site: Module 8, Linux boots, shows the kernel starting programs. This week grades one program's build and its stack.

Lab

  1. Build a two-file program step by step with `gcc -E`, `-S`, `-c`, and a link, and fix one undefined-symbol error using `nm`.
  2. In the assembly of one two-argument function, mark where the arguments arrive in `x0` and `x1` and where the result leaves in `x0`. In `gdb`, stop inside a recursive function and print the backtrace. Second pass: recurse three levels deeper and compare the stack pointer between frames.
  3. Assemble the lab hand-in: The annotated assembly of the function, the `nm` line that fixed the link error, and the backtrace with the stack-pointer difference per frame.

Hand in: The annotated assembly of the function, the `nm` line that fixed the link error, and the backtrace with the stack-pointer difference per frame.

Homework

Write the four build steps from source to executable and the file each one produces, before the lab. Turn in: The four steps and their output files.

Week 7

In class

Linux shows the system as files. open gives you a file descriptor, read and write move bytes through it, and a failure sets errno. Every program starts with three descriptors already open.

The board's model and its uptime are files under /proc. Read both with open and read, not with a library call, and append the uptime to a log with write.

On the lab site: Module 10, I/O, reaches devices through drivers. This week grades a C program that reads the system through files.

Lab

  1. In C, with `open` and `read`, print the board model from `/proc/device-tree/model` and the uptime from `/proc/uptime`.
  2. With `write`, append the uptime to a log file, and open a path that does not exist to print its `errno` message. Second pass: run the program five times and keep the five log lines.
  3. Assemble the lab hand-in: The program, the board model it printed, the five log lines, and the error line for the missing path.

Hand in: The program, the board model it printed, the five log lines, and the error line for the missing path.

Homework

Write what a file descriptor is and which three a program starts with, before the lab. Turn in: The definition and the three descriptors.

Week 8

In class

A register is a byte whose bits mean different things. Masks and shifts pull each field out. volatile tells the compiler a value can change without the program writing it, and byte order says which byte of a wider value comes first.

The station sensor is on the I2C bus the image already enables; the lecture names its device file. No device-tree edit. Read one register with ioctl and read, then decode its fields from the datasheet. Write the mask for each field before the lab.

On the lab site: Module 10, I/O, decodes a bus on an analyser. This week grades a C read of one register and its decoded bits. Stop before the analyser capture.

Lab

  1. On the I2C bus the image already enables, through the device file the lecture names, read one register of the station sensor with `ioctl` and `read`. Do not edit a device tree.
  2. Decode its fields with masks and shifts, using the sensor's datasheet. Second pass: print the raw byte in binary beside the decoded fields.
  3. Assemble the lab hand-in: The program, the register address, the raw byte, the decoded fields, and the datasheet page you used.

Hand in: The program, the register address, the raw byte, the decoded fields, and the datasheet page you used.

Homework

From the datasheet, write the bit positions and the mask for each field you will decode, before the lab. Turn in: The mask table.

Week 9

In class

A GPIO line is requested from the Linux character device, then set or read. A button bounces, so the program waits a debounce interval before it counts another press. Use only the pins the station sheet lists.

A Makefile rebuilds only what changed. Change one source file and show that only it recompiles. This week is the project checkpoint: the button program, built with make. No overlay. No driver.

On the lab site: Module 9, Device tree and pin multiplexing, reaches GPIO through an overlay. This week grades a C program on the lines the image already exposes. Stop before an overlay and before a driver.

Lab

  1. With the GPIO character-device interface, light one LED and read one button on the pins the station sheet lists.
  2. Debounce the button, count 20 presses, and build the program with a `Makefile`. Second pass: change one source file, run `make`, and show that only that file recompiles.
  3. Assemble the lab hand-in: The program, the `Makefile`, the pin numbers, and the count from 20 presses.

Hand in: The program, the `Makefile`, the pin numbers, and the count from 20 presses.

Homework

Write the `Makefile` rule for one object file and say what makes it rebuild. Turn in: The rule and what triggers it.

Week 10

In class

The demo is one C program: each button press logs one decoded register reading to a file. It builds with make and runs clean under valgrind. Write two questions a partner might ask about pointers or memory in your code, and your answers, before the demo. That writing is the homework.

Each partner answers one question about their own code. Keep the repository as it was at the demo.

On the lab site: Module 12, A whole system, is a full product. This week grades one C program that joins a register and a button.

Lab

  1. Demonstrate the project: each button press logs one decoded register reading to a file.
  2. Each partner answers one question about pointers or memory in their own code. Second pass: run the demo under valgrind and show no leaks.
  3. Assemble the lab hand-in: The demo, the repository with its `Makefile`, and the valgrind summary.

Hand in: The demo, the repository with its `Makefile`, and the valgrind summary.

Homework

Write two questions a partner might ask about pointers or memory in your code, and your answers, before the demo. Turn in: The two questions and the two answers.