1 |
66 |
zero_gravi |
<<<
|
2 |
|
|
:sectnums:
|
3 |
|
|
==== Internal Bus Monitor (BUSKEEPER)
|
4 |
|
|
|
5 |
|
|
[cols="<3,<3,<4"]
|
6 |
|
|
[frame="topbot",grid="none"]
|
7 |
|
|
|=======================
|
8 |
|
|
| Hardware source file(s): | neorv32_buskeeper.vhd |
|
9 |
70 |
zero_gravi |
| Software driver file(s): | none |
|
10 |
66 |
zero_gravi |
| Top entity port: | none |
|
11 |
|
|
| Configuration generics: | none |
|
12 |
|
|
| Package constants: | `max_proc_int_response_time_c` | Access time window (#cycles)
|
13 |
|
|
| CPU interrupts: | none |
|
14 |
|
|
|=======================
|
15 |
|
|
|
16 |
68 |
zero_gravi |
|
17 |
66 |
zero_gravi |
**Theory of Operation**
|
18 |
|
|
|
19 |
|
|
The Bus Keeper is a fundamental component of the processor's internal bus system that ensures correct bus operations
|
20 |
|
|
to maintain execution safety. The Bus Keeper monitors every single bus transactions that is intimated by the CPU.
|
21 |
|
|
If an accessed device responds with an error condition or do not respond within a specific _access time window_,
|
22 |
|
|
the according bus access fault exception is raised. The following exceptions can be raised by the Bus Keeper
|
23 |
|
|
(see section <<_neorv32_trap_listing>> for all CPU exceptions):
|
24 |
|
|
|
25 |
|
|
* `TRAP_CODE_I_ACCESS`: error during instruction fetch bus access
|
26 |
|
|
* `TRAP_CODE_S_ACCESS`: error during data store bus access
|
27 |
|
|
* `TRAP_CODE_L_ACCESS`: error during data load bus access
|
28 |
|
|
|
29 |
|
|
The **access time window**, in which an accessed device has to respond, is defined by the `max_proc_int_response_time_c`
|
30 |
|
|
constant from the processor's VHDL package file (`rtl/neorv32_package.vhd`). The default value is **15 clock cycles**.
|
31 |
|
|
|
32 |
|
|
In case of a bus access fault exception application software can evaluate the Bus Keeper's control register
|
33 |
|
|
`NEORV32_BUSKEEPER.CTRL` to retrieve further details of the bus exception. The _BUSKEEPER_ERR_FLAG_ bit indicates
|
34 |
68 |
zero_gravi |
that an actual bus access fault has occurred. The bit is sticky once set and is automatically cleared when reading or
|
35 |
70 |
zero_gravi |
writing the `NEORV32_BUSKEEPER.CTRL` register. The _BUSKEEPER_ERR_TYPE_ bit defines the type of the bus fault:
|
36 |
66 |
zero_gravi |
|
37 |
70 |
zero_gravi |
* `0` - "Device Error": The bus access exception was cause by the memory-mapped device that
|
38 |
66 |
zero_gravi |
has been accessed (the device asserted it's `err_o`).
|
39 |
70 |
zero_gravi |
* `1` - "Timeout Error": The bus access exception was caused by the Bus Keeper because the
|
40 |
68 |
zero_gravi |
accessed memory-mapped device did not respond within the access time window. Note that this error type can also be raised
|
41 |
|
|
by the optional timeout feature of the <<_processor_external_memory_interface_wishbone_axi4_lite>>).
|
42 |
66 |
zero_gravi |
|
43 |
|
|
[NOTE]
|
44 |
70 |
zero_gravi |
Bus access fault exceptions are also raised if a physical memory protection (PMP) rule is violated. In this case
|
45 |
|
|
the _BUSKEEPER_ERR_FLAG_ bit remains zero (since the error signal is not triggered by the BUSKEEPER but by
|
46 |
|
|
the CPU's PMP logic).
|
47 |
66 |
zero_gravi |
|
48 |
|
|
|
49 |
70 |
zero_gravi |
**NULL Address Check**
|
50 |
|
|
|
51 |
|
|
The bus keeper can ensure that no accesses are permitted to NULL addresses (`addr = 0x00000000`). These kind of
|
52 |
|
|
access often occur when using uninitialized pointers. If the _BUSKEEPER_NULL_CHECK_EN_ bit is set, any access to
|
53 |
|
|
address zero (instruction fetch, load data, store data) will raise an according bus exception. This flag
|
54 |
|
|
automatically clears on a hardware reset.
|
55 |
|
|
|
56 |
|
|
If a NULL address access has been detected the _BUSKEEPER_ERR_FLAG_ flag is set and the _BUSKEEPER_ERR_TYPE_
|
57 |
|
|
flag is cleared indicating a "Device Error".
|
58 |
|
|
|
59 |
|
|
[NOTE]
|
60 |
|
|
Address 0 is normally used by the IMEM and contains boot code instructions that are executed _once_ right after
|
61 |
|
|
hardware reset. Hence, activating the bus keeper's NULL check in application code will not corrupt code execution
|
62 |
|
|
at all.
|
63 |
|
|
|
64 |
|
|
|
65 |
66 |
zero_gravi |
.BUSKEEPER register map (`struct NEORV32_BUSKEEPER`)
|
66 |
|
|
[cols="<2,<2,<4,^1,<4"]
|
67 |
|
|
[options="header",grid="all"]
|
68 |
|
|
|=======================
|
69 |
|
|
| Address | Name [C] | Bit(s), Name [C] | R/W | Function
|
70 |
70 |
zero_gravi |
.3+<| `0xffffff7C` .3+<| `NEORV32_BUSKEEPER.CTRL` <|`0` _BUSKEEPER_ERR_TYPE_ ^| r/- | Bus error type, valid if _BUSKEEPER_ERR_FLAG_
|
71 |
|
|
<|`16` _BUSKEEPER_NULL_CHECK_EN_ ^| r/w <| Enable NULL address check when set
|
72 |
|
|
<|`31` _BUSKEEPER_ERR_FLAG_ ^| r/- <| Sticky error flag, clears after read or write access
|
73 |
66 |
zero_gravi |
|=======================
|