Skip to content

Commit bc7fa15

Browse files
committed
Übung 4
1 parent 7d97568 commit bc7fa15

17 files changed

+542
-200
lines changed

lib/lib_gpio.s

+193-96
Original file line numberDiff line numberDiff line change
@@ -9,146 +9,243 @@
99
.cpu cortex-m3
1010
.thumb
1111

12-
.word 0x20000400
13-
.word 0x080000ed
14-
.space 0xe4
15-
16-
/***********************************************************************/
17-
/* library: lib_gpio.s */
18-
/* description: TODO Provides mathematical functions */
19-
/* function mult_r0_by_r1: multiplies two numbers */
20-
/* function div_r0_by_r1: divides one number by another */
21-
/* depends on: - */
22-
/***********************************************************************/
12+
/************************************************************************/
13+
/* library: lib_gpio.s */
14+
/* description: Provides functions for handling GPIO of NUCLEO-F103RB */
15+
/* function port_open: enables IO port clock */
16+
/* function gpio_init: configures pin */
17+
/* function gpio_set: sets output of pin */
18+
/* depends on: - */
19+
/************************************************************************/
2320

2421
.global port_open
2522
port_open:
26-
/********************************************************************************/
27-
/* function: mult_r0_by_r1 */
28-
/* description: multiplies the values in r0 and r1 and returns the result in r0 */
29-
/********************************************************************************/
30-
/* input: r0: multiplier (how many times to add) */
31-
/* r1: multiplicand (what to add) */
32-
/* output: r0: product of multiplicand and multiplier */
33-
/* helper: r2 (no need to save, is saved on the stack in this function) */
34-
/********************************************************************************/
23+
/**************************************************************/
24+
/* function: port_open */
25+
/* description: enables the clock for the specified IO port */
26+
/**************************************************************/
27+
/* input: r0: port (A: 0, B: 1, ...), must be >= 0 and <= 4 */
28+
/* otherwise this function has no effect */
29+
/* output: r0: preserves input */
30+
/**************************************************************/
31+
/* check parameter */
32+
push {lr}
33+
bl check_port @ failed check will return early
34+
pop {lr}
35+
36+
/* begin function */
3537
push {r1-r3}
38+
3639
/*
3740
* configure APB2 peripheral clock enable register (RCC_APB2ENR)
38-
*
39-
* base RCC address: 0x40021000
41+
*/
42+
43+
/*
44+
* base reset and clock control RCC address: 0x40021000
4045
* RCC_APB2ENR offset: 0x18
4146
* -> 0x40021018
4247
*/
43-
ldr r1, =0x40021018 @ base address
44-
ldr r2, [r1]
45-
mov r3, #0b100
46-
lsl r3, r3, r0
47-
orr r2, r2, r3
48-
str r2, [r1]
48+
ldr r1, =0x40021018 @ RCC_APB2ENR address
49+
ldr r2, [r1] @ load previous register value
50+
51+
mov r3, #0b100 @ bitmask, ports start at bit 2
52+
lsl r3, r0 @ shift mask by port number
53+
orr r2, r3 @ enable clock for port
4954

55+
str r2, [r1] @ store new register value
56+
57+
/* end function and return */
5058
pop {r1-r3}
5159
bx lr
5260

5361

5462

5563
.global gpio_init
5664
gpio_init:
57-
push {r3-r5}
65+
/***************************************************************************/
66+
/* function: gpio_init */
67+
/* description: configures the specified GPIO pin as an input/output pin */
68+
/***************************************************************************/
69+
/* input: r0: port the pin belongs to (A: 0, B: 1, ...), */
70+
/* must be >= 0 and <= 4 otherwise this function has no effect */
71+
/* r1: pin, must be >= 0 and <= 15 */
72+
/* otherwise this function has no effect */
73+
/* r2: mode, 0 for floating input, anything else for general */
74+
/* purpose output push-pull, max speed 50 MHz */
75+
/* output: r0: preserves input */
76+
/* r1: preserves input */
77+
/* r2: preserves input */
78+
/***************************************************************************/
79+
/* check parameters */
80+
push {lr}
81+
bl check_port
82+
bl check_pin @ failed check will return early
83+
pop {lr}
84+
85+
/* begin function */
86+
push {r0-r5}
5887

