You are on page 1of 42

F28HS Hardware-Software Interface:

Systems Programming

Hans-Wolfgang Loidl

School of Mathematical and Computer Sciences,


Heriot-Watt University, Edinburgh

Semester 2 — 2020/21

0
No proprietary software has been used in producing these slides
Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface 2020/21 1 / 39
Outline

1 Tutorial 1: ARM Assembler Exercise: Caesar Cipher (ROT13)

2 Tutorial 2: Programming an LED

3 Tutorial 3: Programming a Button

4 Tutorial 4: Programming a HEX display

5 Tutorial 5: Cache-friendly Programming

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface 2020/21 2 / 39


Overview of the Caesar Cipher (ROT13) Exercises

This sequence of screencasts is intended to give you a deeper


understanding of ARM Assembler programming
We will develop one non-trivial program step-by-step in ARM
Assembler
Follow the online screencasts, and do the matching lab exercises
A Caesar cipher is a very simple cipher, that encodes a string by
rotating each char by a certain amount
For example, with rotation value of 1: a → b, b → c, ..., z → a
A Caesar cipher with rotation value of 13 (ROT13) is sometimes
used for low-security encryption.
Background on Caesar cipher:
I see slides (15–20) in Introduction to Cryptography
I exercise of breaking (optional, search for “Exercise 1: Caesar
cipher”)
I see also this wikipedia page on ROT13
Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 1: Prging an LED 3 / 39
Structure of the Sequence of Screencasts

TASK: Implement a Caesar cipher (rotation cipher) in ARM


Assembler
Background: you should have watched the ARM Assembler
programming leactures (F28HS lectures Assembler 1-5) and done
the matching tutorials and lab exercises
Structure:
I Version 0: C version
I Version 1: plain (lower case letters only)
I Version 2: printing the result (using printf libc function)
I Version 3: using subroutines
I Version 4: covering upper case letters as well
I Version 5: using word load and store (for fewer memory operations)
I Version 6: printing the result (in Assembler as well)

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 1: Prging an LED 4 / 39
Tutorial 2: Programming an LED

This tutorial will deal with programming an LED output device.


This is the “hello world” program for external devices.
It will deal with programming techniques common to other output
devices.
The learning objective of this exercise is to learn how to directly
control an external device through C and Assembler programs.
Note: This year we will be using the online CPUlator (an ARM
simulator) for programming (virtual) external devices. This uses a
different chipset (De1-SoC by Altera) from the chip-set that’s on a RPi
(BCM2836 SoC by Broadcom). The RPi code that you might find
online, will NOT work on the CPUlator.
Documentation for the De1-SoC (Altera) chip is available here.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 5 / 39
Tutorial 2: Programming an LED

This tutorial will deal with programming an LED output device.


This is the “hello world” program for external devices.
It will deal with programming techniques common to other output
devices.
The learning objective of this exercise is to learn how to directly
control an external device through C and Assembler programs.
Note: This year we will be using the online CPUlator (an ARM
simulator) for programming (virtual) external devices. This uses a
different chipset (De1-SoC by Altera) from the chip-set that’s on a RPi
(BCM2836 SoC by Broadcom). The RPi code that you might find
online, will NOT work on the CPUlator.
Documentation for the De1-SoC (Altera) chip is available here.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 5 / 39
The high-level picture

From the main chip we want to control an (external) device, here


an LED.
We use one of the LEDs that is connected to the chip on the
CPUlator.
Logically we want to send 1 bit to this device to turn it on/off.
Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 6 / 39
The low-level picture

Programmatically we need to go through these steps:


Identify the peripheral registers, in charge of LEDs, from the Altera
De1-SoC manual
Identify the bits in the registers that control a specific LED
Then, directly access the device via memory read/writes into
these registers
Note: In the program, turning on an LED is typically just one write
operation
Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 7 / 39
Finding the registers in the manual

The relevant information can be found the hardware manual for


the relevant chip (for us, the DE1-SoC chip by Altera)
Such manuals are very detailed, since they need to cover all
issues about programming and usage (for CS as well as EE
applications)
To find the info in these documents, look for sections on
components / peripherals (for us, “2. DE1-SoC Computer
Contents”)
Specifically, we need the information on the LEDs, in Section
“2.5.7. Red LED Parallel Port”.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 8 / 39
Data explained

The picture (and discussion in the manual) tells us


The lowest 10 bits in the register at address 0xFF200020 are in
charge of 10 LEDs hard-wired to the chip
The remaining bits in the register are unused
Note that the processor has a word-size of 32-bits
Each of the lower bits controls one LED, and turns it on (bit: 1) or
off (bit: 0)
Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 9 / 39
Controlling an LED in C

