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
|
/***************************************************************************
* Copyright (c) 2026 10xEngineers
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* SPDX-License-Identifier: MIT
**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** ThreadX Component */
/** */
/** Timer */
/** */
/**************************************************************************/
/**************************************************************************/
.section .text
.align 4
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
/* */
/* _tx_timer_interrupt RISC-V64/GNU */
/* 6.2.1 */
/* AUTHOR */
/* */
/* Akif Ejaz, 10xEngineers */
/* */
/* DESCRIPTION */
/* */
/* This function processes the hardware timer interrupt. This */
/* processing includes incrementing the system clock and checking for */
/* time slice and/or timer expiration. If either is found, the */
/* interrupt context save/restore functions are called along with the */
/* expiration functions. */
/* */
/* INPUT */
/* */
/* None */
/* */
/* OUTPUT */
/* */
/* None */
/* */
/* CALLS */
/* */
/* _tx_timer_expiration_process Timer expiration processing */
/* _tx_thread_time_slice Time slice interrupted thread */
/* */
/* CALLED BY */
/* */
/* interrupt vector */
/* */
/**************************************************************************/
/* VOID _tx_timer_interrupt(VOID)
{ */
.global _tx_timer_interrupt
_tx_timer_interrupt:
/* Increment the system clock. */
/* _tx_timer_system_clock++; */
la t0, _tx_timer_system_clock // Pickup address of system clock
lw t1, 0(t0) // Pickup system clock
la t2, _tx_timer_time_slice // Pickup address of time slice
lw t3, 0(t2) // Pickup time slice
addi t1, t1, 1 // Increment system clock
sw t1, 0(t0) // Store new system clock
li t6, 0 // Clear local expired flag
/* Test for time-slice expiration. */
/* if (_tx_timer_time_slice)
{ */
beqz t3, _tx_timer_no_time_slice // If 0, skip time slice processing
addi t3, t3, -1 // Decrement the time slice
/* Decrement the time_slice. */
/* _tx_timer_time_slice--; */
sw t3, 0(t2) // Store new time slice
/* Check for expiration. */
/* if (_tx_timer_time_slice == 0) */
bgtz t3, _tx_timer_no_time_slice // If not 0, has not expired yet
li t1, 1 // Build expired flag
/* Set the time-slice expired flag. */
/* _tx_timer_expired_time_slice = TX_TRUE; */
la t4, _tx_timer_expired_time_slice // Get address of expired flag
sw t1, 0(t4) // Set expired flag (UINT)
ori t6, t6, 1 // Set local expired flag
/* } */
_tx_timer_no_time_slice:
/* Test for timer expiration. */
/* if (*_tx_timer_current_ptr)
{ */
la t0, _tx_timer_current_ptr // Pickup address of current ptr
ld t1, 0(t0) // Pickup current pointer (double word)
ld t3, 0(t1) // Pickup the current timer entry (double word)
la t2, _tx_timer_expired // Pickup address of timer expired flag
li t4, 1 // Build TX_TRUE flag
beqz t3, _tx_timer_no_timer // If NULL, no timer has expired
/* Set expiration flag. */
/* _tx_timer_expired = TX_TRUE; */
ori t6, t6, 2 // Set local expired flag
sw t4, 0(t2) // Set expired flag in memory (UINT)
j _tx_timer_done // Finished timer processing
/* }
else
{ */
_tx_timer_no_timer:
/* No timer expired, increment the timer pointer. */
/* _tx_timer_current_ptr++; */
/* Check for wrap-around. */
/* if (_tx_timer_current_ptr == _tx_timer_list_end) */
la t2, _tx_timer_list_end // Pickup address of list end pointer
ld t3, 0(t2) // Pickup actual list end
addi t1, t1, 8 // Point to next timer entry
sd t1, 0(t0) // Store new timer pointer
bne t1, t3, _tx_timer_skip_wrap // If not same, good pointer
/* Wrap to beginning of list. */
/* _tx_timer_current_ptr = _tx_timer_list_start; */
la t2, _tx_timer_list_start // Pickup address of list start pointer
ld t4, 0(t2) // Pickup start of the list
sd t4, 0(t0) // Store new timer pointer
_tx_timer_skip_wrap:
/* } */
_tx_timer_done:
/* See if anything has expired. */
/* if ((_tx_timer_expired_time_slice) || (_tx_timer_expired))
{ */
beqz t6, _tx_timer_nothing_expired // If nothing expired skip the rest
addi sp, sp, -16 // Allocate some storage on the stack
sd t6, 0(sp) // Save local expired flag
sd ra, 8(sp) // Save ra (8-byte aligned)
/* Did a timer expire? */
/* if (_tx_timer_expired)
{ */
andi t2, t6, 2 // Isolate the timer expired bit
beqz t2, _tx_timer_dont_activate // No, timer not expired
/* Call the timer expiration processing. */
/* _tx_timer_expiration_process(void); */
call _tx_timer_expiration_process // Call _tx_timer_expiration_process
ld t6, 0(sp) // Recover local expired flag
/* } */
_tx_timer_dont_activate:
/* Did time slice expire? */
/* if (_tx_timer_expired_time_slice)
{ */
andi t2, t6, 1 // Is the timer expired bit set?
beqz t2, _tx_timer_not_ts_expiration // If not, skip time slice processing
/* Time slice interrupted thread. */
/* _tx_thread_time_slice(); */
call _tx_thread_time_slice // Call time slice
/* } */
_tx_timer_not_ts_expiration:
ld ra, 8(sp) // Recover ra
addi sp, sp, 16 // Recover stack space
/* } */
_tx_timer_nothing_expired:
ret
/* } */
|