source: rtems/cpukit/score/cpu/or1k/include/rtems/score/cpu.h @ 48dd7b8c

Last change on this file since 48dd7b8c was 48dd7b8c, checked in by Kinsey Moore <kinsey.moore@…>, on 06/29/20 at 19:35:08

score: Add CPU_USE_LIBC_INIT_FINI_ARRAY

This introduces the CPU_USE_LIBC_INIT_FINI_ARRAY define for use by CPU
ports to determine which global constructor and destructor methods are
used instead of placing architecture defines where they shouldn't be.

Close #4018

  • Property mode set to 100644
File size: 16.5 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup RTEMScoreCPUor1k
5 */
6
7/*
8 *  This include file contains macros pertaining to the Opencores
9 *  or1k processor family.
10 *
11 *  COPYRIGHT (c) 2014 Hesham ALMatary <heshamelmatary@gmail.com>
12 *  COPYRIGHT (c) 1989-1999.
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 *  This file adapted from no_cpu example of the RTEMS distribution.
20 *  The body has been modified for the Opencores OR1k implementation by
21 *  Chris Ziomkowski. <chris@asics.ws>
22 *
23 */
24
25#ifndef _OR1K_CPU_H
26#define _OR1K_CPU_H
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
32
33#include <rtems/score/or1k.h>            /* pick up machine definitions */
34#include <rtems/score/or1k-utility.h>
35#include <rtems/score/basedefs.h>
36#ifndef ASM
37#include <rtems/bspIo.h>
38#include <stdint.h>
39#include <stdio.h> /* for printk */
40#endif
41
42/* conditional compilation parameters */
43
44/*
45 *  Does the RTEMS invoke the user's ISR with the vector number and
46 *  a pointer to the saved interrupt frame (1) or just the vector
47 *  number (0)?
48 *
49 */
50
51#define CPU_ISR_PASSES_FRAME_POINTER TRUE
52
53#define CPU_HARDWARE_FP FALSE
54
55#define CPU_SOFTWARE_FP FALSE
56
57#define CPU_ALL_TASKS_ARE_FP FALSE
58
59#define CPU_IDLE_TASK_IS_FP FALSE
60
61#define CPU_USE_DEFERRED_FP_SWITCH TRUE
62
63#define CPU_ENABLE_ROBUST_THREAD_DISPATCH FALSE
64
65/*
66 *  Does the stack grow up (toward higher addresses) or down
67 *  (toward lower addresses)?
68 *
69 *  If TRUE, then the grows upward.
70 *  If FALSE, then the grows toward smaller addresses.
71 *
72 */
73
74#define CPU_STACK_GROWS_UP               FALSE
75
76/* FIXME: Is this the right value? */
77#define CPU_CACHE_LINE_BYTES 32
78
79#define CPU_STRUCTURE_ALIGNMENT RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES )
80
81/*
82 *  The following defines the number of bits actually used in the
83 *  interrupt field of the task mode.  How those bits map to the
84 *  CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
85 *
86 */
87
88#define CPU_MODES_INTERRUPT_MASK   0x00000001
89
90/*
91 *  Processor defined structures required for cpukit/score.
92 */
93
94
95/*
96 * Contexts
97 *
98 *  Generally there are 2 types of context to save.
99 *     1. Interrupt registers to save
100 *     2. Task level registers to save
101 *
102 *  This means we have the following 3 context items:
103 *     1. task level context stuff::  Context_Control
104 *     2. floating point task stuff:: Context_Control_fp
105 *     3. special interrupt level context :: Context_Control_interrupt
106 *
107 *  On some processors, it is cost-effective to save only the callee
108 *  preserved registers during a task context switch.  This means
109 *  that the ISR code needs to save those registers which do not
110 *  persist across function calls.  It is not mandatory to make this
111 *  distinctions between the caller/callee saves registers for the
112 *  purpose of minimizing context saved during task switch and on interrupts.
113 *  If the cost of saving extra registers is minimal, simplicity is the
114 *  choice.  Save the same context on interrupt entry as for tasks in
115 *  this case.
116 *
117 *  Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
118 *  care should be used in designing the context area.
119 *
120 *  On some CPUs with hardware floating point support, the Context_Control_fp
121 *  structure will not be used or it simply consist of an array of a
122 *  fixed number of bytes.   This is done when the floating point context
123 *  is dumped by a "FP save context" type instruction and the format
124 *  is not really defined by the CPU.  In this case, there is no need
125 *  to figure out the exact format -- only the size.  Of course, although
126 *  this is enough information for RTEMS, it is probably not enough for
127 *  a debugger such as gdb.  But that is another problem.
128 *
129 *
130 */
131#ifndef ASM
132#ifdef OR1K_64BIT_ARCH
133#define or1kreg uint64_t
134#else
135#define or1kreg uint32_t
136#endif
137
138typedef struct {
139  uint32_t  r1;     /* Stack pointer */
140  uint32_t  r2;     /* Frame pointer */
141  uint32_t  r3;
142  uint32_t  r4;
143  uint32_t  r5;
144  uint32_t  r6;
145  uint32_t  r7;
146  uint32_t  r8;
147  uint32_t  r9;
148  uint32_t  r10;
149  uint32_t  r11;
150  uint32_t  r12;
151  uint32_t  r13;
152  uint32_t  r14;
153  uint32_t  r15;
154  uint32_t  r16;
155  uint32_t  r17;
156  uint32_t  r18;
157  uint32_t  r19;
158  uint32_t  r20;
159  uint32_t  r21;
160  uint32_t  r22;
161  uint32_t  r23;
162  uint32_t  r24;
163  uint32_t  r25;
164  uint32_t  r26;
165  uint32_t  r27;
166  uint32_t  r28;
167  uint32_t  r29;
168  uint32_t  r30;
169  uint32_t  r31;
170
171  uint32_t  sr;  /* Current supervision register non persistent values */
172  uint32_t  epcr;
173  uint32_t  eear;
174  uint32_t  esr;
175} Context_Control;
176
177#define _CPU_Context_Get_SP( _context ) \
178  (_context)->r1
179
180typedef Context_Control CPU_Interrupt_frame;
181
182/*
183 *  Amount of extra stack (above minimum stack size) required by
184 *  MPCI receive server thread.  Remember that in a multiprocessor
185 *  system this thread must exist and be able to process all directives.
186 *
187 */
188
189#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
190
191/*
192 *  Should be large enough to run all RTEMS tests.  This insures
193 *  that a "reasonable" small application should not have any problems.
194 *
195 */
196
197#define CPU_STACK_MINIMUM_SIZE  4096
198
199/*
200 *  CPU's worst alignment requirement for data types on a byte boundary.  This
201 *  alignment does not take into account the requirements for the stack.
202 *
203 */
204
205#define CPU_ALIGNMENT  8
206
207/*
208 *  This is defined if the port has a special way to report the ISR nesting
209 *  level.  Most ports maintain the variable _ISR_Nest_level.
210 */
211#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
212
213/**
214 * Size of a pointer.
215 *
216 * This must be an integer literal that can be used by the assembler.  This
217 * value will be used to calculate offsets of structure members.  These
218 * offsets will be used in assembler code.
219 */
220#define CPU_SIZEOF_POINTER         4
221
222/*
223 *  This number corresponds to the byte alignment requirement for the
224 *  heap handler.  This alignment requirement may be stricter than that
225 *  for the data types alignment specified by CPU_ALIGNMENT.  It is
226 *  common for the heap to follow the same alignment requirement as
227 *  CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict enough for the heap,
228 *  then this should be set to CPU_ALIGNMENT.
229 *
230 *  NOTE:  This does not have to be a power of 2 although it should be
231 *         a multiple of 2 greater than or equal to 2.  The requirement
232 *         to be a multiple of 2 is because the heap uses the least
233 *         significant field of the front and back flags to indicate
234 *         that a block is in use or free.  So you do not want any odd
235 *         length blocks really putting length data in that bit.
236 *
237 *         On byte oriented architectures, CPU_HEAP_ALIGNMENT normally will
238 *         have to be greater or equal to than CPU_ALIGNMENT to ensure that
239 *         elements allocated from the heap meet all restrictions.
240 *
241 */
242
243#define CPU_HEAP_ALIGNMENT         CPU_ALIGNMENT
244
245/*
246 *  This number corresponds to the byte alignment requirement for the
247 *  stack.  This alignment requirement may be stricter than that for the
248 *  data types alignment specified by CPU_ALIGNMENT.  If the CPU_ALIGNMENT
249 *  is strict enough for the stack, then this should be set to 0.
250 *
251 *  NOTE:  This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
252 *
253 */
254
255#define CPU_STACK_ALIGNMENT        0
256
257#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
258
259/* ISR handler macros */
260
261/*
262 *  Support routine to initialize the RTEMS vector table after it is allocated.
263 *
264 *  NO_CPU Specific Information:
265 *
266 *  XXX document implementation including references if appropriate
267 */
268
269#define _CPU_Initialize_vectors()
270
271/*
272 *  Disable all interrupts for an RTEMS critical section.  The previous
273 *  level is returned in _level.
274 *
275 */
276
277static inline uint32_t or1k_interrupt_disable( void )
278{
279  uint32_t sr;
280  sr = _OR1K_mfspr(CPU_OR1K_SPR_SR);
281
282  _OR1K_mtspr(CPU_OR1K_SPR_SR, (sr & ~CPU_OR1K_SPR_SR_IEE));
283
284  return sr;
285}
286
287static inline void or1k_interrupt_enable(uint32_t level)
288{
289  uint32_t sr;
290
291  /* Enable interrupts and restore rs */
292  sr = level | CPU_OR1K_SPR_SR_IEE | CPU_OR1K_SPR_SR_TEE;
293  _OR1K_mtspr(CPU_OR1K_SPR_SR, sr);
294
295}
296
297#define _CPU_ISR_Disable( _level ) \
298    _level = or1k_interrupt_disable()
299
300
301/*
302 *  Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
303 *  This indicates the end of an RTEMS critical section.  The parameter
304 *  _level is not modified.
305 *
306 */
307
308#define _CPU_ISR_Enable( _level )  \
309  or1k_interrupt_enable( _level )
310
311/*
312 *  This temporarily restores the interrupt to _level before immediately
313 *  disabling them again.  This is used to divide long RTEMS critical
314 *  sections into two or more parts.  The parameter _level is not
315 *  modified.
316 *
317 */
318
319#define _CPU_ISR_Flash( _level ) \
320  do{ \
321      _CPU_ISR_Enable( _level ); \
322      _OR1K_mtspr(CPU_OR1K_SPR_SR, (_level & ~CPU_OR1K_SPR_SR_IEE)); \
323    } while(0)
324
325RTEMS_INLINE_ROUTINE bool _CPU_ISR_Is_enabled( uint32_t level )
326{
327  return ( level & CPU_OR1K_SPR_SR ) != 0;
328}
329
330/*
331 *  Map interrupt level in task mode onto the hardware that the CPU
332 *  actually provides.  Currently, interrupt levels which do not
333 *  map onto the CPU in a generic fashion are undefined.  Someday,
334 *  it would be nice if these were "mapped" by the application
335 *  via a callout.  For example, m68k has 8 levels 0 - 7, levels
336 *  8 - 255 would be available for bsp/application specific meaning.
337 *  This could be used to manage a programmable interrupt controller
338 *  via the rtems_task_mode directive.
339 *
340 *  The get routine usually must be implemented as a subroutine.
341 *
342 */
343
344void _CPU_ISR_Set_level( uint32_t level );
345
346uint32_t _CPU_ISR_Get_level( void );
347
348/* end of ISR handler macros */
349
350/* Context handler macros */
351
352#define OR1K_FAST_CONTEXT_SWITCH_ENABLED FALSE
353/*
354 *  Initialize the context to a state suitable for starting a
355 *  task after a context restore operation.  Generally, this
356 *  involves:
357 *
358 *     - setting a starting address
359 *     - preparing the stack
360 *     - preparing the stack and frame pointers
361 *     - setting the proper interrupt level in the context
362 *     - initializing the floating point context
363 *
364 *  This routine generally does not set any unnecessary register
365 *  in the context.  The state of the "general data" registers is
366 *  undefined at task start time.
367 *
368 *  NOTE: This is_fp parameter is TRUE if the thread is to be a floating
369 *        point thread.  This is typically only used on CPUs where the
370 *        FPU may be easily disabled by software such as on the SPARC
371 *        where the PSR contains an enable FPU bit.
372 *
373 */
374
375/**
376 * @brief Initializes the CPU context.
377 *
378 * The following steps are performed:
379 *  - setting a starting address
380 *  - preparing the stack
381 *  - preparing the stack and frame pointers
382 *  - setting the proper interrupt level in the context
383 *
384 * @param[in] context points to the context area
385 * @param[in] stack_area_begin is the low address of the allocated stack area
386 * @param[in] stack_area_size is the size of the stack area in bytes
387 * @param[in] new_level is the interrupt level for the task
388 * @param[in] entry_point is the task's entry point
389 * @param[in] is_fp is set to @c true if the task is a floating point task
390 * @param[in] tls_area is the thread-local storage (TLS) area
391 */
392void _CPU_Context_Initialize(
393  Context_Control *context,
394  void *stack_area_begin,
395  size_t stack_area_size,
396  uint32_t new_level,
397  void (*entry_point)( void ),
398  bool is_fp,
399  void *tls_area
400);
401
402/*
403 *  This routine is responsible for somehow restarting the currently
404 *  executing task.  If you are lucky, then all that is necessary
405 *  is restoring the context.  Otherwise, there will need to be
406 *  a special assembly routine which does something special in this
407 *  case.  Context_Restore should work most of the time.  It will
408 *  not work if restarting self conflicts with the stack frame
409 *  assumptions of restoring a context.
410 *
411 */
412
413#define _CPU_Context_Restart_self( _the_context ) \
414   _CPU_Context_restore( (_the_context) );
415
416/* end of Context handler macros */
417
418/* Fatal Error manager macros */
419
420/*
421 *  This routine copies _error into a known place -- typically a stack
422 *  location or a register, optionally disables interrupts, and
423 *  halts/stops the CPU.
424 *
425 */
426
427#include <inttypes.h>
428
429#define _CPU_Fatal_halt(_source, _error ) \
430        printk("Fatal Error %d.%" PRId32 " Halted\n",_source, _error); \
431        _OR1KSIM_CPU_Halt(); \
432        for(;;)
433
434/* end of Fatal Error manager macros */
435
436#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
437
438#define CPU_USE_LIBC_INIT_FINI_ARRAY TRUE
439
440#endif /* ASM */
441
442#define CPU_SIZEOF_POINTER 4
443
444#define CPU_MAXIMUM_PROCESSORS 32
445
446#ifndef ASM
447typedef struct {
448  uint32_t r[32];
449
450  /* The following registers must be saved if we have
451  fast context switch disabled and nested interrupt
452  levels are enabled.
453  */
454#if !OR1K_FAST_CONTEXT_SWITCH_ENABLED
455  uint32_t epcr; /* exception PC register */
456  uint32_t eear; /* exception effective address register */
457  uint32_t esr; /* exception supervision register */
458#endif
459
460} CPU_Exception_frame;
461
462/**
463 * @brief Prints the exception frame via printk().
464 *
465 * @see rtems_fatal() and RTEMS_FATAL_SOURCE_EXCEPTION.
466 */
467void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
468
469
470/* end of Priority handler macros */
471
472/* functions */
473
474/*
475 *  _CPU_Initialize
476 *
477 *  This routine performs CPU dependent initialization.
478 *
479 */
480
481void _CPU_Initialize(
482  void
483);
484
485typedef void ( *CPU_ISR_raw_handler )( uint32_t, CPU_Exception_frame * );
486
487void _CPU_ISR_install_raw_handler(
488  uint32_t             vector,
489  CPU_ISR_raw_handler  new_handler,
490  CPU_ISR_raw_handler *old_handler
491);
492
493typedef void ( *CPU_ISR_handler )( uint32_t );
494
495RTEMS_INLINE_ROUTINE void _CPU_ISR_install_vector(
496  uint32_t         vector,
497  CPU_ISR_handler  new_handler,
498  CPU_ISR_handler *old_handler
499)
500{
501  _CPU_ISR_install_raw_handler(
502    vector,
503    (CPU_ISR_raw_handler) new_handler,
504    (CPU_ISR_raw_handler *) old_handler
505  );
506}
507
508void *_CPU_Thread_Idle_body( uintptr_t ignored );
509
510/*
511 *  _CPU_Context_switch
512 *
513 *  This routine switches from the run context to the heir context.
514 *
515 *  Or1k Specific Information:
516 *
517 *  Please see the comments in the .c file for a description of how
518 *  this function works. There are several things to be aware of.
519 */
520
521void _CPU_Context_switch(
522  Context_Control  *run,
523  Context_Control  *heir
524);
525
526/*
527 *  _CPU_Context_restore
528 *
529 *  This routine is generally used only to restart self in an
530 *  efficient manner.  It may simply be a label in _CPU_Context_switch.
531 *
532 *  NOTE: May be unnecessary to reload some registers.
533 *
534 */
535
536void _CPU_Context_restore(
537  Context_Control *new_context
538) RTEMS_NO_RETURN;
539
540/*
541 *  _CPU_Context_save_fp
542 *
543 *  This routine saves the floating point context passed to it.
544 *
545 */
546
547void _CPU_Context_save_fp(
548  void **fp_context_ptr
549);
550
551/*
552 *  _CPU_Context_restore_fp
553 *
554 *  This routine restores the floating point context passed to it.
555 *
556 */
557
558void _CPU_Context_restore_fp(
559  void **fp_context_ptr
560);
561
562/*  The following routine swaps the endian format of an unsigned int.
563 *  It must be static because it is referenced indirectly.
564 *
565 *  This version will work on any processor, but if there is a better
566 *  way for your CPU PLEASE use it.  The most common way to do this is to:
567 *
568 *     swap least significant two bytes with 16-bit rotate
569 *     swap upper and lower 16-bits
570 *     swap most significant two bytes with 16-bit rotate
571 *
572 *  Some CPUs have special instructions which swap a 32-bit quantity in
573 *  a single instruction (e.g. i486).  It is probably best to avoid
574 *  an "endian swapping control bit" in the CPU.  One good reason is
575 *  that interrupts would probably have to be disabled to insure that
576 *  an interrupt does not try to access the same "chunk" with the wrong
577 *  endian.  Another good reason is that on some CPUs, the endian bit
578 *  endianness for ALL fetches -- both code and data -- so the code
579 *  will be fetched incorrectly.
580 *
581 */
582
583static inline unsigned int CPU_swap_u32(
584  unsigned int value
585)
586{
587  uint32_t   byte1, byte2, byte3, byte4, swapped;
588
589  byte4 = (value >> 24) & 0xff;
590  byte3 = (value >> 16) & 0xff;
591  byte2 = (value >> 8)  & 0xff;
592  byte1 =  value        & 0xff;
593
594  swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
595  return( swapped );
596}
597
598#define CPU_swap_u16( value ) \
599  (((value&0xff) << 8) | ((value >> 8)&0xff))
600
601typedef uint32_t CPU_Counter_ticks;
602
603uint32_t _CPU_Counter_frequency( void );
604
605CPU_Counter_ticks _CPU_Counter_read( void );
606
607static inline CPU_Counter_ticks _CPU_Counter_difference(
608  CPU_Counter_ticks second,
609  CPU_Counter_ticks first
610)
611{
612  return second - first;
613}
614
615/** Type that can store a 32-bit integer or a pointer. */
616typedef uintptr_t CPU_Uint32ptr;
617
618#endif /* ASM */
619
620#ifdef __cplusplus
621}
622#endif
623
624#endif
Note: See TracBrowser for help on using the repository browser.