summaryrefslogtreecommitdiff
path: root/cpukit/score/cpu/nios2/include/rtems/score/cpu.h
blob: 5fffed646eb6d1c62e92c057f1b76795c3589409 (plain)
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
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
/**
 * @file
 * 
 * @addtogroup RTEMSScoreCPUnios2
 *
 * @brief Altera Nios II CPU Department Source
 */

/*
 *  Copyright (c) 2011 embedded brains GmbH
 *
 *  Copyright (c) 2006 Kolja Waschk (rtemsdev/ixo.de)
 *
 *  COPYRIGHT (c) 1989-2004.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */

#ifndef _RTEMS_SCORE_CPU_H
#define _RTEMS_SCORE_CPU_H

#ifdef __cplusplus
extern "C" {
#endif

#include <rtems/score/basedefs.h>
#include <rtems/score/nios2.h>

#define CPU_SIMPLE_VECTORED_INTERRUPTS TRUE

#define CPU_INTERRUPT_NUMBER_OF_VECTORS 32

#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)

#define CPU_PROVIDES_ISR_IS_IN_PROGRESS TRUE

#define CPU_ISR_PASSES_FRAME_POINTER FALSE

#define CPU_HARDWARE_FP FALSE

#define CPU_SOFTWARE_FP FALSE

#define CPU_ALL_TASKS_ARE_FP FALSE

#define CPU_IDLE_TASK_IS_FP FALSE

#define CPU_USE_DEFERRED_FP_SWITCH FALSE

#define CPU_ENABLE_ROBUST_THREAD_DISPATCH FALSE

#define CPU_STACK_GROWS_UP FALSE

/* FIXME: Is this the right value? */
#define CPU_CACHE_LINE_BYTES 32

#define CPU_STRUCTURE_ALIGNMENT \
  RTEMS_SECTION( ".sdata" ) RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES )

#define CPU_STACK_MINIMUM_SIZE (4 * 1024)

#define CPU_SIZEOF_POINTER 4

/*
 * Alignment value according to "Nios II Processor Reference" chapter 7
 * "Application Binary Interface" section "Memory Alignment".
 */
#define CPU_ALIGNMENT 4

#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT

/*
 * Alignment value according to "Nios II Processor Reference" chapter 7
 * "Application Binary Interface" section "Stacks".
 */
#define CPU_STACK_ALIGNMENT 4

#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES

/*
 * A Nios II configuration with an external interrupt controller (EIC) supports
 * up to 64 interrupt levels.  A Nios II configuration with an internal
 * interrupt controller (IIC) has only two interrupt levels (enabled and
 * disabled).  The _CPU_ISR_Get_level() and _CPU_ISR_Set_level() functions will
 * take care about configuration specific mappings.
 */
#define CPU_MODES_INTERRUPT_MASK 0x3f

#define CPU_USE_GENERIC_BITFIELD_CODE TRUE

#define CPU_USE_LIBC_INIT_FINI_ARRAY FALSE

#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0

#define CPU_MAXIMUM_PROCESSORS 32

#ifndef ASM

/**
 * @brief Thread register context.
 *
 * The thread register context covers the non-volatile registers, the thread
 * stack pointer, the return address, and the processor status.
 *
 * There is no need to save the global pointer (gp) since it is a system wide
 * constant and set-up with the C runtime environment.
 *
 * The @a thread_dispatch_disabled field is used for the external interrupt
 * controller (EIC) support.
 *
 * @see _Nios2_Thread_dispatch_disabled
 */
typedef struct {
  uint32_t r16;
  uint32_t r17;
  uint32_t r18;
  uint32_t r19;
  uint32_t r20;
  uint32_t r21;
  uint32_t r22;
  uint32_t r23;
  uint32_t fp;
  uint32_t status;
  uint32_t sp;
  uint32_t ra;
  uint32_t thread_dispatch_disabled;
  uint32_t stack_mpubase;
  uint32_t stack_mpuacc;
} Context_Control;

#define _CPU_Context_Get_SP( _context ) \
  (_context)->sp

typedef void CPU_Interrupt_frame;

typedef struct {
  uint32_t r1;
  uint32_t r2;
  uint32_t r3;
  uint32_t r4;
  uint32_t r5;
  uint32_t r6;
  uint32_t r7;
  uint32_t r8;
  uint32_t r9;
  uint32_t r10;
  uint32_t r11;
  uint32_t r12;
  uint32_t r13;
  uint32_t r14;
  uint32_t r15;
  uint32_t r16;
  uint32_t r17;
  uint32_t r18;
  uint32_t r19;
  uint32_t r20;
  uint32_t r21;
  uint32_t r22;
  uint32_t r23;
  uint32_t gp;
  uint32_t fp;
  uint32_t sp;
  uint32_t ra;
  uint32_t et;
  uint32_t ea;
  uint32_t status;
  uint32_t ienable;
  uint32_t ipending;
} CPU_Exception_frame;

#define _CPU_Initialize_vectors()

/**
 * @brief Macro to disable interrupts.
 *
 * The processor status before disabling the interrupts will be stored in
 * @a _isr_cookie.  This value will be used in _CPU_ISR_Flash() and
 * _CPU_ISR_Enable().
 *
 * The global symbol _Nios2_ISR_Status_mask will be used to clear the bits in
 * the status register representing the interrupt level.  The global symbol
 * _Nios2_ISR_Status_bits will be used to set the bits representing an
 * interrupt level that disables interrupts.  Both global symbols must be
 * provided by the board support package.
 *
 * In case the Nios II uses the internal interrupt controller (IIC), then only
 * the PIE status bit is used.
 *
 * In case the Nios II uses the external interrupt controller (EIC), then the
 * RSIE status bit or the IL status field is used depending on the interrupt
 * handling variant and the shadow register usage.
 */
#define _CPU_ISR_Disable( _isr_cookie ) \
  do { \
    int _tmp; \
    __asm__ volatile ( \
      "rdctl %0, status\n" \
      "movhi %1, %%hiadj(_Nios2_ISR_Status_mask)\n" \
      "addi %1, %1, %%lo(_Nios2_ISR_Status_mask)\n" \
      "and %1, %0, %1\n" \
      "ori %1, %1, %%lo(_Nios2_ISR_Status_bits)\n" \
      "wrctl status, %1" \
      : "=&r" (_isr_cookie), "=&r" (_tmp) \
    ); \
  } while ( 0 )

/**
 * @brief Macro to restore the processor status.
 *
 * The @a _isr_cookie must contain the processor status returned by
 * _CPU_ISR_Disable().  The value is not modified.
 */
#define _CPU_ISR_Enable( _isr_cookie ) \
  __builtin_wrctl( 0, (int) _isr_cookie )

/**
 * @brief Macro to restore the processor status and disable the interrupts
 * again.
 *
 * The @a _isr_cookie must contain the processor status returned by
 * _CPU_ISR_Disable().  The value is not modified.
 *
 * This flash code is optimal for all Nios II configurations.  The rdctl does
 * not flush the pipeline and has only a late result penalty.  The wrctl on
 * the other hand leads to a pipeline flush.
 */
#define _CPU_ISR_Flash( _isr_cookie ) \
  do { \
    int _status = __builtin_rdctl( 0 ); \
    __builtin_wrctl( 0, (int) _isr_cookie ); \
    __builtin_wrctl( 0, _status ); \
  } while ( 0 )

bool _CPU_ISR_Is_enabled( uint32_t level );

/**
 * @brief Sets the interrupt level for the executing thread.
 *
 * The valid values of @a new_level depend on the Nios II configuration.  A
 * value of zero represents enabled interrupts in all configurations.
 *
 * @see _CPU_ISR_Get_level()
 */
void _CPU_ISR_Set_level( uint32_t new_level );

/**
 * @brief Returns the interrupt level of the executing thread.
 *
 * @retval 0 Interrupts are enabled.
 * @retval otherwise The value depends on the Nios II configuration.  In case
 * of an internal interrupt controller (IIC) the only valid value is one which
 * indicates disabled interrupts.  In case of an external interrupt controller
 * (EIC) there are two possibilities.  Firstly if the RSIE status bit is used
 * to disable interrupts, then one is the only valid value indicating disabled
 * interrupts.  Secondly if the IL status field is used to disable interrupts,
 * then this value will be returned.  Interrupts are disabled at the maximum
 * level specified by the _Nios2_ISR_Status_bits.
 */
uint32_t _CPU_ISR_Get_level( void );

/**
 * @brief Initializes the CPU context.
 *
 * The following steps are performed:
 *  - setting a starting address
 *  - preparing the stack
 *  - preparing the stack and frame pointers
 *  - setting the proper interrupt level in the context
 *
 * @param[in] context points to the context area
 * @param[in] stack_area_begin is the low address of the allocated stack area
 * @param[in] stack_area_size is the size of the stack area in bytes
 * @param[in] new_level is the interrupt level for the task
 * @param[in] entry_point is the task's entry point
 * @param[in] is_fp is set to @c true if the task is a floating point task
 * @param[in] tls_area is the thread-local storage (TLS) area
 */
void _CPU_Context_Initialize(
  Context_Control *context,
  void *stack_area_begin,
  size_t stack_area_size,
  uint32_t new_level,
  void (*entry_point)( void ),
  bool is_fp,
  void *tls_area
);

#define _CPU_Context_Restart_self( _the_context ) \
  _CPU_Context_restore( (_the_context) );

RTEMS_NO_RETURN void _CPU_Fatal_halt( uint32_t _source, uint32_t _error );

/**
 * @brief CPU initialization.
 */
void _CPU_Initialize( void );

typedef void ( *CPU_ISR_handler )( uint32_t );

void _CPU_ISR_install_vector(
  uint32_t         vector,
  CPU_ISR_handler  new_handler,
  CPU_ISR_handler *old_handler
);

void *_CPU_Thread_Idle_body( uintptr_t ignored );

void _CPU_Context_switch( Context_Control *run, Context_Control *heir );

RTEMS_NO_RETURN void _CPU_Context_restore( Context_Control *new_context );

void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );

static inline uint32_t CPU_swap_u32( uint32_t value )
{
  uint32_t byte1, byte2, byte3, byte4, swapped;

  byte4 = (value >> 24) & 0xff;
  byte3 = (value >> 16) & 0xff;
  byte2 = (value >> 8)  & 0xff;
  byte1 =  value        & 0xff;

  swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;

  return swapped;
}

#define CPU_swap_u16( value ) \
  (((value&0xff) << 8) | ((value >> 8)&0xff))

typedef uint32_t CPU_Counter_ticks;

uint32_t _CPU_Counter_frequency( void );

CPU_Counter_ticks _CPU_Counter_read( void );

static inline CPU_Counter_ticks _CPU_Counter_difference(
  CPU_Counter_ticks second,
  CPU_Counter_ticks first
)
{
  return second - first;
}

/** Type that can store a 32-bit integer or a pointer. */
typedef uintptr_t CPU_Uint32ptr;

#endif /* ASM */

#ifdef __cplusplus
}
#endif

#endif