-
Notifications
You must be signed in to change notification settings - Fork 21
/
gpio.s
executable file
·118 lines (103 loc) · 2.93 KB
/
gpio.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/******************************************************************************
* gpio.s
* by Alex Chadwick
*
* A sample assembly code implementation of the input02 operating system.
* See main.s for details.
*
* gpio.s contains the rountines for manipulation of the GPIO ports.
******************************************************************************/
/*
* According to the EABI, all method calls should use r0-r3 for passing
* parameters, should preserve registers r4-r8,r10-r11,sp between calls, and
* should return values in r0 (and r1 if needed).
* It does also stipulate many things about how methods should use the registers
* and stack during calls, but we're using hand coded assembly. All we need to
* do is obey the start and end conditions, and if all our methods do this, they
* would all work from C.
*/
/*
* GetGpioAddress returns the base address of the GPIO region as a physical address
* in register r0.
* C++ Signature: void* GetGpioAddress()
*/
.globl GetGpioAddress
GetGpioAddress:
gpioAddr .req r0
ldr gpioAddr,=0x20200000
mov pc,lr
.unreq gpioAddr
/*
* SetGpioFunction sets the function of the GPIO register addressed by r0 to the
* low 3 bits of r1.
* C++ Signature: void SetGpioFunction(u32 gpioRegister, u32 function)
*/
.globl SetGpioFunction
SetGpioFunction:
pinNum .req r0
pinFunc .req r1
cmp pinNum,#53
cmpls pinFunc,#7
movhi pc,lr
push {lr}
mov r2,pinNum
.unreq pinNum
pinNum .req r2
bl GetGpioAddress
gpioAddr .req r0
functionLoop$:
cmp pinNum,#9
subhi pinNum,#10
addhi gpioAddr,#4
bhi functionLoop$
add pinNum, pinNum,lsl #1
lsl pinFunc,pinNum
mask .req r3
mov mask,#7 /* r3 = 111 in binary */
lsl mask,pinNum /* r3 = 11100..00 where the 111 is in the same position as the function in r1 */
.unreq pinNum
mvn mask,mask /* r3 = 11..1100011..11 where the 000 is in the same poisiont as the function in r1 */
oldFunc .req r2
ldr oldFunc,[gpioAddr] /* r2 = existing code */
and oldFunc,mask /* r2 = existing code with bits for this pin all 0 */
.unreq mask
orr pinFunc,oldFunc /* r1 = existing code with correct bits set */
.unreq oldFunc
str pinFunc,[gpioAddr]
.unreq pinFunc
.unreq gpioAddr
pop {pc}
/*
* SetGpio sets the GPIO pin addressed by register r0 high if r1 != 0 and low
* otherwise.
* C++ Signature: void SetGpio(u32 gpioRegister, u32 value)
*/
.globl SetGpio
SetGpio:
pinNum .req r0
pinVal .req r1
cmp pinNum,#53
movhi pc,lr
push {lr}
mov r2,pinNum
.unreq pinNum
pinNum .req r2
bl GetGpioAddress
gpioAddr .req r0
pinBank .req r3
lsr pinBank,pinNum,#5
lsl pinBank,#2
add gpioAddr,pinBank
.unreq pinBank
and pinNum,#31
setBit .req r3
mov setBit,#1
lsl setBit,pinNum
.unreq pinNum
teq pinVal,#0
.unreq pinVal
streq setBit,[gpioAddr,#40]
strne setBit,[gpioAddr,#28]
.unreq setBit
.unreq gpioAddr
pop {pc}