- The document describes an experiment involving interfacing an ARM microcontroller with LEDs using GPIO pins and writing assembly code subroutines.
- Key objectives were to gain experience with the ARM development environment, writing subroutines, GPIO initialization, and generating LED flashing patterns.
- The experiment involved writing subroutines to turn individual LED pins on and off without affecting others, and a function to toggle a green LED at different rates depending on whether a button was pressed.
Gain Experience with GPIO, LED Interface and Functions in TI TIVA C Launchpad Development Board.
1. AENG 505 – INTRO TO EMBEDDED SYSTEMS
Dr. Jaerock Kwon
Experiment-2
GPIO, LED Interface, Functions
Nipun Kumar – 31440148
2. Objectives:
● To gain experience with the ARM Assembly and the TI TIVA C Launchpad Development
Board.
● To gain experience the CCS ARM development environment and debugging features.
● To gain experience writing subroutines and passing parameters.
● To gain experience with software delay loops and generating square waves, flashing LED.
● To gain experience with general purpose input/output (GPIO) subsystem initialization.
Experiment Result:
Q1) After installation of CCS, Exp1 starter project is imported and built for any errors.
Later it is flashed to the controller and observed that blue LED starts blinking and turns
off after 1 second. By changing the code in LoopBlue, it is observed that blinking pattern
can be delayed by adding more delay functions.
Ans: To set Pin0 off in Port D, first bit in GPIO_PORTD_DATA_R has to be set to 0. AND
Op code is used to perform bit wise AND operation for GPIO_PORTD_DATA_R value and
0xFE ( first bit is 0 and remaining all are ones). All other seven-bit values are restored except
for first bit which becomes 0. Subroutine PortD_Pin0_Off is exported from Port D.asm file
and imported in main.asm file before accessing.
;------------PortD_Pin0_Off------
; Turn off the Port D Pin 0 without changing other pin values
; Input: None
; Output: None
; Modifies: R0, R1
PortD_Pin0_Off: .asmfunc
LDR R1, GPIO_PORTD_DATA_R ; R1 = &GPIO_PORTD_DATA_R
LDR R0, [R1] ; R0 = [R1]
AND R0, R0, #0xFE ; R0 = R0 & 0xFE set pin_0 to 0
STR R0, [R1] ; [R1] = R0
BX LR
.endasmfunc
3. • After subroutine PortD_Pin0_On:
• After subroutine PortD_Pin0_Off:
Q2) Show and discuss your green_led_toggle function. This function should only
manipulate the green LED pin and leave other Port F pins as they were.
Ans: Green LED is hardwired to fourth pin in port F. To toggle the LED on and off, fourth bit
value in GPIO_PORTF_DATA_R address must be changed from 0 to 1 and vice versa. So, bit
wise XOR operation is done with Port F data and 0x08 (fourth bit is 1) as operand to change
4. the fourth bit value. Subroutine code is shown below. R1 register stores the address of
GPIO_PORTF_DATA_R and R0 register is used to store its value and perform XOR operation.
Register bit Operand bit After XOR operation
1 1 0(~ Register bit=1)
0 1 1(~ Register bit=0)
;------------green_led_toggle------
; Change the green Led light from on to off and vice versa
; Input: None
; Output: None
; Modifies: R0, R1
green_led_toggle: .asmfunc
LDR R1, GPIO_PORTF_DATA_R ; R1 = &GPIO_PORTF_DATA_R
LDR R0, [R1] ; R0 = [R1]
EOR R0, R0, #0x08 ; R0 = R0 XOR 0x08 changes the
4th bit(Green LED) value from 0 to 1 and vice versa
STR R0, [R1] ; [R1] = R0
BX LR
.endasmfunc
Q3) Show and describe how you implemented your subroutine and the mechanism you
used to pass the input parameters to it. Also describe how the CPU registers are affected
by your subroutine.
Ans:
• Firstly, the address in LR, which is the next line after calling timed_green_led_toggle
subroutine in main code, must be stored in stack to remember the address. This is needed
as there are multiple functions called inside a function using BL Op code. R13 register
(Stack pointer) is modified by using push operation code.
• Green LED is toggled by calling the function green_led_toggle, which acts as an on/off
switch for green LED. R0 and R1 registers are modified to perform the toggle operation
as explained above.
5. • By calling the delay function, green LED condition is retained for stored delay time in R10
register. At the end of delay function, R10 register value becomes 0.
• Address stored in the stack is popped back into the Link register using POP op code to
execute the next code in main block. R13 register( Stack pointer) is modified.
;------------timed_green_led_toggle------
; Toggles the green Led light based on inputted delay time in R10 register
; Input: R10 in delay subroutine
; Output: None
; Modifies: None
timed_green_led_toggle: .asmfunc
PUSH {LR} ; Push the next address in LR into stack
BL green_led_toggle ; Toggles the green LED on or off
BL delay ; Delays the green LED in on or off
condition for time stored in R10
POP {LR} ; Restores the initially saved address
back to LR from stack
BX LR ; Go to the address in LR i.e., the
B Mainloop in main
.endasmfunc
Q3) Next, write a program in main that calls your subroutine to flash the green LED at
two different rates based on whether switch 1 pressed or not:
- Left button (SW1) not pressed: green LED flashes at a rate of once per second. On for
one second off for one second then the sequence repeats as long as the button is not
pressed.
- LEFT button pressed: green LED flashes at a rate of 10 times per second. On for one
0.1 second off for 0.1 second then the sequence repeats as long as the button is pressed.
Ans:
• SW1 is hardwired to pin 5 of port F. Switches are connected using negative logic which
sets the fifth bit to 0 when pressed, else to 1.
• So, to check whether SW1 is pressed or not AND op code is used to perform bit wise
AND with port F data and 0x10. The result will set the Z bit when switch is pressed
else no.
6. When SW1 is pressed When SW1 is not pressed
Port F data (first 8 bits) ---0---- ---1----
0x10 00010000 00010000
AND operation result 00000000 00010000
Z bit 1 0
• BEQ op code is used to go to else loop when Z bit is set, or else next set of code is
executed.
• R10 value is set to ONESEC when Z bit is not set i.e., when SW1 is not pressed. Then
timed_green_led_toggle subroutine is executed with saved R10 value.
• R10 value is set to POINTONESEC in Else loop when Z bit is set i.e., when SW1 is
pressed. Then timed_green_led_toggle subroutine is executed with saved R10 value.
MainLoop
LDR R1, GPIO_PORTF_DATA_R ; R1 = &GPIO_PORTF_DATA_R
LDR R0, [R1] ;R0 = [R1]
MOV R3, #0x10 ; R3 = #0x10
ANDS R3, R0 ; R3 = R3 & #0x10 which sets all other bits to
zero except the fifth and sets the Z bit when
switch is pressed else not
BEQ Else ;Go to else loop if Z bit is set
LDR R10, ONESEC ; R10 = 5333333,32 value for 1 sec delay
BL timed_green_led_toggle ; Go to timed_green_led_toggle subroutine
B MainLoop ; Go to MainLoop and repeat
;Else block to be executed when SW1 is pressed i.e., when Z bit is set
Else
LDR R10, POINTONESEC ; R10 = 533333,32 value for 0.1 sec delay
BL timed_green_led_toggle ; Go to timed_green_led_toggle subroutine
B MainLoop ; Go to MainLoop and repeat
.endasmfunc
Q4) Record a brief video demonstrating this program.
https://youtu.be/8B6D2RfFwzo
7. Conclusion:
• In this experiment, initialization of GPIO port D and F is done and specific pins inside
a GPIO can be set as on or off using subroutines written in different assembly files by
import and export. With this, we can connect the specific ports after initialization as
above, to external components either as input or output.
• By using conditional branching based on SW1 input, blinking pattern of green LED
output is varied with the help of nested subroutines and stack pointer. The similar
function is achieved using If else logic in high level languages.
• The importance of Link register and stack pointer is understood with the usage of
multiple BL op codes inside a single subroutine. Initial address in LR, while calling
first subroutine, is stored inside stack pointer to return to the same address at the end of
subroutine.
• In this experiment, it is not possible to call delay subroutine multiple times without
restoring the R10 register value. This is because delay function takes R10 as input and
makes it 0 when it is completed.
• When multiple push is done inside the stack pointer, program seems to enter an infinite
loop after the second push operation.