summaryrefslogtreecommitdiff
path: root/src/main.s
blob: a9f7af331ae8437ceb113614a4ac0977040a281e (plain)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
@ Tiny bare metal example
@ vim:ft=armv5

.section .init

_start:
	LDR	PC, [PC, #24]	@ Reset
	LDR	PC, [PC, #24]	@ Undefined
	LDR	PC, [PC, #24]	@ SWI
	LDR	PC, [PC, #24]	@ Prefetch abort
	LDR	PC, [PC, #24]	@ Data abort
	LDR	PC, [PC, #24]	@ Reserved
	LDR	PC, [PC, #24]	@ IRQ
	LDR	PC, [PC, #24]	@ FIQ
	.word	reset		@ Reset
	.word	hang		@ Undefined
	.word	swi_handler	@ SWI
	.word	hang		@ Prefetch abort
	.word	hang		@ Data abort
	.word	hang		@ Reserved
	.word	hang		@ IRQ
	.word	hang		@ FIQ

hang:
	B	hang

reset:
	@ Get out of HYP mode
	MRS	R0, CPSR
	BIC	R0, R0, #0x1f
	ORR	R0, R0, #0x13
	MSR	SPSR_cxsf, R0
	ADD	R0, PC, #4
	MSR	ELR_hyp,r0
	ERET

	LDR	R13, =stack_svc		@ Set up stack for SVC mode

	@ Relocate vector table
	MOV	R10, #0x8000
	MOV	R11, #0
	LDMIA	R10!, {R0-R7}
	STMIA	R11!, {R0-R7}
	LDMIA	R10!, {R0-R7}
	STMIA	R11!, {R0-R7}

	LDR R0, =start_cpu1
	MOV R1, #0x40000000
	STR R0,[R1, #0xac]
	SEV

	LDR	R8, =0x3f200000
	LDR	R1, [R8, #0x04]		@ GPFSEL1
	ORR	R1, R1, #1<<18		@ GPIO pin 16 is output
	BIC	R1, R1, #3<<21		@ GPIO pin 17 is input
	ORR	R1, R1, #1<<24		@ GPIO pin 18 is output
	STR	R1, [R8, #0x04]		@ GPFSEL1

	@ Flash green LED
	MRC	P15, 0, R0, C0, C0, 5
	AND	R0, R0, #0x0f
	CMP	R0, #0
	BNE	skip_flash

	MOV	R1, #1<<18
	STR	R1, [R8, #0x1c]		@ GPSET0
	BL	pause
	MOV	R1, #1<<18
	STR	R1, [R8, #0x28]		@ GPCLR0
	BL	pause

skip_flash:

	@ Switch to USR mode and set up stack
	MRS	R0, CPSR
	BIC	R0, R0, #0x1f
	ORR	R0, R0, #0x10
	MSR	CPSR_c, R0
	LDR	R13, =stack_usr

repeat:
	MOV	R0, #0
	SWI	0
	TST	R0, #1<<17
	MOVNE	R0, #1
	SWINE	0
	B	repeat


start_cpu1:
	LDR	R8, =0x3f200000
	LDR	R1, [R8, #0x04]		@ GPFSEL1
	ORR	R1, R1, #1<<18		@ GPIO pin 16 is output
	BIC	R1, R1, #3<<21		@ GPIO pin 17 is input
	ORR	R1, R1, #1<<24		@ GPIO pin 18 is output
	STR	R1, [R8, #0x04]		@ GPFSEL1

forever:
	MRC	P15, 0, R0, C0, C0, 5
	AND	R0, R0, #0x0f
flashred:
	MOV	R1, #1<<29
	STR	R1, [R8, #0x1c]		@ GPSET0
	BL	longpause
	MOV	R1, #1<<29
	STR	R1, [R8, #0x28]		@ GPCLR0
	BL	longpause
	SUBS	R0, R0, #1
	BNE	flashred

	BL	longpause
	BL	longpause
	BL	longpause
	B	forever

swi_handler:
	STMDB	R13!, {R8, LR}
	LDR	R8, =0x3f200000
	CMP	R0, #0
	BEQ	get_gpio
	CMP	R0, #1
	BLEQ	flash
	LDMIA	R13!, {R8, PC}^

get_gpio:
	LDR	R0, [R8, #0x34]		@ GPLEV0
	LDMIA	R13!, {R8, PC}^


flash:
	STMDB	R13!, {R1, R2, R4, LR}
	MOV	R4, #5

flashloop:
	MOV	R1, #1<<16
	STR	R1, [R8, #0x28]		@ GPCLR0
	MOV	R1, #1<<18
	STR	R1, [R8, #0x1c]		@ GPSET0

	BL	pause

	MOV	R1, #1<<18
	STR	R1, [R8, #0x28]		@ GPCLR0
	MOV	R1, #1<<16
	STR	R1, [R8, #0x1c]		@ GPSET0

	BL	pause

	MOV	R1, #1<<18
	ORR	R1, #1<<16
	STR	R1, [R8, #0x28]		@ GPCLR0

	SUBS	R4, R4, #1
	BNE	flashloop

	LDMIA	R13!, {R1, R2, R4, PC}

pause:
	MOV	R2, #0x3f000
wait:
	SUBS	R2, R2, #1
	BNE	wait
	MOV	PC, LR

longpause:
	MOV	R2, #0x3f0000
	B	wait