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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//! Module for interfacing with the GBA's Direct Memory Access units.
//!
//! The GBA has four DMA units, numbered from 0 to 3. They can be used for
//! extremely efficient memory transfers, and they can also be set to
//! automatically transfer in response to select events.
//!
//! Whenever a DMA unit is active, the CPU does not operate at all. Not even
//! hardware interrupts will occur while a DMA is running. The interrupt will
//! instead happen after the DMA transfer is done. When it's critical that an
//! interrupt be handled exactly on time (such as when using serial interrupts)
//! then you should avoid any large DMA transfers.
//!
//! In any situation when more than one DMA unit would be active at the same
//! time, the lower-numbered DMA unit runs first.
//!
//! Each DMA unit is controlled by 4 different MMIO addresses, as follows
//! (replace `x` with the DMA unit's number):
//! * `DMAx_SRC` and `DMAx_DEST`: source and destination address. DMA 0 can only
//! use internal memory, DMA 1 and 2 can read from the gamepak but not write
//! to it, and DMA 3 can even write to the gamepak (when the gamepak itself
//! supports that). In all cases, SRAM cannot be accessed. The addresses of a
//! transfer should always be aliged to the element size.
//! * `DMAx_COUNT`: Number of elements to transfer. The number of elements is
//! either a 14-bit (DMA 0/1/2) or 16-bit (DMA3) number. If the count is set
//! to 0 then the transfer will instead copy one more than the normal maximum
//! of that number's range (DMA 0/1/2: 16_384, DMA 3: 65_536).
//! * `DMAx_CONTROL`: Configuration bits for the transfer, see [`DmaControl`].
//!
//! ## Safety
//!
//! The DMA units are the least safe part of the GBA and should be used with
//! caution.
//!
//! Because Rust doesn't have a fully precise memory model, and because LLVM is
//! a little fuzzy about the limits of what a volatile address access can do,
//! you are advised to **not** use DMA to alter any memory that is part of
//! Rust's compilation (stack variables, static variables, etc).
//!
//! You are advised to only use the DMA units to transfer data into VRAM,
//! PALRAM, OAM, and MMIO controls (eg: the FIFO sound buffers).
//!
//! In the future the situation may improve.
use crate;
/// Sets the change in destination address after each transfer.
/// Sets the change in source address after each transfer.
/// When the DMA unit should start doing work.
/// DMA control configuration.
///
/// * `dest_addr_control`: How the destination address changes per element
/// transferred.
/// * `src_addr_control`: How the source address changes per element
/// transferred.
/// * `repeat`: If the DMA should automatically trigger again at the next start
/// time (vblank, hblank, or special). Caution: if you use `repeat` in
/// combination with the `Immediate` start time then the DMA will run over and
/// over and lock up the system.
/// * `transfer_32bit`: When set the DMA will transfer in 32-bit elements.
/// Otherwise, it will transfer in 16-bit elements. In general, you should
/// always transfer using 32-bit units when possible.
/// * `start_time`: When the DMA unit should begin a transfer.
/// * `irq_after`: If the end of the DMA transfer should send a hardware
/// interrupt.
/// * `enabled`: If the DMA unit is active.
;
/// Uses `stm` to set all parts of a DMA as a single instruction.
///
/// * `dma_id` is 0, 1, 2, or 3 (this is debug asserted).
/// * `src` address for the transfer
/// * `dest` address for the transfer
/// * `count_ctrl` is the count in the low half and control in the upper half
// we may make this pub in the future, until then this is basically a note
unsafe