source: rtems/cpukit/score/cpu/nios2/include/rtems/score/nios2-utility.h @ 9165349d

Last change on this file since 9165349d was 9165349d, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 12, 2021 at 6:13:08 AM

nios2: Use Per_CPU_Control::isr_dispatch_disable

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