Week 7
ASM Programming: Turn on an LED (Part 1)
COS10004 Computer Systems · Lecture 7.4 ASM Programming: Turn on an LED (Part 1)
- ASM basics
TURNING ON A LIGHT!
- We are now ready to program, so lets start playing!
- We’re going to walk through the asm code for turning on an LED connected to a pin
FIRST WE WIRE IT UP
See https://www.youtube.com/watch?v=Rd9kvVs1lSQ for my tutorial on wiring this circuit
We “write” bits to the LED via this pin
See https://www.youtube.com/watch?v=Rd9kvVs1lSQ for my tutorial on wiring this circuit
This is the ground pin
We “write” bits to the LED via this pin
See https://www.youtube.com/watch?v=Rd9kvVs1lSQ for my tutorial on wiring this circuit
- Lets look at the code in FASMARM first, then unpack how it works
TURNING ON AN LED
BASE = $FE000000 ; $ means HEX GPIO_OFFSET=$200000 mov r0,BASE orr r0,GPIO_OFFSET ;r0 now equals 0xFE200000 mov r1,#1 lsl r1,#24 ;write 1 into r1, lsl 24 times to move the 1 to bit 24 str r1,[r0,#4] ;write it into 5th (16/4+1)block of function register mov r1,#1 lsl r1,#18 ;write 1 into r1, lsl 18 times to move the 1 to bit 18 str r1,[r0,#28] ;write it into first block of pull-up register
loop$: b loop$;loop forever
TURNING ON AN LED
We can set constants.
BASE = $FE000000 ; $ means HEX GPIO_OFFSET=$200000 The name on the left must
be a unique name. Make it
mov r0,BASE sensible so you know what it orr r0,GPIO_OFFSET ;r0 now equals 0xFE200000 represents. mov r1,#1 lsl r1,#24 ;write 1 into r1, lsl 24 times to move the 1 to bit 24 str r1,[r0,#4] ;write it into 5th (16/4+1)block of function register The value on the right can be
expressed as a decimal value
mov r1,#1 or HEX. lsl r1,#18 ;write 1 into r1, lsl 18 times to move the 1 to bit 18 str r1,[r0,#28] ;write it into first block of pull-up register Decimal starts with a #
loop$: Hex values start with a $ b loop$;loop forever
BASE = $FE000000 ; $ means HEX Instructions to execute. GPIO_OFFSET=$200000
Here you can see the
mov r0,BASE following instructions orr r0,GPIO_OFFSET ;r0 now equals 0xFE200000 being used:
Mov, orr, lsl, str, b
mov r1,#1 lsl r1,#24 ;write 1 into r1, lsl 24 times to move the 1 to bit 24 We’ll look at them in more str r1,[r0,#4] ;write it into 5th (16/4+1)block of function register detail shortly mov r1,#1 lsl r1,#18 ;write 1 into r1, lsl 18 times to move the 1 to bit 18 str r1,[r0,#28] ;write it into first block of pull-up register
loop$: b loop$;loop forever
TURNING ON AN LED
BASE = $FE000000 ; $ means HEX GPIO_OFFSET=$200000 mov r0,BASE orr r0,GPIO_OFFSET ;r0 now equals 0xFE200000 mov r1,#1 lsl r1,#24 ;write 1 into r1, lsl 24 times to move the 1 to bit 24 In-line comments (non str r1,[r0,#4] ;write it into 5th (16/4+1)block of function register executable) start with a semi
colon
mov r1,#1 lsl r1,#18 ;write 1 into r1, lsl 18 times to move the 1 to bit 18 Use these to make your code str r1,[r0,#28] ;write it into first block of pull-up register Easily readable and
interpretable loop$: b loop$;loop forever
BASE = $FE000000 ; $ means HEX GPIO_OFFSET=$200000 mov r0,BASE Labels mark a location (an orr r0,GPIO_OFFSET ;r0 now equals 0xFE200000 actual address!) in your asm
code.
mov r1,#1 lsl r1,#24 ;write 1 into r1, lsl 24 times to move the 1 to bit 24 They are uniquely named str r1,[r0,#4] ;write it into 5th (16/4+1)block of function register and end with a colon. mov r1,#1 These allow you to jump lsl r1,#18 ;write 1 into r1, lsl 18 times to move the 1 to bit 18 from one location to another str r1,[r0,#28] ;write it into first block of pull-up register in your code
(eg. for looping, branching loop$: b loop$;loop forever function calls etc)
In this case its being used as part of an infinite loop..but why?
ASSEMBLY
mov;move value into register (does not require RAM)* lsl;logical left shift (double a number n times) str;store (write) value from register to a memory location Loop:;a label** b;branch (goto)
*mov cannot be used to represent some 32-bit numbers. The alternative is ldr, which we will cover later. For more explanations look here:
http://stackoverflow.com/questions/14046686/why-use-ldr-over-mov-or-vice- versa-in-arm-assembly
**In some ASM the word loop is reserved, so people use loop$, l00p, loop2 etc.
delimiter
MOVE
mov r1,#1
register 1 value in decimal
literal value
(not a pointer)
- load register 1 with the value 1*
*not all numbers can be used
delimiter
OR
orr r1,$21
register 1 value in
HEX
operand (may be a register,
pointer, • r1 = r1 OR operand
literal)
- Adds two numbers together without possibility of overflow or carry operations
delimiter
LOGICAL SHIFT LEFT
lsl r1,#21
register 1 value in decimal
literal value
(not a pointer) • logical shift left (double) register 1 21 times
- (multiply by 221)
- (r1 = 2097152 = 0x200000)
- (bit 21 is set)
- (00000000 00100000 00000000 00000000)
BRANCH
- Loop: label
- b Loop
branch label (could also use a (goto) where to memory address if we go knew where the code was loaded)
- loop forever
- stops it from crashing
delimiter
STORE REGISTER
str r1,[r0,#16]
register 1 offset value in decimal
reference
(a pointer)
- write value r1 into the memory location: 16 bytes after the value in r0
- [0x20200010] = 0x200000
delimiter
LOAD REGISTER
ldr r0,[r1] r1 must contain a
pointer to a value in memory
- load register 0 with the value pointed to by r1
GENERAL PURPOSE REGISTERS
- The Armv7 CPU has 13 General Purpose 32-bit registers to work with.
- Armv8 (e.g.,RPi4) actually has 31 64-bit registers.
- r0, r1,... r12.
- We use these registers to load in values, perform operations and write back out to memory
- We also use them to pass arguments to functions (we’ll get to these later)
TURNING ON AN LED
BASE = $FE000000 ; $ means HEX GPIO_OFFSET=$200000 You will notice a lot of
numbers being referred to
mov r0,BASE in this code. orr r0,GPIO_OFFSET ;r0 now equals 0xFE200000
Lets look at some of these
mov r1,#1 and why they are there lsl r1,#24 ;write 1 into r1, lsl 24 times to move the 1 to bit 24 str r1,[r0,#4] ;write it into 5th (16/4+1)block of function register mov r1,#1 lsl r1,#18 ;write 1 into r1, lsl 18 times to move the 1 to bit 18 str r1,[r0,#28] ;write it into first block of pull-up register
loop$: b loop$;loop forever
TURNING ON AN LED
This is the “peripheral”
BASE = $FE000000 ; $ means HEX base address. This specific GPIO_OFFSET=$200000 value represents the base
address of all registers on
mov r0,BASE the RPi 4 that interface orr r0,GPIO_OFFSET ;r0 now equals 0xFE200000 with peripheral
components (eg the GPIO
mov r1,#1 pins) lsl r1,#24 ;write 1 into r1, lsl 24 times to move the 1 to bit 24 str r1,[r0,#4] ;write it into 5th (16/4+1)block of function register mov r1,#1 lsl r1,#18 ;write 1 into r1, lsl 18 times to move the 1 to bit 18 str r1,[r0,#28] ;write it into first block of pull-up register
loop$: b loop$;loop forever
TURNING ON AN LED
BASE = $FE000000 ; $ means HEX This is the offset from the GPIO_OFFSET= $200000 base address that marks mov r0,BASE the start of the GPIO orr r0,GPIO_OFFSET ;r0 now equals 0xFE200000 registers (which we need
to read and write to/from
mov r1,#1 the GPIO pins). lsl r1,#24 ;write 1 into r1, lsl 24 times to move the 1 to bit 24 str r1,[r0,#4] ;write it into 5th (16/4+1)block of function register mov r1,#1 lsl r1,#18 ;write 1 into r1, lsl 18 times to move the 1 to bit 18 str r1,[r0,#28] ;write it into first block of pull-up register
loop$: b loop$;loop forever
TURNING ON AN LED
These two operations add
BASE = $FE000000 ; $ means HEX the GPIO OFFSET to the GPIO_OFFSET= $200000 BASE address. mov r0,BASE Mov moves the value orr r0,GPIO_OFFSET ;r0 now equals 0xFE200000 referred to by BASE into mov r1,#1 the register r0 lsl r1,#24 ;write 1 into r1, lsl 24 times to move the 1 to bit 24 str r1,[r0,#4] ;write it into 5th (16/4+1)block of function register orr has the effect of
adding GPIO_OFFSET to
mov r1,#1 the current contents of r0 lsl r1,#18 ;write 1 into r1, lsl 18 times to move the 1 to bit 18 (BASE). str r1,[r0,#28] ;write it into first block of pull-up register The result is stored in r0,
loop$: which now refers to the b loop$;loop forever base memory address of the GPIO registers
WHICH BASE ADDRESS FOR WHICH RPI
The peripheral base address depends on which model Pi you are using.
Notice however that the GPIO offset value is the same for all See https://github.com/FelipMarti/COS10004-RPi for more information on Pi model specifics
TURNING ON AN LED
BASE = $FE000000 ; $ means HEX GPIO_OFFSET=$200000
What about these numbers?
mov r0,BASE orr r0,GPIO_OFFSET ;r0 now equals 0xFE200000
Where did they come from
mov r1,#1 And what do they mean ? lsl r1,#24 ;write 1 into r1, lsl 24 times to move the 1 to bit 24 str r1,[r0,#4] ;write it into 5th (16/4+1)block of function register These numbers all refer to
settings and programming of
mov r1,#1 the GPIO registers. lsl r1,#18 ;write 1 into r1, lsl 18 times to move the 1 to bit 18 str r1,[r0,#28] ;write it into first block of pull-up register To understand this part of the
Code we need to understand loop$: what the GPIO chip is, and b loop$;loop forever how we interface with it to read to and write from the GPIO header pins.
SUMMARY
- We have seen the structure of a simple Arm asm program
- We have defined some operations:
- Mov, orr, lsl, str, ldr, b
- ARMv7 gives us 13 general purpose registers (r0- r12) to store values with
- The peripheral base address refers to the start of the peripheral registers:
- Pi model specific so you need to know which one is for you!
- Next – the GPIO chip and how to program it!