-
Notifications
You must be signed in to change notification settings - Fork 6
/
highint5.S
277 lines (235 loc) · 8.18 KB
/
highint5.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
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/*
* MIT License
*
* Copyright (c) 2020 Christopher B. Liebman
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <xtensa/coreasm.h>
#include <xtensa/corebits.h>
#include <xtensa/config/system.h>
#include "freertos/xtensa_context.h"
#include "esp_private/panic_reason.h"
#include "sdkconfig.h"
#include "soc/soc.h"
#include "soc/gpio_reg.h"
#include "soc/timer_group_reg.h"
#define L5_INTR_A2_OFFSET 0
#define L5_INTR_A3_OFFSET 4
#define L5_INTR_A4_OFFSET 8
#define L5_INTR_A5_OFFSET 12
#define L5_INTR_A6_OFFSET 16
#define L5_INTR_SAR_OFFSET 20
#define L5_INTR_STACK_SIZE 24
.data
_l5_intr_stack:
.space L5_INTR_STACK_SIZE
/* GPIO interrupt register offsets */
#define STATUS_OFFSET 0
#define W1TC_OFFSET 8
#define LATENCY_GPIO_NUM 2
#define LATENCY_GPIO_BIT (1<<LATENCY_GPIO_NUM)
#define PPS_SHORT_VALUE 999500
#define PPS_LONG_VALUE 1000500
#define PPS_DATA_SIZE 44
#define PPS_PIN_OFFSET 0 /* pin number */
#define PPS_LAST_OFFSET 4 /* timer value for last interrupt, used to computer microseconds */
#define PPS_TIME_OFFSET 8 /* time in seconds */
#define PPS_MIN 12 /* min */
#define PPS_MAX 16 /* max */
#define PPS_INTERVAL 20 /* last interval */
#define PPS_DELTA 24 /* offset from ref if ref not 0 */
#define PPS_REF 28 /* pointer to ref data or 0 */
#define PPS_SHORT_OFFSET 32 /* short counter */
#define PPS_LONG_OFFSET 36 /* long counter */
#define PPS_DISABLED 40 /* disabled flag */
.align 4
.global gps_pps_data
.type gps_pps_data,@object
.size gps_pps_data,PPS_DATA_SIZE
gps_pps_data:
.space PPS_DATA_SIZE
.global rtc_pps_data
.type rtc_pps_data,@object
.size rtc_pps_data,PPS_DATA_SIZE
rtc_pps_data:
.space PPS_DATA_SIZE
pps_entry_end:
.section .iram1,"ax"
.global xt_highint5
.type xt_highint5,@function
.align 4
xt_highint5:
/* Save A2, A3, A4, A5 so we can use those registers */
movi a0, _l5_intr_stack
s32i a2, a0, L5_INTR_A2_OFFSET
s32i a3, a0, L5_INTR_A3_OFFSET
s32i a4, a0, L5_INTR_A4_OFFSET
s32i a5, a0, L5_INTR_A5_OFFSET
s32i a6, a0, L5_INTR_A6_OFFSET
rsr a6, SAR
s32i a6, a0, L5_INTR_SAR_OFFSET
/* set the latency pin */
movi a2, GPIO_OUT_W1TS_REG
movi a0, LATENCY_GPIO_BIT
s32i a0, a2, 0
memw
/* load timer value into a0 */
/* trigger timer update */
movi a2, TIMG_T0UPDATE_REG(0)
s32i a0, a2, 0
memw
/* wait to insure timer value was updated before reading */
wait_for_timer:
l32i a0, a2, 0
bnez a0, wait_for_timer
/* read timer value lower 32 bits A6 will hold this value thruout */
movi a2, TIMG_T0LO_REG(0)
l32i a6, a2, 0
l32i a6, a2, 0 /* load again as sometimes its not updated yet? */
movi a2, gps_pps_data /* TODO: use more generic label */
check_intr_status:
/* generate pin mask in a3 & intr status reg in a5 */
movi a5, GPIO_STATUS_REG
l32i a3, a2, PPS_PIN_OFFSET
beqz a3, next_pin /* if the pin number is zero then skip it */
movi a4, 32
bgeu a4, a3, make_intr_bit
sub a3, a3, a4
movi a5, GPIO_STATUS1_REG
make_intr_bit:
ssl a3
movi a3, 1
sll a3, a3
/* check intr status for this bit */
l32i a4, a5, STATUS_OFFSET
and a4, a4, a3
beqz a4, next_pin
/* clear interrupt bit */
memw
s32i a3, a5, W1TC_OFFSET
#if 1
/* use if double interrupts? */
memw
l32i a4, a5, STATUS_OFFSET
#endif
/* check for disabled */
l32i a3, a2, PPS_DISABLED
bnez a3, next_pin
/* store last value */
l32i a3, a2, PPS_LAST_OFFSET /* save previous value */
s32i a6, a2, PPS_LAST_OFFSET /* store new value */
sub a3, a6, a3 /* compute interval */
/* increment time */
l32i a4, a2, PPS_TIME_OFFSET
addi a0, a4, 1
s32i a0, a2, PPS_TIME_OFFSET
/* if this is teh first second, previous value was 0 then don't compute stats */
blti a4, 12, next_pin
/* save the last interval */
s32i a3, a2, PPS_INTERVAL
/* check for long value and reset max to 0 if exceeded */
/* A2 has data ptr */
/* A3 has interval value */
check_long:
movi a0, PPS_LONG_VALUE
blt a3, a0, check_max
/* increment the long count and clear the max value, skip max value check */
l32i a0, a2, PPS_LONG_OFFSET
addi a0, a0, 1
s32i a0, a2, PPS_LONG_OFFSET
movi a0, 0
s32i a0, a2, PPS_MAX
j check_min /* dont need to check short as we are long! */
/* track the max interval value */
check_max:
l32i a0, a2, PPS_MAX
blt a3, a0, check_short
s32i a3, a2, PPS_MAX
/* check for short value and reset min to 0 if exceeded */
/* A2 has data ptr */
/* A3 has interval value */
check_short:
movi a0, PPS_SHORT_VALUE
blt a0, a3, check_min
/* increment the short count and clear the min value, skip min value check */
l32i a0, a2, PPS_SHORT_OFFSET
addi a0, a0, 1
s32i a0, a2, PPS_SHORT_OFFSET
movi a0, 0
s32i a0, a2, PPS_MIN
j do_delta
/* track the min interval value */
check_min:
l32i a0, a2, PPS_MIN
beqz a0, set_min /* if its zero then just store the first value */
blt a0, a3, do_delta
set_min:
s32i a3, a2, PPS_MIN
do_delta:
/* if the reference pointer is not 0 then compute offset & store in PPS_DELTA */
/* A0 will have curent last value */
/* A2 has current data ptr */
/* A3 will have ref last value */
/* A4 will have REF data ptr */
l32i a4, a2, PPS_REF
beqz a4, next_pin
memw
l32i a0, a4, PPS_LAST_OFFSET
l32i a3, a2, PPS_LAST_OFFSET
sub a0, a3, a0 /* last - ref */
movi a4, 1000000
check_pos:
movi a3, 500000
blt a0, a3, check_neg
sub a0, a0, a4
j store_offset
check_neg:
movi a3, -500000
blt a3, a0, store_offset
add a0, a0, a4
store_offset:
s32i a0, a2, PPS_DELTA
next_pin:
addi a2, a2, PPS_DATA_SIZE /* increment to the next pin */
/* check a2 for being at or past pps_entry_end and exit */
movi a3, pps_entry_end
blt a2, a3, check_intr_status
exit_interrupt:
/* clear the latency pin */
movi a2, GPIO_OUT_W1TC_REG
movi a0, LATENCY_GPIO_BIT
s32i a0, a2, 0
/* Done. Restore registers and return. */
movi a0, _l5_intr_stack
l32i a2, a0, L5_INTR_SAR_OFFSET
wsr a2, SAR
l32i a2, a0, L5_INTR_A2_OFFSET
l32i a3, a0, L5_INTR_A3_OFFSET
l32i a4, a0, L5_INTR_A4_OFFSET
l32i a5, a0, L5_INTR_A5_OFFSET
l32i a6, a0, L5_INTR_A6_OFFSET
rsync /* ensure register restored */
rsr a0, EXCSAVE_5 // restore a0
rfi 5
/* The linker has no reason to link in this file; all symbols it exports are already defined
(weakly!) in the default int handler. Define a symbol here so we can use it to have the
linker inspect this anyway. */
.global ld_include_xt_highint5
ld_include_xt_highint5: