source: rtems/cpukit/score/cpu/nios2/include/rtems/score/cpu.h @ 511dc4b

5
Last change on this file since 511dc4b was 511dc4b, checked in by Sebastian Huber <sebastian.huber@…>, on 06/19/18 at 07:09:51

Rework initialization and interrupt stack support

Statically initialize the interrupt stack area
(_Configuration_Interrupt_stack_area_begin,
_Configuration_Interrupt_stack_area_end, and
_Configuration_Interrupt_stack_size) via <rtems/confdefs.h>. Place the
interrupt stack area in a special section ".rtemsstack.interrupt". Let
BSPs define the optimal placement of this section in their linker
command files (e.g. in a fast on-chip memory).

This change makes makes the CPU_HAS_SOFTWARE_INTERRUPT_STACK and
CPU_HAS_HARDWARE_INTERRUPT_STACK CPU port defines superfluous, since the
low level initialization code has all information available via global
symbols.

This change makes the CPU_ALLOCATE_INTERRUPT_STACK CPU port define
superfluous, since the interrupt stacks are allocated by confdefs.h for
all architectures. There is no need for BSP-specific linker command
file magic (except the section placement), see previous ARM linker
command file as a bad example.

Remove _CPU_Install_interrupt_stack(). Initialize the hardware
interrupt stack in _CPU_Initialize() if necessary (e.g.
m68k_install_interrupt_stack()).

The optional _CPU_Interrupt_stack_setup() is still useful to customize
the registration of the interrupt stack area in the per-CPU information.

The initialization stack can reuse the interrupt stack, since

  • interrupts are disabled during the sequential system initialization, and
  • the boot_card() function does not return.

This stack resuse saves memory.

Changes per architecture:

arm:

  • Mostly replace the linker symbol based configuration of stacks with the standard <rtems/confdefs.h> configuration via CONFIGURE_INTERRUPT_STACK_SIZE. The size of the FIQ, ABT and UND mode stack is still defined via linker symbols. These modes are rarely used in applications and the default values provided by the BSP should be sufficient in most cases.
  • Remove the bsp_processor_count linker symbol hack used for the SMP support. This is possible since the interrupt stack area is now allocated by the linker and not allocated from the heap. This makes some configure.ac stuff obsolete. Remove the now superfluous BSP variants altcycv_devkit_smp and realview_pbx_a9_qemu_smp.

bfin:

  • Remove unused magic linker command file allocation of initialization stack. Maybe a previous linker command file copy and paste problem? In the start.S the initialization stack is set to a hard coded value.

lm32, m32c, mips, nios2, riscv, sh, v850:

  • Remove magic linker command file allocation of initialization stack. Reuse interrupt stack for initialization stack.

m68k:

  • Remove magic linker command file allocation of initialization stack. Reuse interrupt stack for initialization stack.

powerpc:

  • Remove magic linker command file allocation of initialization stack. Reuse interrupt stack for initialization stack.
  • Used dedicated memory region (REGION_RTEMSSTACK) for the interrupt stack on BSPs using the shared linkcmds.base (replacement for REGION_RWEXTRA).

sparc:

  • Remove the hard coded initialization stack. Use the interrupt stack for the initialization stack on the boot processor. This saves 16KiB of RAM.

