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
|
/*
* Copyright (c) 2011 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Obere Lagerstr. 30
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <rtems/score/nios2-utility.h>
static bool _Nios2_Is_power_of_two( uint32_t size )
{
bool ok = false;
int i = 0;
for ( i = 0; !ok && i < 32; ++i ) {
ok = size == (1U << i);
}
return ok;
}
static bool _Nios2_Is_valid_base_and_end(
const Nios2_MPU_Configuration *config,
bool data,
uint32_t base,
uint32_t end,
uint32_t *mask_or_limit
)
{
uint32_t size = end - base;
uint32_t end_limit = data ?
(1U << config->data_address_width)
: (1U << config->instruction_address_width);
uint32_t mask = data ?
((1U << config->data_region_size_log2)) - 1
: ((1U << config->instruction_region_size_log2)) - 1;
bool ok = base < end && end <= end_limit
&& (base & mask) == 0 && (end & mask) == 0;
if ( config->region_uses_limit ) {
*mask_or_limit = end;
} else {
ok = ok && _Nios2_Is_power_of_two( size );
*mask_or_limit = (~(size - 1)) & NIOS2_MPUACC_MASK_MASK;
}
return ok;
}
static bool _Nios2_Is_valid_permission(
bool data,
int perm
)
{
int max = data ? 6 : 2;
return 0 <= perm && perm <= max && (!data || (data && perm != 3));
}
bool _Nios2_MPU_Setup_region_registers(
const Nios2_MPU_Configuration *config,
const Nios2_MPU_Region_descriptor *desc,
uint32_t *mpubase,
uint32_t *mpuacc
)
{
uint32_t base = (uint32_t) desc->base;
uint32_t end = (uint32_t) desc->end;
uint32_t mask_or_limit = 0;
bool is_valid_base_and_end = _Nios2_Is_valid_base_and_end(
config,
desc->data,
base,
end,
&mask_or_limit
);
bool ok = is_valid_base_and_end
&& _Nios2_MPU_Is_valid_index( config, desc->index, desc->data )
&& _Nios2_Is_valid_permission( desc->data, desc->perm )
&& !(!desc->data && desc->cacheable)
&& !(desc->read && desc->write);
if ( ok ) {
*mpubase = (base & NIOS2_MPUBASE_BASE_MASK)
| ((desc->index << NIOS2_MPUBASE_INDEX_OFFSET) & NIOS2_MPUBASE_INDEX_MASK)
| (desc->data ? NIOS2_MPUBASE_D : 0);
*mpuacc = mask_or_limit
| (desc->cacheable ? NIOS2_MPUACC_C : 0)
| ((desc->perm << NIOS2_MPUACC_PERM_OFFSET) & NIOS2_MPUACC_PERM_MASK)
| (desc->read ? NIOS2_MPUACC_RD : 0)
| (desc->write ? NIOS2_MPUACC_WR : 0);
}
return ok;
}
|