source: rtems/cpukit/score/cpu/nios2/rtems/score/nios2-utility.h @ 8eb559d3

4.115
Last change on this file since 8eb559d3 was 8eb559d3, checked in by Sebastian Huber <sebastian.huber@…>, on 04/11/12 at 08:34:01

nios2: New functions

Add

o _Nios2_MPU_Get_region_descriptor(), and
o _Nios2_MPU_Set_region_registers().

  • Property mode set to 100644
File size: 13.9 KB
Line 
1/*
2 * Copyright (c) 2011 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Obere Lagerstr. 30
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
12 * http://www.rtems.com/license/LICENSE.
13 *
14 * $Id$
15 */
16
17#ifndef _RTEMS_SCORE_NIOS2_UTILITY_H
18#define _RTEMS_SCORE_NIOS2_UTILITY_H
19
20#define NIOS2_CTLREG_INDEX_STATUS 0
21#define NIOS2_CTLREG_INDEX_ESTATUS 1
22#define NIOS2_CTLREG_INDEX_BSTATUS 2
23#define NIOS2_CTLREG_INDEX_IENABLE 3
24#define NIOS2_CTLREG_INDEX_IPENDING 4
25#define NIOS2_CTLREG_INDEX_CPUID 5
26#define NIOS2_CTLREG_INDEX_EXCEPTION 7
27#define NIOS2_CTLREG_INDEX_PTEADDR 8
28#define NIOS2_CTLREG_INDEX_TLBACC 9
29#define NIOS2_CTLREG_INDEX_TLBMISC 10
30#define NIOS2_CTLREG_INDEX_BADADDR 12
31#define NIOS2_CTLREG_INDEX_CONFIG 13
32#define NIOS2_CTLREG_INDEX_MPUBASE 14
33#define NIOS2_CTLREG_INDEX_MPUACC 15
34
35#define NIOS2_CONTEXT_OFFSET_R16 0
36#define NIOS2_CONTEXT_OFFSET_R17 4
37#define NIOS2_CONTEXT_OFFSET_R18 8
38#define NIOS2_CONTEXT_OFFSET_R19 12
39#define NIOS2_CONTEXT_OFFSET_R20 16
40#define NIOS2_CONTEXT_OFFSET_R21 20
41#define NIOS2_CONTEXT_OFFSET_R22 24
42#define NIOS2_CONTEXT_OFFSET_R23 28
43#define NIOS2_CONTEXT_OFFSET_FP 32
44#define NIOS2_CONTEXT_OFFSET_STATUS 36
45#define NIOS2_CONTEXT_OFFSET_SP 40
46#define NIOS2_CONTEXT_OFFSET_RA 44
47#define NIOS2_CONTEXT_OFFSET_THREAD_DISPATCH_DISABLED 48
48#define NIOS2_CONTEXT_OFFSET_STACK_MPUBASE 52
49#define NIOS2_CONTEXT_OFFSET_STACK_MPUACC 56
50
51#define NIOS2_ISR_STATUS_MASK_IIC 0xfffffffe
52#define NIOS2_ISR_STATUS_BITS_IIC 0x00000000
53
54#define NIOS2_ISR_STATUS_MASK_EIC_IL 0xfffffc0f
55#define NIOS2_ISR_STATUS_BITS_EIC_IL 0x000003f0
56
57#define NIOS2_ISR_STATUS_MASK_EIC_RSIE 0xf7ffffff
58#define NIOS2_ISR_STATUS_BITS_EIC_RSIE 0x00000000
59
60#define NIOS2_STATUS_RSIE (1 << 23)
61#define NIOS2_STATUS_NMI (1 << 22)
62#define NIOS2_STATUS_PRS_OFFSET 16
63#define NIOS2_STATUS_PRS_MASK (0x3f << NIOS2_STATUS_PRS_OFFSET)
64#define NIOS2_STATUS_CRS_OFFSET 10
65#define NIOS2_STATUS_CRS_MASK (0x3f << NIOS2_STATUS_CRS_OFFSET)
66#define NIOS2_STATUS_IL_OFFSET 4
67#define NIOS2_STATUS_IL_MASK (0x3f << NIOS2_STATUS_IL_OFFSET)
68#define NIOS2_STATUS_IH (1 << 3)
69#define NIOS2_STATUS_EH (1 << 2)
70#define NIOS2_STATUS_U (1 << 1)
71#define NIOS2_STATUS_PIE (1 << 0)
72
73#define NIOS2_EXCEPTION_CAUSE_OFFSET 2
74#define NIOS2_EXCEPTION_CAUSE_MASK (0x1f << NIOS2_EXCEPTION_CAUSE_OFFSET)
75
76#define NIOS2_PTEADDR_PTBASE_OFFSET 22
77#define NIOS2_PTEADDR_PTBASE_MASK (0x3ff << NIOS2_PTEADDR_PTBASE_OFFSET)
78#define NIOS2_PTEADDR_VPN_OFFSET 2
79#define NIOS2_PTEADDR_VPN_MASK (0xfffff << NIOS2_PTEADDR_VPN_OFFSET)
80
81#define NIOS2_TLBACC_IG_OFFSET 25
82#define NIOS2_TLBACC_IG_MASK (0x3ff << NIOS2_TLBACC_IG_OFFSET)
83#define NIOS2_TLBACC_C (1 << 24)
84#define NIOS2_TLBACC_R (1 << 23)
85#define NIOS2_TLBACC_W (1 << 22)
86#define NIOS2_TLBACC_X (1 << 21)
87#define NIOS2_TLBACC_G (1 << 20)
88#define NIOS2_TLBACC_PFN_OFFSET 2
89#define NIOS2_TLBACC_PFN_MASK (0xfffff << NIOS2_TLBACC_PFN_OFFSET)
90
91#define NIOS2_TLBMISC_WAY_OFFSET 20
92#define NIOS2_TLBMISC_WAY_MASK (0xf << NIOS2_TLBMISC_WAY_OFFSET)
93#define NIOS2_TLBMISC_RD (1 << 19)
94#define NIOS2_TLBMISC_WE (1 << 18)
95#define NIOS2_TLBMISC_PID_OFFSET 5
96#define NIOS2_TLBMISC_PID_MASK (0x3fff << NIOS2_TLBMISC_PID_OFFSET)
97#define NIOS2_TLBMISC_DBL (1 << 3)
98#define NIOS2_TLBMISC_BAD (1 << 2)
99#define NIOS2_TLBMISC_PERM (1 << 1)
100#define NIOS2_TLBMISC_D (1 << 0)
101
102#define NIOS2_CONFIG_ANI (1 << 1)
103#define NIOS2_CONFIG_PE (1 << 0)
104
105#define NIOS2_MPUBASE_BASE_OFFSET 6
106#define NIOS2_MPUBASE_BASE_MASK (0x1ffffff << NIOS2_MPUBASE_BASE_OFFSET)
107#define NIOS2_MPUBASE_INDEX_OFFSET 1
108
109/* Avoid redefines with Altera HAL */
110#define NIOS2_MPUBASE_INDEX_MASK (0x0000003e)
111
112#define NIOS2_MPUBASE_D (1 << 0)
113
114#define NIOS2_MPUACC_MASK_OFFSET 6
115
116/* Avoid redefines with Altera HAL */
117#define NIOS2_MPUACC_MASK_MASK (0x7fffffc0)
118
119#define NIOS2_MPUACC_LIMIT_OFFSET 6
120
121/* Avoid redefines with Altera HAL */
122#define NIOS2_MPUACC_LIMIT_MASK (0xffffffc0)
123
124#define NIOS2_MPUACC_C (1 << 5)
125#define NIOS2_MPUACC_PERM_OFFSET 2
126
127/* Avoid redefines with Altera HAL */
128#define NIOS2_MPUACC_PERM_MASK (0x0000001c)
129
130#define NIOS2_MPUACC_RD (1 << 1)
131#define NIOS2_MPUACC_WR (1 << 0)
132
133#ifndef ASM
134
135#include <stddef.h>
136#include <stdint.h>
137#include <stdbool.h>
138
139#ifdef __cplusplus
140extern "C" {
141#endif /* __cplusplus */
142
143/**
144 * @brief Nios II specific thread dispatch disabled indicator.
145 *
146 * This global variable is used by the interrupt dispatch support for the
147 * external interrupt controller (EIC) with shadow registers.  This makes it
148 * possible to do the thread dispatch after an interrupt without disabled
149 * interrupts and thus probably reduce the maximum interrupt latency.  Its
150 * purpose is to prevent unbounded stack usage of the interrupted thread.
151 */
152extern uint32_t _Nios2_Thread_dispatch_disabled;
153
154/**
155 * @brief This global symbol specifies the status register mask used to disable
156 * interrupts.
157 *
158 * The board support package must provide a global symbol with this name to
159 * specifiy the status register mask used in _CPU_ISR_Disable().
160 */
161extern char _Nios2_ISR_Status_mask [];
162
163/**
164 * @brief This symbol specifies the status register bits used to disable
165 * interrupts.
166 *
167 * The board support package must provide a global symbol with this name to
168 * specifiy the status register bits used in _CPU_ISR_Disable().
169 */
170extern char _Nios2_ISR_Status_bits [];
171
172static inline void _Nios2_Flush_pipeline( void )
173{
174  __asm__ volatile ("flushp");
175}
176
177static inline uint32_t _Nios2_Get_ctlreg_status( void )
178{
179  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_STATUS );
180}
181
182static inline void _Nios2_Set_ctlreg_status( uint32_t value )
183{
184  __builtin_wrctl( NIOS2_CTLREG_INDEX_STATUS, (int) value );
185}
186
187static inline uint32_t _Nios2_Get_ctlreg_estatus( void )
188{
189  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_ESTATUS );
190}
191
192static inline void _Nios2_Set_ctlreg_estatus( uint32_t value )
193{
194  __builtin_wrctl( NIOS2_CTLREG_INDEX_ESTATUS, (int) value );
195}
196
197static inline uint32_t _Nios2_Get_ctlreg_bstatus( void )
198{
199  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_BSTATUS );
200}
201
202static inline void _Nios2_Set_ctlreg_bstatus( uint32_t value )
203{
204  __builtin_wrctl( NIOS2_CTLREG_INDEX_BSTATUS, (int) value );
205}
206
207static inline uint32_t _Nios2_Get_ctlreg_ienable( void )
208{
209  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_IENABLE );
210}
211
212static inline void _Nios2_Set_ctlreg_ienable( uint32_t value )
213{
214  __builtin_wrctl( NIOS2_CTLREG_INDEX_IENABLE, (int) value );
215}
216
217static inline uint32_t _Nios2_Get_ctlreg_ipending( void )
218{
219  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_IPENDING );
220}
221
222static inline uint32_t _Nios2_Get_ctlreg_cpuid( void )
223{
224  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_CPUID );
225}
226
227static inline uint32_t _Nios2_Get_ctlreg_exception( void )
228{
229  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_EXCEPTION );
230}
231
232static inline uint32_t _Nios2_Get_ctlreg_pteaddr( void )
233{
234  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_PTEADDR );
235}
236
237static inline void _Nios2_Set_ctlreg_pteaddr( uint32_t value )
238{
239  __builtin_wrctl( NIOS2_CTLREG_INDEX_PTEADDR, (int) value );
240}
241
242static inline uint32_t _Nios2_Get_ctlreg_tlbacc( void )
243{
244  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_TLBACC );
245}
246
247static inline void _Nios2_Set_ctlreg_tlbacc( uint32_t value )
248{
249  __builtin_wrctl( NIOS2_CTLREG_INDEX_TLBACC, (int) value );
250}
251
252static inline uint32_t _Nios2_Get_ctlreg_tlbmisc( void )
253{
254  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_TLBMISC );
255}
256
257static inline void _Nios2_Set_ctlreg_tlbmisc( uint32_t value )
258{
259  __builtin_wrctl( NIOS2_CTLREG_INDEX_TLBMISC, (int) value );
260}
261
262static inline uint32_t _Nios2_Get_ctlreg_badaddr( void )
263{
264  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_BADADDR );
265}
266
267static inline uint32_t _Nios2_Get_ctlreg_config( void )
268{
269  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_CONFIG );
270}
271
272static inline void _Nios2_Set_ctlreg_config( uint32_t value )
273{
274  __builtin_wrctl( NIOS2_CTLREG_INDEX_CONFIG, (int) value );
275}
276
277static inline uint32_t _Nios2_Get_ctlreg_mpubase( void )
278{
279  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_MPUBASE );
280}
281
282static inline void _Nios2_Set_ctlreg_mpubase( uint32_t value )
283{
284  __builtin_wrctl( NIOS2_CTLREG_INDEX_MPUBASE, (int) value );
285}
286
287static inline uint32_t _Nios2_Get_ctlreg_mpuacc( void )
288{
289  return (uint32_t) __builtin_rdctl( NIOS2_CTLREG_INDEX_MPUACC );
290}
291
292static inline void _Nios2_Set_ctlreg_mpuacc( uint32_t value )
293{
294  __builtin_wrctl( NIOS2_CTLREG_INDEX_MPUACC, (int) value );
295}
296
297static inline uint32_t _Nios2_ISR_Get_status_mask( void )
298{
299  return (uint32_t) &_Nios2_ISR_Status_mask [0];
300}
301
302static inline uint32_t _Nios2_ISR_Get_status_bits( void )
303{
304  return (uint32_t) &_Nios2_ISR_Status_bits [0];
305}
306
307static inline bool _Nios2_Has_internal_interrupt_controller( void )
308{
309  return _Nios2_ISR_Get_status_mask() == NIOS2_ISR_STATUS_MASK_IIC;
310}
311
312uint32_t _Nios2_ISR_Set_level( uint32_t new_level, uint32_t status );
313
314typedef struct {
315  int data_address_width;
316  int instruction_address_width;
317  int data_region_size_log2;
318  int instruction_region_size_log2;
319  int data_region_count;
320  int instruction_region_count;
321  int data_index_for_stack_protection;
322  bool region_uses_limit;
323  bool enable_data_cache_for_stack;
324} Nios2_MPU_Configuration;
325
326void _Nios2_MPU_Set_configuration( const Nios2_MPU_Configuration *config );
327
328const Nios2_MPU_Configuration *_Nios2_MPU_Get_configuration( void );
329
330typedef enum {
331  NIOS2_MPU_INST_PERM_SVR_NONE_USER_NONE = 0,
332  NIOS2_MPU_INST_PERM_SVR_EXECUTE_USER_NONE,
333  NIOS2_MPU_INST_PERM_SVR_EXECUTE_USER_EXECUTE,
334  NIOS2_MPU_DATA_PERM_SVR_NONE_USER_NONE = 0,
335  NIOS2_MPU_DATA_PERM_SVR_READONLY_USER_NONE,
336  NIOS2_MPU_DATA_PERM_SVR_READONLY_USER_READONLY,
337  NIOS2_MPU_DATA_PERM_SVR_READWRITE_USER_NONE = 4,
338  NIOS2_MPU_DATA_PERM_SVR_READWRITE_USER_READONLY,
339  NIOS2_MPU_DATA_PERM_SVR_READWRITE_USER_READWRITE
340} Nios2_MPU_Region_permissions;
341
342typedef struct {
343  int index;
344  const void *base;
345  const void *end;
346  Nios2_MPU_Region_permissions perm;
347  bool data;
348  bool cacheable;
349  bool read;
350  bool write;
351} Nios2_MPU_Region_descriptor;
352
353#define NIOS2_MPU_REGION_DESC_INST( index, base, end ) \
354  { \
355    (index), (base), (end), NIOS2_MPU_INST_PERM_SVR_EXECUTE_USER_NONE, \
356    false, false, false, true \
357  }
358
359#define NIOS2_MPU_REGION_DESC_DATA_RO( index, base, end ) \
360  { \
361    (index), (base), (end), NIOS2_MPU_DATA_PERM_SVR_READONLY_USER_NONE, \
362    true, true, false, true \
363  }
364
365#define NIOS2_MPU_REGION_DESC_DATA_RW( index, base, end ) \
366  { \
367    (index), (base), (end), NIOS2_MPU_DATA_PERM_SVR_READWRITE_USER_NONE, \
368    true, true, false, true \
369  }
370
371#define NIOS2_MPU_REGION_DESC_DATA_IO( index, base, end ) \
372  { \
373    (index), (base), (end), NIOS2_MPU_DATA_PERM_SVR_READWRITE_USER_NONE, \
374    true, false, false, true \
375  }
376
377static inline int _Nios2_MPU_Get_region_count(
378  const Nios2_MPU_Configuration *config,
379  bool data
380)
381{
382  return data ?
383    config->data_region_count
384      : config->instruction_region_count;
385}
386
387static inline bool _Nios2_MPU_Is_valid_index(
388  const Nios2_MPU_Configuration *config,
389  int index,
390  bool data
391)
392{
393  return 0 <= index
394    && index < _Nios2_MPU_Get_region_count( config, data );
395}
396
397bool _Nios2_MPU_Setup_region_registers(
398  const Nios2_MPU_Configuration *config,
399  const Nios2_MPU_Region_descriptor *desc,
400  uint32_t *mpubase,
401  uint32_t *mpuacc
402);
403
404bool _Nios2_MPU_Get_region_descriptor(
405  const Nios2_MPU_Configuration *config,
406  int index,
407  bool data,
408  Nios2_MPU_Region_descriptor *desc
409);
410
411/**
412 * @brief Seaches the region table part for a disabled region.
413 *
414 * The table will be searched between indices @a begin and @a end.  The @a end
415 * index is not part of the search range.  If @a end is negative, then the
416 * region count will be used.  Thus a @a begin of 0 and a @a end of -1 will
417 * specifiy the complete table.
418 *
419 * @retval -1 No disabled region is available.
420 * @retval other Index of disabled region.
421 */
422int _Nios2_MPU_Get_disabled_region_index(
423  const Nios2_MPU_Configuration *config,
424  bool data,
425  int begin,
426  int end
427);
428
429/**
430 * @brief Adds a region according to region descriptor @a desc.
431 *
432 * If @a force is true, then an enabled region will be overwritten.
433 *
434 * @retval true Successful operation.
435 * @retval false Invalid region descriptor or region already in use.
436 */
437bool _Nios2_MPU_Add_region(
438  const Nios2_MPU_Configuration *config,
439  const Nios2_MPU_Region_descriptor *desc,
440  bool force
441);
442
443static inline void _Nios2_MPU_Get_region_registers(
444  int index,
445  bool data,
446  uint32_t *mpubase,
447  uint32_t *mpuacc
448)
449{
450  uint32_t base = (uint32_t)
451    (((index << NIOS2_MPUBASE_INDEX_OFFSET) & NIOS2_MPUBASE_INDEX_MASK)
452      | (data ? NIOS2_MPUBASE_D : 0));
453
454  _Nios2_Set_ctlreg_mpubase( base );
455  _Nios2_Set_ctlreg_mpuacc( NIOS2_MPUACC_RD );
456  _Nios2_Flush_pipeline();
457  *mpubase = _Nios2_Get_ctlreg_mpubase() | base;
458  *mpuacc = _Nios2_Get_ctlreg_mpuacc();
459}
460
461static inline void _Nios2_MPU_Set_region_registers(
462  uint32_t mpubase,
463  uint32_t mpuacc
464)
465{
466  _Nios2_Set_ctlreg_mpubase( mpubase );
467  _Nios2_Set_ctlreg_mpuacc( mpuacc );
468  _Nios2_Flush_pipeline();
469}
470
471static inline void _Nios2_MPU_Enable( void )
472{
473  uint32_t config = _Nios2_Get_ctlreg_config();
474
475  _Nios2_Set_ctlreg_config( config | NIOS2_CONFIG_PE );
476}
477
478static inline uint32_t _Nios2_MPU_Disable( void )
479{
480  uint32_t config = _Nios2_Get_ctlreg_config();
481  uint32_t config_pe = NIOS2_CONFIG_PE;
482
483  _Nios2_Set_ctlreg_config( config & ~config_pe );
484
485  return config;
486}
487
488static inline void _Nios2_MPU_Restore( uint32_t config )
489{
490  _Nios2_Set_ctlreg_config( config );
491}
492
493uint32_t _Nios2_MPU_Disable_protected( void );
494
495void _Nios2_MPU_Reset( const Nios2_MPU_Configuration *config );
496
497#ifdef __cplusplus
498}
499#endif /* __cplusplus */
500
501#else /* ASM */
502
503        .macro  NIOS2_ASM_DISABLE_INTERRUPTS new_status, current_status
504        movhi   \new_status, %hiadj(_Nios2_ISR_Status_mask)
505        addi    \new_status, \new_status, %lo(_Nios2_ISR_Status_mask)
506        and     \new_status, \current_status, \new_status
507        ori     \new_status, \new_status, %lo(_Nios2_ISR_Status_bits)
508        wrctl   status, \new_status
509        .endm
510
511#endif /* ASM */
512
513#endif /* _RTEMS_SCORE_NIOS2_UTILITY_H */
Note: See TracBrowser for help on using the repository browser.