~ruther/uni-mam-arm

ref: 3789894a7dbda0e114dbfccb85c8ff7a2cb93690 uni-mam-arm/arm02/src/main.S -rw-r--r-- 4.7 KiB
3789894a — Rutherther fix(arm04): dot position when empty digits 4 months ago
                                                                                
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
.syntax unified         @ Use the unified syntax

.thumb                  @ Use the Thumb instruction set

.global leds_blink
.global delay_loop
.global leds_init
.global main

.equ	rcc_reg,            0x40023800   // adresa registru RCC
.equ	rcc_ahb1enr_offset, 0x30         // offset registru AHB1ENR
.equ	rcc_gpiob_en,       0x0002       // bit pro povoleni hodin pro GPIOB
.equ	rcc_gpioa_en,			  0x0001       // bit pro povoleni hodin pro GPIOB

.equ 	gpio_a,             0x40020000   // adresa registru GPIOA
.equ 	gpio_b,             0x40020400   // adresa registru GPIOA
// .equ 	gpio_c,             0x40020800   // adresa registru GPIOB

.equ	gpio_moder_offset,  0x00         // offset adresy registru MODER
.equ	gpio_otyper_offset, 0x04         // offset adresy registru OTYPER
.equ	gpio_odr_offset,	  0x14         // offset adresy registru ODR

.equ	gpioa_odr_init,     (0 << 5)   // inicializacni hodnota pro registr ODR (turn off upper 4 leds)

// Initialization values for moder, odr, otyper
.equ	gpioa_moder_leds,   (0x01 << (2 * 5)) | (0x01 << (2 * 6)) | (0x01 << (2 * 7))
.equ	gpiob_moder_leds,   (0x01 << (2 * 6))
.equ	gpioa_odr_leds,     (0x7 << 5)
.equ	gpiob_odr_leds,     (0x1 << 6)
.equ	gpioa_otyper_leds,  (0x3 << 6) // The first one should not be open-drain.
.equ	gpiob_otyper_leds,  gpiob_odr_leds

.equ	gpioa_leds_count,   3 // How many leds correspond to first gpio - gpioa
.equ	gpioa_leds_lsb_pos, 5 // What is the position of leds lsb in gpioa
.equ	gpiob_leds_lsb_pos, 6 // What is the position of led  lsb in gpiob

.equ	last_led_position,  (0x1 << 3) // Four LEDs total
.equ	init_led_position,  (0x3 << 0) // The inital value for the shift value (1 means off)
.equ	mask_led_position,  0xF // The mask for all leds (4 leds total)

.equ	count_1ms,          7999  // pocet opakovani na 1 ms
.equ	delay,              500   // zpozdeni 500 ms

.section .data
shift_value:
  .word

.section .text

.thumb_func
leds_init:
	push 	{R0-R3};

//  Enable GPIOA in  RCC->AHB1ENR
	ldr		R0, =rcc_reg;
	ldr		R1, =rcc_ahb1enr_offset;
	ldr		R2, [R0, R1];
	ldr		R3, =rcc_gpioa_en;
  orr   R2, R3           ;
	ldr		R3, =rcc_gpiob_en;
	orr		R2, R3;
	str		R2, [R0, R1];

	ldr		R0, =gpio_a;
	ldr		R1, =gpio_moder_offset;
	ldr		R2, =gpioa_moder_leds;
  ldr   R3, [R0, R1]         ;
  orr   R3, R2
	str		R3, [R0, R1];

	ldr		R0, =gpio_b;
	ldr		R1, =gpio_moder_offset;
	ldr		R2, =gpiob_moder_leds;
  ldr   R3, [R0, R1]         ;
  orr   R3, R2
	str		R3, [R0, R1];

//  Output open-drain
	ldr		R0, =gpio_a;
	ldr		R1, =gpio_otyper_offset;
	ldr		R2, =gpioa_otyper_leds;
	str		R2, [R0, R1];

	ldr		R0, =gpio_b;
	ldr		R1, =gpio_otyper_offset;
	ldr		R2, =gpiob_otyper_leds;
	str		R2, [R0, R1];

	pop 	{R0-R3};
	bx		lr;

.thumb_func
shift:
  push {R0-R1}
  ldr R0, =shift_value
  ldr R1, [R0]

  // Shift right by one
  lsrs R1, R1, #1

  // Skip next section if no carry
  bcc shift_next

  // Set last bit, as one has just disappeared
  ldr R0, =last_led_position
  orr R1, R0

shift_next:
  ldr R0, =shift_value
  str R1, [R0]

  bx lr

.thumb_func
write_leds:
  push {R0-R4}
  // GPIOA first
  // Load the shift value, to R1
  ldr R0, =shift_value
  ldr R2, [R0] // R2 contains the shift position
  // Load gpioa leds lsb position
  ldr R0, =gpioa_leds_lsb_pos
  // Shift the shift value to led positions
  lsl R2, R2, R0
  // Mask the value with gpioa_odr_leds
  ldr R0, =gpioa_odr_leds
  and R2, R0

  ldr R0, =gpio_a
  ldr R1, =gpio_odr_offset
  // Store the shift value in R2.
  // NOTE: Ideally, it should only set the few
  // bits, but it does not matter since other
  // bits are always zero in this program.
  str R2, [R0, R1]

  // GPIOB second
  // Load the shift value, to R1
  ldr R0, =shift_value
  ldr R2, [R0] // R2 contains the shift position
  // Shift right by number of leds in gpioa
  ldr R0, =gpioa_leds_count
  lsr R2, R2, R0
  // Shift the shift value to led positions
  ldr R0, =gpiob_leds_lsb_pos
  lsl R2, R2, R0
  // Mask the value with gpiob_odr_leds
  ldr R0, =gpiob_odr_leds
  and R2, R0

  ldr R0, =gpio_b
  ldr R1, =gpio_odr_offset
  // Store the shift value in R2.
  // NOTE: Ideally, it should only set the few
  // bits, but it does not matter since other
  // bits are always zero in this program.
  str R2, [R0, R1]

  pop {R0-R4}
  bx lr

.thumb_func
delay_loop:
	push 	{R0-R1};
	ldr		R1, =delay

//  Load counter for 1ms delay
.thumb_func
load_1ms:
	ldr		R0, =count_1ms

.thumb_func
count_loop:
// Loop through the counter to 1 ms
	subs 	R0, #1
	bne		count_loop

// Loop through the number of ms (delay value)
	subs  R1, #1
	bne		load_1ms

	pop 	{R0-R1};
	bx		lr;

.thumb_func
main:
  bl leds_init;

  ldr R0, =shift_value
  ldr R1, =init_led_position
  str R1, [R0]

main_loop:
  bl shift;
  bl write_leds;
  bl delay_loop;

  b main_loop;
Do not follow this link