59-
/* Port offset -> Ports are 0x400 apart */
60-
mov r3, #0x400
61-
mul r4, r0, r3 @ r0 is Port number (A = 0, ...)
6288
/*
63-
* configure Port configuration register low/high (GPIOx_CRL/GPIOx_CRH)
64-
*
65-
* base GPIO Port A address: 0x40010800
66-
* -> add Port offset in r4 and optional high offset
89+
* configure port configuration register low/high
90+
* (GPIOx_CRL/GPIOx_CRH)
6791
*/
68-
ldr r3, =0x40010800 @ base address
69-
add r3, r3, r4
70-
/* if Pin number > 8 high else low */
71-
cmp r1, #8
72-
blt skip_high
73-
add r3, r3, #0x04 @ extra high offset
74-
skip_high:
75-
/* final GPIOx_CRL/GPIOx_CRH address is in r3 */
7692

7793
/*
78-
* low/high is set (stored in r3)
79-
* -> only care about last 3 bits of Pin number
80-
* -> multiply by 4, use as shift distance
94+
* base GPIO port A address: 0x40010800
95+
* -> add port offset and optional GPIOx_CRH offset (0x04)
8196
*/
82-
and r1, r1, #0b111
83-
mov r5, #4
84-
mul r1, r1, r5
85-
86-
ldr r4, [r3] @ load previous register value
97+
ldr r3, =0x40010800 @ base GPIO port A address
8798

88-
mvn r0, #0b1111 @ invert mask
89-
mov r5, #32
90-
sub r5, r5, r1 @ 32 - bits to rotate left
91-
ror r0, r0, r5 @ to make left rotate with ror
99+
mov r4, #0x400 @ ports are 0x400 bytes apart
100+
mul r4, r0 @ times port number -> offset
101+
add r3, r4 @ add port offset to base
92102

93-
and r4, r4, r0 @ reset CNF and MODE for Pin
103+
cmp r1, #8 @ pin >= 8 -> high else low
104+
it ge @ if high
105+
addge r3, #0x04 @ add GPIOx_CRH offset to base
106+
/* final GPIOx_CRL/GPIOx_CRH address is now in r3 */
94107

95-
cmp r2, #0 @ 0 = input, 1 = output
96-
input:
97-
bne output
98-
mov r0, #0b0100
99-
b change_cnf_and_mode
100-
output:
101-
mov r0, #0b0001
108+
/*
109+
* we now know whether we have a low or high pin (address in r3)
110+
* -> only care about last 3 bits of pin number from here on
111+
* (low and high configuration registers both have
112+
* configurations for 8 = 2^3 pins)
113+
* -> multiply by 4 to use as shift distance later
114+
* (each pin has 4 configuration bits)
115+
*/
116+
and r1, #0b111 @ only keep 3 bits
117+
mov r0, #4
118+
mul r1, r0 @ times 4 for use in shifts
102119

103-
change_cnf_and_mode:
104-
lsl r0, r0, r1 @ shift CNF and MODE to position
105-
orr r4, r4, r0
120+
/* load previous register value */
121+
ldr r4, [r3]
106122

107-
str r4, [r3] @ store new register value
123+
/*
124+
* reset previous CNF and MODE for pin by using a bitmask with
125+
* 4 unset bits rotated into position using ror with adjusted
126+
* shift distance to simulate left rotation
127+
* left shift distance is r1
128+
*/
129+
mvn r0, #0b1111 @ all bits set except last 4
130+
mov r5, #32
131+
sub r5, r1 @ 32 - bits to rotate left
132+
ror r0, r5 @ -> left rotation with ror
133+
and r4, r0 @ reset CNF and MODE for pin
108134

109-
pop {r3-r5}
135+
/*
136+
* set new CNF and MODE for pin based on function parameter r2
137+
* r2 | CNF | MODE
138+
* input -> floating input | 01 | 00
139+
* output -> general purpose output push-pull, | 00 | 11
140+
* max speed 50 MHz | |
141+
*/
142+
cmp r2, #0 @ 0 -> input else output
143+
ite eq @ if input
144+
moveq r0, #0b0100 @ input configuration
145+
movne r0, #0b0011 @ else output configuration
146+
lsl r0, r1 @ shift CNF and MODE to position
147+
orr r4, r0 @ set new CNF and MODE for pin
148+
149+
/* store new register value */
150+
str r4, [r3]
151+
152+
/* end function and return */
153+
pop {r0-r5}
110154
bx lr
111155

112156

113157

114158
.global gpio_set
115159
gpio_set:
116-
push {r3-r5}
160+
/***************************************************************************/
161+
/* function: gpio_set */
162+
/* description: sets the output value of the specified GPIO pin */
163+
/***************************************************************************/
164+
/* input: r0: port the pin belongs to (A: 0, B: 1, ...), */
165+
/* must be >= 0 and <= 4 otherwise this function has no effect */
166+
/* r1: pin, must be >= 0 and <= 15 */
167+
/* otherwise this function has no effect */
168+
/* r2: value, 0 to reset, anything else to set */
169+
/* output: r0: preserves input */
170+
/* r1: preserves input */
171+
/* r2: preserves input */
172+
/***************************************************************************/
173+
/* check parameters */
174+
push {lr}
175+
bl check_port
176+
bl check_pin @ failed check will return early
177+
pop {lr}
178+
179+
/* begin function */
180+
push {r0-r2}
181+
182+
/*
183+
* update pin output value using port bit set/reset register
184+
* (GPIOx_BSRR)
185+
*/
186+
187+
/*
188+
* adjust pin number by 16 if pin should be reset
189+
* (reset bits in GPIOx_BSRR have an offset of 16)
190+
*/
191+
cmp r2, #0 @ 0 -> reset else set
192+
it eq @ if reset
193+
addeq r1, #16 @ add 16 to pin number
194+
195+
/* port offset */
196+
mov r2, #0x400 @ ports are 0x400 bytes apart
197+
mul r0, r2 @ times port number -> offset
117198

118-
/* Port offset -> Ports are 0x400 apart */
119-
mov r3, #0x400
120-
mul r4, r0, r3 @ r0 is Port number (A = 0, ...)
121199
/*
122-
* change Port bit set/reset register (GPIOx_BSRR)
123-
*
124-
* base GPIO Port A address: 0x40010800
200+
* base GPIO port A address: 0x40010800
125201
* GPIOx_BSRR offset: 0x10
126202
* -> 0x40010810
127-
* -> add Port offset in r4
203+
* -> add port offset
128204
*/
129-
ldr r3, =0x40010810 @ base address
130-
add r3, r3, r4
131-
/* final GPIOx_BSRR address is in r3 */
205+
ldr r2, =0x40010810 @ base adjusted address
206+
add r2, r0 @ add port offset to base
207+
/* final GPIOx_BSRR address is now in r3 */
132208

133-
ldr r4, [r3] @ load previous register value
209+
/*
210+
* write to BSx/BRx, no need to save previous values,
211+
* GPIOx_BSRR is a write-only register
212+
*/
213+
mov r0, #1
214+
lsl r0, r1 @ shift by adjusted pin number
215+
str r0, [r2] @ set/reset pin
134216

135-
mvn r0, 0x10001 @ invert mask
136-
mov r5, #32
137-
sub r5, r5, r1 @ 32 - bits to rotate left
138-
ror r0, r0, r5 @ to make left rotate with ror
217+
/* end function and return */
218+
pop {r0-r2}
219+
bx lr
139220

140-
and r4, r4, r0 @ set and reset bit to 0 for Pin
141221

142-
mov r0, #1
143-
mov r0, r0, lsl r1 @ shift to Pin number
144-
cmp r2, #0 @ 0 = reset, 1 = set
145-
bne change_set_or_reset @ no extra shift for set
146-
lsl r0, r0, #16 @ extra 16 bit shift for reset
147222

148-
change_set_or_reset:
149-
orr r4, r4, r0
223+
check_port:
224+
/* port has to be in range 0-4 (A-E) */
150225

151-
str r4, [r3] @ store new register value
226+
cmp r0, #0 @ port less than 0?
227+
itt lt @ |
228+
poplt {lr} @ v
229+
bxlt lr @ return early from caller
152230

153-
pop {r3-r5}
154-
bx lr
231+
cmp r0, #4 @ port greater than 4?
232+
itt gt @ |
233+
popgt {lr} @ v
234+
bxgt lr @ return early from caller
235+
236+
bx lr @ ok
237+
238+
check_pin:
239+
/* pin has to be in range 0-15 */
240+
241+
cmp r1, #0 @ pin less than 0?
242+
itt lt @ |
243+
poplt {lr} @ v
244+
bxlt lr @ return early from caller
245+
246+
cmp r1, #15 @ pin greater than 15?
247+
itt gt @ |
248+
popgt {lr} @ v
249+
bxgt lr @ return early from caller
250+
251+
bx lr @ ok

0 commit comments

Comments
 (0)