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
RevLine 
[9f1412b9]1/*
[99a1f122]2 * Copyright (c) 2011-2015 embedded brains GmbH.  All rights reserved.
[9f1412b9]3 *
4 *  embedded brains GmbH
[99a1f122]5 *  Dornierstr. 4
[9f1412b9]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
[c499856]12 * http://www.rtems.org/license/LICENSE.
[9f1412b9]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
[99a1f122]40        .set    nobreak
[9f1412b9]41        .section        .text
42
43        .extern _Per_CPU_Information
44        .extern _Nios2_ISR_Status_interrupts_disabled
45
[51e59d5]46        .globl  _Nios2_ISR_Dispatch_with_shadow_register_set
[9f1412b9]47
[51e59d5]48_Nios2_ISR_Dispatch_with_shadow_register_set:
[9f1412b9]49
50        /* Load thread dispatch disable level */
[98c95d1]51        ldw     r16, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
[9f1412b9]52
[51e59d5]53        /* Read status */
54        rdctl   r18, status
55
[9f1412b9]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 */
[19acb3b]61        addi    r17, r16, 1
62        stw     r17, %gprel(_Per_CPU_Information + PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL)(gp)
[9f1412b9]63
[51e59d5]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
[9f1412b9]73        /* Call high level handler with argument */
74        callr   r8
75
[19acb3b]76        /* Load the thread dispatch necessary indicator */
[9f1412b9]77        ldb     r12, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
78
[19acb3b]79        /* Load the thread dispatch after ISR disable indicator */
[9165349d]80        ldw     r13, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
[9f1412b9]81
82        /* Fix return address */
83        subi    ea, ea, 4
84
85        /*
[19acb3b]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.
[9f1412b9]91         */
[19acb3b]92        xor     r12, r17, r12
93        or      r15, r12, r16
[9f1412b9]94
[19acb3b]95        /*
[51e59d5]96         * Get the previous register set from r18.  If it is zero, then this is
[19acb3b]97         * the outermost interrupt.  Or it to the thread dispatch status (r15).
98         */
[51e59d5]99        andhi   r12, r18, 0x3f
[19acb3b]100        or      r15, r12, r15
[9f1412b9]101
[19acb3b]102        /*
103         * Or the thread dispatch after ISR disable indicator (r13) to the
104         * thread dispatch status (r15).
105         */
106        or      r15, r13, r15
[9f1412b9]107
[19acb3b]108        /* Is a thread dispatch necessary and allowed? */
109        bne     r15, zero, no_thread_dispatch
[9f1412b9]110
111        /* Obtain stack frame in normal register set */
112        rdprs   r15, sp, -FRAME_SIZE
113
[9165349d]114        /* Disable thread dispatch after ISR */
[19acb3b]115        stw     r17, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
[9f1412b9]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
[19acb3b]128        /* Jump to thread dispatch helper */
129        eret
130
[9f1412b9]131no_thread_dispatch:
132
[19acb3b]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 */
[9f1412b9]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
[19acb3b]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
[9f1412b9]177do_thread_dispatch:
178
[19acb3b]179        addi    r4, gp, %gprel(_Per_CPU_Information)
180        call    _Thread_Do_dispatch
[9f1412b9]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
[19acb3b]197        /* Disable interrupts, see (1) */
[9f1412b9]198        rdctl   r14, status
199        movi    r15, %lo(_Nios2_ISR_Status_interrupts_disabled)
200        wrctl   status, r15
201
202        /* Load thread dispatch necessary */
[0cce75e]203        ldb     r13, %gprel(_Per_CPU_Information + PER_CPU_DISPATCH_NEEDED)(gp)
[9f1412b9]204
205        /* Is thread dispatch necessary? */
[19acb3b]206        bne     r13, zero, prepare_thread_dispatch
[9f1412b9]207
[9165349d]208        /* Enable thread dispatch after ISR */
209        stw     zero, %gprel(_Per_CPU_Information + PER_CPU_ISR_DISPATCH_DISABLE)(gp)
[9f1412b9]210
211        /* Restore remaining volatile register */
[0cce75e]212        ldw     r13, FRAME_OFFSET_R13(sp)
[9f1412b9]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
[19acb3b]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)
[9f1412b9]235
[19acb3b]236        /* Set interrupt level argument for _Thread_Do_dispatch() */
237        mov     r5, r15
[9f1412b9]238
239        br      do_thread_dispatch
Note: See TracBrowser for help on using the repository browser.