Skip to content

Commit ea00ee9

Browse files
first
0 parents commit ea00ee9

File tree

1 file changed

+311
-0
lines changed

1 file changed

+311
-0
lines changed

371-p2-1.s

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
@ Amanda Falke 2015
2+
@ Sitara ARM GPIO LED Pulse Train
3+
@ Using ARM Assembly, this program implements GPIO button interrupts,
4+
@ timer interrupts (a sort of pre-emption), for an LED pulse train.
5+
@
6+
@ Engin-nerds beware: This program goes over 80 cols.
7+
8+
9+
.text
10+
.global _start
11+
.global INT_DIRECTOR
12+
_start:
13+
14+
@ MAPPING of GPIO2_1 to PIN 18 via gpmc_clk register mapping:
15+
LDR R6, =0x44E1088C
16+
MOV R7, #0x00000027@ copy word to set bits 5, and 0-2 to mode7
17+
LDR R8,[R6]@ READ from it,
18+
ORR R8, R7, R8@ MODIFY Control Module Reg with mode 7,
19+
STR R8, [R6]@ WRITE to Control Module register.
20+
21+
22+
@ Note: Interrupt vector table redirects IRQ to INT_DIRECTOR via hook and chain method.
23+
24+
25+
LDR R13,=STACK1 @ Point to base of STACK for SVC mode
26+
ADD R13, R13, #0x1000@ point to top of stack
27+
CPS #0x12@ Switch to IRQ mode
28+
LDR R13,=STACK2 @ Point to IRQ Stack
29+
ADD R13, R13, #0x1000@ Point to top of Stack
30+
CPS #0x13@ back to SVC mode
31+
32+
33+
LDR R0,=0x4804C000@GPIO1 Base Address
34+
LDR R1,=0x481AC000@GPIO2 Base Address
35+
36+
37+
INT_CLEAR:
38+
ADD R4, R0, #0x190@ GPIO1_CLEARDATAOUT register,
39+
MOV R7, #0x01E00000@ LOAD VALUE TO TURN OFF ALL LED'S,
40+
STR R7, [R4]@ TURN OFF ALL LED'S,
41+
ADD R2, R0, #0x134@ MAKE GPIO1_OE REGISTER ADDRESS,
42+
LDR R6, [R2]@ READ CURRENT GPIO1 ENABLE REGISTER,
43+
LDR R7,=0xFE1FFFFF@ WORD TO ENABLE GPIO1 ALL LED'S AS OUTPUT,
44+
AND R6, R7, R6 @ CLEAR BITS 21, 22, 23, 24 USR0-USR3,
45+
STR R6, [R2]@ WRITE TO GPIO1_CLEARDATAOUT REGISTER.
46+
47+
@ Detect falling edge on GPIO2_1 and enable to assert POINTERPEND1
48+
@ Write 0x0000 0002 to 0x481AC14C to program GPIO2, pin 1, to detect falling edge. RMW.
49+
ADD R2, R1, #0x14C@ R2 = address of GPIO2_FALLINGDETECT reg
50+
MOV R3, #0x00000002@ load value for bit 1
51+
LDR R4, [R2]@ READ GPIO2_FALLINGDETECT reg
52+
ORR R4, R4, R3 @ MODIFY (set bit 1)
53+
STR R4, [R2]@ WRITE
54+
55+
@ Enable GPIO module to send interrupt request to INTC:
56+
@ Write 0x00000002 to 0x481AC034
57+
ADD R2, R1, #0x34@ Address of GPIO2_IRQSTATUS_SET_0 reg
58+
STR R3, [R2]@ enable GPIO2_1 request on POINTERPEND1
59+
60+
61+
62+
@ Initialize INTC :
63+
@ Enable INTC to respond to an interrupt request:
64+
LDR R2,=0x48200000@ Address of INTC base register,
65+
66+
@ TIMER4: CONFIG: Write 0x2 to INTC_SYSCONFIG at 0x4820 0010 to reset INTC:
67+
MOV R3, #0x2@ Value to reset INTC
68+
STR R3, [R2, #0x10]@ Write to INTC Sys CONFIG register.
69+
70+
@ TIMER4: INTERRUPT: Write 0x1000 0000 to 0x482000C8 enable INTC #92 Timer4:
71+
MOV R3, #0x10000000@ unmask INTC #92, MIR2 bit 28, hence IRQ2.
72+
STR R3, [R2, #0xC8]@ INTC base 4820 + offset 0xC8 INTC_MIR_CLEAR2
73+
74+
@ BUTTON: Write 0x0000 0001 to INTC_MIR_SET1 register at address 0x4820 00A8.
75+
MOV R3, #0x00000001@ value to unmask INTC INT 32. GPIOINT2A
76+
STR R3, [R2, #0xA8]@ WRITE to INTC_MIR_CLEAR1 register.
77+
78+
79+
80+
@ Turn on Timer4 clock:
81+
@ Write 0x02 to Base Address of CM_PER 0x44E0 0000 base
82+
@ + offset 0x88 for CM_PER_TIMER4_CLKCTRL = Write 0x2 to 0x 44E0 0088 :
83+
MOV R3, #0x2@ Value to enable TIMER4 CLK
84+
LDR R1,=0x44E00088@ Address CM_PER_TIMER4 CLK
85+
STR R3, [R1]@ Turn on CLK
86+
@Set Timer clock frequency MUX for 32K Hz:
87+
@Write 0x2 to PRCM CLKSEL_TIMER4 register at address 0x44E0 0510 :
88+
LDR R1,=0x44E00510@ Address of PRCM CLKSEL_TIMER4 register
89+
STR R3, [R1]@ Select 32K CLK for timer 4, by writing 0x2.
90+
91+
92+
93+
@ Initialize Timer 4 registers, with count, overflow interrupt generation
94+
@7a. Write 0x1 to Timer4 CFG register at 0x4804 4010 to reset Timer4
95+
LDR R1,=0x48044000@ Base address TIMER4 registers
96+
MOV R3, #0x1@ value to reset TIMER4
97+
STR R3, [R1, #0x10]@ Write to TIMER4 CONFIG register
98+
@7b. Write 0x2 to Timer4 IRQ_ENABLE_SET register at 0x 4804 402C
99+
MOV R3, #0x2@ Value to enable Overflow interrupt
100+
STR R3, [R1, #0x2C]@ Write to TIMER4 IRQENABLE_SET
101+
@7c. Write 0x FFFF 8000 to Timer4 TLDR TimerLoad reg at 0x4804 4040 to get 1sec
102+
LDR R3,=0xFFFF8000@ Count value for 1 second
103+
STR R3, [R1, #0x40]@Timer4 TLDR load reg (reload value)
104+
@7d. Write 0x FFFF 8000 to Timer4 TCRR TimerCounter reg at 0x 4804 403C to get 1sec
105+
STR R3, [R1, #0x3C]@ Write to Timer4 TCRR count register
106+
107+
108+
109+
110+
@ Make sure processor IRQ enabled in CPSR
111+
MRS R3, CPSR @ Copy CPSR to R3
112+
BIC R3, #0x80@ Clear bit 7
113+
MSR CPSR_c, R3 @ Write back to CPSR
114+
115+
MOV R8, #0x0@ set LEDFLAG to zero so it falls through the first time.
116+
117+
@ wait for interrupt
118+
LOOP: NOP
119+
120+
B LOOP
121+
122+
INT_DIRECTOR:
123+
124+
STMFD SP!, {R0-R3, LR} @ push registers on stack
125+
LDR R0,=0x482000B8@ Address of INTC_PENDING_IRQ1 reg, text p. 236
126+
LDR R1, [R0]@ Read INTC_PENDING_IRQ1 register
127+
TST R1, #0x00000001@ test bit ZERO of IRQ 1 !!!
128+
129+
@ IS TIMER?? If bit 0 = 0 then not BUTTON
130+
BEQ TIMERCHECK @ if not from button push, Check if Timer 2, else
131+
132+
@ IS BUTTON?? If bit 0 = 1 then check if button:
133+
LDR R0,=0x481AC02C@ Load GPIO2_IRQSTATUS_0 register address, text p. 131
134+
LDR R1, [R0]@ READ status register, to see if button,
135+
TST R1, #0x00000002@ Check if bit 1 = 1
136+
BNE BUTTON_PUSHED @ If bit 1 = 1, then button pushed!
137+
138+
@ program control moves to PASS_ON here if it's NEITHER button NOR TIMER4:
139+
140+
@ "if bit 1 = 0, then enable new IRQ response in INTC by
141+
@ writing 0x1 to INTC_CONTROL register at 4820 0048 to allow new IRQ.
142+
143+
@BEQ PASS_ON @ if bit 1 = 0, then :
144+
LDR R0,=0x48200048@ Else, go back. Address of INTC_PENDING_IRQ2 reg TIMER4
145+
MOV R3, #01@ value to clear bit 0 per sitara manual
146+
STR R3, [R0]@ Write to INTC_CONTROL register.
147+
LDMFD SP!, {R0-R3, LR} @ Restore registers = POP
148+
SUBS PC, LR, #4@ Pass execution on to wait LOOP for now
149+
150+
151+
152+
153+
154+
TIMERCHECK:
155+
LDR R3,=0x482000D8@ Address of INTC PENDING IRQ2 register
156+
LDR R0, [R3]@ Read value
157+
TST R0, #0x10000000@ Check if interrupt from TIMER4
158+
BEQ PASS_ON @ if not TIMER4 interrupt, return; if YES, check overflow
159+
@ if yes, aka IS TIMER4 interrupt, check for overflow:
160+
LDR R3,=0x48044028@ Address of TIMER4 IRQSTATUS register
161+
LDR R0, [R3]@ read value
162+
TST R0, #0x2@ check bit 1. Sitara manual p 4341, IRQSTATUS OVERFLOW bit.
163+
BNE LEDZ @ if overflow, then go to toggle LEDs
164+
@ else go back to wait loop
165+
PASS_ON:
166+
LDR R0,=0x48200048@ Else, go back. Address of INTC_PENDING_IRQ2 reg TIMER4
167+
MOV R3, #01@ value to clear bit 0
168+
STR R3, [R0]@ Write to INTC_CONTROL register.
169+
LDMFD SP!, {R0-R3, LR} @ Restore registers = POP
170+
SUBS PC, LR, #4@ Pass execution on to wait LOOP for now
171+
172+
173+
174+
175+
176+
BUTTON_PUSHED:
177+
LDR R0,=0x481AC02C@ Load GPIO2_IRQSTATUS_0 register address, text p. 131
178+
MOV R1, #0x00000002@ Value turns off GPIO2_1 interrupt request
179+
@ also INTC interrupt request
180+
STR R1, [R0]@ Write to GPIO2_IRQSTATUS_0 register
181+
182+
183+
@ Start Timer4, and set for auto reload by writing 0x03 to TCLR at 0x 4804 4038:
184+
MOV R3, #0x03@ load value of auto reload timer and start
185+
LDR R1,=0x48044038
186+
STR R3, [R1]
187+
188+
@ turn off NEWIRQA bit in INTC_CONTROL, so
189+
@ processor can respond to new IRQ:
190+
LDR R0,=0x48200048@ Address of INTC_CONTROL reg p.236
191+
MOV R1, #01@ Clear Bit 0
192+
STR R1, [R0]@ Write to INTC_CONTROL register
193+
194+
195+
LDR R0,=0x4804C000@ LOAD ADDRESS OF GPIO1 REGISTER for LED's.
196+
197+
198+
@ if LED's are off, fall through to flash LED's. Else, stop it!
199+
TST R8, #0x1@ Check if bit 1 = 1
200+
BNE STOPIT @ If bit LEDFLAG = 1, then button pushed!
201+
@ if bit LEDFLAG = 0, then FALL THROUGH
202+
203+
/* IF LED'S ARE ON, THEN FALL THROUGH TO LEDZ AND THE PARITY CHECK. */
204+
205+
206+
207+
208+
LEDZ:
209+
MOV R8, #0x1@ set LEDFLAG to 1, therefore "LEDs on."
210+
211+
LDR R0,=0x4804C000@ LOAD ADDRESS OF GPIO1 REGISTER for LED's.
212+
213+
@ Turn off Timer4 Overflow Interrupt request:
214+
@ Write 0x2 to IRQSTATUS register at 0x4804 4028 :
215+
LDR R1,=0x48044028@ load address of Timer4 IRQSTATUS register
216+
MOV R2, #0x2@ value to reset timer4 overflow IRQ request (bit1)
217+
STR R2, [R1]@ write.
218+
219+
220+
/* when hitting the button to START the LEDs, we MUST RESET/ENABLE timer overflow IRQ's.
221+
TO DO SO, WE USE IRQENABLE_SET REGISTERS IN SITARA MANUAL (TIMER).
222+
*/
223+
LDR R1,=0x48044000@ BASE ADDRESS OF TIMER4,
224+
MOV R3, #0x2@ WRITE A 1 TO BIT 1 OF BOTH SET AND CLR REGISTERS,
225+
STR R3, [R1, #0x2C]@ IRQENABLE_SET
226+
227+
228+
229+
TOGGLEPARITY:
230+
231+
@ TEST PARITY : EVEN OR ODD. IF 0, GOTO ODDS. IF 1, GOTO EVEN.
232+
233+
TST R9, #0x1@ Check if bit 1 = 1
234+
BNE EVENS
235+
236+
ODDS:
237+
MOV R9, #0x1@ SET PARITY TO ODD
238+
@ clear evens:
239+
MOV R11, #0x00A00000@ COPY MASK: EVENS,
240+
ADD R2, R0, #0x190@ CLEARDATAOUT ADDRESS,
241+
STR R11, [R2]@ WRITE MASK. CLEAR EVENS.
242+
243+
@ Set odds:
244+
MOV R11, #0x01400000@ COPY MASK: ODDS,
245+
ADD R2, R0, #0x194@ SETDATAOUT ADDRESS,
246+
STR R11, [R2]@ WRITE MASK. LIGHT ODDS.
247+
B PASS_ON_TEMP
248+
249+
EVENS:
250+
MOV R9, #0x0@ SET PARITY TO EVEN
251+
@ Clear odds:
252+
MOV R11, #0x01400000@ COPY MASK: ODDS
253+
ADD R2, R0, #0x190@ CLEARDATAOUT ADDRESS
254+
STR R11, [R2]@ WRITE MASK. CLEAR ODDS.
255+
256+
MOV R11, #0x00A00000@ COPY MASK: EVENS.
257+
ADD R2, R0, #0x194@ SETDATAOUT address,
258+
STR R11, [R2]@ WRITE MASK, LIGHT EVENS.
259+
B PASS_ON_TEMP
260+
261+
262+
STOPIT:
263+
@ CLEAR LED'S
264+
MOV R8, #0x0@ set LEDFLAG to zero
265+
266+
ADD R4, R0, #0x190@ GPIO1_CLEARDATAOUT register,
267+
MOV R7, #0x01E00000@ LOAD VALUE TO TURN OFF ALL LED'S,
268+
STR R7, [R4]@ TURN OFF ALL LED'S.
269+
270+
/* when hitting the button to stop the LEDs, we MUST disable timer overflow IRQ's.
271+
TO DO SO, WE USE IRQENABLE_SET AND IRQENABLE_CLR REGISTERS IN SITARA MANUAL (TIMER).
272+
*/
273+
LDR R1,=0x48044000@ BASE ADDRESS OF TIMER4,
274+
MOV R3, #0x2@ WRITE A 1 TO BIT 1 OF BOTH SET AND CLR REGISTERS,
275+
STR R3, [R1, #0x2C]@ IRQENABLE_SET
276+
STR R3, [R1, #0X30]@ IRQENABLE_CLR
277+
278+
PASS_ON_TEMP:
279+
@ INTC : RESET FOR NEW IRQ'S!
280+
LDR R1,=0x48200048@ address of INTC control register
281+
MOV R3, #0x01
282+
STR R3, [R1]@ Write to INTC_CONTROL register
283+
284+
@return to wait loop
285+
LDMFD SP!, {R0-R3, LR} @ Restore registers
286+
SUBS PC, LR, #4@ Pass execution on to wait LOOP for now
287+
288+
@LDR R1,=0x481AC02C@ Load GPIO2_IRQSTATUS_0 register address, text p. 131
289+
@LDR R2, [R1]@ READ status register,
290+
@TST R2, #0x00000002@ Check if bit 1 = 1
291+
@BNE STOPIT @ If bit 1 = 1, then button pushed again, so go back to WAIT!
292+
293+
294+
.align 2
295+
SYS_IRQ: .WORD 0@location to store systems’ IRQ address!
296+
297+
.data
298+
299+
.align 2
300+
301+
STACK1: .rept 1024
302+
.word 0x0000
303+
.endr
304+
STACK2: .rept 1024
305+
.word 0x0000
306+
.endr
307+
308+
.END
309+
310+
311+

0 commit comments

Comments
 (0)