1- Introduction:
Lesson 5 basically builds on the
operating system of lesson4 and the objective of lesson 5 is to show how we can
use the SOS, which is a Morse Code ,in order to flashing the ‘ACT’ LED. Morse
Code (SOS) is a sequence of three dots, three slashes, then three dots (…---…).
Generally, we classify data into a specific type such as text, image, and so,
then we store different types of data into their related files. Actually, a
computer deals with different types of data in the same manner; they are
represented in binary numbers. This data explanation is also true
for Mores Code, so we are going to use a sequence of SOS Mores Code pattern in
order to flash “ACT LED. The flashing pattern should be a sequence of three
short pulses, three long pulses and finally three more shorts pulses, and after
the required delay is over, this sequence of flashing keeps on
forever until disconnecting the Raspberry PI from a proper supply source.
2-
Materials and Procedures:
In
order to carry this assignment out, there are two types of requirements .The
first type is the required equipment and the second one is the software and the
operating system.
2.1Equipment:
1-A Raspberry
Pi board (it is a single circuit that considered as a
computer which, primary runs on a version of Linux).
2-A
computer uses a Microsoft Windows-based Operating System.
3- A
SD card (it is a memory card).
4-
A power supply.
2.2Software:
1- Using the GNU
compiler toolchain in order to deal with the architecture
2- The OS Template File
(It
provides a Makefile script, a Linker script and no assembly
code would be provided. Since the compiler needs required instructions in order to create Operating
System for the Raspberry Pi, those instructions have been provided by the OS
Template file )
2.3 Experimental Procedure
The ARM assembly code for Lesson 5:
main's:
main's:
.section .init
.globl _start
_start:
.section .init
and .globl _start are directives that instructs the assembler in order to put
our assembly code in a section its name is ( .init ). Because of
that, we will be able to control the order of the code execution.
Also, the GNU toolchain needs a entry point to work properly, so we need
to include symbol _start. Then, we need global, which is
required by the linker. Then ( _start:) to start the address of
the new line.
In order to branch to the actual main code, we use (b main)
In order to put this code with the rest, we use this command
(.section .text) tells the assembler.
main:
Now we are making the stack pointer to point to setting the 0x8000.
mov sp,#0x8000
In order to set the function of GPIO port 16 to be ‘’ACT” LED with
(001 base 2 or binary), we use a new SetGpioFunction function.
mov r0,#16
set r0 to pin 16
mov r1,#1
set r1 to pin 1
bl SetGpioFunction
In this block of instructions, our objective to load the pattern into
flash and also storing the required position in the flaqsh sequence.
ptrn .req r4
store ptrn in register r4
ldr ptrn,=pattern
load the pattern in r4
ldr ptrn,[ptrn]
seq .req r5
load register r0 in the
register r5 with ability of
always finding the sequence location
mov seq,#0
loop$:
If the pattern contains 0 then the LED will turn on, but if the
pattern contains 1 then the LED will turn off.in order to do that, we use the
new GPIO 16 base on the current bit.
mov r0,#16
pin 16 in r0
mov r1,#1
pin 1 in ri
lsl r1,seq
Using logical-shift-left (lsl) to shift r1 to the left by sequence
value.
and r1,ptrn
here is condition that states; if there exists 1 bl SetGPIO ,then r1 holds nonzero value
bl SetGpio.
In order to achieve the delay, we load a value of 250000 micrseconds
into the register r0 and that will make the processor busy by counting down
from 250000 micrseconds to 0 second.
ldr r0,=250000
bl Wait
When the sequence counter reaches 32 its pattern holds 100000. Then
by applying this loop over this process in order to increment the sequence
counter , its pattern holds 11111
makes it return to 0.But all of that has no effect on less than 32.
add seq,#1
and seq,#0b11111
b loop$
.section .data
In order to separate data from instructions, we put (.section .data)
at the end of the code and keeping the data in it. So in the case of
implementing some security on our operating system, we can control which part
that need to be executed apart from the other.
.align 2
In order to be sure that the address of the next line will be
multiplied by 2^2, we use the (align 2).
pattern: .int 0b11111111101010100010001000101010
I use this quote from http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/ok05.html to describe( pattern:
.int 0b11111111101010100010001000101010);
“The .int command
copies the constant after it into the output directly. That means that
111111111010101000100010001010102 will
be placed into the output, and so the label pattern actually labels this
piece of data as pattern.”
From the previous description, if the output
holds a zero values then the LED will be off ,and if the output holds one(1)
value then the LED will be on”ACT” ,or
OK.
push {lr}
mov r2,pinNum
.unreq pinNum
pinNum .req r2
bl GetGpioAddress
gpioAddr .req r0
|
systemtimer's:
We need code to deal with the system timer, which is a counter that
runs at 1MHz, and that system timer is used to count the difference between
two measurements.
In order to return the value of the base address of the System Timer
region into register r0, we use GetSystemTimerBase.
.globl GetTimeStamp
GetSystemTimerBase:
ldr
r0,=0x20003000
mov pc,lr
Loading the address of the system timer (0x20003000) in r0, then move
the pc to the value of the lr.
In order to get the current timestamp of the system timer, we use the
GetTimeStamp. Then the return will be in register r0 and r1, while r1 is the
most significant 32 bits.
.globl GetTimeStamp
GetTimeStamp:
push {lr}
bl
GetSystemTimerBase
ldrd
r0,r1,[r0,#4]
pop {pc}
Pushing the ( lr ),then we call the function
(GetSystemTimerBase).since the value of
counter is 8 byte and a register is 4byte,we need to store
the value of the counter which is 8 byte into two registers. After that, we
pop the pc.
.globl Wait
Wait:
delay .req r2
mov delay,r0
push {lr}
bl GetTimeStamp
start .req r3
mov start,r0
In order to make a delay, we need to store a specified number of
microseconds in r2, and then copy this waiting value from r2 into r0. Pushing
the lr, then call the function of (GetTimeStamp).after assigned the register
r3, copy the value of r0 into r3.
loop$:
bl
GetTimeStamp
elapsed
.req r1
sub
elapsed,r0,start
cmp
elapsed,delay
.unreq
elapsed
bls
loop$
.unreq delay
.unreq start
pop {pc}
Calling the function of (GetTimeStamp), then subtract r3 from r0.
Now, we have a condition that compares if the delay not equals elapsed then
continue, otherwise, stop. if the elapsed is less than delay ,then continue
and delete alias. Finally, pop pc.
|
GPIO's:
In order to return the base address of the GPIO region in register
r0, we use GetGpioAddress.
.globl GetGpioAddress
GetGpioAddress:
gpioAddr .req r0
ldr
gpioAddr,=0x20200000
mov pc,lr
.unreq gpioAddr
Assigned gpioAddr to register r0, and then loading GPIO address in
r0. 0x20200000 will be copied into program counter (pc), and then deleting
stored GPIO address.
In order to set the function of the GPIO register addressed by r0 to
the low 3 bits of r1, we use SetGpioFunction.
.globl SetGpioFunction
SetGpioFunction:
pinNum .req r0
pinFunc .req r1
Assigned pinNumt to register r0 and pinFunc to r1.
cmp pinNum,#53
cmpls pinFunc,#7
since range is (from 0 to 53
pins) of GPIO, then using the comparing r0 in order to set the range
In this the condition; 1-comparing r0 with #53 and if the value is
less or equal to 53.
2- r1 with 7 in order to verify if r1 within the 8 function pins .
movhi pc,lr
In this condition. If the both (1)&(2) are satisfied then do not
run, otherwise runs.
push {lr}
Copy the value in lr into r0.
mov r2,pinNum
Move GPIO address from r0 to r2.
.unreq pinNum
Delete the assigned.
pinNum .req r2
Assigned pinNum to register r2.
bl GetGpioAddress
Call the function.
gpioAddr .req r0
Assigned gpioAddr register r0.
functionLoop$:
cmp pinNum,#9
Comparing pinNum, to #9.
subhi pinNum,#10
If the value is greater than 9 then subtract 10 from the pin.
addhi gpioAddr,#4
bhi functionLoop$
Add 4 to GPIO,then run
add pinNum, pinNum,lsl #1
Logical-left-shift by 1 is equivalent to multiplication by 2 then add
the value of r2 (r2*2+r2) .
lsl pinFunc,pinNum
The function value will be shifted by the value of r2.
mask .req r3
Assigned mask to r3,.
mov mask,#7
r3 takes the value of 7, r3 =
111 (base2).
lsl mask,pinNum
Shifting r3 left by the value of r2.
Where r3 and the function in r1 have the same position 111.
.unreq pinNum
Deleting assigned.
mvn mask,mask
r3 = 11..1100011..11 and the
function in r1 have the same position 000 .
oldFunc .req r2
oldFunc is assigned to register r2.
ldr oldFunc,[gpioAddr]
Loading the GPIO address into r2.
.unreq mask
Deleting assigned.
.unreq oldFunc
Deleting assigned.
str pinFunc,[gpioAddr]
store the value of GPIO in pinFunc.
.unreq pinFunc
Deleting assigned.
unreq gpioAddr
Deleting assigned.
pop {pc}
/* NEW
In order to set the GPIO pin addressed (in r0) as high if r1 is not
equal to 0 , otherwise, set the GPIO pin addressed as low .we use SetGpio.
.globl SetGpio
SetGpio:
pinNum .req r0
Assinged pinNum to register r0
.
pinVal .req r1
Assinged pinVal to register r1.
cmp pinNum,#53
by comparing r0 with 53 ,we set the range from(0 to 53 pins in GPIO)
movhi pc,lr
The return is done when r0 is greater than 53.
push {lr}
mov r2,pinNum
miving the value from r0 to r2.
.unreq pinNum
Delete assigned.
pinNum .req r2
Assigned pinNum to register r2.
bl GetGpioAddress
Call function.
gpioAddr .req r0
Assigned gpioAddr to register r0.
pinBank .req r3
Assigned pinBank to register r3.
lsr pinBank,pinNum,#5
Since GPIO has two sets of 4 bytes, we divide the pins numbers by 32
in order to turn pins on and off (32 and 22).
lsl pinBank,#2
Logical-shift-left by 2 is equivalent to multiplication by 4 ,(4
bytes will be multiplied by 4).
add gpioAddr,pinBank
The pin will be on if the 28-10 is added, and the pin will be off if
40-10 is added.
.unreq pinBank
Delete assigned.
and pinNum,#31
pinNum is divided by 32 then
the remainder will never be greater than 0-31.
setBit .req r3
Assigned setBit to r3.
mov setBit,#1
setBit takes value of 1.
lsl setBit,pinNum
Logical-shift-left by 1 for the value of pinNum.
.unreq pinNum
Delete assigned.
teq pinVal,#0
Test if the value of pinVal equals to zero.
.unreq pinVal
Delete assigned.
streq setBit,[gpioAddr,#40]
Store setBit at 40 away from GPIO if the value of pinVal is equal to
zero. As result of that, the pin will be off, and the LED will be on.
strne setBit,[gpioAddr,#28]
Store setBit at 28 away from GPIO if the value of pinVal is not equal
to zero. As result of that, the pin will be on, and the LED will be off.
.unreq setBit
.unreq gpioAddr
Delete the two assigned.
pop {pc}
The value of pc will set back to the value of the lr.
|
3. Results: