source: rtems/cpukit/score/cpu/nios2/nios2-eic-il-low-level.S @ 51e59d5

Last change on this file since 51e59d5 was 51e59d5, checked in by Sebastian Huber <sebastian.huber@…>, on 01/12/21 at 13:03:41

nios2: Allow ISR nesting in dispatch variant

Rename _Nios2_ISR_Dispatch_with_shadow_non_preemptive() in
_Nios2_ISR_Dispatch_with_shadow_register_set(). Remove
_Nios2_ISR_Dispatch_with_shadow_preemptive().

  • Property mode set to 100644
File size: 6.4 KB
Line 
1/*
2 * Copyright (c) 2011-2015 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <rtems/score/percpu.h>
16#include <rtems/score/nios2-utility.h>
17
18#define FRAME_OFFSET_RA 0
19#define FRAME_OFFSET_AT 4
20#define FRAME_OFFSET_R2 8
21#define FRAME_OFFSET_R3 12
22#define FRAME_OFFSET_R4 16
23#define FRAME_OFFSET_R5 20
24#define FRAME_OFFSET_R6 24
25#define FRAME_OFFSET_R7 28
26#define FRAME_OFFSET_R8 32
27#define FRAME_OFFSET_R9 36
28#define FRAME_OFFSET_R10 40
29#define FRAME_OFFSET_R11 44
30#define FRAME_OFFSET_R12 48
31#define FRAME_OFFSET_R13 52
32#define FRAME_OFFSET_R14 56
33#define FRAME_OFFSET_R15 60
34#define FRAME_OFFSET_STATUS 64
35#define FRAME_OFFSET_EA  68
36
37#define FRAME_SIZE (FRAME_OFFSET_EA + 4)
38
39        .set    noat
40        .set    nobreak
41        .section        .text
42
43        .extern _Per_CPU_Information
44        .extern _Nios2_ISR_Status_interrupts_disabled
45
46        .globl  _Nios2_ISR_Dispatch_with_shadow_register_set
47
48_Nios2_ISR_Dispatch_with_shadow_register_set:
49
50        /* Load thread dispatch disable level */
51        ldw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
52
53        /* Read status */
54        rdctl   r18, status
55
56        /* Load high level handler address and argument */
57        ldw     r8, 4(et)
58        ldw     r4, 8(et)
59
60        /* Increment and store thread dispatch disable level */
61        addi    r17, r16, 1
62        stw     r17, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
63
64        /*
65         * Enable higher level interrupts.  This is safe since status.RSIE is
66         * always 0 and thread dispatching is disabled right above.  Higher
67         * priority interrupts shall not share shadow register sets with lower
68         * priority interrupts.
69         */
70        ori     r5, r18, 1
71        wrctl   status, r5
72
73        /* Call high level handler with argument */
74        callr   r8
75
76        /* Load the thread dispatch necessary indicator */
77        ldb     r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
78
79        /* Load the thread dispatch after ISR disable indicator */
80        ldw     r13, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
81
82        /* Fix return address */
83        subi    ea, ea, 4
84
85        /*
86         * If the current thread dispatch disable level (r17) is one, then
87         * negate the thread dispatch necessary indicator, otherwise the value
88         * is irrelevant.  Or it with the previous thread dispatch disable
89         * level value (r16).  The r15 which will be used as a status to
90         * determine if a thread dispatch is necessary and allowed.
91         */
92        xor     r12, r17, r12
93        or      r15, r12, r16
94
95        /*
96         * Get the previous register set from r18.  If it is zero, then this is
97         * the outermost interrupt.  Or it to the thread dispatch status (r15).
98         */
99        andhi   r12, r18, 0x3f
100        or      r15, r12, r15
101
102        /*
103         * Or the thread dispatch after ISR disable indicator (r13) to the
104         * thread dispatch status (r15).
105         */
106        or      r15, r13, r15
107
108        /* Is a thread dispatch necessary and allowed? */
109        bne     r15, zero, no_thread_dispatch
110
111        /* Obtain stack frame in normal register set */
112        rdprs   r15, sp, -FRAME_SIZE
113
114        /* Disable thread dispatch after ISR */
115        stw     r17, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
116
117        /* Save context */
118        stw     sstatus, FRAME_OFFSET_STATUS(r15)
119        stw     ea, FRAME_OFFSET_EA(r15)
120
121        /* Set thread dispatch helper address */
122        movhi   ea, %hiadj(thread_dispatch_helper)
123        addi    ea, ea, %lo(thread_dispatch_helper)
124
125        /* Update stack pointer in normal register set */
126        wrprs   sp, r15
127
128        /* Jump to thread dispatch helper */
129        eret
130
131no_thread_dispatch:
132
133        /* Restore the thread dispatch disable level */
134        stw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
135
136        /* Return to interrupted context */
137        eret
138
139thread_dispatch_helper:
140
141        /* This code executes in the context of the interrupted thread */
142
143        /* Save volatile registers */
144        stw     ra, FRAME_OFFSET_RA(sp)
145        stw     at, FRAME_OFFSET_AT(sp)
146        stw     r2, FRAME_OFFSET_R2(sp)
147        stw     r3, FRAME_OFFSET_R3(sp)
148        stw     r4, FRAME_OFFSET_R4(sp)
149        stw     r5, FRAME_OFFSET_R5(sp)
150        stw     r6, FRAME_OFFSET_R6(sp)
151        stw     r7, FRAME_OFFSET_R7(sp)
152        stw     r8, FRAME_OFFSET_R8(sp)
153        stw     r9, FRAME_OFFSET_R9(sp)
154        stw     r10, FRAME_OFFSET_R10(sp)
155        stw     r11, FRAME_OFFSET_R11(sp)
156        stw     r12, FRAME_OFFSET_R12(sp)
157        stw     r13, FRAME_OFFSET_R13(sp)
158        stw     r14, FRAME_OFFSET_R14(sp)
159        stw     r15, FRAME_OFFSET_R15(sp)
160
161        /*
162         * Disable interrupts (1).
163         *
164         * We have the following invariants:
165         *   1. status.RSIE == 0: thread context initialization
166         *   2. status.CRS == 0: thread context initialization
167         *   3. status.PRS: arbitrary
168         *   4. status.IL < interrupt disable IL: else we would not be here
169         *   5. status.IH == 0: thread context initialization
170         *   6. status.U == 0: thread context initialization
171         *   7. status.PIE == 1: thread context initialization
172         * Thus we can use a constant to disable interrupts.
173         */
174        movi    r5, %lo(_Nios2_ISR_Status_interrupts_disabled)
175        wrctl   status, r5
176
177do_thread_dispatch:
178
179        addi    r4, gp, %gprel(_Per_CPU_Information)
180        call    _Thread_Do_dispatch
181
182        /* Restore some volatile registers */
183        ldw     ra, FRAME_OFFSET_RA(sp)
184        ldw     at, FRAME_OFFSET_AT(sp)
185        ldw     r2, FRAME_OFFSET_R2(sp)
186        ldw     r3, FRAME_OFFSET_R3(sp)
187        ldw     r4, FRAME_OFFSET_R4(sp)
188        ldw     r5, FRAME_OFFSET_R5(sp)
189        ldw     r6, FRAME_OFFSET_R6(sp)
190        ldw     r7, FRAME_OFFSET_R7(sp)
191        ldw     r8, FRAME_OFFSET_R8(sp)
192        ldw     r9, FRAME_OFFSET_R9(sp)
193        ldw     r10, FRAME_OFFSET_R10(sp)
194        ldw     r11, FRAME_OFFSET_R11(sp)
195        ldw     r12, FRAME_OFFSET_R12(sp)
196
197        /* Disable interrupts, see (1) */
198        rdctl   r14, status
199        movi    r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
200        wrctl   status, r15
201
202        /* Load thread dispatch necessary */
203        ldb     r13, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
204
205        /* Is thread dispatch necessary? */
206        bne     r13, zero, prepare_thread_dispatch
207
208        /* Enable thread dispatch after ISR */
209        stw     zero, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
210
211        /* Restore remaining volatile register */
212        ldw     r13, FRAME_OFFSET_R13(sp)
213        ldw     r14, FRAME_OFFSET_R14(sp)
214        ldw     r15, FRAME_OFFSET_R15(sp)
215
216        /* Restore context */
217        ldw     et, FRAME_OFFSET_STATUS(sp)
218        ldw     ea, FRAME_OFFSET_EA(sp)
219
220        /* Release stack frame */
221        addi    sp, sp, FRAME_SIZE
222
223        /* Restore context */
224        wrctl   estatus, et
225
226        /* Return to interrupted thread */
227        eret
228
229prepare_thread_dispatch:
230
231        /* Disable thread dispatching */
232        movi    r4, 1
233        stw     r4, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
234        stw     r4, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
235
236        /* Set interrupt level argument for _Thread_Do_dispatch() */
237        mov     r5, r15
238
239        br      do_thread_dispatch
Note: See TracBrowser for help on using the repository browser.