Here is a simple program to turn on the first LED (from the right):
#define GPIOBASE 0xFF200000
static unsigned long *gpio = GPIOBASE;
void main () {
*gpio = 0b00000001;
}

In essence, this program performs one write operation: it writes the


value 1 into the memory address 0xFF200000, which we know is in
charge of the LEDs.
The value 1 represents the bitmask 0b00000001, meaning turn on the
first (rightmost) LED.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 10 / 39
CPUlator after running the program

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 11 / 39
Controlling an LED in ARM Assembler

We can achieve the same behaviour in ARM Assembler:


.text
LDR R0, =LEDBASE @ physical address of LEDs
MOV R2, #0b00000001 @ bitmask to turn on first LED
STR R2, [R0, #0] @ turn it on

.data
.equ LEDBASE, 0xFF200000

First we load the bitmask 0b00000001 (first LED on, all other
LEDs off) into register R2.
Then we write this value into the LED register.
The behaviour is the same as in the C program before.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 12 / 39
Next Task: Blinking LED in ARM Assembler

We now want to implement a blinking LED


This should be coded in ARM Assembler
We use the same principles as before, but need an (infinite) loop
We also need some kind of delay / timer functionality

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 13 / 39
Blinking LED in ARM Assembler

.global _start
_start:

start: LDR R2, =LEDBASE @ physical address of the LED


MOV R1, #10 @ counter
loop: NOP
EOR R3, #0b1 @ flip current value: 1->0, 0->1
STR R3, [R2] @ store value into LED register
BL delay
SUBS R1, #1 @ decrement counter & set flags
BNE loop @ R1 != 0 => continue loop
.data
.equ LEDBASE, 0xFF200000

One loop (with counter in R1), flipping a value (R3) in each iteration.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 14 / 39
The delay function in ARM Assembler

delay: PUSH {R4-R7,LR}


MOV R4, #0x0f
loop1: LDR R5, =#0xffff
body: NOP
SUBS R5, #1
BNE body
SUBS R4, #1
BNE loop1
POP {R4-R7,LR}
BX LR

In essence, two nested loops that do nothing.


The choice of the counters depends on the chip / simulator speed.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 15 / 39
Summary

Controlling a simple external device means logically sending 1 bit


of information (on/off)
Realising this control means physically writing into special
registers which have special meaning
The information on the special meaning is usually in bulky
hardware-description documentation
Once uncovered, the code for direct device control is fairly short

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 2: Prging an LED 16 / 39
Tutorial 3: Programming a Button input device

In this tutorial we want to use a button, as simulated on the


CPUlator
Usually, these devices would be connected through a breadboard.
A button is the simplest input device that we will cover.
The CPUlator simulates 4 push-buttons
The code needed to control is typical for such devices.
This tutorial deals with programming a button as input device.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 3: Prging a Button 17 / 39
Accessing Push-Buttons on the CPUlator

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 3: Prging a Button 18 / 39
Core Techniques

In the LED tutorial, we have seen that we first need to identify the
registers that give control to the device.
For that we will again look into the De1-SoC Manual
We need to identify the documentation for peripheral devices:
“2.5.10 Pushbutton Key Parallel Port” on page 10.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 3: Prging a Button 19 / 39
The low-level picture

We need to read from address 0xFF200050 to determine the


state of the buttons
Again there is a one-to-one relationship between the lowest 4 bits
in the register and the buttons:
if button 0 is pressed, bit 0 will be set to 1
if button 1 is pressed, bit 1 will be set to 1 etc
Thus, reading from the register and masking the right bit is all we
need to do.
Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 3: Prging a Button 20 / 39
Reading from a Button in ARM Assembler

.global _start
_start:
LDR R0, =BUTTONBASE @ physical address of the buttons
LDR R3, [R0] @ read value from BUTTON register
@ this will be a binary
representation of buttons
pressed
@ i.e. 1st and 2nd button pressed
=> 0b11 == 3
.data
.equ BUTTONBASE, 0xFF200050

We read the contents of the button register, containing the status of all
buttons, into register R3.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 3: Prging a Button 21 / 39
A button Press Counter in ARM Assembler
.global _start
_start:
start: LDR R0, =BUTTONBASE @ physical address of buttons
MOV R1, #10 @ loop counter
MOV R2, #0 @ button press counter
MOV R5, #1
LSL R5, #BUTTON_NO @ bitmask for testing BUTTON_NO
loop0: NOP
LDR R3, [R0] @ read value from BUTTON
register
CMP R3, R5
BNE nocount
ADD R2, R2, #1 @ increment press counter
nocount: BL delay
SUBS R1, #1
BNE loop0
.data
.equ BUTTONBASE, 0xFF200050
.equ BUTTON_NO, 0

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 3: Prging a Button 22 / 39
A button Press Counter in ARM Assembler
(Discussion)

This code continuously reads the button register


We prepare a bit-mask in R5 to identify the bit in charge of button
number BUTTON_NO.
We first read the contents of the button register into register R3.
We use the bit-mask in R5 to extract the bit in charge of button
number BUTTON_NO.
If this bit is on, we increment the counter in R2.
We finish the program after a fixed number of iterations (could
also use an infinite loop here)
When running this in the CPUlator do check that R2 acts as a
counter of how often a press has been registered
Note: In practice, you want to count distinct button presses, i.e.
don’t count a continuous button press several times
Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 3: Prging a Button 23 / 39
A button Press Counter in ARM Assembler
.global _start
_start:
start: LDR R0, =BUTTONBASE @ physical address of buttons
MOV R1, #10 @ loop counter
MOV R2, #0 @ button press counter
MOV R5, #1
LSL R5, #BUTTON_NO @ bitmask for testing BUTTON_NO
loop0: NOP
LDR R3, [R0] @ read value from register
AND R3, R5 @ extract the relevant bit
CMP R3, #0 @ check whether it is on
BEQ nocount
ADD R2, R2, #1 @ increment press counter
nocount: BL delay
SUBS R1, #1
BNE loop0
.data
.equ BUTTONBASE, 0xFF200050
.equ BUTTON_NO, 0
This version checks only for the specific button BUTTON_NO.
Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 3: Prging a Button 24 / 39
The delay function is the same as before

delay: PUSH {R4-R7,LR}


MOV R4, #0x0f
loop1: LDR R5, =#0xffff
body: NOP
SUBS R5, #1
BNE body
SUBS R4, #1
BNE loop1
POP {R4-R7,LR}
BX LR

These are in essence two nested loops, doing nothing in the body.
Needed to provide a delay between button reads.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 3: Prging a Button 25 / 39
Summary

Reading input from a button works in the same way as writing to


the LED:
I We need to read from a certain bit in a register, in charge of buttons.
With the button you have a basic input device to communicate
with the system
Other devices use the same principle, but communicate more
data, e.g. an 8-bit wide parallel port for I/O communication
With the CPUlator’s restrictions, we don’t discuss these devices in
any more detail this year

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 3: Prging a Button 26 / 39
Tutorial 4: Programming a HEX display

The De1-SoC chip (by Altera) on the CPUlator, provides several


7-segment displays, or HEX displays
These displays can be used to display numbers, and some letters
Therefore, the output is more meaningful than just one LED
The principle to program the display is the same as for the LED
But first we need to find the relevant information in the manual:
“2.5.8 7-Segment Displays Parallel Port” (page 10)

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 27 / 39
Program the 7-Segment (HEX) Displays in Assembler
Note:
1 segment controlled by 1 bit

The address for the data register of the HEX displays is


0xFF200020
The 7 segments in the HEX display are each controlled by 1 bit in
the HEX data register
The mapping of the bit positions to the segments is shown in the
picture on the right, e.g. bit 0 controls the upper bar in display 1
We need 7 bits per HEX display in the register (8th bit unused).
The next 7 bits are in charge of the next HEX display (HEX1) etc.
Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 28 / 39
Program the 7-Segment (HEX) Displays in Assembler
Note:
1 segment controlled by 1 bit

The address for the data register of the HEX displays is


0xFF200020
The 7 segments in the HEX display are each controlled by 1 bit in
the HEX data register
The mapping of the bit positions to the segments is shown in the
picture on the right, e.g. bit 0 controls the upper bar in display 1
We need 7 bits per HEX display in the register (8th bit unused).
The next 7 bits are in charge of the next HEX display (HEX1) etc.
Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 28 / 39
Controlling a HEX display in ARM Assembler

.global _start
_start: LDR R0, =HEXBASE @ physical address of the HEX
MOV R2, #0b1011011 @ bitmask for pattern of a ’2’
MOV R3, R2, LSL #24 @ display: 2
MOV R2, #0x3f @ bitmask using hex-repres.
ORR R3, R2, LSL #16 @ display: 0
MOV R2, #91 @ bitmask using a decimal no.
ORR R3, R2, LSL #8 @ display: 2
MOV R2, #6 @ again usin a decimal value
ORR R3, R2, LSL #0 @ display: 1
STR R3, [R0]
.data
.equ HEXBASE, 0xFF200020

This code displays the number 2021 on the four rightmost displays of
the CPUlator

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 29 / 39
HEX Display Example

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 30 / 39
Exercise: Button read and HEX display

As next exercise we want to continuously read from a button


device
and display on the HEX display whether we detected a press
(“on”) or not (“off”)
This combines the previous 2 exercises
The core structure is a loop (either infinite or with a fixed counter)
A delay is used in the loop to control the frequency of checks

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 31 / 39
Exercise: Button read and HEX display (structure)

_start:
start: LDR R2, =BUTTONBASE @ physical address of buttons

________________________ @ (1) construct bitmask


________________________ @ (1) construct bitmask
loop0: NOP
LDR R3, [R2] @ read value from BUT register
CMP R3, ___ @ (2) check against bitmask
______________________ @ (3) not pressed => OFF
nocount:
______________________ @ (3) pressed => ON
BL delay
B loop0 @ NB: infinite loop

We need to construct a bitmask for selecting the bit matching button


BUTTON_NO in (1).

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 32 / 39
Exercise: Button read and HEX display (structure)

_start:
start: LDR R2, =BUTTONBASE @ physical address of buttons

MOV R5, #1
LSL R5, #BUTTON_NO @ (1) bitmask testing BUTTON_NO
loop0: NOP
LDR R3, [R2] @ read value from BUT register
CMP R3, ___ @ (2) check against bitmask
______________________ @ (3) not pressed => OFF
nocount:
______________________ @ (3) pressed => ON
BL delay
B loop0 @ NB: infinite loop

In (2) we need to check R3 against the bitmask constructed above.


In (3) we need to call sub-routines to show either “on” or “off”.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 33 / 39
Exercise: Button read and HEX display

_start:
start: LDR R2, =BUTTONBASE @ physical address of buttons

MOV R5, #1
LSL R5, #BUTTON_NO @ (1) bitmask for testing
BUTTON_NO
loop0: NOP
LDR R3, [R2] @ read value from BUT register
CMP R3, R5
BLNE showoff @ (3) not pressed => OFF
nocount:
BLEQ showon @ (3) pressed => ON
BL delay
B loop0 @ NB: infinite loop

Now we still need to define the sub-routines showon and showff.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 34 / 39
Exercise: Button read and HEX display (show)

showon: PUSH {R4-R7, LR}


LDR R4, =HEXBASE
LDR R5, =char_o
LDRB R6, [R5]
LSL R6, #8
LDR R5, =char_n
LDRB R7, [R5]
ORR R6, R7
MOV R0, R6
STR R0, [R4]
POP {R4-R7, LR}
BX LR

This displays “on” on the HEX displays, without disrupting registers.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 35 / 39
Exercise: Button read and HEX display (show)

showoff: PUSH {R4-R7, LR}


LDR R4, =HEXBASE
LDR R5, =char_o
LDRB R6, [R5]
LSL R6, #8
LDR R5, =char_f
LDRB R7, [R5]
ORR R6, R7
LSL R6, #8
LDR R5, =char_f
LDRB R7, [R5]
ORR R6, R7
MOV R0, R6
STR R0, [R4]
POP {R4-R7, LR}
BX LR

This displays “off” on the HEX displays, without disrupting registers.


Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 36 / 39
Constants for the letters to display

Below we define the bit-patterns for the letters that we need.


.align 4
char_o: .byte 0b1011100 @ o
char_n: .byte 0b1010100 @ n
char_f: .byte 0b1110001 @ f

See the picture about the 7-segement display at the beginning of the
slide set to match bit-patterns to segments on the display.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 37 / 39
Summary

Reading from a button, amounts to reading from a register and


selecting the right bit (1 bit)
Writing to a display, amounts to writing to a register and defining
the right bit pattern (7 bits)
All other input/output operations for external devices can be built
on top of this basic functionality
Details of registers and how to access them vary from chip to chip
For example, the Raspberry Pi 2 also uses an ARM core, but a
BCM2835 chip
The handling of LEDs and buttons is therefore different, and more
complex on the Raspberry Pi 2.
Optional: For those interested, complete tutorials for programming the
Raspberry Pi 2 are available on the course’s web page for 2019/20.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 38 / 39
Summary

Reading from a button, amounts to reading from a register and


selecting the right bit (1 bit)
Writing to a display, amounts to writing to a register and defining
the right bit pattern (7 bits)
All other input/output operations for external devices can be built
on top of this basic functionality
Details of registers and how to access them vary from chip to chip
For example, the Raspberry Pi 2 also uses an ARM core, but a
BCM2835 chip
The handling of LEDs and buttons is therefore different, and more
complex on the Raspberry Pi 2.
Optional: For those interested, complete tutorials for programming the
Raspberry Pi 2 are available on the course’s web page for 2019/20.

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 4: Prging a Button 38 / 39
Tutorial 5: Cache-friendly Programming

Hans-Wolfgang Loidl (Heriot-Watt Univ) F28HS Hardware-Software Interface Tutorial 5: Cache-friendly Programming 39

You might also like