Update #3459.

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/**
2 * @file
3 *
4 * @brief Altera Nios II CPU Department Source
5 */
6
7/*
8 *  Copyright (c) 2011 embedded brains GmbH
9 *
10 *  Copyright (c) 2006 Kolja Waschk (rtemsdev/ixo.de)
11 *
12 *  COPYRIGHT (c) 1989-2004.
13 *  On-Line Applications Research Corporation (OAR).
14 *
15 *  The license and distribution terms for this file may be
16 *  found in the file LICENSE in this distribution or at
17 *  http://www.rtems.org/license/LICENSE.
18 */
19
20#ifndef _RTEMS_SCORE_CPU_H
21#define _RTEMS_SCORE_CPU_H
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27#include <rtems/score/basedefs.h>
28#include <rtems/score/nios2.h>
29
30#define CPU_SIMPLE_VECTORED_INTERRUPTS TRUE
31
32#define CPU_INTERRUPT_NUMBER_OF_VECTORS 32
33
34#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
35
36#define CPU_PROVIDES_ISR_IS_IN_PROGRESS TRUE
37
38#define CPU_ISR_PASSES_FRAME_POINTER FALSE
39
40#define CPU_HARDWARE_FP FALSE
41
42#define CPU_SOFTWARE_FP FALSE
43
44#define CPU_CONTEXT_FP_SIZE 0
45
46#define CPU_ALL_TASKS_ARE_FP FALSE
47
48#define CPU_IDLE_TASK_IS_FP FALSE
49
50#define CPU_USE_DEFERRED_FP_SWITCH FALSE
51
52#define CPU_ENABLE_ROBUST_THREAD_DISPATCH FALSE
53
54#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
55
56#define CPU_STACK_GROWS_UP FALSE
57
58/* FIXME: Is this the right value? */
59#define CPU_CACHE_LINE_BYTES 32
60
61#define CPU_STRUCTURE_ALIGNMENT \
62  RTEMS_SECTION( ".sdata" ) RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES )
63
64#define CPU_STACK_MINIMUM_SIZE (4 * 1024)
65
66#define CPU_SIZEOF_POINTER 4
67
68/*
69 * Alignment value according to "Nios II Processor Reference" chapter 7
70 * "Application Binary Interface" section "Memory Alignment".
71 */
72#define CPU_ALIGNMENT 4
73
74#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
75
76#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
77
78/*
79 * Alignment value according to "Nios II Processor Reference" chapter 7
80 * "Application Binary Interface" section "Stacks".
81 */
82#define CPU_STACK_ALIGNMENT 4
83
84#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
85
86/*
87 * A Nios II configuration with an external interrupt controller (EIC) supports
88 * up to 64 interrupt levels.  A Nios II configuration with an internal
89 * interrupt controller (IIC) has only two interrupt levels (enabled and
90 * disabled).  The _CPU_ISR_Get_level() and _CPU_ISR_Set_level() functions will
91 * take care about configuration specific mappings.
92 */
93#define CPU_MODES_INTERRUPT_MASK 0x3f
94
95#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
96
97#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
98
99#define CPU_MAXIMUM_PROCESSORS 32
100
101#ifndef ASM
102
103/**
104 * @brief Thread register context.
105 *
106 * The thread register context covers the non-volatile registers, the thread
107 * stack pointer, the return address, and the processor status.
108 *
109 * There is no need to save the global pointer (gp) since it is a system wide
110 * constant and set-up with the C runtime environment.
111 *
112 * The @a thread_dispatch_disabled field is used for the external interrupt
113 * controller (EIC) support.
114 *
115 * @see _Nios2_Thread_dispatch_disabled
116 */
117typedef struct {
118  uint32_t r16;
119  uint32_t r17;
120  uint32_t r18;
121  uint32_t r19;
122  uint32_t r20;
123  uint32_t r21;
124  uint32_t r22;
125  uint32_t r23;
126  uint32_t fp;
127  uint32_t status;
128  uint32_t sp;
129  uint32_t ra;
130  uint32_t thread_dispatch_disabled;
131  uint32_t stack_mpubase;
132  uint32_t stack_mpuacc;
133} Context_Control;
134
135#define _CPU_Context_Get_SP( _context ) \
136  (_context)->sp
137
138typedef void CPU_Interrupt_frame;
139
140typedef struct {
141  uint32_t r1;
142  uint32_t r2;
143  uint32_t r3;
144  uint32_t r4;
145  uint32_t r5;
146  uint32_t r6;
147  uint32_t r7;
148  uint32_t r8;
149  uint32_t r9;
150  uint32_t r10;
151  uint32_t r11;
152  uint32_t r12;
153  uint32_t r13;
154  uint32_t r14;
155  uint32_t r15;
156  uint32_t r16;
157  uint32_t r17;
158  uint32_t r18;
159  uint32_t r19;
160  uint32_t r20;
161  uint32_t r21;
162  uint32_t r22;
163  uint32_t r23;
164  uint32_t gp;
165  uint32_t fp;
166  uint32_t sp;
167  uint32_t ra;
168  uint32_t et;
169  uint32_t ea;
170  uint32_t status;
171  uint32_t ienable;
172  uint32_t ipending;
173} CPU_Exception_frame;
174
175#define _CPU_Initialize_vectors()
176
177/**
178 * @brief Macro to disable interrupts.
179 *
180 * The processor status before disabling the interrupts will be stored in
181 * @a _isr_cookie.  This value will be used in _CPU_ISR_Flash() and
182 * _CPU_ISR_Enable().
183 *
184 * The global symbol _Nios2_ISR_Status_mask will be used to clear the bits in
185 * the status register representing the interrupt level.  The global symbol
186 * _Nios2_ISR_Status_bits will be used to set the bits representing an
187 * interrupt level that disables interrupts.  Both global symbols must be
188 * provided by the board support package.
189 *
190 * In case the Nios II uses the internal interrupt controller (IIC), then only
191 * the PIE status bit is used.
192 *
193 * In case the Nios II uses the external interrupt controller (EIC), then the
194 * RSIE status bit or the IL status field is used depending on the interrupt
195 * handling variant and the shadow register usage.
196 */
197#define _CPU_ISR_Disable( _isr_cookie ) \
198  do { \
199    int _tmp; \
200    __asm__ volatile ( \
201      "rdctl %0, status\n" \
202      "movhi %1, %%hiadj(_Nios2_ISR_Status_mask)\n" \
203      "addi %1, %1, %%lo(_Nios2_ISR_Status_mask)\n" \
204      "and %1, %0, %1\n" \
205      "ori %1, %1, %%lo(_Nios2_ISR_Status_bits)\n" \
206      "wrctl status, %1" \
207      : "=&r" (_isr_cookie), "=&r" (_tmp) \
208    ); \
209  } while ( 0 )
210
211/**
212 * @brief Macro to restore the processor status.
213 *
214 * The @a _isr_cookie must contain the processor status returned by
215 * _CPU_ISR_Disable().  The value is not modified.
216 */
217#define _CPU_ISR_Enable( _isr_cookie ) \
218  __builtin_wrctl( 0, (int) _isr_cookie )
219
220/**
221 * @brief Macro to restore the processor status and disable the interrupts
222 * again.
223 *
224 * The @a _isr_cookie must contain the processor status returned by
225 * _CPU_ISR_Disable().  The value is not modified.
226 *
227 * This flash code is optimal for all Nios II configurations.  The rdctl does
228 * not flush the pipeline and has only a late result penalty.  The wrctl on
229 * the other hand leads to a pipeline flush.
230 */
231#define _CPU_ISR_Flash( _isr_cookie ) \
232  do { \
233    int _status = __builtin_rdctl( 0 ); \
234    __builtin_wrctl( 0, (int) _isr_cookie ); \
235    __builtin_wrctl( 0, _status ); \
236  } while ( 0 )
237
238bool _CPU_ISR_Is_enabled( uint32_t level );
239
240/**
241 * @brief Sets the interrupt level for the executing thread.
242 *
243 * The valid values of @a new_level depend on the Nios II configuration.  A
244 * value of zero represents enabled interrupts in all configurations.
245 *
246 * @see _CPU_ISR_Get_level()
247 */
248void _CPU_ISR_Set_level( uint32_t new_level );
249
250/**
251 * @brief Returns the interrupt level of the executing thread.
252 *
253 * @retval 0 Interrupts are enabled.
254 * @retval otherwise The value depends on the Nios II configuration.  In case
255 * of an internal interrupt controller (IIC) the only valid value is one which
256 * indicates disabled interrupts.  In case of an external interrupt controller
257 * (EIC) there are two possibilities.  Firstly if the RSIE status bit is used
258 * to disable interrupts, then one is the only valid value indicating disabled
259 * interrupts.  Secondly if the IL status field is used to disable interrupts,
260 * then this value will be returned.  Interrupts are disabled at the maximum
261 * level specified by the _Nios2_ISR_Status_bits.
262 */
263uint32_t _CPU_ISR_Get_level( void );
264
265/**
266 * @brief Initializes the CPU context.
267 *
268 * The following steps are performed:
269 *  - setting a starting address
270 *  - preparing the stack
271 *  - preparing the stack and frame pointers
272 *  - setting the proper interrupt level in the context
273 *
274 * @param[in] context points to the context area
275 * @param[in] stack_area_begin is the low address of the allocated stack area
276 * @param[in] stack_area_size is the size of the stack area in bytes
277 * @param[in] new_level is the interrupt level for the task
278 * @param[in] entry_point is the task's entry point
279 * @param[in] is_fp is set to @c true if the task is a floating point task
280 * @param[in] tls_area is the thread-local storage (TLS) area
281 */
282void _CPU_Context_Initialize(
283  Context_Control *context,
284  void *stack_area_begin,
285  size_t stack_area_size,
286  uint32_t new_level,
287  void (*entry_point)( void ),
288  bool is_fp,
289  void *tls_area
290);
291
292#define _CPU_Context_Restart_self( _the_context ) \
293  _CPU_Context_restore( (_the_context) );
294
295void _CPU_Fatal_halt( uint32_t _source, uint32_t _error )
296  RTEMS_NO_RETURN;
297
298/**
299 * @brief CPU initialization.
300 */
301void _CPU_Initialize( void );
302
303/**
304 * @brief CPU ISR install raw handler.
305 */
306void _CPU_ISR_install_raw_handler(
307  uint32_t vector,
308  proc_ptr new_handler,
309  proc_ptr *old_handler
310);
311
312/**
313 * @brief CPU ISR install vector.
314 */
315void _CPU_ISR_install_vector(
316  uint32_t vector,
317  proc_ptr new_handler,
318  proc_ptr *old_handler
319);
320
321void _CPU_Context_switch( Context_Control *run, Context_Control *heir );
322
323void _CPU_Context_restore(
324  Context_Control *new_context
325) RTEMS_NO_RETURN;
326
327void _CPU_Context_volatile_clobber( uintptr_t pattern );
328
329void _CPU_Context_validate( uintptr_t pattern );
330
331void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
332
333static inline uint32_t CPU_swap_u32( uint32_t value )
334{
335  uint32_t byte1, byte2, byte3, byte4, swapped;
336
337  byte4 = (value >> 24) & 0xff;
338  byte3 = (value >> 16) & 0xff;
339  byte2 = (value >> 8)  & 0xff;
340  byte1 =  value        & 0xff;
341
342  swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
343
344  return swapped;
345}
346
347#define CPU_swap_u16( value ) \
348  (((value&0xff) << 8) | ((value >> 8)&0xff))
349
350typedef uint32_t CPU_Counter_ticks;
351
352uint32_t _CPU_Counter_frequency( void );
353
354CPU_Counter_ticks _CPU_Counter_read( void );
355
356static inline CPU_Counter_ticks _CPU_Counter_difference(
357  CPU_Counter_ticks second,
358  CPU_Counter_ticks first
359)
360{
361  return second - first;
362}
363
364/** Type that can store a 32-bit integer or a pointer. */
365typedef uintptr_t CPU_Uint32ptr;
366
367#endif /* ASM */
368
369#ifdef __cplusplus
370}
371#endif
372
373#endif
Note: See TracBrowser for help on using the repository browser.