source: rtems/cpukit/score/cpu/or1k/include/rtems/score/cpu.h @ 8b65b574

Last change on this file since 8b65b574 was 8b65b574, checked in by Sebastian Huber <sebastian.huber@…>, on 07/28/21 at 12:41:32

score: Canonicalize _CPU_Fatal_halt()

Move _CPU_Fatal_halt() declaration to <rtems/score/cpuimpl.h> and make sure it
is a proper declaration of a function which does not return. Fix the type of
the error code. If necessary, add the implementation to cpu.c. Implementing
_CPU_Fatal_halt() as a function makes it possible to wrap this function for
example to fully test _Terminate().

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