|
1 | NO CONTENT: new file 10644 |
This diff has been collapsed as it changes many lines, (704 lines changed) Show them Hide them | |||
@@ -0,0 +1,704 | |||
|
1 | Dynamic DMA mapping using the generic device | |
|
No newline at end of file | ||
|
2 | ============================================ | |
|
No newline at end of file | ||
|
3 | ||
|
No newline at end of file | ||
|
4 | James E.J. Bottomley <James.Bottomley@HansenPartnership.com> | |
|
No newline at end of file | ||
|
5 | ||
|
No newline at end of file | ||
|
6 | This document describes the DMA API. For a more gentle introduction | |
|
No newline at end of file | ||
|
7 | of the API (and actual examples), see Documentation/DMA-API-HOWTO.txt. | |
|
No newline at end of file | ||
|
8 | ||
|
No newline at end of file | ||
|
9 | This API is split into two pieces. Part I describes the basic API. | |
|
No newline at end of file | ||
|
10 | Part II describes extensions for supporting non-consistent memory | |
|
No newline at end of file | ||
|
11 | machines. Unless you know that your driver absolutely has to support | |
|
No newline at end of file | ||
|
12 | non-consistent platforms (this is usually only legacy platforms) you | |
|
No newline at end of file | ||
|
13 | should only use the API described in part I. | |
|
No newline at end of file | ||
|
14 | ||
|
No newline at end of file | ||
|
15 | Part I - dma_ API | |
|
No newline at end of file | ||
|
16 | ------------------------------------- | |
|
No newline at end of file | ||
|
17 | ||
|
No newline at end of file | ||
|
18 | To get the dma_ API, you must #include <linux/dma-mapping.h>. This | |
|
No newline at end of file | ||
|
19 | provides dma_addr_t and the interfaces described below. | |
|
No newline at end of file | ||
|
20 | ||
|
No newline at end of file | ||
|
21 | A dma_addr_t can hold any valid DMA or bus address for the platform. It | |
|
No newline at end of file | ||
|
22 | can be given to a device to use as a DMA source or target. A CPU cannot | |
|
No newline at end of file | ||
|
23 | reference a dma_addr_t directly because there may be translation between | |
|
No newline at end of file | ||
|
24 | its physical address space and the bus address space. | |
|
No newline at end of file | ||
|
25 | ||
|
No newline at end of file | ||
|
26 | Part Ia - Using large DMA-coherent buffers | |
|
No newline at end of file | ||
|
27 | ------------------------------------------ | |
|
No newline at end of file | ||
|
28 | ||
|
No newline at end of file | ||
|
29 | void * | |
|
No newline at end of file | ||
|
30 | dma_alloc_coherent(struct device *dev, size_t size, | |
|
No newline at end of file | ||
|
31 | dma_addr_t *dma_handle, gfp_t flag) | |
|
No newline at end of file | ||
|
32 | ||
|
No newline at end of file | ||
|
33 | Consistent memory is memory for which a write by either the device or | |
|
No newline at end of file | ||
|
34 | the processor can immediately be read by the processor or device | |
|
No newline at end of file | ||
|
35 | without having to worry about caching effects. (You may however need | |
|
No newline at end of file | ||
|
36 | to make sure to flush the processor's write buffers before telling | |
|
No newline at end of file | ||
|
37 | devices to read that memory.) | |
|
No newline at end of file | ||
|
38 | ||
|
No newline at end of file | ||
|
39 | This routine allocates a region of <size> bytes of consistent memory. | |
|
No newline at end of file | ||
|
40 | ||
|
No newline at end of file | ||
|
41 | It returns a pointer to the allocated region (in the processor's virtual | |
|
No newline at end of file | ||
|
42 | address space) or NULL if the allocation failed. | |
|
No newline at end of file | ||
|
43 | ||
|
No newline at end of file | ||
|
44 | It also returns a <dma_handle> which may be cast to an unsigned integer the | |
|
No newline at end of file | ||
|
45 | same width as the bus and given to the device as the bus address base of | |
|
No newline at end of file | ||
|
46 | the region. | |
|
No newline at end of file | ||
|
47 | ||
|
No newline at end of file | ||
|
48 | Note: consistent memory can be expensive on some platforms, and the | |
|
No newline at end of file | ||
|
49 | minimum allocation length may be as big as a page, so you should | |
|
No newline at end of file | ||
|
50 | consolidate your requests for consistent memory as much as possible. | |
|
No newline at end of file | ||
|
51 | The simplest way to do that is to use the dma_pool calls (see below). | |
|
No newline at end of file | ||
|
52 | ||
|
No newline at end of file | ||
|
53 | The flag parameter (dma_alloc_coherent() only) allows the caller to | |
|
No newline at end of file | ||
|
54 | specify the GFP_ flags (see kmalloc()) for the allocation (the | |
|
No newline at end of file | ||
|
55 | implementation may choose to ignore flags that affect the location of | |
|
No newline at end of file | ||
|
56 | the returned memory, like GFP_DMA). | |
|
No newline at end of file | ||
|
57 | ||
|
No newline at end of file | ||
|
58 | void * | |
|
No newline at end of file | ||
|
59 | dma_zalloc_coherent(struct device *dev, size_t size, | |
|
No newline at end of file | ||
|
60 | dma_addr_t *dma_handle, gfp_t flag) | |
|
No newline at end of file | ||
|
61 | ||
|
No newline at end of file | ||
|
62 | Wraps dma_alloc_coherent() and also zeroes the returned memory if the | |
|
No newline at end of file | ||
|
63 | allocation attempt succeeded. | |
|
No newline at end of file | ||
|
64 | ||
|
No newline at end of file | ||
|
65 | void | |
|
No newline at end of file | ||
|
66 | dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | |
|
No newline at end of file | ||
|
67 | dma_addr_t dma_handle) | |
|
No newline at end of file | ||
|
68 | ||
|
No newline at end of file | ||
|
69 | Free a region of consistent memory you previously allocated. dev, | |
|
No newline at end of file | ||
|
70 | size and dma_handle must all be the same as those passed into | |
|
No newline at end of file | ||
|
71 | dma_alloc_coherent(). cpu_addr must be the virtual address returned by | |
|
No newline at end of file | ||
|
72 | the dma_alloc_coherent(). | |
|
No newline at end of file | ||
|
73 | ||
|
No newline at end of file | ||
|
74 | Note that unlike their sibling allocation calls, these routines | |
|
No newline at end of file | ||
|
75 | may only be called with IRQs enabled. | |
|
No newline at end of file | ||
|
76 | ||
|
No newline at end of file | ||
|
77 | ||
|
No newline at end of file | ||
|
78 | Part Ib - Using small DMA-coherent buffers | |
|
No newline at end of file | ||
|
79 | ------------------------------------------ | |
|
No newline at end of file | ||
|
80 | ||
|
No newline at end of file | ||
|
81 | To get this part of the dma_ API, you must #include <linux/dmapool.h> | |
|
No newline at end of file | ||
|
82 | ||
|
No newline at end of file | ||
|
83 | Many drivers need lots of small DMA-coherent memory regions for DMA | |
|
No newline at end of file | ||
|
84 | descriptors or I/O buffers. Rather than allocating in units of a page | |
|
No newline at end of file | ||
|
85 | or more using dma_alloc_coherent(), you can use DMA pools. These work | |
|
No newline at end of file | ||
|
86 | much like a struct kmem_cache, except that they use the DMA-coherent allocator, | |
|
No newline at end of file | ||
|
87 | not __get_free_pages(). Also, they understand common hardware constraints | |
|
No newline at end of file | ||
|
88 | for alignment, like queue heads needing to be aligned on N-byte boundaries. | |
|
No newline at end of file | ||
|
89 | ||
|
No newline at end of file | ||
|
90 | ||
|
No newline at end of file | ||
|
91 | struct dma_pool * | |
|
No newline at end of file | ||
|
92 | dma_pool_create(const char *name, struct device *dev, | |
|
No newline at end of file | ||
|
93 | size_t size, size_t align, size_t alloc); | |
|
No newline at end of file | ||
|
94 | ||
|
No newline at end of file | ||
|
95 | dma_pool_create() initializes a pool of DMA-coherent buffers | |
|
No newline at end of file | ||
|
96 | for use with a given device. It must be called in a context which | |
|
No newline at end of file | ||
|
97 | can sleep. | |
|
No newline at end of file | ||
|
98 | ||
|
No newline at end of file | ||
|
99 | The "name" is for diagnostics (like a struct kmem_cache name); dev and size | |
|
No newline at end of file | ||
|
100 | are like what you'd pass to dma_alloc_coherent(). The device's hardware | |
|
No newline at end of file | ||
|
101 | alignment requirement for this type of data is "align" (which is expressed | |
|
No newline at end of file | ||
|
102 | in bytes, and must be a power of two). If your device has no boundary | |
|
No newline at end of file | ||
|
103 | crossing restrictions, pass 0 for alloc; passing 4096 says memory allocated | |
|
No newline at end of file | ||
|
104 | from this pool must not cross 4KByte boundaries. | |
|
No newline at end of file | ||
|
105 | ||
|
No newline at end of file | ||
|
106 | ||
|
No newline at end of file | ||
|
107 | void *dma_pool_alloc(struct dma_pool *pool, gfp_t gfp_flags, | |
|
No newline at end of file | ||
|
108 | dma_addr_t *dma_handle); | |
|
No newline at end of file | ||
|
109 | ||
|
No newline at end of file | ||
|
110 | This allocates memory from the pool; the returned memory will meet the | |
|
No newline at end of file | ||
|
111 | size and alignment requirements specified at creation time. Pass | |
|
No newline at end of file | ||
|
112 | GFP_ATOMIC to prevent blocking, or if it's permitted (not | |
|
No newline at end of file | ||
|
113 | in_interrupt, not holding SMP locks), pass GFP_KERNEL to allow | |
|
No newline at end of file | ||
|
114 | blocking. Like dma_alloc_coherent(), this returns two values: an | |
|
No newline at end of file | ||
|
115 | address usable by the CPU, and the DMA address usable by the pool's | |
|
No newline at end of file | ||
|
116 | device. | |
|
No newline at end of file | ||
|
117 | ||
|
No newline at end of file | ||
|
118 | ||
|
No newline at end of file | ||
|
119 | void dma_pool_free(struct dma_pool *pool, void *vaddr, | |
|
No newline at end of file | ||
|
120 | dma_addr_t addr); | |
|
No newline at end of file | ||
|
121 | ||
|
No newline at end of file | ||
|
122 | This puts memory back into the pool. The pool is what was passed to | |
|
No newline at end of file | ||
|
123 | dma_pool_alloc(); the CPU (vaddr) and DMA addresses are what | |
|
No newline at end of file | ||
|
124 | were returned when that routine allocated the memory being freed. | |
|
No newline at end of file | ||
|
125 | ||
|
No newline at end of file | ||
|
126 | ||
|
No newline at end of file | ||
|
127 | void dma_pool_destroy(struct dma_pool *pool); | |
|
No newline at end of file | ||
|
128 | ||
|
No newline at end of file | ||
|
129 | dma_pool_destroy() frees the resources of the pool. It must be | |
|
No newline at end of file | ||
|
130 | called in a context which can sleep. Make sure you've freed all allocated | |
|
No newline at end of file | ||
|
131 | memory back to the pool before you destroy it. | |
|
No newline at end of file | ||
|
132 | ||
|
No newline at end of file | ||
|
133 | ||
|
No newline at end of file | ||
|
134 | Part Ic - DMA addressing limitations | |
|
No newline at end of file | ||
|
135 | ------------------------------------ | |
|
No newline at end of file | ||
|
136 | ||
|
No newline at end of file | ||
|
137 | int | |
|
No newline at end of file | ||
|
138 | dma_supported(struct device *dev, u64 mask) | |
|
No newline at end of file | ||
|
139 | ||
|
No newline at end of file | ||
|
140 | Checks to see if the device can support DMA to the memory described by | |
|
No newline at end of file | ||
|
141 | mask. | |
|
No newline at end of file | ||
|
142 | ||
|
No newline at end of file | ||
|
143 | Returns: 1 if it can and 0 if it can't. | |
|
No newline at end of file | ||
|
144 | ||
|
No newline at end of file | ||
|
145 | Notes: This routine merely tests to see if the mask is possible. It | |
|
No newline at end of file | ||
|
146 | won't change the current mask settings. It is more intended as an | |
|
No newline at end of file | ||
|
147 | internal API for use by the platform than an external API for use by | |
|
No newline at end of file | ||
|
148 | driver writers. | |
|
No newline at end of file | ||
|
149 | ||
|
No newline at end of file | ||
|
150 | int | |
|
No newline at end of file | ||
|
151 | dma_set_mask_and_coherent(struct device *dev, u64 mask) | |
|
No newline at end of file | ||
|
152 | ||
|
No newline at end of file | ||
|
153 | Checks to see if the mask is possible and updates the device | |
|
No newline at end of file | ||
|
154 | streaming and coherent DMA mask parameters if it is. | |
|
No newline at end of file | ||
|
155 | ||
|
No newline at end of file | ||
|
156 | Returns: 0 if successful and a negative error if not. | |
|
No newline at end of file | ||
|
157 | ||
|
No newline at end of file | ||
|
158 | int | |
|
No newline at end of file | ||
|
159 | dma_set_mask(struct device *dev, u64 mask) | |
|
No newline at end of file | ||
|
160 | ||
|
No newline at end of file | ||
|
161 | Checks to see if the mask is possible and updates the device | |
|
No newline at end of file | ||
|
162 | parameters if it is. | |
|
No newline at end of file | ||
|
163 | ||
|
No newline at end of file | ||
|
164 | Returns: 0 if successful and a negative error if not. | |
|
No newline at end of file | ||
|
165 | ||
|
No newline at end of file | ||
|
166 | int | |
|
No newline at end of file | ||
|
167 | dma_set_coherent_mask(struct device *dev, u64 mask) | |
|
No newline at end of file | ||
|
168 | ||
|
No newline at end of file | ||
|
169 | Checks to see if the mask is possible and updates the device | |
|
No newline at end of file | ||
|
170 | parameters if it is. | |
|
No newline at end of file | ||
|
171 | ||
|
No newline at end of file | ||
|
172 | Returns: 0 if successful and a negative error if not. | |
|
No newline at end of file | ||
|
173 | ||
|
No newline at end of file | ||
|
174 | u64 | |
|
No newline at end of file | ||
|
175 | dma_get_required_mask(struct device *dev) | |
|
No newline at end of file | ||
|
176 | ||
|
No newline at end of file | ||
|
177 | This API returns the mask that the platform requires to | |
|
No newline at end of file | ||
|
178 | operate efficiently. Usually this means the returned mask | |
|
No newline at end of file | ||
|
179 | is the minimum required to cover all of memory. Examining the | |
|
No newline at end of file | ||
|
180 | required mask gives drivers with variable descriptor sizes the | |
|
No newline at end of file | ||
|
181 | opportunity to use smaller descriptors as necessary. | |
|
No newline at end of file | ||
|
182 | ||
|
No newline at end of file | ||
|
183 | Requesting the required mask does not alter the current mask. If you | |
|
No newline at end of file | ||
|
184 | wish to take advantage of it, you should issue a dma_set_mask() | |
|
No newline at end of file | ||
|
185 | call to set the mask to the value returned. | |
|
No newline at end of file | ||
|
186 | ||
|
No newline at end of file | ||
|
187 | ||
|
No newline at end of file | ||
|
188 | Part Id - Streaming DMA mappings | |
|
No newline at end of file | ||
|
189 | -------------------------------- | |
|
No newline at end of file | ||
|
190 | ||
|
No newline at end of file | ||
|
191 | dma_addr_t | |
|
No newline at end of file | ||
|
192 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, | |
|
No newline at end of file | ||
|
193 | enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
194 | ||
|
No newline at end of file | ||
|
195 | Maps a piece of processor virtual memory so it can be accessed by the | |
|
No newline at end of file | ||
|
196 | device and returns the bus address of the memory. | |
|
No newline at end of file | ||
|
197 | ||
|
No newline at end of file | ||
|
198 | The direction for both APIs may be converted freely by casting. | |
|
No newline at end of file | ||
|
199 | However the dma_ API uses a strongly typed enumerator for its | |
|
No newline at end of file | ||
|
200 | direction: | |
|
No newline at end of file | ||
|
201 | ||
|
No newline at end of file | ||
|
202 | DMA_NONE no direction (used for debugging) | |
|
No newline at end of file | ||
|
203 | DMA_TO_DEVICE data is going from the memory to the device | |
|
No newline at end of file | ||
|
204 | DMA_FROM_DEVICE data is coming from the device to the memory | |
|
No newline at end of file | ||
|
205 | DMA_BIDIRECTIONAL direction isn't known | |
|
No newline at end of file | ||
|
206 | ||
|
No newline at end of file | ||
|
207 | Notes: Not all memory regions in a machine can be mapped by this API. | |
|
No newline at end of file | ||
|
208 | Further, contiguous kernel virtual space may not be contiguous as | |
|
No newline at end of file | ||
|
209 | physical memory. Since this API does not provide any scatter/gather | |
|
No newline at end of file | ||
|
210 | capability, it will fail if the user tries to map a non-physically | |
|
No newline at end of file | ||
|
211 | contiguous piece of memory. For this reason, memory to be mapped by | |
|
No newline at end of file | ||
|
212 | this API should be obtained from sources which guarantee it to be | |
|
No newline at end of file | ||
|
213 | physically contiguous (like kmalloc). | |
|
No newline at end of file | ||
|
214 | ||
|
No newline at end of file | ||
|
215 | Further, the bus address of the memory must be within the | |
|
No newline at end of file | ||
|
216 | dma_mask of the device (the dma_mask is a bit mask of the | |
|
No newline at end of file | ||
|
217 | addressable region for the device, i.e., if the bus address of | |
|
No newline at end of file | ||
|
218 | the memory ANDed with the dma_mask is still equal to the bus | |
|
No newline at end of file | ||
|
219 | address, then the device can perform DMA to the memory). To | |
|
No newline at end of file | ||
|
220 | ensure that the memory allocated by kmalloc is within the dma_mask, | |
|
No newline at end of file | ||
|
221 | the driver may specify various platform-dependent flags to restrict | |
|
No newline at end of file | ||
|
222 | the bus address range of the allocation (e.g., on x86, GFP_DMA | |
|
No newline at end of file | ||
|
223 | guarantees to be within the first 16MB of available bus addresses, | |
|
No newline at end of file | ||
|
224 | as required by ISA devices). | |
|
No newline at end of file | ||
|
225 | ||
|
No newline at end of file | ||
|
226 | Note also that the above constraints on physical contiguity and | |
|
No newline at end of file | ||
|
227 | dma_mask may not apply if the platform has an IOMMU (a device which | |
|
No newline at end of file | ||
|
228 | maps an I/O bus address to a physical memory address). However, to be | |
|
No newline at end of file | ||
|
229 | portable, device driver writers may *not* assume that such an IOMMU | |
|
No newline at end of file | ||
|
230 | exists. | |
|
No newline at end of file | ||
|
231 | ||
|
No newline at end of file | ||
|
232 | Warnings: Memory coherency operates at a granularity called the cache | |
|
No newline at end of file | ||
|
233 | line width. In order for memory mapped by this API to operate | |
|
No newline at end of file | ||
|
234 | correctly, the mapped region must begin exactly on a cache line | |
|
No newline at end of file | ||
|
235 | boundary and end exactly on one (to prevent two separately mapped | |
|
No newline at end of file | ||
|
236 | regions from sharing a single cache line). Since the cache line size | |
|
No newline at end of file | ||
|
237 | may not be known at compile time, the API will not enforce this | |
|
No newline at end of file | ||
|
238 | requirement. Therefore, it is recommended that driver writers who | |
|
No newline at end of file | ||
|
239 | don't take special care to determine the cache line size at run time | |
|
No newline at end of file | ||
|
240 | only map virtual regions that begin and end on page boundaries (which | |
|
No newline at end of file | ||
|
241 | are guaranteed also to be cache line boundaries). | |
|
No newline at end of file | ||
|
242 | ||
|
No newline at end of file | ||
|
243 | DMA_TO_DEVICE synchronisation must be done after the last modification | |
|
No newline at end of file | ||
|
244 | of the memory region by the software and before it is handed off to | |
|
No newline at end of file | ||
|
245 | the driver. Once this primitive is used, memory covered by this | |
|
No newline at end of file | ||
|
246 | primitive should be treated as read-only by the device. If the device | |
|
No newline at end of file | ||
|
247 | may write to it at any point, it should be DMA_BIDIRECTIONAL (see | |
|
No newline at end of file | ||
|
248 | below). | |
|
No newline at end of file | ||
|
249 | ||
|
No newline at end of file | ||
|
250 | DMA_FROM_DEVICE synchronisation must be done before the driver | |
|
No newline at end of file | ||
|
251 | accesses data that may be changed by the device. This memory should | |
|
No newline at end of file | ||
|
252 | be treated as read-only by the driver. If the driver needs to write | |
|
No newline at end of file | ||
|
253 | to it at any point, it should be DMA_BIDIRECTIONAL (see below). | |
|
No newline at end of file | ||
|
254 | ||
|
No newline at end of file | ||
|
255 | DMA_BIDIRECTIONAL requires special handling: it means that the driver | |
|
No newline at end of file | ||
|
256 | isn't sure if the memory was modified before being handed off to the | |
|
No newline at end of file | ||
|
257 | device and also isn't sure if the device will also modify it. Thus, | |
|
No newline at end of file | ||
|
258 | you must always sync bidirectional memory twice: once before the | |
|
No newline at end of file | ||
|
259 | memory is handed off to the device (to make sure all memory changes | |
|
No newline at end of file | ||
|
260 | are flushed from the processor) and once before the data may be | |
|
No newline at end of file | ||
|
261 | accessed after being used by the device (to make sure any processor | |
|
No newline at end of file | ||
|
262 | cache lines are updated with data that the device may have changed). | |
|
No newline at end of file | ||
|
263 | ||
|
No newline at end of file | ||
|
264 | void | |
|
No newline at end of file | ||
|
265 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | |
|
No newline at end of file | ||
|
266 | enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
267 | ||
|
No newline at end of file | ||
|
268 | Unmaps the region previously mapped. All the parameters passed in | |
|
No newline at end of file | ||
|
269 | must be identical to those passed in (and returned) by the mapping | |
|
No newline at end of file | ||
|
270 | API. | |
|
No newline at end of file | ||
|
271 | ||
|
No newline at end of file | ||
|
272 | dma_addr_t | |
|
No newline at end of file | ||
|
273 | dma_map_page(struct device *dev, struct page *page, | |
|
No newline at end of file | ||
|
274 | unsigned long offset, size_t size, | |
|
No newline at end of file | ||
|
275 | enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
276 | void | |
|
No newline at end of file | ||
|
277 | dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | |
|
No newline at end of file | ||
|
278 | enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
279 | ||
|
No newline at end of file | ||
|
280 | API for mapping and unmapping for pages. All the notes and warnings | |
|
No newline at end of file | ||
|
281 | for the other mapping APIs apply here. Also, although the <offset> | |
|
No newline at end of file | ||
|
282 | and <size> parameters are provided to do partial page mapping, it is | |
|
No newline at end of file | ||
|
283 | recommended that you never use these unless you really know what the | |
|
No newline at end of file | ||
|
284 | cache width is. | |
|
No newline at end of file | ||
|
285 | ||
|
No newline at end of file | ||
|
286 | int | |
|
No newline at end of file | ||
|
287 | dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | |
|
No newline at end of file | ||
|
288 | ||
|
No newline at end of file | ||
|
289 | In some circumstances dma_map_single() and dma_map_page() will fail to create | |
|
No newline at end of file | ||
|
290 | a mapping. A driver can check for these errors by testing the returned | |
|
No newline at end of file | ||
|
291 | DMA address with dma_mapping_error(). A non-zero return value means the mapping | |
|
No newline at end of file | ||
|
292 | could not be created and the driver should take appropriate action (e.g. | |
|
No newline at end of file | ||
|
293 | reduce current DMA mapping usage or delay and try again later). | |
|
No newline at end of file | ||
|
294 | ||
|
No newline at end of file | ||
|
295 | int | |
|
No newline at end of file | ||
|
296 | dma_map_sg(struct device *dev, struct scatterlist *sg, | |
|
No newline at end of file | ||
|
297 | int nents, enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
298 | ||
|
No newline at end of file | ||
|
299 | Returns: the number of bus address segments mapped (this may be shorter | |
|
No newline at end of file | ||
|
300 | than <nents> passed in if some elements of the scatter/gather list are | |
|
No newline at end of file | ||
|
301 | physically or virtually adjacent and an IOMMU maps them with a single | |
|
No newline at end of file | ||
|
302 | entry). | |
|
No newline at end of file | ||
|
303 | ||
|
No newline at end of file | ||
|
304 | Please note that the sg cannot be mapped again if it has been mapped once. | |
|
No newline at end of file | ||
|
305 | The mapping process is allowed to destroy information in the sg. | |
|
No newline at end of file | ||
|
306 | ||
|
No newline at end of file | ||
|
307 | As with the other mapping interfaces, dma_map_sg() can fail. When it | |
|
No newline at end of file | ||
|
308 | does, 0 is returned and a driver must take appropriate action. It is | |
|
No newline at end of file | ||
|
309 | critical that the driver do something, in the case of a block driver | |
|
No newline at end of file | ||
|
310 | aborting the request or even oopsing is better than doing nothing and | |
|
No newline at end of file | ||
|
311 | corrupting the filesystem. | |
|
No newline at end of file | ||
|
312 | ||
|
No newline at end of file | ||
|
313 | With scatterlists, you use the resulting mapping like this: | |
|
No newline at end of file | ||
|
314 | ||
|
No newline at end of file | ||
|
315 | int i, count = dma_map_sg(dev, sglist, nents, direction); | |
|
No newline at end of file | ||
|
316 | struct scatterlist *sg; | |
|
No newline at end of file | ||
|
317 | ||
|
No newline at end of file | ||
|
318 | for_each_sg(sglist, sg, count, i) { | |
|
No newline at end of file | ||
|
319 | hw_address[i] = sg_dma_address(sg); | |
|
No newline at end of file | ||
|
320 | hw_len[i] = sg_dma_len(sg); | |
|
No newline at end of file | ||
|
321 | } | |
|
No newline at end of file | ||
|
322 | ||
|
No newline at end of file | ||
|
323 | where nents is the number of entries in the sglist. | |
|
No newline at end of file | ||
|
324 | ||
|
No newline at end of file | ||
|
325 | The implementation is free to merge several consecutive sglist entries | |
|
No newline at end of file | ||
|
326 | into one (e.g. with an IOMMU, or if several pages just happen to be | |
|
No newline at end of file | ||
|
327 | physically contiguous) and returns the actual number of sg entries it | |
|
No newline at end of file | ||
|
328 | mapped them to. On failure 0, is returned. | |
|
No newline at end of file | ||
|
329 | ||
|
No newline at end of file | ||
|
330 | Then you should loop count times (note: this can be less than nents times) | |
|
No newline at end of file | ||
|
331 | and use sg_dma_address() and sg_dma_len() macros where you previously | |
|
No newline at end of file | ||
|
332 | accessed sg->address and sg->length as shown above. | |
|
No newline at end of file | ||
|
333 | ||
|
No newline at end of file | ||
|
334 | void | |
|
No newline at end of file | ||
|
335 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, | |
|
No newline at end of file | ||
|
336 | int nhwentries, enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
337 | ||
|
No newline at end of file | ||
|
338 | Unmap the previously mapped scatter/gather list. All the parameters | |
|
No newline at end of file | ||
|
339 | must be the same as those and passed in to the scatter/gather mapping | |
|
No newline at end of file | ||
|
340 | API. | |
|
No newline at end of file | ||
|
341 | ||
|
No newline at end of file | ||
|
342 | Note: <nents> must be the number you passed in, *not* the number of | |
|
No newline at end of file | ||
|
343 | bus address entries returned. | |
|
No newline at end of file | ||
|
344 | ||
|
No newline at end of file | ||
|
345 | void | |
|
No newline at end of file | ||
|
346 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, | |
|
No newline at end of file | ||
|
347 | enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
348 | void | |
|
No newline at end of file | ||
|
349 | dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, | |
|
No newline at end of file | ||
|
350 | enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
351 | void | |
|
No newline at end of file | ||
|
352 | dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, | |
|
No newline at end of file | ||
|
353 | enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
354 | void | |
|
No newline at end of file | ||
|
355 | dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, | |
|
No newline at end of file | ||
|
356 | enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
357 | ||
|
No newline at end of file | ||
|
358 | Synchronise a single contiguous or scatter/gather mapping for the CPU | |
|
No newline at end of file | ||
|
359 | and device. With the sync_sg API, all the parameters must be the same | |
|
No newline at end of file | ||
|
360 | as those passed into the single mapping API. With the sync_single API, | |
|
No newline at end of file | ||
|
361 | you can use dma_handle and size parameters that aren't identical to | |
|
No newline at end of file | ||
|
362 | those passed into the single mapping API to do a partial sync. | |
|
No newline at end of file | ||
|
363 | ||
|
No newline at end of file | ||
|
364 | Notes: You must do this: | |
|
No newline at end of file | ||
|
365 | ||
|
No newline at end of file | ||
|
366 | - Before reading values that have been written by DMA from the device | |
|
No newline at end of file | ||
|
367 | (use the DMA_FROM_DEVICE direction) | |
|
No newline at end of file | ||
|
368 | - After writing values that will be written to the device using DMA | |
|
No newline at end of file | ||
|
369 | (use the DMA_TO_DEVICE) direction | |
|
No newline at end of file | ||
|
370 | - before *and* after handing memory to the device if the memory is | |
|
No newline at end of file | ||
|
371 | DMA_BIDIRECTIONAL | |
|
No newline at end of file | ||
|
372 | ||
|
No newline at end of file | ||
|
373 | See also dma_map_single(). | |
|
No newline at end of file | ||
|
374 | ||
|
No newline at end of file | ||
|
375 | dma_addr_t | |
|
No newline at end of file | ||
|
376 | dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size, | |
|
No newline at end of file | ||
|
377 | enum dma_data_direction dir, | |
|
No newline at end of file | ||
|
378 | struct dma_attrs *attrs) | |
|
No newline at end of file | ||
|
379 | ||
|
No newline at end of file | ||
|
380 | void | |
|
No newline at end of file | ||
|
381 | dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr, | |
|
No newline at end of file | ||
|
382 | size_t size, enum dma_data_direction dir, | |
|
No newline at end of file | ||
|
383 | struct dma_attrs *attrs) | |
|
No newline at end of file | ||
|
384 | ||
|
No newline at end of file | ||
|
385 | int | |
|
No newline at end of file | ||
|
386 | dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, | |
|
No newline at end of file | ||
|
387 | int nents, enum dma_data_direction dir, | |
|
No newline at end of file | ||
|
388 | struct dma_attrs *attrs) | |
|
No newline at end of file | ||
|
389 | ||
|
No newline at end of file | ||
|
390 | void | |
|
No newline at end of file | ||
|
391 | dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, | |
|
No newline at end of file | ||
|
392 | int nents, enum dma_data_direction dir, | |
|
No newline at end of file | ||
|
393 | struct dma_attrs *attrs) | |
|
No newline at end of file | ||
|
394 | ||
|
No newline at end of file | ||
|
395 | The four functions above are just like the counterpart functions | |
|
No newline at end of file | ||
|
396 | without the _attrs suffixes, except that they pass an optional | |
|
No newline at end of file | ||
|
397 | struct dma_attrs*. | |
|
No newline at end of file | ||
|
398 | ||
|
No newline at end of file | ||
|
399 | struct dma_attrs encapsulates a set of "DMA attributes". For the | |
|
No newline at end of file | ||
|
400 | definition of struct dma_attrs see linux/dma-attrs.h. | |
|
No newline at end of file | ||
|
401 | ||
|
No newline at end of file | ||
|
402 | The interpretation of DMA attributes is architecture-specific, and | |
|
No newline at end of file | ||
|
403 | each attribute should be documented in Documentation/DMA-attributes.txt. | |
|
No newline at end of file | ||
|
404 | ||
|
No newline at end of file | ||
|
405 | If struct dma_attrs* is NULL, the semantics of each of these | |
|
No newline at end of file | ||
|
406 | functions is identical to those of the corresponding function | |
|
No newline at end of file | ||
|
407 | without the _attrs suffix. As a result dma_map_single_attrs() | |
|
No newline at end of file | ||
|
408 | can generally replace dma_map_single(), etc. | |
|
No newline at end of file | ||
|
409 | ||
|
No newline at end of file | ||
|
410 | As an example of the use of the *_attrs functions, here's how | |
|
No newline at end of file | ||
|
411 | you could pass an attribute DMA_ATTR_FOO when mapping memory | |
|
No newline at end of file | ||
|
412 | for DMA: | |
|
No newline at end of file | ||
|
413 | ||
|
No newline at end of file | ||
|
414 | #include <linux/dma-attrs.h> | |
|
No newline at end of file | ||
|
415 | /* DMA_ATTR_FOO should be defined in linux/dma-attrs.h and | |
|
No newline at end of file | ||
|
416 | * documented in Documentation/DMA-attributes.txt */ | |
|
No newline at end of file | ||
|
417 | ... | |
|
No newline at end of file | ||
|
418 | ||
|
No newline at end of file | ||
|
419 | DEFINE_DMA_ATTRS(attrs); | |
|
No newline at end of file | ||
|
420 | dma_set_attr(DMA_ATTR_FOO, &attrs); | |
|
No newline at end of file | ||
|
421 | .... | |
|
No newline at end of file | ||
|
422 | n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, &attr); | |
|
No newline at end of file | ||
|
423 | .... | |
|
No newline at end of file | ||
|
424 | ||
|
No newline at end of file | ||
|
425 | Architectures that care about DMA_ATTR_FOO would check for its | |
|
No newline at end of file | ||
|
426 | presence in their implementations of the mapping and unmapping | |
|
No newline at end of file | ||
|
427 | routines, e.g.: | |
|
No newline at end of file | ||
|
428 | ||
|
No newline at end of file | ||
|
429 | void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr, | |
|
No newline at end of file | ||
|
430 | size_t size, enum dma_data_direction dir, | |
|
No newline at end of file | ||
|
431 | struct dma_attrs *attrs) | |
|
No newline at end of file | ||
|
432 | { | |
|
No newline at end of file | ||
|
433 | .... | |
|
No newline at end of file | ||
|
434 | int foo = dma_get_attr(DMA_ATTR_FOO, attrs); | |
|
No newline at end of file | ||
|
435 | .... | |
|
No newline at end of file | ||
|
436 | if (foo) | |
|
No newline at end of file | ||
|
437 | /* twizzle the frobnozzle */ | |
|
No newline at end of file | ||
|
438 | .... | |
|
No newline at end of file | ||
|
439 | ||
|
No newline at end of file | ||
|
440 | ||
|
No newline at end of file | ||
|
441 | Part II - Advanced dma_ usage | |
|
No newline at end of file | ||
|
442 | ----------------------------- | |
|
No newline at end of file | ||
|
443 | ||
|
No newline at end of file | ||
|
444 | Warning: These pieces of the DMA API should not be used in the | |
|
No newline at end of file | ||
|
445 | majority of cases, since they cater for unlikely corner cases that | |
|
No newline at end of file | ||
|
446 | don't belong in usual drivers. | |
|
No newline at end of file | ||
|
447 | ||
|
No newline at end of file | ||
|
448 | If you don't understand how cache line coherency works between a | |
|
No newline at end of file | ||
|
449 | processor and an I/O device, you should not be using this part of the | |
|
No newline at end of file | ||
|
450 | API at all. | |
|
No newline at end of file | ||
|
451 | ||
|
No newline at end of file | ||
|
452 | void * | |
|
No newline at end of file | ||
|
453 | dma_alloc_noncoherent(struct device *dev, size_t size, | |
|
No newline at end of file | ||
|
454 | dma_addr_t *dma_handle, gfp_t flag) | |
|
No newline at end of file | ||
|
455 | ||
|
No newline at end of file | ||
|
456 | Identical to dma_alloc_coherent() except that the platform will | |
|
No newline at end of file | ||
|
457 | choose to return either consistent or non-consistent memory as it sees | |
|
No newline at end of file | ||
|
458 | fit. By using this API, you are guaranteeing to the platform that you | |
|
No newline at end of file | ||
|
459 | have all the correct and necessary sync points for this memory in the | |
|
No newline at end of file | ||
|
460 | driver should it choose to return non-consistent memory. | |
|
No newline at end of file | ||
|
461 | ||
|
No newline at end of file | ||
|
462 | Note: where the platform can return consistent memory, it will | |
|
No newline at end of file | ||
|
463 | guarantee that the sync points become nops. | |
|
No newline at end of file | ||
|
464 | ||
|
No newline at end of file | ||
|
465 | Warning: Handling non-consistent memory is a real pain. You should | |
|
No newline at end of file | ||
|
466 | only use this API if you positively know your driver will be | |
|
No newline at end of file | ||
|
467 | required to work on one of the rare (usually non-PCI) architectures | |
|
No newline at end of file | ||
|
468 | that simply cannot make consistent memory. | |
|
No newline at end of file | ||
|
469 | ||
|
No newline at end of file | ||
|
470 | void | |
|
No newline at end of file | ||
|
471 | dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr, | |
|
No newline at end of file | ||
|
472 | dma_addr_t dma_handle) | |
|
No newline at end of file | ||
|
473 | ||
|
No newline at end of file | ||
|
474 | Free memory allocated by the nonconsistent API. All parameters must | |
|
No newline at end of file | ||
|
475 | be identical to those passed in (and returned by | |
|
No newline at end of file | ||
|
476 | dma_alloc_noncoherent()). | |
|
No newline at end of file | ||
|
477 | ||
|
No newline at end of file | ||
|
478 | int | |
|
No newline at end of file | ||
|
479 | dma_get_cache_alignment(void) | |
|
No newline at end of file | ||
|
480 | ||
|
No newline at end of file | ||
|
481 | Returns the processor cache alignment. This is the absolute minimum | |
|
No newline at end of file | ||
|
482 | alignment *and* width that you must observe when either mapping | |
|
No newline at end of file | ||
|
483 | memory or doing partial flushes. | |
|
No newline at end of file | ||
|
484 | ||
|
No newline at end of file | ||
|
485 | Notes: This API may return a number *larger* than the actual cache | |
|
No newline at end of file | ||
|
486 | line, but it will guarantee that one or more cache lines fit exactly | |
|
No newline at end of file | ||
|
487 | into the width returned by this call. It will also always be a power | |
|
No newline at end of file | ||
|
488 | of two for easy alignment. | |
|
No newline at end of file | ||
|
489 | ||
|
No newline at end of file | ||
|
490 | void | |
|
No newline at end of file | ||
|
491 | dma_cache_sync(struct device *dev, void *vaddr, size_t size, | |
|
No newline at end of file | ||
|
492 | enum dma_data_direction direction) | |
|
No newline at end of file | ||
|
493 | ||
|
No newline at end of file | ||
|
494 | Do a partial sync of memory that was allocated by | |
|
No newline at end of file | ||
|
495 | dma_alloc_noncoherent(), starting at virtual address vaddr and | |
|
No newline at end of file | ||
|
496 | continuing on for size. Again, you *must* observe the cache line | |
|
No newline at end of file | ||
|
497 | boundaries when doing this. | |
|
No newline at end of file | ||
|
498 | ||
|
No newline at end of file | ||
|
499 | int | |
|
No newline at end of file | ||
|
500 | dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, | |
|
No newline at end of file | ||
|
501 | dma_addr_t device_addr, size_t size, int | |
|
No newline at end of file | ||
|
502 | flags) | |
|
No newline at end of file | ||
|
503 | ||
|
No newline at end of file | ||
|
504 | Declare region of memory to be handed out by dma_alloc_coherent() when | |
|
No newline at end of file | ||
|
505 | it's asked for coherent memory for this device. | |
|
No newline at end of file | ||
|
506 | ||
|
No newline at end of file | ||
|
507 | phys_addr is the CPU physical address to which the memory is currently | |
|
No newline at end of file | ||
|
508 | assigned (this will be ioremapped so the CPU can access the region). | |
|
No newline at end of file | ||
|
509 | ||
|
No newline at end of file | ||
|
510 | device_addr is the bus address the device needs to be programmed | |
|
No newline at end of file | ||
|
511 | with to actually address this memory (this will be handed out as the | |
|
No newline at end of file | ||
|
512 | dma_addr_t in dma_alloc_coherent()). | |
|
No newline at end of file | ||
|
513 | ||
|
No newline at end of file | ||
|
514 | size is the size of the area (must be multiples of PAGE_SIZE). | |
|
No newline at end of file | ||
|
515 | ||
|
No newline at end of file | ||
|
516 | flags can be ORed together and are: | |
|
No newline at end of file | ||
|
517 | ||
|
No newline at end of file | ||
|
518 | DMA_MEMORY_MAP - request that the memory returned from | |
|
No newline at end of file | ||
|
519 | dma_alloc_coherent() be directly writable. | |
|
No newline at end of file | ||
|
520 | ||
|
No newline at end of file | ||
|
521 | DMA_MEMORY_IO - request that the memory returned from | |
|
No newline at end of file | ||
|
522 | dma_alloc_coherent() be addressable using read()/write()/memcpy_toio() etc. | |
|
No newline at end of file | ||
|
523 | ||
|
No newline at end of file | ||
|
524 | One or both of these flags must be present. | |
|
No newline at end of file | ||
|
525 | ||
|
No newline at end of file | ||
|
526 | DMA_MEMORY_INCLUDES_CHILDREN - make the declared memory be allocated by | |
|
No newline at end of file | ||
|
527 | dma_alloc_coherent of any child devices of this one (for memory residing | |
|
No newline at end of file | ||
|
528 | on a bridge). | |
|
No newline at end of file | ||
|
529 | ||
|
No newline at end of file | ||
|
530 | DMA_MEMORY_EXCLUSIVE - only allocate memory from the declared regions. | |
|
No newline at end of file | ||
|
531 | Do not allow dma_alloc_coherent() to fall back to system memory when | |
|
No newline at end of file | ||
|
532 | it's out of memory in the declared region. | |
|
No newline at end of file | ||
|
533 | ||
|
No newline at end of file | ||
|
534 | The return value will be either DMA_MEMORY_MAP or DMA_MEMORY_IO and | |
|
No newline at end of file | ||
|
535 | must correspond to a passed in flag (i.e. no returning DMA_MEMORY_IO | |
|
No newline at end of file | ||
|
536 | if only DMA_MEMORY_MAP were passed in) for success or zero for | |
|
No newline at end of file | ||
|
537 | failure. | |
|
No newline at end of file | ||
|
538 | ||
|
No newline at end of file | ||
|
539 | Note, for DMA_MEMORY_IO returns, all subsequent memory returned by | |
|
No newline at end of file | ||
|
540 | dma_alloc_coherent() may no longer be accessed directly, but instead | |
|
No newline at end of file | ||
|
541 | must be accessed using the correct bus functions. If your driver | |
|
No newline at end of file | ||
|
542 | isn't prepared to handle this contingency, it should not specify | |
|
No newline at end of file | ||
|
543 | DMA_MEMORY_IO in the input flags. | |
|
No newline at end of file | ||
|
544 | ||
|
No newline at end of file | ||
|
545 | As a simplification for the platforms, only *one* such region of | |
|
No newline at end of file | ||
|
546 | memory may be declared per device. | |
|
No newline at end of file | ||
|
547 | ||
|
No newline at end of file | ||
|
548 | For reasons of efficiency, most platforms choose to track the declared | |
|
No newline at end of file | ||
|
549 | region only at the granularity of a page. For smaller allocations, | |
|
No newline at end of file | ||
|
550 | you should use the dma_pool() API. | |
|
No newline at end of file | ||
|
551 | ||
|
No newline at end of file | ||
|
552 | void | |
|
No newline at end of file | ||
|
553 | dma_release_declared_memory(struct device *dev) | |
|
No newline at end of file | ||
|
554 | ||
|
No newline at end of file | ||
|
555 | Remove the memory region previously declared from the system. This | |
|
No newline at end of file | ||
|
556 | API performs *no* in-use checking for this region and will return | |
|
No newline at end of file | ||
|
557 | unconditionally having removed all the required structures. It is the | |
|
No newline at end of file | ||
|
558 | driver's job to ensure that no parts of this memory region are | |
|
No newline at end of file | ||
|
559 | currently in use. | |
|
No newline at end of file | ||
|
560 | ||
|
No newline at end of file | ||
|
561 | void * | |
|
No newline at end of file | ||
|
562 | dma_mark_declared_memory_occupied(struct device *dev, | |
|
No newline at end of file | ||
|
563 | dma_addr_t device_addr, size_t size) | |
|
No newline at end of file | ||
|
564 | ||
|
No newline at end of file | ||
|
565 | This is used to occupy specific regions of the declared space | |
|
No newline at end of file | ||
|
566 | (dma_alloc_coherent() will hand out the first free region it finds). | |
|
No newline at end of file | ||
|
567 | ||
|
No newline at end of file | ||
|
568 | device_addr is the *device* address of the region requested. | |
|
No newline at end of file | ||
|
569 | ||
|
No newline at end of file | ||
|
570 | size is the size (and should be a page-sized multiple). | |
|
No newline at end of file | ||
|
571 | ||
|
No newline at end of file | ||
|
572 | The return value will be either a pointer to the processor virtual | |
|
No newline at end of file | ||
|
573 | address of the memory, or an error (via PTR_ERR()) if any part of the | |
|
No newline at end of file | ||
|
574 | region is occupied. | |
|
No newline at end of file | ||
|
575 | ||
|
No newline at end of file | ||
|
576 | Part III - Debug drivers use of the DMA-API | |
|
No newline at end of file | ||
|
577 | ------------------------------------------- | |
|
No newline at end of file | ||
|
578 | ||
|
No newline at end of file | ||
|
579 | The DMA-API as described above has some constraints. DMA addresses must be | |
|
No newline at end of file | ||
|
580 | released with the corresponding function with the same size for example. With | |
|
No newline at end of file | ||
|
581 | the advent of hardware IOMMUs it becomes more and more important that drivers | |
|
No newline at end of file | ||
|
582 | do not violate those constraints. In the worst case such a violation can | |
|
No newline at end of file | ||
|
583 | result in data corruption up to destroyed filesystems. | |
|
No newline at end of file | ||
|
584 | ||
|
No newline at end of file | ||
|
585 | To debug drivers and find bugs in the usage of the DMA-API checking code can | |
|
No newline at end of file | ||
|
586 | be compiled into the kernel which will tell the developer about those | |
|
No newline at end of file | ||
|
587 | violations. If your architecture supports it you can select the "Enable | |
|
No newline at end of file | ||
|
588 | debugging of DMA-API usage" option in your kernel configuration. Enabling this | |
|
No newline at end of file | ||
|
589 | option has a performance impact. Do not enable it in production kernels. | |
|
No newline at end of file | ||
|
590 | ||
|
No newline at end of file | ||
|
591 | If you boot the resulting kernel will contain code which does some bookkeeping | |
|
No newline at end of file | ||
|
592 | about what DMA memory was allocated for which device. If this code detects an | |
|
No newline at end of file | ||
|
593 | error it prints a warning message with some details into your kernel log. An | |
|
No newline at end of file | ||
|
594 | example warning message may look like this: | |
|
No newline at end of file | ||
|
595 | ||
|
No newline at end of file | ||
|
596 | ------------[ cut here ]------------ | |
|
No newline at end of file | ||
|
597 | WARNING: at /data2/repos/linux-2.6-iommu/lib/dma-debug.c:448 | |
|
No newline at end of file | ||
|
598 | check_unmap+0x203/0x490() | |
|
No newline at end of file | ||
|
599 | Hardware name: | |
|
No newline at end of file | ||
|
600 | forcedeth 0000:00:08.0: DMA-API: device driver frees DMA memory with wrong | |
|
No newline at end of file | ||
|
601 | function [device address=0x00000000640444be] [size=66 bytes] [mapped as | |
|
No newline at end of file | ||
|
602 | single] [unmapped as page] | |
|
No newline at end of file | ||
|
603 | Modules linked in: nfsd exportfs bridge stp llc r8169 | |
|
No newline at end of file | ||
|
604 | Pid: 0, comm: swapper Tainted: G W 2.6.28-dmatest-09289-g8bb99c0 #1 | |
|
No newline at end of file | ||
|
605 | Call Trace: | |
|
No newline at end of file | ||
|
606 | <IRQ> [<ffffffff80240b22>] warn_slowpath+0xf2/0x130 | |
|
No newline at end of file | ||
|
607 | [<ffffffff80647b70>] _spin_unlock+0x10/0x30 | |
|
No newline at end of file | ||
|
608 | [<ffffffff80537e75>] usb_hcd_link_urb_to_ep+0x75/0xc0 | |
|
No newline at end of file | ||
|
609 | [<ffffffff80647c22>] _spin_unlock_irqrestore+0x12/0x40 | |
|
No newline at end of file | ||
|
610 | [<ffffffff8055347f>] ohci_urb_enqueue+0x19f/0x7c0 | |
|
No newline at end of file | ||
|
611 | [<ffffffff80252f96>] queue_work+0x56/0x60 | |
|
No newline at end of file | ||
|
612 | [<ffffffff80237e10>] enqueue_task_fair+0x20/0x50 | |
|
No newline at end of file | ||
|
613 | [<ffffffff80539279>] usb_hcd_submit_urb+0x379/0xbc0 | |
|
No newline at end of file | ||
|
614 | [<ffffffff803b78c3>] cpumask_next_and+0x23/0x40 | |
|
No newline at end of file | ||
|
615 | [<ffffffff80235177>] find_busiest_group+0x207/0x8a0 | |
|
No newline at end of file | ||
|
616 | [<ffffffff8064784f>] _spin_lock_irqsave+0x1f/0x50 | |
|
No newline at end of file | ||
|
617 | [<ffffffff803c7ea3>] check_unmap+0x203/0x490 | |
|
No newline at end of file | ||
|
618 | [<ffffffff803c8259>] debug_dma_unmap_page+0x49/0x50 | |
|
No newline at end of file | ||
|
619 | [<ffffffff80485f26>] nv_tx_done_optimized+0xc6/0x2c0 | |
|
No newline at end of file | ||
|
620 | [<ffffffff80486c13>] nv_nic_irq_optimized+0x73/0x2b0 | |
|
No newline at end of file | ||
|
621 | [<ffffffff8026df84>] handle_IRQ_event+0x34/0x70 | |
|
No newline at end of file | ||
|
622 | [<ffffffff8026ffe9>] handle_edge_irq+0xc9/0x150 | |
|
No newline at end of file | ||
|
623 | [<ffffffff8020e3ab>] do_IRQ+0xcb/0x1c0 | |
|
No newline at end of file | ||
|
624 | [<ffffffff8020c093>] ret_from_intr+0x0/0xa | |
|
No newline at end of file | ||
|
625 | <EOI> <4>---[ end trace f6435a98e2a38c0e ]--- | |
|
No newline at end of file | ||
|
626 | ||
|
No newline at end of file | ||
|
627 | The driver developer can find the driver and the device including a stacktrace | |
|
No newline at end of file | ||
|
628 | of the DMA-API call which caused this warning. | |
|
No newline at end of file | ||
|
629 | ||
|
No newline at end of file | ||
|
630 | Per default only the first error will result in a warning message. All other | |
|
No newline at end of file | ||
|
631 | errors will only silently counted. This limitation exist to prevent the code | |
|
No newline at end of file | ||
|
632 | from flooding your kernel log. To support debugging a device driver this can | |
|
No newline at end of file | ||
|
633 | be disabled via debugfs. See the debugfs interface documentation below for | |
|
No newline at end of file | ||
|
634 | details. | |
|
No newline at end of file | ||
|
635 | ||
|
No newline at end of file | ||
|
636 | The debugfs directory for the DMA-API debugging code is called dma-api/. In | |
|
No newline at end of file | ||
|
637 | this directory the following files can currently be found: | |
|
No newline at end of file | ||
|
638 | ||
|
No newline at end of file | ||
|
639 | dma-api/all_errors This file contains a numeric value. If this | |
|
No newline at end of file | ||
|
640 | value is not equal to zero the debugging code | |
|
No newline at end of file | ||
|
641 | will print a warning for every error it finds | |
|
No newline at end of file | ||
|
642 | into the kernel log. Be careful with this | |
|
No newline at end of file | ||
|
643 | option, as it can easily flood your logs. | |
|
No newline at end of file | ||
|
644 | ||
|
No newline at end of file | ||
|
645 | dma-api/disabled This read-only file contains the character 'Y' | |
|
No newline at end of file | ||
|
646 | if the debugging code is disabled. This can | |
|
No newline at end of file | ||
|
647 | happen when it runs out of memory or if it was | |
|
No newline at end of file | ||
|
648 | disabled at boot time | |
|
No newline at end of file | ||
|
649 | ||
|
No newline at end of file | ||
|
650 | dma-api/error_count This file is read-only and shows the total | |
|
No newline at end of file | ||
|
651 | numbers of errors found. | |
|
No newline at end of file | ||
|
652 | ||
|
No newline at end of file | ||
|
653 | dma-api/num_errors The number in this file shows how many | |
|
No newline at end of file | ||
|
654 | warnings will be printed to the kernel log | |
|
No newline at end of file | ||
|
655 | before it stops. This number is initialized to | |
|
No newline at end of file | ||
|
656 | one at system boot and be set by writing into | |
|
No newline at end of file | ||
|
657 | this file | |
|
No newline at end of file | ||
|
658 | ||
|
No newline at end of file | ||
|
659 | dma-api/min_free_entries | |
|
No newline at end of file | ||
|
660 | This read-only file can be read to get the | |
|
No newline at end of file | ||
|
661 | minimum number of free dma_debug_entries the | |
|
No newline at end of file | ||
|
662 | allocator has ever seen. If this value goes | |
|
No newline at end of file | ||
|
663 | down to zero the code will disable itself | |
|
No newline at end of file | ||
|
664 | because it is not longer reliable. | |
|
No newline at end of file | ||
|
665 | ||
|
No newline at end of file | ||
|
666 | dma-api/num_free_entries | |
|
No newline at end of file | ||
|
667 | The current number of free dma_debug_entries | |
|
No newline at end of file | ||
|
668 | in the allocator. | |
|
No newline at end of file | ||
|
669 | ||
|
No newline at end of file | ||
|
670 | dma-api/driver-filter | |
|
No newline at end of file | ||
|
671 | You can write a name of a driver into this file | |
|
No newline at end of file | ||
|
672 | to limit the debug output to requests from that | |
|
No newline at end of file | ||
|
673 | particular driver. Write an empty string to | |
|
No newline at end of file | ||
|
674 | that file to disable the filter and see | |
|
No newline at end of file | ||
|
675 | all errors again. | |
|
No newline at end of file | ||
|
676 | ||
|
No newline at end of file | ||
|
677 | If you have this code compiled into your kernel it will be enabled by default. | |
|
No newline at end of file | ||
|
678 | If you want to boot without the bookkeeping anyway you can provide | |
|
No newline at end of file | ||
|
679 | 'dma_debug=off' as a boot parameter. This will disable DMA-API debugging. | |
|
No newline at end of file | ||
|
680 | Notice that you can not enable it again at runtime. You have to reboot to do | |
|
No newline at end of file | ||
|
681 | so. | |
|
No newline at end of file | ||
|
682 | ||
|
No newline at end of file | ||
|
683 | If you want to see debug messages only for a special device driver you can | |
|
No newline at end of file | ||
|
684 | specify the dma_debug_driver=<drivername> parameter. This will enable the | |
|
No newline at end of file | ||
|
685 | driver filter at boot time. The debug code will only print errors for that | |
|
No newline at end of file | ||
|
686 | driver afterwards. This filter can be disabled or changed later using debugfs. | |
|
No newline at end of file | ||
|
687 | ||
|
No newline at end of file | ||
|
688 | When the code disables itself at runtime this is most likely because it ran | |
|
No newline at end of file | ||
|
689 | out of dma_debug_entries. These entries are preallocated at boot. The number | |
|
No newline at end of file | ||
|
690 | of preallocated entries is defined per architecture. If it is too low for you | |
|
No newline at end of file | ||
|
691 | boot with 'dma_debug_entries=<your_desired_number>' to overwrite the | |
|
No newline at end of file | ||
|
692 | architectural default. | |
|
No newline at end of file | ||
|
693 | ||
|
No newline at end of file | ||
|
694 | void debug_dmap_mapping_error(struct device *dev, dma_addr_t dma_addr); | |
|
No newline at end of file | ||
|
695 | ||
|
No newline at end of file | ||
|
696 | dma-debug interface debug_dma_mapping_error() to debug drivers that fail | |
|
No newline at end of file | ||
|
697 | to check DMA mapping errors on addresses returned by dma_map_single() and | |
|
No newline at end of file | ||
|
698 | dma_map_page() interfaces. This interface clears a flag set by | |
|
No newline at end of file | ||
|
699 | debug_dma_map_page() to indicate that dma_mapping_error() has been called by | |
|
No newline at end of file | ||
|
700 | the driver. When driver does unmap, debug_dma_unmap() checks the flag and if | |
|
No newline at end of file | ||
|
701 | this flag is still set, prints warning message that includes call trace that | |
|
No newline at end of file | ||
|
702 | leads up to the unmap. This interface can be called from dma_mapping_error() | |
|
No newline at end of file | ||
|
703 | routines to enable DMA mapping error check debugging. | |
|
No newline at end of file | ||
|
704 | No newline at end of file |
@@ -0,0 +1,24 | |||
|
1 | This is free and unencumbered software released into the public domain. | |
|
No newline at end of file | ||
|
2 | ||
|
No newline at end of file | ||
|
3 | Anyone is free to copy, modify, publish, use, compile, sell, or | |
|
No newline at end of file | ||
|
4 | distribute this software, either in source code form or as a compiled | |
|
No newline at end of file | ||
|
5 | binary, for any purpose, commercial or non-commercial, and by any | |
|
No newline at end of file | ||
|
6 | means. | |
|
No newline at end of file | ||
|
7 | ||
|
No newline at end of file | ||
|
8 | In jurisdictions that recognize copyright laws, the author or authors | |
|
No newline at end of file | ||
|
9 | of this software dedicate any and all copyright interest in the | |
|
No newline at end of file | ||
|
10 | software to the public domain. We make this dedication for the benefit | |
|
No newline at end of file | ||
|
11 | of the public at large and to the detriment of our heirs and | |
|
No newline at end of file | ||
|
12 | successors. We intend this dedication to be an overt act of | |
|
No newline at end of file | ||
|
13 | relinquishment in perpetuity of all present and future rights to this | |
|
No newline at end of file | ||
|
14 | software under copyright law. | |
|
No newline at end of file | ||
|
15 | ||
|
No newline at end of file | ||
|
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
|
No newline at end of file | ||
|
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
|
No newline at end of file | ||
|
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
|
No newline at end of file | ||
|
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
|
No newline at end of file | ||
|
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
|
No newline at end of file | ||
|
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
|
No newline at end of file | ||
|
22 | OTHER DEALINGS IN THE SOFTWARE. | |
|
No newline at end of file | ||
|
23 | ||
|
No newline at end of file | ||
|
24 | For more information, please refer to <http://unlicense.org> No newline at end of file |
@@ -0,0 +1,14 | |||
|
1 | CC := gcc | |
|
No newline at end of file | ||
|
2 | CFLAGS := -g | |
|
No newline at end of file | ||
|
3 | ||
|
No newline at end of file | ||
|
4 | all: dma-example dma-gpio | |
|
No newline at end of file | ||
|
5 | ||
|
No newline at end of file | ||
|
6 | dma-example: dma-example.c | |
|
No newline at end of file | ||
|
7 | $(CC) $(CFLAGS) -o dma-example dma-example.c | |
|
No newline at end of file | ||
|
8 | dma-gpio: dma-gpio.c | |
|
No newline at end of file | ||
|
9 | $(CC) $(CFLAGS) -O2 -std=gnu99 -o dma-gpio dma-gpio.c -lrt | |
|
No newline at end of file | ||
|
10 | ||
|
No newline at end of file | ||
|
11 | clean: | |
|
No newline at end of file | ||
|
12 | rm -rf dma-example dma-gpio | |
|
No newline at end of file | ||
|
13 | ||
|
No newline at end of file | ||
|
14 | .PHONY: clean No newline at end of file |
@@ -0,0 +1,22 | |||
|
1 | Raspberry-Pi-DMA-Example | |
|
No newline at end of file | ||
|
2 | ======================== | |
|
No newline at end of file | ||
|
3 | ||
|
No newline at end of file | ||
|
4 | Simplest example of copying memory from one region to another using DMA ("Direct Memory Access") in userland | |
|
No newline at end of file | ||
|
5 | ||
|
No newline at end of file | ||
|
6 | Just type `make`, and then `sudo ./dma-example` (must use sudo to get permissions for writing to DMA peripheral) | |
|
No newline at end of file | ||
|
7 | ||
|
No newline at end of file | ||
|
8 | The example simply copies the string "hello world" from one place in memory to another through the use of the Raspberry Pi's DMA peripheral. | |
|
No newline at end of file | ||
|
9 | ||
|
No newline at end of file | ||
|
10 | Run `sudo ./dma-gpio` for an example which toggles a GPIO output pin at 500Hz using DMA. This code (dma-gpio.c) creates a 8ms circular buffer of future output states for all 64 IOs and uses DMA to sequentially copy this buffer into the memory-mapped GPIO registers at a rate of 250,000 frames per second. This allows one to output precise waveforms to any GPIO pin without worrying about Linux task scheduling. The PWM peripheral is used for pacing the DMA transaction, so simultaneous audio output will likely cause errors. Heavy network or USB usage will decrease the timing accuracy for frame rates of 500,000+ fps, due to bus-contention, but even downloading a file at 1MB/sec only has a *very* small impact at 250,000 fps. | |
|
No newline at end of file | ||
|
11 | ||
|
No newline at end of file | ||
|
12 | Some code, namely for translating virtual addresses to physical ones within dma-example.c, was based on that found in the Raspberry Pi FM Transmitter which I *think* is by either Oliver Mattos or Oskar Weigl, but their website has been down for a while now. Some of the code can still be found here: http://www.raspians.com/turning-the-raspberry-pi-into-an-fm-transmitter/ | |
|
No newline at end of file | ||
|
13 | ||
|
No newline at end of file | ||
|
14 | Problems | |
|
No newline at end of file | ||
|
15 | ====== | |
|
No newline at end of file | ||
|
16 | ||
|
No newline at end of file | ||
|
17 | The virtual->physical mapping function in `dma-example.c` is not cache-coherent. That means that the dma engine might see different data than the cpu. The equivalent functions in `dma-gpio.c` behave correctly, so it is only a matter of porting that code once I have time. | |
|
No newline at end of file | ||
|
18 | ||
|
No newline at end of file | ||
|
19 | License | |
|
No newline at end of file | ||
|
20 | ====== | |
|
No newline at end of file | ||
|
21 | ||
|
No newline at end of file | ||
|
22 | I'm putting this code in the public domain. However, the two functions in dma-example.c - `makeVirtPhysPage` and `freeVirtPhysPage` - were based on code found in the FM Transmitter, which was GPL-licensed. If you want to use this code under a non-GPL license, I would recommend replacing those functions with your own code, just to be extra safe. **Disclaimer**: I am not a lawyer. No newline at end of file |
@@ -0,0 +1,261 | |||
|
1 | /* | |
|
No newline at end of file | ||
|
2 | * https://github.com/Wallacoloo/Raspberry-Pi-DMA-Example : DMA Raspberry Pi Examples | |
|
No newline at end of file | ||
|
3 | * Author: Colin Wallace | |
|
No newline at end of file | ||
|
4 | ||
|
No newline at end of file | ||
|
5 | This is free and unencumbered software released into the public domain. | |
|
No newline at end of file | ||
|
6 | ||
|
No newline at end of file | ||
|
7 | Anyone is free to copy, modify, publish, use, compile, sell, or | |
|
No newline at end of file | ||
|
8 | distribute this software, either in source code form or as a compiled | |
|
No newline at end of file | ||
|
9 | binary, for any purpose, commercial or non-commercial, and by any | |
|
No newline at end of file | ||
|
10 | means. | |
|
No newline at end of file | ||
|
11 | ||
|
No newline at end of file | ||
|
12 | In jurisdictions that recognize copyright laws, the author or authors | |
|
No newline at end of file | ||
|
13 | of this software dedicate any and all copyright interest in the | |
|
No newline at end of file | ||
|
14 | software to the public domain. We make this dedication for the benefit | |
|
No newline at end of file | ||
|
15 | of the public at large and to the detriment of our heirs and | |
|
No newline at end of file | ||
|
16 | successors. We intend this dedication to be an overt act of | |
|
No newline at end of file | ||
|
17 | relinquishment in perpetuity of all present and future rights to this | |
|
No newline at end of file | ||
|
18 | software under copyright law. | |
|
No newline at end of file | ||
|
19 | ||
|
No newline at end of file | ||
|
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
|
No newline at end of file | ||
|
21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
|
No newline at end of file | ||
|
22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
|
No newline at end of file | ||
|
23 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
|
No newline at end of file | ||
|
24 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
|
No newline at end of file | ||
|
25 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
|
No newline at end of file | ||
|
26 | OTHER DEALINGS IN THE SOFTWARE. | |
|
No newline at end of file | ||
|
27 | ||
|
No newline at end of file | ||
|
28 | For more information, please refer to <http://unlicense.org/> | |
|
No newline at end of file | ||
|
29 | */ | |
|
No newline at end of file | ||
|
30 | ||
|
No newline at end of file | ||
|
31 | /* | |
|
No newline at end of file | ||
|
32 | * processor documentation is at: http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf | |
|
No newline at end of file | ||
|
33 | * pg 38 for DMA | |
|
No newline at end of file | ||
|
34 | */ | |
|
No newline at end of file | ||
|
35 | ||
|
No newline at end of file | ||
|
36 | #include <sys/mman.h> //for mmap | |
|
No newline at end of file | ||
|
37 | #include <unistd.h> //for NULL | |
|
No newline at end of file | ||
|
38 | #include <stdio.h> //for printf | |
|
No newline at end of file | ||
|
39 | #include <stdlib.h> //for exit | |
|
No newline at end of file | ||
|
40 | #include <fcntl.h> //for file opening | |
|
No newline at end of file | ||
|
41 | #include <stdint.h> //for uint32_t | |
|
No newline at end of file | ||
|
42 | #include <string.h> //for memset | |
|
No newline at end of file | ||
|
43 | ||
|
No newline at end of file | ||
|
44 | #define PAGE_SIZE 4096 //mmap maps pages of memory, so we must give it multiples of this size | |
|
No newline at end of file | ||
|
45 | ||
|
No newline at end of file | ||
|
46 | //physical addresses for the DMA peripherals, as found in the processor documentation: | |
|
No newline at end of file | ||
|
47 | #define DMA_BASE 0x20007000 | |
|
No newline at end of file | ||
|
48 | //DMA Channel register sets (format of these registers is found in DmaChannelHeader struct): | |
|
No newline at end of file | ||
|
49 | #define DMACH0 0x20007000 | |
|
No newline at end of file | ||
|
50 | #define DMACH1 0x20007100 | |
|
No newline at end of file | ||
|
51 | #define DMACH2 0x20007200 | |
|
No newline at end of file | ||
|
52 | #define DMACH3 0x20007300 | |
|
No newline at end of file | ||
|
53 | //... | |
|
No newline at end of file | ||
|
54 | #define DMACH(n) (DMACH0 + (n)*0x100) | |
|
No newline at end of file | ||
|
55 | //Each DMA channel has some associated registers, but only CS (control and status), CONBLK_AD (control block address), and DEBUG are writeable | |
|
No newline at end of file | ||
|
56 | //DMA is started by writing address of the first Control Block to the DMA channel's CONBLK_AD register and then setting the ACTIVE bit inside the CS register (bit 0) | |
|
No newline at end of file | ||
|
57 | //Note: DMA channels are connected directly to peripherals, so physical addresses should be used (affects control block's SOURCE, DEST and NEXTCONBK addresses). | |
|
No newline at end of file | ||
|
58 | #define DMAENABLE 0x20007ff0 //bit 0 should be set to 1 to enable channel 0. bit 1 enables channel 1, etc. | |
|
No newline at end of file | ||
|
59 | ||
|
No newline at end of file | ||
|
60 | //flags used in the DmaChannelHeader struct: | |
|
No newline at end of file | ||
|
61 | #define DMA_CS_RESET (1<<31) | |
|
No newline at end of file | ||
|
62 | #define DMA_CS_ACTIVE (1<<0) | |
|
No newline at end of file | ||
|
63 | ||
|
No newline at end of file | ||
|
64 | #define DMA_DEBUG_READ_ERROR (1<<2) | |
|
No newline at end of file | ||
|
65 | #define DMA_DEBUG_FIFO_ERROR (1<<1) | |
|
No newline at end of file | ||
|
66 | #define DMA_DEBUG_READ_LAST_NOT_SET_ERROR (1<<0) | |
|
No newline at end of file | ||
|
67 | ||
|
No newline at end of file | ||
|
68 | //flags used in the DmaControlBlock struct: | |
|
No newline at end of file | ||
|
69 | #define DMA_CB_TI_DEST_INC (1<<4) | |
|
No newline at end of file | ||
|
70 | #define DMA_CB_TI_SRC_INC (1<<8) | |
|
No newline at end of file | ||
|
71 | ||
|
No newline at end of file | ||
|
72 | //set bits designated by (mask) at the address (dest) to (value), without affecting the other bits | |
|
No newline at end of file | ||
|
73 | //eg if x = 0b11001100 | |
|
No newline at end of file | ||
|
74 | // writeBitmasked(&x, 0b00000110, 0b11110011), | |
|
No newline at end of file | ||
|
75 | // then x now = 0b11001110 | |
|
No newline at end of file | ||
|
76 | void writeBitmasked(volatile uint32_t *dest, uint32_t mask, uint32_t value) { | |
|
No newline at end of file | ||
|
77 | uint32_t cur = *dest; | |
|
No newline at end of file | ||
|
78 | uint32_t new = (cur & (~mask)) | (value & mask); | |
|
No newline at end of file | ||
|
79 | *dest = new; | |
|
No newline at end of file | ||
|
80 | *dest = new; //added safety for when crossing memory barriers. | |
|
No newline at end of file | ||
|
81 | } | |
|
No newline at end of file | ||
|
82 | ||
|
No newline at end of file | ||
|
83 | struct DmaChannelHeader { | |
|
No newline at end of file | ||
|
84 | uint32_t CS; //Control and Status | |
|
No newline at end of file | ||
|
85 | //31 RESET; set to 1 to reset DMA | |
|
No newline at end of file | ||
|
86 | //30 ABORT; set to 1 to abort current DMA control block (next one will be loaded & continue) | |
|
No newline at end of file | ||
|
87 | //29 DISDEBUG; set to 1 and DMA won't be paused when debug signal is sent | |
|
No newline at end of file | ||
|
88 | //28 WAIT_FOR_OUTSTANDING_WRITES; set to 1 and DMA will wait until peripheral says all writes have gone through before loading next CB | |
|
No newline at end of file | ||
|
89 | //24-74 reserved | |
|
No newline at end of file | ||
|
90 | //20-23 PANIC_PRIORITY; 0 is lowest priority | |
|
No newline at end of file | ||
|
91 | //16-19 PRIORITY; bus scheduling priority. 0 is lowest | |
|
No newline at end of file | ||
|
92 | //9-15 reserved | |
|
No newline at end of file | ||
|
93 | //8 ERROR; read as 1 when error is encountered. error can be found in DEBUG register. | |
|
No newline at end of file | ||
|
94 | //7 reserved | |
|
No newline at end of file | ||
|
95 | //6 WAITING_FOR_OUTSTANDING_WRITES; read as 1 when waiting for outstanding writes | |
|
No newline at end of file | ||
|
96 | //5 DREQ_STOPS_DMA; read as 1 if DREQ is currently preventing DMA | |
|
No newline at end of file | ||
|
97 | //4 PAUSED; read as 1 if DMA is paused | |
|
No newline at end of file | ||
|
98 | //3 DREQ; copy of the data request signal from the peripheral, if DREQ is enabled. reads as 1 if data is being requested, else 0 | |
|
No newline at end of file | ||
|
99 | //2 INT; set when current CB ends and its INTEN=1. Write a 1 to this register to clear it | |
|
No newline at end of file | ||
|
100 | //1 END; set when the transfer defined by current CB is complete. Write 1 to clear. | |
|
No newline at end of file | ||
|
101 | //0 ACTIVE; write 1 to activate DMA (load the CB before hand) | |
|
No newline at end of file | ||
|
102 | uint32_t CONBLK_AD; //Control Block Address | |
|
No newline at end of file | ||
|
103 | uint32_t TI; //transfer information; see DmaControlBlock.TI for description | |
|
No newline at end of file | ||
|
104 | uint32_t SOURCE_AD; //Source address | |
|
No newline at end of file | ||
|
105 | uint32_t DEST_AD; //Destination address | |
|
No newline at end of file | ||
|
106 | uint32_t TXFR_LEN; //transfer length. | |
|
No newline at end of file | ||
|
107 | uint32_t STRIDE; //2D Mode Stride. Only used if TI.TDMODE = 1 | |
|
No newline at end of file | ||
|
108 | uint32_t NEXTCONBK; //Next control block. Must be 256-bit aligned (32 bytes; 8 words) | |
|
No newline at end of file | ||
|
109 | uint32_t DEBUG; //controls debug settings | |
|
No newline at end of file | ||
|
110 | }; | |
|
No newline at end of file | ||
|
111 | ||
|
No newline at end of file | ||
|
112 | struct DmaControlBlock { | |
|
No newline at end of file | ||
|
113 | uint32_t TI; //transfer information | |
|
No newline at end of file | ||
|
114 | //31:27 unused | |
|
No newline at end of file | ||
|
115 | //26 NO_WIDE_BURSTS | |
|
No newline at end of file | ||
|
116 | //21:25 WAITS; number of cycles to wait between each DMA read/write operation | |
|
No newline at end of file | ||
|
117 | //16:20 PERMAP; peripheral number to be used for DREQ signal (pacing). set to 0 for unpaced DMA. | |
|
No newline at end of file | ||
|
118 | //12:15 BURST_LENGTH | |
|
No newline at end of file | ||
|
119 | //11 SRC_IGNORE; set to 1 to not perform reads. Used to manually fill caches | |
|
No newline at end of file | ||
|
120 | //10 SRC_DREQ; set to 1 to have the DREQ from PERMAP gate requests. | |
|
No newline at end of file | ||
|
121 | //9 SRC_WIDTH; set to 1 for 128-bit moves, 0 for 32-bit moves | |
|
No newline at end of file | ||
|
122 | //8 SRC_INC; set to 1 to automatically increment the source address after each read (you'll want this if you're copying a range of memory) | |
|
No newline at end of file | ||
|
123 | //7 DEST_IGNORE; set to 1 to not perform writes. | |
|
No newline at end of file | ||
|
124 | //6 DEST_DREG; set to 1 to have the DREQ from PERMAP gate *writes* | |
|
No newline at end of file | ||
|
125 | //5 DEST_WIDTH; set to 1 for 128-bit moves, 0 for 32-bit moves | |
|
No newline at end of file | ||
|
126 | //4 DEST_INC; set to 1 to automatically increment the destination address after each read (Tyou'll want this if you're copying a range of memory) | |
|
No newline at end of file | ||
|
127 | //3 WAIT_RESP; make DMA wait for a response from the peripheral during each write. Ensures multiple writes don't get stacked in the pipeline | |
|
No newline at end of file | ||
|
128 | //2 unused (0) | |
|
No newline at end of file | ||
|
129 | //1 TDMODE; set to 1 to enable 2D mode | |
|
No newline at end of file | ||
|
130 | //0 INTEN; set to 1 to generate an interrupt upon completion | |
|
No newline at end of file | ||
|
131 | uint32_t SOURCE_AD; //Source address | |
|
No newline at end of file | ||
|
132 | uint32_t DEST_AD; //Destination address | |
|
No newline at end of file | ||
|
133 | uint32_t TXFR_LEN; //transfer length. | |
|
No newline at end of file | ||
|
134 | uint32_t STRIDE; //2D Mode Stride. Only used if TI.TDMODE = 1 | |
|
No newline at end of file | ||
|
135 | uint32_t NEXTCONBK; //Next control block. Must be 256-bit aligned (32 bytes; 8 words) | |
|
No newline at end of file | ||
|
136 | uint32_t _reserved[2]; | |
|
No newline at end of file | ||
|
137 | }; | |
|
No newline at end of file | ||
|
138 | ||
|
No newline at end of file | ||
|
139 | //allocate a page & simultaneously determine its physical address. | |
|
No newline at end of file | ||
|
140 | //virtAddr and physAddr are essentially passed by-reference. | |
|
No newline at end of file | ||
|
141 | //this allows for: | |
|
No newline at end of file | ||
|
142 | //void *virt, *phys; | |
|
No newline at end of file | ||
|
143 | //makeVirtPhysPage(&virt, &phys) | |
|
No newline at end of file | ||
|
144 | //now, virt[N] exists for 0 <= N < PAGE_SIZE, | |
|
No newline at end of file | ||
|
145 | // and phys+N is the physical address for virt[N] | |
|
No newline at end of file | ||
|
146 | //based on http://www.raspians.com/turning-the-raspberry-pi-into-an-fm-transmitter/ | |
|
No newline at end of file | ||
|
147 | void makeVirtPhysPage(void** virtAddr, void** physAddr) { | |
|
No newline at end of file | ||
|
148 | *virtAddr = valloc(PAGE_SIZE); //allocate one page of RAM | |
|
No newline at end of file | ||
|
149 | ||
|
No newline at end of file | ||
|
150 | //force page into RAM and then lock it there: | |
|
No newline at end of file | ||
|
151 | ((int*)*virtAddr)[0] = 1; | |
|
No newline at end of file | ||
|
152 | mlock(*virtAddr, PAGE_SIZE); | |
|
No newline at end of file | ||
|
153 | memset(*virtAddr, 0, PAGE_SIZE); //zero-fill the page for convenience | |
|
No newline at end of file | ||
|
154 | ||
|
No newline at end of file | ||
|
155 | //Magic to determine the physical address for this page: | |
|
No newline at end of file | ||
|
156 | uint64_t pageInfo; | |
|
No newline at end of file | ||
|
157 | int file = open("/proc/self/pagemap", 'r'); | |
|
No newline at end of file | ||
|
158 | lseek(file, ((uint32_t)*virtAddr)/PAGE_SIZE*8, SEEK_SET); | |
|
No newline at end of file | ||
|
159 | read(file, &pageInfo, 8); | |
|
No newline at end of file | ||
|
160 | ||
|
No newline at end of file | ||
|
161 | *physAddr = (void*)(uint32_t)(pageInfo*PAGE_SIZE); | |
|
No newline at end of file | ||
|
162 | printf("makeVirtPhysPage virtual to phys: %p -> %p\n", *virtAddr, *physAddr); | |
|
No newline at end of file | ||
|
163 | } | |
|
No newline at end of file | ||
|
164 | ||
|
No newline at end of file | ||
|
165 | //call with virtual address to deallocate a page allocated with makeVirtPhysPage | |
|
No newline at end of file | ||
|
166 | void freeVirtPhysPage(void* virtAddr) { | |
|
No newline at end of file | ||
|
167 | munlock(virtAddr, PAGE_SIZE); | |
|
No newline at end of file | ||
|
168 | free(virtAddr); | |
|
No newline at end of file | ||
|
169 | } | |
|
No newline at end of file | ||
|
170 | ||
|
No newline at end of file | ||
|
171 | //map a physical address into our virtual address space. memfd is the file descriptor for /dev/mem | |
|
No newline at end of file | ||
|
172 | volatile uint32_t* mapPeripheral(int memfd, int addr) { | |
|
No newline at end of file | ||
|
173 | ///dev/mem behaves as a file. We need to map that file into memory: | |
|
No newline at end of file | ||
|
174 | void *mapped = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, addr); | |
|
No newline at end of file | ||
|
175 | //now, *mapped = memory at physical address of addr. | |
|
No newline at end of file | ||
|
176 | if (mapped == MAP_FAILED) { | |
|
No newline at end of file | ||
|
177 | printf("failed to map memory (did you remember to run as root?)\n"); | |
|
No newline at end of file | ||
|
178 | exit(1); | |
|
No newline at end of file | ||
|
179 | } else { | |
|
No newline at end of file | ||
|
180 | printf("mapped: %p\n", mapped); | |
|
No newline at end of file | ||
|
181 | } | |
|
No newline at end of file | ||
|
182 | return (volatile uint32_t*)mapped; | |
|
No newline at end of file | ||
|
183 | } | |
|
No newline at end of file | ||
|
184 | ||
|
No newline at end of file | ||
|
185 | int main() { | |
|
No newline at end of file | ||
|
186 | //cat /sys/module/dma/parameters/dmachans gives a bitmask of DMA channels that are not used by GPU. Results: ch 1, 3, 6, 7 are reserved. | |
|
No newline at end of file | ||
|
187 | //dmesg | grep "DMA"; results: Ch 2 is used by SDHC host | |
|
No newline at end of file | ||
|
188 | //ch 0 is known to be used for graphics acceleration | |
|
No newline at end of file | ||
|
189 | //Thus, applications can use ch 4, 5, or the LITE channels @ 8 and beyond. | |
|
No newline at end of file | ||
|
190 | int dmaChNum = 5; | |
|
No newline at end of file | ||
|
191 | //First, open the linux device, /dev/mem | |
|
No newline at end of file | ||
|
192 | //dev/mem provides access to the physical memory of the entire processor+ram | |
|
No newline at end of file | ||
|
193 | //This is needed because Linux uses virtual memory, thus the process's memory at 0x00000000 will NOT have the same contents as the physical memory at 0x00000000 | |
|
No newline at end of file | ||
|
194 | int memfd = open("/dev/mem", O_RDWR | O_SYNC); | |
|
No newline at end of file | ||
|
195 | if (memfd < 0) { | |
|
No newline at end of file | ||
|
196 | printf("Failed to open /dev/mem (did you remember to run as root?)\n"); | |
|
No newline at end of file | ||
|
197 | exit(1); | |
|
No newline at end of file | ||
|
198 | } | |
|
No newline at end of file | ||
|
199 | //now map /dev/mem into memory, but only map specific peripheral sections: | |
|
No newline at end of file | ||
|
200 | volatile uint32_t *dmaBaseMem = mapPeripheral(memfd, DMA_BASE); | |
|
No newline at end of file | ||
|
201 | ||
|
No newline at end of file | ||
|
202 | //configure DMA: | |
|
No newline at end of file | ||
|
203 | //allocate 1 page for the source and 1 page for the destination: | |
|
No newline at end of file | ||
|
204 | void *virtSrcPage, *physSrcPage; | |
|
No newline at end of file | ||
|
205 | makeVirtPhysPage(&virtSrcPage, &physSrcPage); | |
|
No newline at end of file | ||
|
206 | void *virtDestPage, *physDestPage; | |
|
No newline at end of file | ||
|
207 | makeVirtPhysPage(&virtDestPage, &physDestPage); | |
|
No newline at end of file | ||
|
208 | ||
|
No newline at end of file | ||
|
209 | //write a few bytes to the source page: | |
|
No newline at end of file | ||
|
210 | char *srcArray = (char*)virtSrcPage; | |
|
No newline at end of file | ||
|
211 | srcArray[0] = 'h'; | |
|
No newline at end of file | ||
|
212 | srcArray[1] = 'e'; | |
|
No newline at end of file | ||
|
213 | srcArray[2] = 'l'; | |
|
No newline at end of file | ||
|
214 | srcArray[3] = 'l'; | |
|
No newline at end of file | ||
|
215 | srcArray[4] = 'o'; | |
|
No newline at end of file | ||
|
216 | srcArray[5] = ' '; | |
|
No newline at end of file | ||
|
217 | srcArray[6] = 'w'; | |
|
No newline at end of file | ||
|
218 | srcArray[7] = 'o'; | |
|
No newline at end of file | ||
|
219 | srcArray[8] = 'r'; | |
|
No newline at end of file | ||
|
220 | srcArray[9] = 'l'; | |
|
No newline at end of file | ||
|
221 | srcArray[10] = 'd'; | |
|
No newline at end of file | ||
|
222 | srcArray[11] = 0; //null terminator used for printf call. | |
|
No newline at end of file | ||
|
223 | ||
|
No newline at end of file | ||
|
224 | //allocate 1 page for the control blocks | |
|
No newline at end of file | ||
|
225 | void *virtCbPage, *physCbPage; | |
|
No newline at end of file | ||
|
226 | makeVirtPhysPage(&virtCbPage, &physCbPage); | |
|
No newline at end of file | ||
|
227 | ||
|
No newline at end of file | ||
|
228 | //dedicate the first 8 words of this page to holding the cb. | |
|
No newline at end of file | ||
|
229 | struct DmaControlBlock *cb1 = (struct DmaControlBlock*)virtCbPage; | |
|
No newline at end of file | ||
|
230 | ||
|
No newline at end of file | ||
|
231 | //fill the control block: | |
|
No newline at end of file | ||
|
232 | cb1->TI = DMA_CB_TI_SRC_INC | DMA_CB_TI_DEST_INC; //after each byte copied, we want to increment the source and destination address of the copy, otherwise we'll be copying to the same address. | |
|
No newline at end of file | ||
|
233 | cb1->SOURCE_AD = (uint32_t)physSrcPage; //set source and destination DMA address | |
|
No newline at end of file | ||
|
234 | cb1->DEST_AD = (uint32_t)physDestPage; | |
|
No newline at end of file | ||
|
235 | cb1->TXFR_LEN = 12; //transfer 12 bytes | |
|
No newline at end of file | ||
|
236 | cb1->STRIDE = 0; //no 2D stride | |
|
No newline at end of file | ||
|
237 | cb1->NEXTCONBK = 0; //no next control block | |
|
No newline at end of file | ||
|
238 | ||
|
No newline at end of file | ||
|
239 | printf("destination was initially: '%s'\n", (char*)virtDestPage); | |
|
No newline at end of file | ||
|
240 | ||
|
No newline at end of file | ||
|
241 | //enable DMA channel (it's probably already enabled, but we want to be sure): | |
|
No newline at end of file | ||
|
242 | writeBitmasked(dmaBaseMem + DMAENABLE - DMA_BASE, 1 << dmaChNum, 1 << dmaChNum); | |
|
No newline at end of file | ||
|
243 | ||
|
No newline at end of file | ||
|
244 | //configure the DMA header to point to our control block: | |
|
No newline at end of file | ||
|
245 | volatile struct DmaChannelHeader *dmaHeader = (volatile struct DmaChannelHeader*)(dmaBaseMem + (DMACH(dmaChNum) - DMA_BASE)/4); //dmaBaseMem is a uint32_t ptr, so divide by 4 before adding byte offset | |
|
No newline at end of file | ||
|
246 | dmaHeader->CS = DMA_CS_RESET; //make sure to disable dma first. | |
|
No newline at end of file | ||
|
247 | sleep(1); //give time for the reset command to be handled. | |
|
No newline at end of file | ||
|
248 | dmaHeader->DEBUG = DMA_DEBUG_READ_ERROR | DMA_DEBUG_FIFO_ERROR | DMA_DEBUG_READ_LAST_NOT_SET_ERROR; // clear debug error flags | |
|
No newline at end of file | ||
|
249 | dmaHeader->CONBLK_AD = (uint32_t)physCbPage; //we have to point it to the PHYSICAL address of the control block (cb1) | |
|
No newline at end of file | ||
|
250 | dmaHeader->CS = DMA_CS_ACTIVE; //set active bit, but everything else is 0. | |
|
No newline at end of file | ||
|
251 | ||
|
No newline at end of file | ||
|
252 | sleep(1); //give time for copy to happen | |
|
No newline at end of file | ||
|
253 | ||
|
No newline at end of file | ||
|
254 | printf("destination reads: '%s'\n", (char*)virtDestPage); | |
|
No newline at end of file | ||
|
255 | ||
|
No newline at end of file | ||
|
256 | //cleanup | |
|
No newline at end of file | ||
|
257 | freeVirtPhysPage(virtCbPage); | |
|
No newline at end of file | ||
|
258 | freeVirtPhysPage(virtDestPage); | |
|
No newline at end of file | ||
|
259 | freeVirtPhysPage(virtSrcPage); | |
|
No newline at end of file | ||
|
260 | return 0; | |
|
No newline at end of file | ||
|
261 | } No newline at end of file |
This diff has been collapsed as it changes many lines, (829 lines changed) Show them Hide them | |||
@@ -0,0 +1,829 | |||
|
1 | /* | |
|
No newline at end of file | ||
|
2 | * https://github.com/Wallacoloo/Raspberry-Pi-DMA-Example : DMA Raspberry Pi Examples | |
|
No newline at end of file | ||
|
3 | * Author: Colin Wallace | |
|
No newline at end of file | ||
|
4 | ||
|
No newline at end of file | ||
|
5 | This is free and unencumbered software released into the public domain. | |
|
No newline at end of file | ||
|
6 | ||
|
No newline at end of file | ||
|
7 | Anyone is free to copy, modify, publish, use, compile, sell, or | |
|
No newline at end of file | ||
|
8 | distribute this software, either in source code form or as a compiled | |
|
No newline at end of file | ||
|
9 | binary, for any purpose, commercial or non-commercial, and by any | |
|
No newline at end of file | ||
|
10 | means. | |
|
No newline at end of file | ||
|
11 | ||
|
No newline at end of file | ||
|
12 | In jurisdictions that recognize copyright laws, the author or authors | |
|
No newline at end of file | ||
|
13 | of this software dedicate any and all copyright interest in the | |
|
No newline at end of file | ||
|
14 | software to the public domain. We make this dedication for the benefit | |
|
No newline at end of file | ||
|
15 | of the public at large and to the detriment of our heirs and | |
|
No newline at end of file | ||
|
16 | successors. We intend this dedication to be an overt act of | |
|
No newline at end of file | ||
|
17 | relinquishment in perpetuity of all present and future rights to this | |
|
No newline at end of file | ||
|
18 | software under copyright law. | |
|
No newline at end of file | ||
|
19 | ||
|
No newline at end of file | ||
|
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
|
No newline at end of file | ||
|
21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
|
No newline at end of file | ||
|
22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
|
No newline at end of file | ||
|
23 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
|
No newline at end of file | ||
|
24 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
|
No newline at end of file | ||
|
25 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
|
No newline at end of file | ||
|
26 | OTHER DEALINGS IN THE SOFTWARE. | |
|
No newline at end of file | ||
|
27 | ||
|
No newline at end of file | ||
|
28 | For more information, please refer to <http://unlicense.org/> | |
|
No newline at end of file | ||
|
29 | */ | |
|
No newline at end of file | ||
|
30 | /* | |
|
No newline at end of file | ||
|
31 | * processor documentation is at: http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf | |
|
No newline at end of file | ||
|
32 | * pg 38 for DMA | |
|
No newline at end of file | ||
|
33 | * pg 61 for DMA DREQ PERMAP | |
|
No newline at end of file | ||
|
34 | * pg 89 for gpio | |
|
No newline at end of file | ||
|
35 | * pg 119 for PCM | |
|
No newline at end of file | ||
|
36 | * pg 138 for PWM | |
|
No newline at end of file | ||
|
37 | * pg 172 for timer info | |
|
No newline at end of file | ||
|
38 | * Addendum is http://www.scribd.com/doc/127599939/BCM2835-Audio-clocks | |
|
No newline at end of file | ||
|
39 | * | |
|
No newline at end of file | ||
|
40 | * A few annotations for GPIO/DMA/PWM are available here: https://github.com/626Pilot/RaspberryPi-NeoPixel-WS2812/blob/master/ws2812-RPi.c | |
|
No newline at end of file | ||
|
41 | * https://github.com/metachris/raspberrypi-pwm/blob/master/rpio-pwm/rpio_pwm.c | |
|
No newline at end of file | ||
|
42 | * https://github.com/richardghirst/PiBits/blob/master/ServoBlaster/user/servod.c | |
|
No newline at end of file | ||
|
43 | * | |
|
No newline at end of file | ||
|
44 | * Cache info can be found here: http://www.freelists.org/post/raspi-internals/caches,18 | |
|
No newline at end of file | ||
|
45 | * 0x00000000 - L1 & L2 cache | |
|
No newline at end of file | ||
|
46 | * 0x40000000 - L2 cache coherent (ie L1 writes are propagated to L2?) | |
|
No newline at end of file | ||
|
47 | * 0x80000000 - L2 cache only | |
|
No newline at end of file | ||
|
48 | * 0xc0000000 - direct uncached | |
|
No newline at end of file | ||
|
49 | * | |
|
No newline at end of file | ||
|
50 | * Useful DMA timings, etc: http://www.raspberrypi.org/forums/viewtopic.php?f=37&t=7696&start=50 | |
|
No newline at end of file | ||
|
51 | * | |
|
No newline at end of file | ||
|
52 | * The general idea is to have a buffer of N blocks, where each block is the same size as the gpio registers, | |
|
No newline at end of file | ||
|
53 | * and have the DMA module continually copying the data in this buffer into those registers. | |
|
No newline at end of file | ||
|
54 | * In this way, we can have (say) 32 blocks, and then be able to buffer the next 32 IO frames. | |
|
No newline at end of file | ||
|
55 | * | |
|
No newline at end of file | ||
|
56 | * How is DMA transfer rate controlled? | |
|
No newline at end of file | ||
|
57 | * We can use the DREQ (data request) feature. | |
|
No newline at end of file | ||
|
58 | * PWM supports a configurable data consumption clock (defaults to 100MHz) | |
|
No newline at end of file | ||
|
59 | * PWM (and SPI, PCM) can fire a DREQ signal any time its fifo falls below a certain point. | |
|
No newline at end of file | ||
|
60 | * But we are never filling the FIFO, so DREQ would be permanently high. | |
|
No newline at end of file | ||
|
61 | * Could feed PWM with dummy data, and use 2 DMA channels (one to PWM, one to GPIO, both gated), but the write-time to GPIOs may vary from the PWM, so gating may be improper | |
|
No newline at end of file | ||
|
62 | * Or we can use the WAITS portion of the CB header. This allows up to 31 cycle delay -> ~25MHz? | |
|
No newline at end of file | ||
|
63 | * Will have to manually determine timing characteristics though. | |
|
No newline at end of file | ||
|
64 | * Or use 2 dma channels: | |
|
No newline at end of file | ||
|
65 | * Have one sending the data into PWM, which is DREQ limited | |
|
No newline at end of file | ||
|
66 | * Have another copying from PWM Fifo to GPIOs at a non-limited rate. This is peripheral -> peripheral, so I think it will have its own data bus. | |
|
No newline at end of file | ||
|
67 | * Unfortunately, the destination can only be one word. Luckily, we have 2 PWM channels - one for setting & one for clearing GPIOs. All gpios that are broken out into the header are in the first register (verified) | |
|
No newline at end of file | ||
|
68 | * Sadly, it appears that the PWM FIFO cannot be read from. One can read the current PWM output, but only if the FIFO is disabled, in which case the DREQ is too. | |
|
No newline at end of file | ||
|
69 | * | |
|
No newline at end of file | ||
|
70 | **Or use 1 dma channel, but additionally write to a dreq-able peripheral (PWM): | |
|
No newline at end of file | ||
|
71 | * By using control-blocks, one can copy a word to the GPIOs, then have the next CB copy a word to the PWM fifo, and repeat | |
|
No newline at end of file | ||
|
72 | * By having BOTH control-blocks be dreq-limited by the PWM's dreq, they can BOTH be rate-limited. | |
|
No newline at end of file | ||
|
73 | * PWM clock works as so: 500MHz / clock_div = PWM_BITRATE (note: bitrate!) | |
|
No newline at end of file | ||
|
74 | * PWM_BITRATE / PWM_RNG1 = #of FIFO writes/sec | |
|
No newline at end of file | ||
|
75 | * Max PWM_BITRATE = 25MHz | |
|
No newline at end of file | ||
|
76 | * Also, dest_addr = 0x7e20b000 // the testbus interface which is a dump peripheral that goes nowhere (http://www.raspberrypi.org/forums/viewtopic.php?f=37&t=7696&start=25 ) | |
|
No newline at end of file | ||
|
77 | * | |
|
No newline at end of file | ||
|
78 | * DMA Control Block layout: | |
|
No newline at end of file | ||
|
79 | * repeat #srcBlock times: | |
|
No newline at end of file | ||
|
80 | * 1.copy srcBlock to gpios | |
|
No newline at end of file | ||
|
81 | * 2.zero srcBlock | |
|
No newline at end of file | ||
|
82 | * 3.move byte to PWM (paced via DREQ) | |
|
No newline at end of file | ||
|
83 | * These are largely redundant; it may be possible to use less memory (each cb uses 32 bytes of memory) | |
|
No newline at end of file | ||
|
84 | * | |
|
No newline at end of file | ||
|
85 | * Problem: each "frame" is currently 6 words (but the last word is padding), and 1 PAGE_SIZE is not an integer multiple of 6*4 | |
|
No newline at end of file | ||
|
86 | * Thus, the very last frame on each page cannot be used with DMA. Because of this, too, the virtual addressing of each frame is messed up - we must skip one frame per page. | |
|
No newline at end of file | ||
|
87 | * One solution is to append 2 more pad words to each frame (so that it is 8 words in length). This fixes all issues, but increases ram usage and potentially cache problems (L2 is 128KB). However, since data reads are sequential, even if all data doesn't fit in cache, it will be prefetched. | |
|
No newline at end of file | ||
|
88 | * Another solution is to decrease frame size to 4 words, and use 2 control blocks for each frame (thus eliminating the 1-byte padding in the center). This will have an even LARGER impact on ram usage - effectively using 20 words/frame vs current 14 words/frame & alternative 16words/frame | |
|
No newline at end of file | ||
|
89 | * Another solution is to directly mix src data with CB data. Each CB has 2 words of padding, and a data frame is 5 words, and each CB must be aligned to 8 words. Therefore, the following is possible, assuming each frame requires 3 CBs: | |
|
No newline at end of file | ||
|
90 | * CB1.1(padded) | CB1.2(padded) | CB1.3(padded) | CB2.1(padded) | CB2.2(padded) | CB2.3(unpadded) | SRC(5) | SRC(5) <- uses 56 words per 2 frames | |
|
No newline at end of file | ||
|
91 | * HOWEVER, PAGE_SIZE is not an integral multiple of 56 words | |
|
No newline at end of file | ||
|
92 | * Although, 1 of those CBs (the one which zeros the previous source) could be shared amongst multiple frames - that is, only zero every, say, 4 frames. The effect is: | |
|
No newline at end of file | ||
|
93 | * *32 words for 1 frame grouped (5 src words - 2 means pad to 8 words for src) | |
|
No newline at end of file | ||
|
94 | * 48 words for 2 frames grouped (10 src words - 2 means pad to 8 words for src) | |
|
No newline at end of file | ||
|
95 | * 72 words for 3 frames grouped (15 src words - 2 means pad to 16 words for src) | |
|
No newline at end of file | ||
|
96 | * 96 words for 4 frames grouped (20 src words - 2 means pad to 24 words for src) | |
|
No newline at end of file | ||
|
97 | * 112 words for 5 frames grouped(25 src words - 2 means pad to 24 words for src) | |
|
No newline at end of file | ||
|
98 | * 136 words for 6 frames grouped(30 src words - 2 means pad to 32 words for src) | |
|
No newline at end of file | ||
|
99 | * 160 words for 7 frames grouped(35 src words - 2 means pad to 40 words for src) | |
|
No newline at end of file | ||
|
100 | * 176 words for 8 frames grouped(40 src words - 2 means pad to 40 words for src) | |
|
No newline at end of file | ||
|
101 | * 200 words for 9 frames grouped(45 src words - 2 means pad to 48 words for src) | |
|
No newline at end of file | ||
|
102 | * 216 words for 10frames grouped(50 src words - 2 means pad to 48 words for src) | |
|
No newline at end of file | ||
|
103 | * 240 words for 11frames grouped(55 src words - 2 means pad to 56 words for src) | |
|
No newline at end of file | ||
|
104 | * 264 words for 12frames grouped(60 src words - 2 means pad to 64 words for src) | |
|
No newline at end of file | ||
|
105 | * ...432 words for 20frames grouped(100src words - 2 means pad to 104 words for src) | |
|
No newline at end of file | ||
|
106 | * ...*512 words for 24frames grouped(120src words - 2 means pad to 120 words for src) | |
|
No newline at end of file | ||
|
107 | * As can be seen, this still requires extra padding. Could do 128 words for 5 frames, or 256 words for 11 frames (23.3 words/frame), and that requires funky math. | |
|
No newline at end of file | ||
|
108 | * The 24 frame option would work OK. 24 is a relatively easy number to work with, and 21.3 words/frame (limit is 21 words/frame) | |
|
No newline at end of file | ||
|
109 | * Another solution is to use the 2D stride functionality. The source frame is really 4 words and the destination is really 2 words, a 1 word gap, and then the other 2 words. Thus 2d stride can be used to skip over that one word gap. | |
|
No newline at end of file | ||
|
110 | * | |
|
No newline at end of file | ||
|
111 | * How to determine the current source word being processed? | |
|
No newline at end of file | ||
|
112 | * dma header points to the physical CONBLOCK_AD. This can be linked to the virtual source address via a map. | |
|
No newline at end of file | ||
|
113 | * OR: STRIDE register is unused in 1D mode. Could write the src index that this block is linked to in that register. But then we can't use stride feature. | |
|
No newline at end of file | ||
|
114 | * Rather, we can't use the stride feature on ONE cb per frame. So, use stride on the buffer->GPIO cb, and use the stride register to indicate index on the zeros-copy and the PWM cb. Can tell which CB we're looking at based on the 2DEN flag. If we're looking at the buffer->GPIO cb, then instead look at NEXTCON_BK | |
|
No newline at end of file | ||
|
115 | * NOTE: if 2d stride is disabled, it appears that the DMA engine doesn't even load the STRIDE register (it's read as garbage). It may PERHAPS display the last loaded word. | |
|
No newline at end of file | ||
|
116 | * Note: unused fields are read as "Don't care", meaning we can't use them to store user-data. | |
|
No newline at end of file | ||
|
117 | * | |
|
No newline at end of file | ||
|
118 | * http://www.raspberrypi.org/forums/viewtopic.php?f=44&t=26907 | |
|
No newline at end of file | ||
|
119 | * Says gpu halts all DMA for 16us every 500ms. To bypass, add 'disable_pvt=1' to /boot/cmdline.txt | |
|
No newline at end of file | ||
|
120 | * http://www.raspberrypi.org/forums/viewtopic.php?f=37&t=7696&start=25 | |
|
No newline at end of file | ||
|
121 | * Says it's possible to get access to a 250MHz clock. | |
|
No newline at end of file | ||
|
122 | * How to make DMA more consistent (ie reduce bus contention?): | |
|
No newline at end of file | ||
|
123 | * disable interrupts 1 uS before any 'real' transaction, enable them afterwards | |
|
No newline at end of file | ||
|
124 | * Make sure dummy writes DON'T READ FROM RAM (ie, use src_ignore = 1) | |
|
No newline at end of file | ||
|
125 | * boot with disable_pvt=1 (prevents gpu from halting everything to adjust ram refresh rate twice per second) in /boot/cmdline.txt. Does this affect system stability? | |
|
No newline at end of file | ||
|
126 | */ | |
|
No newline at end of file | ||
|
127 | ||
|
No newline at end of file | ||
|
128 | #include <sys/mman.h> //for mmap | |
|
No newline at end of file | ||
|
129 | #include <sys/time.h> //for timespec | |
|
No newline at end of file | ||
|
130 | #include <time.h> //for timespec / nanosleep (need -std=gnu99) | |
|
No newline at end of file | ||
|
131 | #include <signal.h> //for sigaction | |
|
No newline at end of file | ||
|
132 | #include <unistd.h> //for NULL | |
|
No newline at end of file | ||
|
133 | #include <stdio.h> //for printf | |
|
No newline at end of file | ||
|
134 | #include <stdlib.h> //for exit, valloc | |
|
No newline at end of file | ||
|
135 | //#include <malloc.h> //some implementations declare valloc inside malloc.h | |
|
No newline at end of file | ||
|
136 | #include <fcntl.h> //for file opening | |
|
No newline at end of file | ||
|
137 | #include <stdint.h> //for uint32_t | |
|
No newline at end of file | ||
|
138 | #include <string.h> //for memset | |
|
No newline at end of file | ||
|
139 | #include <errno.h> //for errno | |
|
No newline at end of file | ||
|
140 | #include <pthread.h> //for pthread_setschedparam | |
|
No newline at end of file | ||
|
141 | ||
|
No newline at end of file | ||
|
142 | //config settings: | |
|
No newline at end of file | ||
|
143 | #define PWM_FIFO_SIZE 1 //The DMA transaction is paced through the PWM FIFO. The PWM FIFO consumes 1 word every N uS (set in clock settings). Once the fifo has fewer than PWM_FIFO_SIZE words available, it will request more data from DMA. Thus, a high buffer length will be more resistant to clock drift, but may occasionally request multiple frames in a short succession (faster than FRAME_PER_SEC) in the presence of bus contention, whereas a low buffer length will always space frames AT LEAST 1/FRAMES_PER_SEC seconds apart, but may experience clock drift. | |
|
No newline at end of file | ||
|
144 | #define SOURCE_BUFFER_FRAMES 8192 //number of gpio timeslices to buffer. These are processed at ~1 million/sec. So 1000 framse is 1 ms. Using a power-of-two is a good idea as it simplifies some of the arithmetic (modulus operations) | |
|
No newline at end of file | ||
|
145 | #define SCHED_PRIORITY 30 //Linux scheduler priority. Higher = more realtime | |
|
No newline at end of file | ||
|
146 | ||
|
No newline at end of file | ||
|
147 | #define NOMINAL_CLOCK_FREQ 500000000 //PWM Clock runs at 500 MHz, unless overclocking | |
|
No newline at end of file | ||
|
148 | #define BITS_PER_CLOCK 10 //# of bits to be used in each PWM cycle. Effectively acts as a clock divisor for us, since the PWM clock is in bits/second | |
|
No newline at end of file | ||
|
149 | #define CLOCK_DIV 200 //# to divide the NOMINAL_CLOCK_FREQ by before passing it to the PWM peripheral. | |
|
No newline at end of file | ||
|
150 | //gpio frames per second is a product of the nominal clock frequency divided by BITS_PER_CLOCK and divided again by CLOCK_DIV | |
|
No newline at end of file | ||
|
151 | //At 500,000 frames/sec, memory bandwidth does not appear to be an issue (jitter of -1 to +2 uS) | |
|
No newline at end of file | ||
|
152 | //attempting 1,000,000 frames/sec results in an actual 800,000 frames/sec, though with a lot of jitter. | |
|
No newline at end of file | ||
|
153 | //Note that these numbers might very with heavy network or usb usage. | |
|
No newline at end of file | ||
|
154 | // eg at 500,000 fps, with 1MB/sec network download, jitter is -1 to +30 uS | |
|
No newline at end of file | ||
|
155 | // at 250,000 fps, with 1MB/sec network download, jitter is only -3 to +3 uS | |
|
No newline at end of file | ||
|
156 | #define FRAMES_PER_SEC NOMINAL_CLOCK_FREQ/BITS_PER_CLOCK/CLOCK_DIV | |
|
No newline at end of file | ||
|
157 | #define SEC_TO_FRAME(s) ((int64_t)(s)*FRAMES_PER_SEC) | |
|
No newline at end of file | ||
|
158 | #define USEC_TO_FRAME(u) (SEC_TO_FRAME(u)/1000000) | |
|
No newline at end of file | ||
|
159 | #define FRAME_TO_SEC(f) ((int64_t)(f)*BITS_PER_CLOCK*CLOCK_DIV/NOMINAL_CLOCK_FREQ) | |
|
No newline at end of file | ||
|
160 | #define FRAME_TO_USEC(f) FRAME_TO_SEC((int64_t)(f)*1000000) | |
|
No newline at end of file | ||
|
161 | ||
|
No newline at end of file | ||
|
162 | #define TIMER_BASE 0x20003000 | |
|
No newline at end of file | ||
|
163 | #define TIMER_CLO 0x00000004 //lower 32-bits of 1 MHz timer | |
|
No newline at end of file | ||
|
164 | #define TIMER_CHI 0x00000008 //upper 32-bits | |
|
No newline at end of file | ||
|
165 | ||
|
No newline at end of file | ||
|
166 | ||
|
No newline at end of file | ||
|
167 | #define GPIO_BASE 0x20200000 //base address of the GPIO control registers. | |
|
No newline at end of file | ||
|
168 | #define GPIO_BASE_BUS 0x7E200000 //this is the physical bus address of the GPIO module. This is only used when other peripherals directly connected to the bus (like DMA) need to read/write the GPIOs | |
|
No newline at end of file | ||
|
169 | #define PAGE_SIZE 4096 //mmap maps pages of memory, so we must give it multiples of this size | |
|
No newline at end of file | ||
|
170 | #define GPFSEL0 0x00000000 //gpio function select. There are 6 of these (32 bit registers) | |
|
No newline at end of file | ||
|
171 | #define GPFSEL1 0x00000004 | |
|
No newline at end of file | ||
|
172 | #define GPFSEL2 0x00000008 | |
|
No newline at end of file | ||
|
173 | #define GPFSEL3 0x0000000c | |
|
No newline at end of file | ||
|
174 | #define GPFSEL4 0x00000010 | |
|
No newline at end of file | ||
|
175 | #define GPFSEL5 0x00000014 | |
|
No newline at end of file | ||
|
176 | //bits 2-0 of GPFSEL0: set to 000 to make Pin 0 an output. 001 is an input. Other combinations represent alternate functions | |
|
No newline at end of file | ||
|
177 | //bits 3-5 are for pin 1. | |
|
No newline at end of file | ||
|
178 | //... | |
|
No newline at end of file | ||
|
179 | //bits 27-29 are for pin 9. | |
|
No newline at end of file | ||
|
180 | //GPFSEL1 repeats, but bits 2-0 are Pin 10, 27-29 are pin 19. | |
|
No newline at end of file | ||
|
181 | //... | |
|
No newline at end of file | ||
|
182 | #define GPSET0 0x0000001C //GPIO Pin Output Set. There are 2 of these (32 bit registers) | |
|
No newline at end of file | ||
|
183 | #define GPSET1 0x00000020 | |
|
No newline at end of file | ||
|
184 | //writing a '1' to bit N of GPSET0 makes that pin HIGH. | |
|
No newline at end of file | ||
|
185 | //writing a '0' has no effect. | |
|
No newline at end of file | ||
|
186 | //GPSET0[0-31] maps to pins 0-31 | |
|
No newline at end of file | ||
|
187 | //GPSET1[0-21] maps to pins 32-53 | |
|
No newline at end of file | ||
|
188 | #define GPCLR0 0x00000028 //GPIO Pin Output Clear. There are 2 of these (32 bits each) | |
|
No newline at end of file | ||
|
189 | #define GPCLR1 0x0000002C | |
|
No newline at end of file | ||
|
190 | //GPCLR acts the same way as GPSET, but clears the pin instead. | |
|
No newline at end of file | ||
|
191 | #define GPLEV0 0x00000034 //GPIO Pin Level. There are 2 of these (32 bits each) | |
|
No newline at end of file | ||
|
192 | ||
|
No newline at end of file | ||
|
193 | //physical addresses for the DMA peripherals, as found in the processor documentation: | |
|
No newline at end of file | ||
|
194 | #define DMA_BASE 0x20007000 | |
|
No newline at end of file | ||
|
195 | #define DMACH(n) (0x100*(n)) | |
|
No newline at end of file | ||
|
196 | //DMA Channel register sets (format of these registers is found in DmaChannelHeader struct): | |
|
No newline at end of file | ||
|
197 | //#define DMACH0 0x00000000 | |
|
No newline at end of file | ||
|
198 | //#define DMACH1 0x00000100 | |
|
No newline at end of file | ||
|
199 | //#define DMACH2 0x00000200 | |
|
No newline at end of file | ||
|
200 | //#define DMACH3 0x00000300 | |
|
No newline at end of file | ||
|
201 | //... | |
|
No newline at end of file | ||
|
202 | //Each DMA channel has some associated registers, but only CS (control and status), CONBLK_AD (control block address), and DEBUG are writeable | |
|
No newline at end of file | ||
|
203 | //DMA is started by writing address of the first Control Block to the DMA channel's CONBLK_AD register and then setting the ACTIVE bit inside the CS register (bit 0) | |
|
No newline at end of file | ||
|
204 | //Note: DMA channels are connected directly to peripherals, so physical addresses should be used (affects control block's SOURCE, DEST and NEXTCONBK addresses). | |
|
No newline at end of file | ||
|
205 | #define DMAENABLE 0x00000ff0 //bit 0 should be set to 1 to enable channel 0. bit 1 enables channel 1, etc. | |
|
No newline at end of file | ||
|
206 | ||
|
No newline at end of file | ||
|
207 | //flags used in the DmaChannelHeader struct: | |
|
No newline at end of file | ||
|
208 | #define DMA_CS_RESET (1<<31) | |
|
No newline at end of file | ||
|
209 | #define DMA_CS_ABORT (1<<30) | |
|
No newline at end of file | ||
|
210 | #define DMA_CS_DISDEBUG (1<<28) //DMA will not stop when debug signal is asserted | |
|
No newline at end of file | ||
|
211 | #define DMA_CS_PRIORITY(x) ((x)&0xf << 16) //higher priority DMA transfers are serviced first, it would appear | |
|
No newline at end of file | ||
|
212 | #define DMA_CS_PRIORITY_MAX DMA_CS_PRIORITY(7) | |
|
No newline at end of file | ||
|
213 | #define DMA_CS_PANIC_PRIORITY(x) ((x)&0xf << 20) | |
|
No newline at end of file | ||
|
214 | #define DMA_CS_PANIC_PRIORITY_MAX DMA_CS_PANIC_PRIORITY(7) | |
|
No newline at end of file | ||
|
215 | #define DMA_CS_END (1<<1) | |
|
No newline at end of file | ||
|
216 | #define DMA_CS_ACTIVE (1<<0) | |
|
No newline at end of file | ||
|
217 | ||
|
No newline at end of file | ||
|
218 | #define DMA_DEBUG_READ_ERROR (1<<2) | |
|
No newline at end of file | ||
|
219 | #define DMA_DEBUG_FIFO_ERROR (1<<1) | |
|
No newline at end of file | ||
|
220 | #define DMA_DEBUG_READ_LAST_NOT_SET_ERROR (1<<0) | |
|
No newline at end of file | ||
|
221 | ||
|
No newline at end of file | ||
|
222 | //flags used in the DmaControlBlock struct: | |
|
No newline at end of file | ||
|
223 | #define DMA_CB_TI_NO_WIDE_BURSTS (1<<26) | |
|
No newline at end of file | ||
|
224 | #define DMA_CB_TI_PERMAP_NONE (0<<16) | |
|
No newline at end of file | ||
|
225 | #define DMA_CB_TI_PERMAP_DSI (1<<16) | |
|
No newline at end of file | ||
|
226 | //... (more found on page 61 of BCM2835 pdf | |
|
No newline at end of file | ||
|
227 | #define DMA_CB_TI_PERMAP_PWM (5<<16) | |
|
No newline at end of file | ||
|
228 | //... | |
|
No newline at end of file | ||
|
229 | #define DMA_CB_TI_SRC_DREQ (1<<10) | |
|
No newline at end of file | ||
|
230 | #define DMA_CB_TI_SRC_INC (1<<8) | |
|
No newline at end of file | ||
|
231 | #define DMA_CB_TI_DEST_DREQ (1<<6) | |
|
No newline at end of file | ||
|
232 | #define DMA_CB_TI_DEST_INC (1<<4) | |
|
No newline at end of file | ||
|
233 | #define DMA_CB_TI_TDMODE (1<<1) | |
|
No newline at end of file | ||
|
234 | ||
|
No newline at end of file | ||
|
235 | ||
|
No newline at end of file | ||
|
236 | //https://dev.openwrt.org/browser/trunk/target/linux/brcm2708/patches-3.10/0070-bcm2708_fb-DMA-acceleration-for-fb_copyarea.patch?rev=39770 says that YLENGTH should actually be written as # of copies *MINUS ONE* | |
|
No newline at end of file | ||
|
237 | #define DMA_CB_TXFR_LEN_YLENGTH(y) (((y-1)&0x4fff) << 16) | |
|
No newline at end of file | ||
|
238 | #define DMA_CB_TXFR_LEN_XLENGTH(x) ((x)&0xffff) | |
|
No newline at end of file | ||
|
239 | #define DMA_CB_TXFR_YLENGTH_MASK (0x4fff << 16) | |
|
No newline at end of file | ||
|
240 | #define DMA_CB_STRIDE_D_STRIDE(x) (((x)&0xffff) << 16) | |
|
No newline at end of file | ||
|
241 | #define DMA_CB_STRIDE_S_STRIDE(x) ((x)&0xffff) | |
|
No newline at end of file | ||
|
242 | ||
|
No newline at end of file | ||
|
243 | ||
|
No newline at end of file | ||
|
244 | //Dma Control Blocks must be located at addresses that are multiples of 32 bytes | |
|
No newline at end of file | ||
|
245 | #define DMA_CONTROL_BLOCK_ALIGNMENT 32 | |
|
No newline at end of file | ||
|
246 | ||
|
No newline at end of file | ||
|
247 | #define PWM_BASE 0x2020C000 | |
|
No newline at end of file | ||
|
248 | #define PWM_BASE_BUS 0x7E20C000 | |
|
No newline at end of file | ||
|
249 | #define PWM_CTL 0x00000000 //control register | |
|
No newline at end of file | ||
|
250 | #define PWM_STA 0x00000004 //status register | |
|
No newline at end of file | ||
|
251 | #define PWM_DMAC 0x00000008 //DMA control register | |
|
No newline at end of file | ||
|
252 | #define PWM_RNG1 0x00000010 //channel 1 range register (# output bits to use per sample) | |
|
No newline at end of file | ||
|
253 | #define PWM_DAT1 0x00000014 //channel 1 data | |
|
No newline at end of file | ||
|
254 | #define PWM_FIF1 0x00000018 //channel 1 fifo (write to this register to queue an output) | |
|
No newline at end of file | ||
|
255 | #define PWM_RNG2 0x00000020 //channel 2 range register | |
|
No newline at end of file | ||
|
256 | #define PWM_DAT2 0x00000024 //channel 2 data | |
|
No newline at end of file | ||
|
257 | ||
|
No newline at end of file | ||
|
258 | #define PWM_CTL_USEFIFO2 (1<<13) | |
|
No newline at end of file | ||
|
259 | #define PWM_CTL_REPEATEMPTY2 (1<<10) | |
|
No newline at end of file | ||
|
260 | #define PWM_CTL_ENABLE2 (1<<8) | |
|
No newline at end of file | ||
|
261 | #define PWM_CTL_CLRFIFO (1<<6) | |
|
No newline at end of file | ||
|
262 | #define PWM_CTL_USEFIFO1 (1<<5) | |
|
No newline at end of file | ||
|
263 | #define PWM_CTL_REPEATEMPTY1 (1<<2) | |
|
No newline at end of file | ||
|
264 | #define PWM_CTL_ENABLE1 (1<<0) | |
|
No newline at end of file | ||
|
265 | ||
|
No newline at end of file | ||
|
266 | #define PWM_STA_BUSERR (1<<8) | |
|
No newline at end of file | ||
|
267 | #define PWM_STA_GAPERRS (0xf << 4) | |
|
No newline at end of file | ||
|
268 | #define PWM_STA_FIFOREADERR (1<<3) | |
|
No newline at end of file | ||
|
269 | #define PWM_STA_FIFOWRITEERR (1<<2) | |
|
No newline at end of file | ||
|
270 | #define PWM_STA_ERRS PWM_STA_BUSERR | PWM_STA_GAPERRS | PWM_STA_FIFOREADERR | PWM_STA_FIFOWRITEERR | |
|
No newline at end of file | ||
|
271 | ||
|
No newline at end of file | ||
|
272 | #define PWM_DMAC_EN (1<<31) | |
|
No newline at end of file | ||
|
273 | #define PWM_DMAC_PANIC(P) (((P)&0xff)<<8) | |
|
No newline at end of file | ||
|
274 | #define PWM_DMAC_DREQ(D) (((D)&0xff)<<0) | |
|
No newline at end of file | ||
|
275 | ||
|
No newline at end of file | ||
|
276 | //The following is undocumented :( Taken from http://www.scribd.com/doc/127599939/BCM2835-Audio-clocks | |
|
No newline at end of file | ||
|
277 | #define CLOCK_BASE 0x20101000 | |
|
No newline at end of file | ||
|
278 | #define CM_PWMCTL 0xa0 | |
|
No newline at end of file | ||
|
279 | #define CM_PWMDIV 0xa4 | |
|
No newline at end of file | ||
|
280 | //each write to CM_PWMTL and CM_PWMDIV requires the password to be written: | |
|
No newline at end of file | ||
|
281 | #define CM_PWMCTL_PASSWD 0x5a000000 | |
|
No newline at end of file | ||
|
282 | #define CM_PWMDIV_PASSWD 0x5a000000 | |
|
No newline at end of file | ||
|
283 | //MASH is used to achieve fractional clock dividers by introducing artificial jitter. | |
|
No newline at end of file | ||
|
284 | //if you want constant frequency (even if it may not be at 100% CORRECT frequency), use MASH0 | |
|
No newline at end of file | ||
|
285 | //if clock divisor is integral, then there's no need to use MASH, and anything above MASH1 can introduce jitter. | |
|
No newline at end of file | ||
|
286 | #define CM_PWMCTL_MASH(x) (((x)&0x3) << 9) | |
|
No newline at end of file | ||
|
287 | #define CM_PWMCTL_MASH0 CM_PWMTRL_MASH(0) | |
|
No newline at end of file | ||
|
288 | #define CM_PWMCTL_MASH1 CM_PWMTRL_MASH(1) | |
|
No newline at end of file | ||
|
289 | #define CM_PWMCTL_MASH2 CM_PWMTRL_MASH(2) | |
|
No newline at end of file | ||
|
290 | #define CM_PWMCTL_MASH3 CM_PWMTRL_MASH(3) | |
|
No newline at end of file | ||
|
291 | #define CM_PWMCTL_FLIP (1<<8) //use to inverse clock polarity | |
|
No newline at end of file | ||
|
292 | #define CM_PWMCTL_BUSY (1<<7) //read-only flag that indicates clock generator is running. | |
|
No newline at end of file | ||
|
293 | #define CM_PWMCTL_KILL (1<<5) //write a 1 to stop & reset clock generator. USED FOR DEBUG ONLY | |
|
No newline at end of file | ||
|
294 | #define CM_PWMCTL_ENAB (1<<4) //gracefully stop/start clock generator. BUSY flag will go low once clock is off. | |
|
No newline at end of file | ||
|
295 | #define CM_PWMCTL_SRC(x) ((x)&0xf) //clock source. 0=gnd. 1=oscillator. 2-3=debug. 4=PLLA per. 5=PLLC per. 6=PLLD per. 7=HDMI aux. 8-15=GND | |
|
No newline at end of file | ||
|
296 | #define CM_PWMCTL_SRC_OSC CM_PWMCTL_SRC(1) | |
|
No newline at end of file | ||
|
297 | #define CM_PWMCTL_SRC_PLLA CM_PWMCTL_SRC(4) | |
|
No newline at end of file | ||
|
298 | #define CM_PWMCTL_SRC_PLLC CM_PWMCTL_SRC(5) | |
|
No newline at end of file | ||
|
299 | #define CM_PWMCTL_SRC_PLLD CM_PWMCTL_SRC(6) | |
|
No newline at end of file | ||
|
300 | ||
|
No newline at end of file | ||
|
301 | //max clock divisor is 4095 | |
|
No newline at end of file | ||
|
302 | #define CM_PWMDIV_DIVI(x) (((x)&0xfff) << 12) | |
|
No newline at end of file | ||
|
303 | #define CM_PWMDIV_DIVF(x) ((x)&0xfff) | |
|
No newline at end of file | ||
|
304 | ||
|
No newline at end of file | ||
|
305 | struct DmaChannelHeader { | |
|
No newline at end of file | ||
|
306 | //Note: dma channels 7-15 are 'LITE' dma engines (or is it 8-15?), with reduced performance & functionality. | |
|
No newline at end of file | ||
|
307 | //Note: only CS, CONBLK_AD and DEBUG are directly writeable | |
|
No newline at end of file | ||
|
308 | volatile uint32_t CS; //Control and Status | |
|
No newline at end of file | ||
|
309 | //31 RESET; set to 1 to reset DMA | |
|
No newline at end of file | ||
|
310 | //30 ABORT; set to 1 to abort current DMA control block (next one will be loaded & continue) | |
|
No newline at end of file | ||
|
311 | //29 DISDEBUG; set to 1 and DMA won't be paused when debug signal is sent | |
|
No newline at end of file | ||
|
312 | //28 WAIT_FOR_OUTSTANDING_WRITES(0x10000000); set to 1 and DMA will wait until peripheral says all writes have gone through before loading next CB | |
|
No newline at end of file | ||
|
313 | //24-74 reserved | |
|
No newline at end of file | ||
|
314 | //20-23 PANIC_PRIORITY; 0 is lowest priority | |
|
No newline at end of file | ||
|
315 | //16-19 PRIORITY; bus scheduling priority. 0 is lowest | |
|
No newline at end of file | ||
|
316 | //9-15 reserved | |
|
No newline at end of file | ||
|
317 | //8 ERROR; read as 1 when error is encountered. error can be found in DEBUG register. | |
|
No newline at end of file | ||
|
318 | //7 reserved | |
|
No newline at end of file | ||
|
319 | //6 WAITING_FOR_OUTSTANDING_WRITES; read as 1 when waiting for outstanding writes | |
|
No newline at end of file | ||
|
320 | //5 DREQ_STOPS_DMA(0x20); read as 1 if DREQ is currently preventing DMA | |
|
No newline at end of file | ||
|
321 | //4 PAUSED(0x10); read as 1 if DMA is paused | |
|
No newline at end of file | ||
|
322 | //3 DREQ; copy of the data request signal from the peripheral, if DREQ is enabled. reads as 1 if data is being requested (or PERMAP=0), else 0 | |
|
No newline at end of file | ||
|
323 | //2 INT; set when current CB ends and its INTEN=1. Write a 1 to this register to clear it | |
|
No newline at end of file | ||
|
324 | //1 END; set when the transfer defined by current CB is complete. Write 1 to clear. | |
|
No newline at end of file | ||
|
325 | //0 ACTIVE(0x01); write 1 to activate DMA (load the CB before hand) | |
|
No newline at end of file | ||
|
326 | volatile uint32_t CONBLK_AD; //Control Block Address | |
|
No newline at end of file | ||
|
327 | volatile uint32_t TI; //transfer information; see DmaControlBlock.TI for description | |
|
No newline at end of file | ||
|
328 | volatile uint32_t SOURCE_AD; //Source address | |
|
No newline at end of file | ||
|
329 | volatile uint32_t DEST_AD; //Destination address | |
|
No newline at end of file | ||
|
330 | volatile uint32_t TXFR_LEN; //transfer length. ONLY THE LOWER 16 BITS ARE USED IN LITE DMA ENGINES | |
|
No newline at end of file | ||
|
331 | volatile uint32_t STRIDE; //2D Mode Stride. Only used if TI.TDMODE = 1. NOT AVAILABLE IN LITE DMA ENGINES | |
|
No newline at end of file | ||
|
332 | volatile uint32_t NEXTCONBK; //Next control block. Must be 256-bit aligned (32 bytes; 8 words) | |
|
No newline at end of file | ||
|
333 | volatile uint32_t DEBUG; //controls debug settings | |
|
No newline at end of file | ||
|
334 | //29-31 unused | |
|
No newline at end of file | ||
|
335 | //28 LITE (0x10000000) | |
|
No newline at end of file | ||
|
336 | //25-27 VERSION | |
|
No newline at end of file | ||
|
337 | //16-24 DMA_STATE (dma engine state machine) | |
|
No newline at end of file | ||
|
338 | //8-15 DMA_ID (AXI bus id) | |
|
No newline at end of file | ||
|
339 | //4-7 OUTSTANDING_WRITES | |
|
No newline at end of file | ||
|
340 | //3 unused | |
|
No newline at end of file | ||
|
341 | //2 READ_ERROR | |
|
No newline at end of file | ||
|
342 | //1 WRITE_ERROR | |
|
No newline at end of file | ||
|
343 | //0 READ_LAST_NOT_SET_ERROR | |
|
No newline at end of file | ||
|
344 | }; | |
|
No newline at end of file | ||
|
345 | void logDmaChannelHeader(struct DmaChannelHeader *h) { | |
|
No newline at end of file | ||
|
346 | printf("Dma Ch Header:\n CS: 0x%08x\n CONBLK_AD: 0x%08x\n TI: 0x%08x\n SOURCE_AD: 0x%08x\n DEST_AD: 0x%08x\n TXFR_LEN: %u\n STRIDE: 0x%08x\n NEXTCONBK: 0x%08x\n DEBUG: 0x%08x\n", h->CS, h->CONBLK_AD, h->TI, h->SOURCE_AD, h->DEST_AD, h->TXFR_LEN, h->STRIDE, h->NEXTCONBK, h->DEBUG); | |
|
No newline at end of file | ||
|
347 | } | |
|
No newline at end of file | ||
|
348 | ||
|
No newline at end of file | ||
|
349 | struct DmaControlBlock { | |
|
No newline at end of file | ||
|
350 | volatile uint32_t TI; //transfer information | |
|
No newline at end of file | ||
|
351 | //31:27 unused | |
|
No newline at end of file | ||
|
352 | //26 NO_WIDE_BURSTS | |
|
No newline at end of file | ||
|
353 | //21:25 WAITS; number of cycles to wait between each DMA read/write operation | |
|
No newline at end of file | ||
|
354 | //16:20 PERMAP(0x000Y0000); peripheral number to be used for DREQ signal (pacing). set to 0 for unpaced DMA. | |
|
No newline at end of file | ||
|
355 | //12:15 BURST_LENGTH | |
|
No newline at end of file | ||
|
356 | //11 SRC_IGNORE; set to 1 to not perform reads. Used to manually fill caches | |
|
No newline at end of file | ||
|
357 | //10 SRC_DREQ; set to 1 to have the DREQ from PERMAP gate requests. | |
|
No newline at end of file | ||
|
358 | //9 SRC_WIDTH; set to 1 for 128-bit moves, 0 for 32-bit moves | |
|
No newline at end of file | ||
|
359 | //8 SRC_INC; set to 1 to automatically increment the source address after each read (you'll want this if you're copying a range of memory) | |
|
No newline at end of file | ||
|
360 | //7 DEST_IGNORE; set to 1 to not perform writes. | |
|
No newline at end of file | ||
|
361 | //6 DEST_DREQ; set to 1 to have the DREQ from PERMAP gate *writes* | |
|
No newline at end of file | ||
|
362 | //5 DEST_WIDTH; set to 1 for 128-bit moves, 0 for 32-bit moves | |
|
No newline at end of file | ||
|
363 | //4 DEST_INC; set to 1 to automatically increment the destination address after each read (Tyou'll want this if you're copying a range of memory) | |
|
No newline at end of file | ||
|
364 | //3 WAIT_RESP; make DMA wait for a response from the peripheral during each write. Ensures multiple writes don't get stacked in the pipeline | |
|
No newline at end of file | ||
|
365 | //2 unused (0) | |
|
No newline at end of file | ||
|
366 | //1 TDMODE; set to 1 to enable 2D mode | |
|
No newline at end of file | ||
|
367 | //0 INTEN; set to 1 to generate an interrupt upon completion | |
|
No newline at end of file | ||
|
368 | volatile uint32_t SOURCE_AD; //Source address | |
|
No newline at end of file | ||
|
369 | volatile uint32_t DEST_AD; //Destination address | |
|
No newline at end of file | ||
|
370 | volatile uint32_t TXFR_LEN; //transfer length. | |
|
No newline at end of file | ||
|
371 | //in 2D mode, TXFR_LEN is separated into two half-words to indicate Y transfers of length X, and STRIDE is added to the src/dest address after each transfer of length X. | |
|
No newline at end of file | ||
|
372 | //30:31 unused | |
|
No newline at end of file | ||
|
373 | //16-29 YLENGTH | |
|
No newline at end of file | ||
|
374 | //0-15 XLENGTH | |
|
No newline at end of file | ||
|
375 | volatile uint32_t STRIDE; //2D Mode Stride (amount to increment/decrement src/dest after each 1d copy when in 2d mode). Only used if TI.TDMODE = 1 | |
|
No newline at end of file | ||
|
376 | //16-31 D_STRIDE; signed (2's complement) byte increment/decrement to apply to destination addr after each XLENGTH transfer | |
|
No newline at end of file | ||
|
377 | //0-15 S_STRIDE; signed (2's complement) byte increment/decrement to apply to source addr after each XLENGTH transfer | |
|
No newline at end of file | ||
|
378 | volatile uint32_t NEXTCONBK; //Next control block. Must be 256-bit aligned (32 bytes; 8 words) | |
|
No newline at end of file | ||
|
379 | uint32_t _reserved[2]; | |
|
No newline at end of file | ||
|
380 | }; | |
|
No newline at end of file | ||
|
381 | ||
|
No newline at end of file | ||
|
382 | void logDmaControlBlock(struct DmaControlBlock *b) { | |
|
No newline at end of file | ||
|
383 | printf("Dma Control Block:\n TI: 0x%08x\n SOURCE_AD: 0x%08x\n DEST_AD: 0x%08x\n TXFR_LEN: 0x%08x\n STRIDE: 0x%08x\n NEXTCONBK: 0x%08x\n unused: 0x%08x %08x\n", b->TI, b->SOURCE_AD, b->DEST_AD, b->TXFR_LEN, b->STRIDE, b->NEXTCONBK, b->_reserved[0], b->_reserved[1]); | |
|
No newline at end of file | ||
|
384 | } | |
|
No newline at end of file | ||
|
385 | ||
|
No newline at end of file | ||
|
386 | struct PwmHeader { | |
|
No newline at end of file | ||
|
387 | volatile uint32_t CTL; // 0x00000000 //control register | |
|
No newline at end of file | ||
|
388 | //16-31 reserved | |
|
No newline at end of file | ||
|
389 | //15 MSEN2 (0: PWM algorithm, 1:M/S transmission used) | |
|
No newline at end of file | ||
|
390 | //14 reserved | |
|
No newline at end of file | ||
|
391 | //13 USEF2 (0: data register is used for transmission, 1: FIFO is used for transmission) | |
|
No newline at end of file | ||
|
392 | //12 POLA2 (0: 0=low, 1=high. 1: 0=high, 1=low (inversion)) | |
|
No newline at end of file | ||
|
393 | //11 SBIT2; defines the state of the output when no transmission is in place | |
|
No newline at end of file | ||
|
394 | //10 RPTL2; 0: transmission interrupts when FIFO is empty. 1: last data in FIFO is retransmitted when FIFO is empty | |
|
No newline at end of file | ||
|
395 | //9 MODE2; 0: PWM mode. 1: serializer mode | |
|
No newline at end of file | ||
|
396 | //8 PWMEN2; 0: channel is disabled. 1: channel is enabled | |
|
No newline at end of file | ||
|
397 | //7 MSEN1; | |
|
No newline at end of file | ||
|
398 | //6 CLRF1; writing a 1 to this bit clears the channel 1 (and channel 2?) fifo | |
|
No newline at end of file | ||
|
399 | //5 USEF1; | |
|
No newline at end of file | ||
|
400 | //4 POLA1; | |
|
No newline at end of file | ||
|
401 | //3 SBIT1; | |
|
No newline at end of file | ||
|
402 | //2 RPTL1; | |
|
No newline at end of file | ||
|
403 | //1 MODE1; | |
|
No newline at end of file | ||
|
404 | //0 PWMEN1; | |
|
No newline at end of file | ||
|
405 | volatile uint32_t STA; // 0x00000004 //status register | |
|
No newline at end of file | ||
|
406 | //13-31 reserved | |
|
No newline at end of file | ||
|
407 | //9-12 STA1-4; indicates whether each channel is transmitting | |
|
No newline at end of file | ||
|
408 | //8 BERR; Bus Error Flag. Write 1 to clear | |
|
No newline at end of file | ||
|
409 | //4-7 GAPO1-4; Gap Occured Flag. Write 1 to clear | |
|
No newline at end of file | ||
|
410 | //3 RERR1; Fifo Read Error Flag (attempt to read empty fifo). Write 1 to clear | |
|
No newline at end of file | ||
|
411 | //2 WERR1; Fifo Write Error Flag (attempt to write to full fifo). Write 1 to clear | |
|
No newline at end of file | ||
|
412 | //1 EMPT1; Reads as 1 if fifo is empty | |
|
No newline at end of file | ||
|
413 | //0 FULL1; Reads as 1 if fifo is full | |
|
No newline at end of file | ||
|
414 | volatile uint32_t DMAC; // 0x00000008 //DMA control register | |
|
No newline at end of file | ||
|
415 | //31 ENAB; set to 1 to enable DMA | |
|
No newline at end of file | ||
|
416 | //16-30 reserved | |
|
No newline at end of file | ||
|
417 | //8-15 PANIC; DMA threshold for panic signal | |
|
No newline at end of file | ||
|
418 | //0-7 DREQ; DMA threshold for DREQ signal | |
|
No newline at end of file | ||
|
419 | uint32_t _padding1; | |
|
No newline at end of file | ||
|
420 | volatile uint32_t RNG1; // 0x00000010 //channel 1 range register (# output bits to use per sample) | |
|
No newline at end of file | ||
|
421 | //0-31 PWM_RNGi; #of bits to modulate PWM. (eg if PWM_RNGi=1024, then each 32-bit sample sent through the FIFO will be modulated into 1024 bits.) | |
|
No newline at end of file | ||
|
422 | volatile uint32_t DAT1; // 0x00000014 //channel 1 data | |
|
No newline at end of file | ||
|
423 | //0-31 PWM_DATi; Stores the 32-bit data to be sent to the PWM controller ONLY WHEN USEFi=0 (FIFO is disabled) | |
|
No newline at end of file | ||
|
424 | volatile uint32_t FIF1; // 0x00000018 //channel 1 fifo (write to this register to queue an output) | |
|
No newline at end of file | ||
|
425 | //writing to this register will queue a sample into the fifo. If 2 channels are enabled, then each even sample (0-indexed) is sent to channel 1, and odd samples are sent to channel 2. WRITE-ONLY | |
|
No newline at end of file | ||
|
426 | uint32_t _padding2; | |
|
No newline at end of file | ||
|
427 | volatile uint32_t RNG2; // 0x00000020 //channel 2 range register | |
|
No newline at end of file | ||
|
428 | volatile uint32_t DAT2; // 0x00000024 //channel 2 data | |
|
No newline at end of file | ||
|
429 | //0-31 PWM_DATi; Stores the 32-bit data to be sent to the PWM controller ONLY WHEN USEFi=1 (FIFO is enabled). TODO: Typo??? | |
|
No newline at end of file | ||
|
430 | }; | |
|
No newline at end of file | ||
|
431 | ||
|
No newline at end of file | ||
|
432 | struct GpioBufferFrame { | |
|
No newline at end of file | ||
|
433 | //custom structure used for storing the GPIO buffer. | |
|
No newline at end of file | ||
|
434 | //These BufferFrame's are DMA'd into the GPIO memory, potentially using the DmaEngine's Stride facility | |
|
No newline at end of file | ||
|
435 | uint32_t gpset[2]; | |
|
No newline at end of file | ||
|
436 | uint32_t gpclr[2]; | |
|
No newline at end of file | ||
|
437 | }; | |
|
No newline at end of file | ||
|
438 | ||
|
No newline at end of file | ||
|
439 | struct DmaChannelHeader *dmaHeader; //must be global for cleanup() | |
|
No newline at end of file | ||
|
440 | ||
|
No newline at end of file | ||
|
441 | void setSchedPriority(int priority) { | |
|
No newline at end of file | ||
|
442 | //In order to get the best timing at a decent queue size, we want the kernel to avoid interrupting us for long durations. | |
|
No newline at end of file | ||
|
443 | //This is done by giving our process a high priority. Note, must run as super-user for this to work. | |
|
No newline at end of file | ||
|
444 | struct sched_param sp; | |
|
No newline at end of file | ||
|
445 | sp.sched_priority=priority; | |
|
No newline at end of file | ||
|
446 | int ret; | |
|
No newline at end of file | ||
|
447 | if (ret = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp)) { | |
|
No newline at end of file | ||
|
448 | printf("Warning: pthread_setschedparam (increase thread priority) returned non-zero: %i\n", ret); | |
|
No newline at end of file | ||
|
449 | } | |
|
No newline at end of file | ||
|
450 | } | |
|
No newline at end of file | ||
|
451 | ||
|
No newline at end of file | ||
|
452 | void writeBitmasked(volatile uint32_t *dest, uint32_t mask, uint32_t value) { | |
|
No newline at end of file | ||
|
453 | //set bits designated by (mask) at the address (dest) to (value), without affecting the other bits | |
|
No newline at end of file | ||
|
454 | //eg if x = 0b11001100 | |
|
No newline at end of file | ||
|
455 | // writeBitmasked(&x, 0b00000110, 0b11110011), | |
|
No newline at end of file | ||
|
456 | // then x now = 0b11001110 | |
|
No newline at end of file | ||
|
457 | uint32_t cur = *dest; | |
|
No newline at end of file | ||
|
458 | uint32_t new = (cur & (~mask)) | (value & mask); | |
|
No newline at end of file | ||
|
459 | *dest = new; | |
|
No newline at end of file | ||
|
460 | *dest = new; //best to be safe when crossing memory boundaries | |
|
No newline at end of file | ||
|
461 | } | |
|
No newline at end of file | ||
|
462 | ||
|
No newline at end of file | ||
|
463 | ||
|
No newline at end of file | ||
|
464 | uint64_t readSysTime(volatile uint32_t *timerBaseMem) { | |
|
No newline at end of file | ||
|
465 | return ((uint64_t)*(timerBaseMem + TIMER_CHI/4) << 32) + (uint64_t)(*(timerBaseMem + TIMER_CLO/4)); | |
|
No newline at end of file | ||
|
466 | } | |
|
No newline at end of file | ||
|
467 | ||
|
No newline at end of file | ||
|
468 | size_t ceilToPage(size_t size) { | |
|
No newline at end of file | ||
|
469 | //round up to nearest page-size multiple | |
|
No newline at end of file | ||
|
470 | if (size & (PAGE_SIZE-1)) { | |
|
No newline at end of file | ||
|
471 | size += PAGE_SIZE - (size & (PAGE_SIZE-1)); | |
|
No newline at end of file | ||
|
472 | } | |
|
No newline at end of file | ||
|
473 | return size; | |
|
No newline at end of file | ||
|
474 | } | |
|
No newline at end of file | ||
|
475 | ||
|
No newline at end of file | ||
|
476 | uintptr_t virtToPhys(void* virt, int pagemapfd) { | |
|
No newline at end of file | ||
|
477 | uintptr_t pgNum = (uintptr_t)(virt)/PAGE_SIZE; | |
|
No newline at end of file | ||
|
478 | int byteOffsetFromPage = (uintptr_t)(virt)%PAGE_SIZE; | |
|
No newline at end of file | ||
|
479 | uint64_t physPage; | |
|
No newline at end of file | ||
|
480 | ///proc/self/pagemap is a uint64_t array where the index represents the virtual page number and the value at that index represents the physical page number. | |
|
No newline at end of file | ||
|
481 | //So if virtual address is 0x1000000, read the value at *array* index 0x1000000/PAGE_SIZE and multiply that by PAGE_SIZE to get the physical address. | |
|
No newline at end of file | ||
|
482 | //because files are bytestreams, one must explicitly multiply each byte index by 8 to treat it as a uint64_t array. | |
|
No newline at end of file | ||
|
483 | int err = lseek(pagemapfd, pgNum*8, SEEK_SET); | |
|
No newline at end of file | ||
|
484 | if (err != pgNum*8) { | |
|
No newline at end of file | ||
|
485 | printf("WARNING: virtToPhys %p failed to seek (expected %i got %i. errno: %i)\n", virt, pgNum*8, err, errno); | |
|
No newline at end of file | ||
|
486 | } | |
|
No newline at end of file | ||
|
487 | read(pagemapfd, &physPage, 8); | |
|
No newline at end of file | ||
|
488 | if (!physPage & (1ull<<63)) { //bit 63 is set to 1 if the page is present in ram | |
|
No newline at end of file | ||
|
489 | printf("WARNING: virtToPhys %p has no physical address\n", virt); | |
|
No newline at end of file | ||
|
490 | } | |
|
No newline at end of file | ||
|
491 | physPage = physPage & ~(0x1ffull << 55); //bits 55-63 are flags. | |
|
No newline at end of file | ||
|
492 | uintptr_t mapped = (uintptr_t)(physPage*PAGE_SIZE + byteOffsetFromPage); | |
|
No newline at end of file | ||
|
493 | return mapped; | |
|
No newline at end of file | ||
|
494 | } | |
|
No newline at end of file | ||
|
495 | ||
|
No newline at end of file | ||
|
496 | uintptr_t virtToUncachedPhys(void *virt, int pagemapfd) { | |
|
No newline at end of file | ||
|
497 | return virtToPhys(virt, pagemapfd) | 0x40000000; //bus address of the ram is 0x40000000. With this binary-or, writes to the returned address will bypass the CPU (L1) cache, but not the L2 cache. 0xc0000000 should be the base address if L2 must also be bypassed. However, the DMA engine is aware of L2 cache - just not the L1 cache (source: http://en.wikibooks.org/wiki/Aros/Platforms/Arm_Raspberry_Pi_support#Framebuffer ) | |
|
No newline at end of file | ||
|
498 | } | |
|
No newline at end of file | ||
|
499 | ||
|
No newline at end of file | ||
|
500 | ||
|
No newline at end of file | ||
|
501 | //allocate some memory and lock it so that its physical address will never change | |
|
No newline at end of file | ||
|
502 | void* makeLockedMem(size_t size) { | |
|
No newline at end of file | ||
|
503 | //void* mem = valloc(size); //memory returned by valloc is not zero'd | |
|
No newline at end of file | ||
|
504 | size = ceilToPage(size); | |
|
No newline at end of file | ||
|
505 | void *mem = mmap( | |
|
No newline at end of file | ||
|
506 | NULL, //let kernel place memory where it wants | |
|
No newline at end of file | ||
|
507 | size, //length | |
|
No newline at end of file | ||
|
508 | PROT_WRITE | PROT_READ, //ask for read and write permissions to memory | |
|
No newline at end of file | ||
|
509 | MAP_SHARED | | |
|
No newline at end of file | ||
|
510 | MAP_ANONYMOUS | //no underlying file; initialize to 0 | |
|
No newline at end of file | ||
|
511 | MAP_NORESERVE | //don't reserve swap space | |
|
No newline at end of file | ||
|
512 | MAP_LOCKED, //lock into *virtual* ram. Physical ram may still change! | |
|
No newline at end of file | ||
|
513 | -1, // File descriptor | |
|
No newline at end of file | ||
|
514 | 0); //no offset into file (file doesn't exist). | |
|
No newline at end of file | ||
|
515 | if (mem == MAP_FAILED) { | |
|
No newline at end of file | ||
|
516 | printf("makeLockedMem failed\n"); | |
|
No newline at end of file | ||
|
517 | exit(1); | |
|
No newline at end of file | ||
|
518 | } | |
|
No newline at end of file | ||
|
519 | memset(mem, 0, size); //simultaneously zero the pages and force them into memory | |
|
No newline at end of file | ||
|
520 | mlock(mem, size); | |
|
No newline at end of file | ||
|
521 | return mem; | |
|
No newline at end of file | ||
|
522 | } | |
|
No newline at end of file | ||
|
523 | ||
|
No newline at end of file | ||
|
524 | //free memory allocated with makeLockedMem | |
|
No newline at end of file | ||
|
525 | void freeLockedMem(void* mem, size_t size) { | |
|
No newline at end of file | ||
|
526 | size = ceilToPage(size); | |
|
No newline at end of file | ||
|
527 | munlock(mem, size); | |
|
No newline at end of file | ||
|
528 | munmap(mem, size); | |
|
No newline at end of file | ||
|
529 | } | |
|
No newline at end of file | ||
|
530 | ||
|
No newline at end of file | ||
|
531 | void* makeUncachedMemView(void* virtaddr, size_t bytes, int memfd, int pagemapfd) { | |
|
No newline at end of file | ||
|
532 | //by default, writing to any virtual address will go through the CPU cache. | |
|
No newline at end of file | ||
|
533 | //this function will return a pointer that behaves the same as virtaddr, but bypasses the CPU L1 cache (note that because of this, the returned pointer and original pointer should not be used in conjunction, else cache-related inconsistencies will arise) | |
|
No newline at end of file | ||
|
534 | //Note: The original memory should not be unmapped during the lifetime of the uncached version, as then the OS won't know that our process still owns the physical memory. | |
|
No newline at end of file | ||
|
535 | bytes = ceilToPage(bytes); | |
|
No newline at end of file | ||
|
536 | //first, just allocate enough *virtual* memory for the operation. This is done so that we can do the later mapping to a contiguous range of virtual memory: | |
|
No newline at end of file | ||
|
537 | void *mem = mmap( | |
|
No newline at end of file | ||
|
538 | NULL, //let kernel place memory where it wants | |
|
No newline at end of file | ||
|
539 | bytes, //length | |
|
No newline at end of file | ||
|
540 | PROT_WRITE | PROT_READ, //ask for read and write permissions to memory | |
|
No newline at end of file | ||
|
541 | MAP_SHARED | | |
|
No newline at end of file | ||
|
542 | MAP_ANONYMOUS | //no underlying file; initialize to 0 | |
|
No newline at end of file | ||
|
543 | MAP_NORESERVE | //don't reserve swap space | |
|
No newline at end of file | ||
|
544 | MAP_LOCKED, //lock into *virtual* ram. Physical ram may still change! | |
|
No newline at end of file | ||
|
545 | -1, // File descriptor | |
|
No newline at end of file | ||
|
546 | 0); //no offset into file (file doesn't exist). | |
|
No newline at end of file | ||
|
547 | //now, free the virtual memory and immediately remap it to the physical addresses used in virtaddr | |
|
No newline at end of file | ||
|
548 | munmap(mem, bytes); //Might not be necessary; MAP_FIXED indicates it can map an already-used page | |
|
No newline at end of file | ||
|
549 | for (int offset=0; offset<bytes; offset += PAGE_SIZE) { | |
|
No newline at end of file | ||
|
550 | void *mappedPage = mmap(mem+offset, PAGE_SIZE, PROT_WRITE|PROT_READ, MAP_SHARED|MAP_FIXED|MAP_NORESERVE|MAP_LOCKED, memfd, virtToUncachedPhys(virtaddr+offset, pagemapfd)); | |
|
No newline at end of file | ||
|
551 | if (mappedPage != mem+offset) { //We need these mappings to be contiguous over virtual memory (in order to replicate the virtaddr array), so we must ensure that the address we requested from mmap was actually used. | |
|
No newline at end of file | ||
|
552 | printf("Failed to create an uncached view of memory at addr %p+0x%08x\n", virtaddr, offset); | |
|
No newline at end of file | ||
|
553 | exit(1); | |
|
No newline at end of file | ||
|
554 | } | |
|
No newline at end of file | ||
|
555 | } | |
|
No newline at end of file | ||
|
556 | memset(mem, 0, bytes); //Although the cached version might have been reset, those writes might not have made it through. | |
|
No newline at end of file | ||
|
557 | return mem; | |
|
No newline at end of file | ||
|
558 | } | |
|
No newline at end of file | ||
|
559 | ||
|
No newline at end of file | ||
|
560 | //free memory allocated with makeLockedMem | |
|
No newline at end of file | ||
|
561 | void freeUncachedMemView(void* mem, size_t size) { | |
|
No newline at end of file | ||
|
562 | size = ceilToPage(size); | |
|
No newline at end of file | ||
|
563 | munmap(mem, size); | |
|
No newline at end of file | ||
|
564 | } | |
|
No newline at end of file | ||
|
565 | ||
|
No newline at end of file | ||
|
566 | //map a physical address into our virtual address space. memfd is the file descriptor for /dev/mem | |
|
No newline at end of file | ||
|
567 | volatile uint32_t* mapPeripheral(int memfd, int addr) { | |
|
No newline at end of file | ||
|
568 | ///dev/mem behaves as a file. We need to map that file into memory: | |
|
No newline at end of file | ||
|
569 | //NULL = virtual address of mapping is chosen by kernel. | |
|
No newline at end of file | ||
|
570 | //PAGE_SIZE = map 1 page. | |
|
No newline at end of file | ||
|
571 | //PROT_READ|PROT_WRITE means give us read and write priveliges to the memory | |
|
No newline at end of file | ||
|
572 | //MAP_SHARED means updates to the mapped memory should be written back to the file & shared with other processes | |
|
No newline at end of file | ||
|
573 | //memfd = /dev/mem file descriptor | |
|
No newline at end of file | ||
|
574 | //addr = offset in file to map | |
|
No newline at end of file | ||
|
575 | void *mapped = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, addr); | |
|
No newline at end of file | ||
|
576 | //now, *mapped = memory at physical address of addr. | |
|
No newline at end of file | ||
|
577 | if (mapped == MAP_FAILED) { | |
|
No newline at end of file | ||
|
578 | printf("failed to map memory (did you remember to run as root?)\n"); | |
|
No newline at end of file | ||
|
579 | exit(1); | |
|
No newline at end of file | ||
|
580 | } else { | |
|
No newline at end of file | ||
|
581 | printf("mapped: %p\n", mapped); | |
|
No newline at end of file | ||
|
582 | } | |
|
No newline at end of file | ||
|
583 | return (volatile uint32_t*)mapped; | |
|
No newline at end of file | ||
|
584 | } | |
|
No newline at end of file | ||
|
585 | ||
|
No newline at end of file | ||
|
586 | ||
|
No newline at end of file | ||
|
587 | void cleanup() { | |
|
No newline at end of file | ||
|
588 | printf("Cleanup\n"); | |
|
No newline at end of file | ||
|
589 | //disable DMA. Otherwise, it will continue to run in the background, potentially overwriting future user data. | |
|
No newline at end of file | ||
|
590 | if(dmaHeader) { | |
|
No newline at end of file | ||
|
591 | writeBitmasked(&dmaHeader->CS, DMA_CS_ACTIVE, 0); | |
|
No newline at end of file | ||
|
592 | usleep(100); | |
|
No newline at end of file | ||
|
593 | writeBitmasked(&dmaHeader->CS, DMA_CS_RESET, DMA_CS_RESET); | |
|
No newline at end of file | ||
|
594 | } | |
|
No newline at end of file | ||
|
595 | //could also disable PWM, but that's not imperative. | |
|
No newline at end of file | ||
|
596 | } | |
|
No newline at end of file | ||
|
597 | ||
|
No newline at end of file | ||
|
598 | void cleanupAndExit(int sig) { | |
|
No newline at end of file | ||
|
599 | cleanup(); | |
|
No newline at end of file | ||
|
600 | printf("Exiting with error; caught signal: %i\n", sig); | |
|
No newline at end of file | ||
|
601 | exit(1); | |
|
No newline at end of file | ||
|
602 | } | |
|
No newline at end of file | ||
|
603 | ||
|
No newline at end of file | ||
|
604 | void sleepUntilMicros(uint64_t micros, volatile uint32_t* timerBaseMem) { | |
|
No newline at end of file | ||
|
605 | //Note: cannot use clock_nanosleep with an absolute time, as the process clock may differ from the RPi clock. | |
|
No newline at end of file | ||
|
606 | //this function doesn't need to be super precise, so we can tolerate interrupts. | |
|
No newline at end of file | ||
|
607 | //Therefore, we can use a relative sleep: | |
|
No newline at end of file | ||
|
608 | uint64_t cur = readSysTime(timerBaseMem); | |
|
No newline at end of file | ||
|
609 | if (micros > cur) { //avoid overflow caused by unsigned arithmetic | |
|
No newline at end of file | ||
|
610 | uint64_t dur = micros - cur; | |
|
No newline at end of file | ||
|
611 | //usleep(dur); //nope, causes problems! | |
|
No newline at end of file | ||
|
612 | struct timespec t; | |
|
No newline at end of file | ||
|
613 | t.tv_sec = dur/1000000; | |
|
No newline at end of file | ||
|
614 | t.tv_nsec = (dur - t.tv_sec*1000000)*1000; | |
|
No newline at end of file | ||
|
615 | nanosleep(&t, NULL); | |
|
No newline at end of file | ||
|
616 | } | |
|
No newline at end of file | ||
|
617 | } | |
|
No newline at end of file | ||
|
618 | ||
|
No newline at end of file | ||
|
619 | ||
|
No newline at end of file | ||
|
620 | //int64_t _lastTimeAtFrame0; | |
|
No newline at end of file | ||
|
621 | ||
|
No newline at end of file | ||
|
622 | void queue(int pin, int mode, uint64_t micros, struct GpioBufferFrame* srcArray, volatile uint32_t* timerBaseMem, struct DmaChannelHeader* dmaHeader) { | |
|
No newline at end of file | ||
|
623 | //This function takes a pin, a mode (0=off, 1=on) and a time. It then manipulates the GpioBufferFrame array in order to ensure that the pin switches to the desired level at the desired time. It will sleep if necessary. | |
|
No newline at end of file | ||
|
624 | //Sleep until we are on the right iteration of the circular buffer (otherwise we cannot queue the command) | |
|
No newline at end of file | ||
|
625 | uint64_t callTime = readSysTime(timerBaseMem); //only used for debugging | |
|
No newline at end of file | ||
|
626 | uint64_t desiredTime = micros - FRAME_TO_USEC(SOURCE_BUFFER_FRAMES); | |
|
No newline at end of file | ||
|
627 | sleepUntilMicros(desiredTime, timerBaseMem); | |
|
No newline at end of file | ||
|
628 | uint64_t awakeTime = readSysTime(timerBaseMem); //only used for debugging | |
|
No newline at end of file | ||
|
629 | ||
|
No newline at end of file | ||
|
630 | //get the current source index at the current time: | |
|
No newline at end of file | ||
|
631 | //must ensure we aren't interrupted during this calculation, hence the two timers instead of 1. | |
|
No newline at end of file | ||
|
632 | //Note: getting the curTime & srcIdx don't have to be done for every call to queue - it could be done eg just once per buffer. | |
|
No newline at end of file | ||
|
633 | // It should be calculated regularly though, to counter clock drift & PWM FIFO underflows | |
|
No newline at end of file | ||
|
634 | // It is done in this function only for simplicity | |
|
No newline at end of file | ||
|
635 | int srcIdx; | |
|
No newline at end of file | ||
|
636 | uint64_t curTime1, curTime2; | |
|
No newline at end of file | ||
|
637 | int tries=0; | |
|
No newline at end of file | ||
|
638 | do { | |
|
No newline at end of file | ||
|
639 | curTime1 = readSysTime(timerBaseMem); | |
|
No newline at end of file | ||
|
640 | srcIdx = dmaHeader->STRIDE; //the source index is stored in the otherwise-unused STRIDE register, for efficiency | |
|
No newline at end of file | ||
|
641 | curTime2 = readSysTime(timerBaseMem); | |
|
No newline at end of file | ||
|
642 | ++tries; | |
|
No newline at end of file | ||
|
643 | } while (curTime2-curTime1 > 1 || (srcIdx & DMA_CB_TXFR_YLENGTH_MASK)); //allow 1 uS variability. | |
|
No newline at end of file | ||
|
644 | //Uncomment the following lines and the above declaration of _lastTimeAtFrame0 to log jitter information: | |
|
No newline at end of file | ||
|
645 | //int64_t curTimeAtFrame0 = curTime2 - FRAME_TO_USEC(srcIdx); | |
|
No newline at end of file | ||
|
646 | //printf("Timing diff: %lli\n", (curTimeAtFrame0-_lastTimeAtFrame0)%FRAME_TO_USEC(SOURCE_BUFFER_FRAMES)); | |
|
No newline at end of file | ||
|
647 | //_lastTimeAtFrame0 = curTimeAtFrame0; | |
|
No newline at end of file | ||
|
648 | //if timing diff is positive, then then curTimeAtFrame0 > _lastTimeAtFrame0 | |
|
No newline at end of file | ||
|
649 | //curTime2 - srcIdx2 > curTime1 - srcIdx1 | |
|
No newline at end of file | ||
|
650 | //curTime2 - curTime2 > srcIdx2 - srcIdx1 | |
|
No newline at end of file | ||
|
651 | //more uS have elapsed than frames; DMA cannot keep up | |
|
No newline at end of file | ||
|
652 | ||
|
No newline at end of file | ||
|
653 | //calculate the frame# at which to place the event: | |
|
No newline at end of file | ||
|
654 | int usecFromNow = micros - curTime2; | |
|
No newline at end of file | ||
|
655 | int framesFromNow = USEC_TO_FRAME(usecFromNow); | |
|
No newline at end of file | ||
|
656 | if (framesFromNow < 10) { //Not safe to schedule less than ~10uS into the future (note: should be operating on usecFromNow, not framesFromNow) | |
|
No newline at end of file | ||
|
657 | printf("Warning: behind schedule: %i (%i uSec) (tries: %i) (sleep %llu -> %llu (wanted %llu))\n", framesFromNow, usecFromNow, tries, callTime, awakeTime, desiredTime); | |
|
No newline at end of file | ||
|
658 | framesFromNow = 10; | |
|
No newline at end of file | ||
|
659 | } | |
|
No newline at end of file | ||
|
660 | int newIdx = (srcIdx + framesFromNow)%SOURCE_BUFFER_FRAMES; | |
|
No newline at end of file | ||
|
661 | //Now queue the command: | |
|
No newline at end of file | ||
|
662 | if (mode == 0) { //turn output off | |
|
No newline at end of file | ||
|
663 | srcArray[newIdx].gpclr[pin>31] |= 1 << (pin%32); | |
|
No newline at end of file | ||
|
664 | } else { //turn output on | |
|
No newline at end of file | ||
|
665 | srcArray[newIdx].gpset[pin>31] |= 1 << (pin%32); | |
|
No newline at end of file | ||
|
666 | } | |
|
No newline at end of file | ||
|
667 | } | |
|
No newline at end of file | ||
|
668 | ||
|
No newline at end of file | ||
|
669 | int main() { | |
|
No newline at end of file | ||
|
670 | volatile uint32_t *gpioBaseMem, *dmaBaseMem, *pwmBaseMem, *timerBaseMem, *clockBaseMem; | |
|
No newline at end of file | ||
|
671 | //emergency clean-up: | |
|
No newline at end of file | ||
|
672 | for (int i = 0; i < 64; i++) { //catch all signals (like ctrl+c, ctrl+z, ...) to ensure DMA is disabled | |
|
No newline at end of file | ||
|
673 | struct sigaction sa; | |
|
No newline at end of file | ||
|
674 | memset(&sa, 0, sizeof(sa)); | |
|
No newline at end of file | ||
|
675 | sa.sa_handler = cleanupAndExit; | |
|
No newline at end of file | ||
|
676 | sigaction(i, &sa, NULL); | |
|
No newline at end of file | ||
|
677 | } | |
|
No newline at end of file | ||
|
678 | setSchedPriority(SCHED_PRIORITY); | |
|
No newline at end of file | ||
|
679 | //First, open the linux device, /dev/mem | |
|
No newline at end of file | ||
|
680 | //dev/mem provides access to the physical memory of the entire processor+ram | |
|
No newline at end of file | ||
|
681 | //This is needed because Linux uses virtual memory, thus the process's memory at 0x00000000 will NOT have the same contents as the physical memory at 0x00000000 | |
|
No newline at end of file | ||
|
682 | int memfd = open("/dev/mem", O_RDWR | O_SYNC); | |
|
No newline at end of file | ||
|
683 | if (memfd < 0) { | |
|
No newline at end of file | ||
|
684 | printf("Failed to open /dev/mem (did you remember to run as root?)\n"); | |
|
No newline at end of file | ||
|
685 | exit(1); | |
|
No newline at end of file | ||
|
686 | } | |
|
No newline at end of file | ||
|
687 | int pagemapfd = open("/proc/self/pagemap", O_RDONLY); | |
|
No newline at end of file | ||
|
688 | //now map /dev/mem into memory, but only map specific peripheral sections: | |
|
No newline at end of file | ||
|
689 | gpioBaseMem = mapPeripheral(memfd, GPIO_BASE); | |
|
No newline at end of file | ||
|
690 | dmaBaseMem = mapPeripheral(memfd, DMA_BASE); | |
|
No newline at end of file | ||
|
691 | pwmBaseMem = mapPeripheral(memfd, PWM_BASE); | |
|
No newline at end of file | ||
|
692 | timerBaseMem = mapPeripheral(memfd, TIMER_BASE); | |
|
No newline at end of file | ||
|
693 | clockBaseMem = mapPeripheral(memfd, CLOCK_BASE); | |
|
No newline at end of file | ||
|
694 | ||
|
No newline at end of file | ||
|
695 | int outPin = 10; | |
|
No newline at end of file | ||
|
696 | //now set our pin as an output: | |
|
No newline at end of file | ||
|
697 | volatile uint32_t *fselAddr = (volatile uint32_t*)(gpioBaseMem + GPFSEL0/4 + outPin/10); | |
|
No newline at end of file | ||
|
698 | writeBitmasked(fselAddr, 0x7 << (3*(outPin%10)), 0x1 << (3*(outPin%10))); | |
|
No newline at end of file | ||
|
699 | //Note: PWM pacing still works, even with no physical outputs, so we don't need to set gpio pin 18 to its alternate function. | |
|
No newline at end of file | ||
|
700 | ||
|
No newline at end of file | ||
|
701 | //Often need to copy zeros with DMA. This array can be the source. Needs to all lie on one page | |
|
No newline at end of file | ||
|
702 | void *zerosPageCached = makeLockedMem(PAGE_SIZE); | |
|
No newline at end of file | ||
|
703 | void *zerosPage = makeUncachedMemView(zerosPageCached, PAGE_SIZE, memfd, pagemapfd); | |
|
No newline at end of file | ||
|
704 | ||
|
No newline at end of file | ||
|
705 | //configure DMA... | |
|
No newline at end of file | ||
|
706 | //First, allocate memory for the source: | |
|
No newline at end of file | ||
|
707 | size_t numSrcBlocks = SOURCE_BUFFER_FRAMES; //We want apx 1M blocks/sec. | |
|
No newline at end of file | ||
|
708 | size_t srcPageBytes = numSrcBlocks*sizeof(struct GpioBufferFrame); | |
|
No newline at end of file | ||
|
709 | void *virtSrcPageCached = makeLockedMem(srcPageBytes); | |
|
No newline at end of file | ||
|
710 | void *virtSrcPage = makeUncachedMemView(virtSrcPageCached, srcPageBytes, memfd, pagemapfd); | |
|
No newline at end of file | ||
|
711 | printf("mappedPhysSrcPage: %p\n", virtToPhys(virtSrcPage, pagemapfd)); | |
|
No newline at end of file | ||
|
712 | ||
|
No newline at end of file | ||
|
713 | //cast virtSrcPage to a GpioBufferFrame array: | |
|
No newline at end of file | ||
|
714 | struct GpioBufferFrame *srcArray = (struct GpioBufferFrame*)virtSrcPage; //Note: calling virtToPhys on srcArray will return NULL. Use srcArrayCached for that. | |
|
No newline at end of file | ||
|
715 | struct GpioBufferFrame *srcArrayCached = (struct GpioBufferFrame*)virtSrcPageCached; | |
|
No newline at end of file | ||
|
716 | //srcArray[0].gpset[0] = (1 << outPin); //set pin ON | |
|
No newline at end of file | ||
|
717 | //srcArray[numSrcBlocks/2].gpclr[0] = (1 << outPin); //set pin OFF; | |
|
No newline at end of file | ||
|
718 | ||
|
No newline at end of file | ||
|
719 | //configure PWM clock: | |
|
No newline at end of file | ||
|
720 | *(clockBaseMem + CM_PWMCTL/4) = CM_PWMCTL_PASSWD | ((*(clockBaseMem + CM_PWMCTL/4))&(~CM_PWMCTL_ENAB)); //disable clock | |
|
No newline at end of file | ||
|
721 | do {} while (*(clockBaseMem + CM_PWMCTL/4) & CM_PWMCTL_BUSY); //wait for clock to deactivate | |
|
No newline at end of file | ||
|
722 | *(clockBaseMem + CM_PWMDIV/4) = CM_PWMDIV_PASSWD | CM_PWMDIV_DIVI(CLOCK_DIV); //configure clock divider (running at 500MHz undivided) | |
|
No newline at end of file | ||
|
723 | *(clockBaseMem + CM_PWMCTL/4) = CM_PWMCTL_PASSWD | CM_PWMCTL_SRC_PLLD; //source 500MHz base clock, no MASH. | |
|
No newline at end of file | ||
|
724 | *(clockBaseMem + CM_PWMCTL/4) = CM_PWMCTL_PASSWD | CM_PWMCTL_SRC_PLLD | CM_PWMCTL_ENAB; //enable clock | |
|
No newline at end of file | ||
|
725 | do {} while (*(clockBaseMem + CM_PWMCTL/4) & CM_PWMCTL_BUSY == 0); //wait for clock to activate | |
|
No newline at end of file | ||
|
726 | ||
|
No newline at end of file | ||
|
727 | //configure rest of PWM: | |
|
No newline at end of file | ||
|
728 | struct PwmHeader *pwmHeader = (struct PwmHeader*)(pwmBaseMem); | |
|
No newline at end of file | ||
|
729 | ||
|
No newline at end of file | ||
|
730 | pwmHeader->DMAC = 0; //disable DMA | |
|
No newline at end of file | ||
|
731 | pwmHeader->CTL |= PWM_CTL_CLRFIFO; //clear pwm | |
|
No newline at end of file | ||
|
732 | usleep(100); | |
|
No newline at end of file | ||
|
733 | ||
|
No newline at end of file | ||
|
734 | pwmHeader->STA = PWM_STA_ERRS; //clear PWM errors | |
|
No newline at end of file | ||
|
735 | usleep(100); | |
|
No newline at end of file | ||
|
736 | ||
|
No newline at end of file | ||
|
737 | pwmHeader->DMAC = PWM_DMAC_EN | PWM_DMAC_DREQ(PWM_FIFO_SIZE) | PWM_DMAC_PANIC(PWM_FIFO_SIZE); //DREQ is activated at queue < PWM_FIFO_SIZE | |
|
No newline at end of file | ||
|
738 | pwmHeader->RNG1 = BITS_PER_CLOCK; //used only for timing purposes; #writes to PWM FIFO/sec = PWM CLOCK / RNG1 | |
|
No newline at end of file | ||
|
739 | pwmHeader->CTL = PWM_CTL_REPEATEMPTY1 | PWM_CTL_ENABLE1 | PWM_CTL_USEFIFO1; | |
|
No newline at end of file | ||
|
740 | ||
|
No newline at end of file | ||
|
741 | //allocate memory for the control blocks | |
|
No newline at end of file | ||
|
742 | size_t cbPageBytes = numSrcBlocks * sizeof(struct DmaControlBlock) * 3; //3 cbs for each source block | |
|
No newline at end of file | ||
|
743 | void *virtCbPageCached = makeLockedMem(cbPageBytes); | |
|
No newline at end of file | ||
|
744 | void *virtCbPage = makeUncachedMemView(virtCbPageCached, cbPageBytes, memfd, pagemapfd); | |
|
No newline at end of file | ||
|
745 | //fill the control blocks: | |
|
No newline at end of file | ||
|
746 | struct DmaControlBlock *cbArrCached = (struct DmaControlBlock*)virtCbPageCached; | |
|
No newline at end of file | ||
|
747 | struct DmaControlBlock *cbArr = (struct DmaControlBlock*)virtCbPage; | |
|
No newline at end of file | ||
|
748 | printf("#dma blocks: %i, #src blocks: %i\n", numSrcBlocks*3, numSrcBlocks); | |
|
No newline at end of file | ||
|
749 | for (int i=0; i<numSrcBlocks*3; i += 3) { | |
|
No newline at end of file | ||
|
750 | //pace DMA through PWM | |
|
No newline at end of file | ||
|
751 | cbArr[i].TI = DMA_CB_TI_PERMAP_PWM | DMA_CB_TI_DEST_DREQ | DMA_CB_TI_NO_WIDE_BURSTS | DMA_CB_TI_TDMODE; | |
|
No newline at end of file | ||
|
752 | cbArr[i].SOURCE_AD = virtToUncachedPhys(srcArrayCached + i/3, pagemapfd); //The data written doesn't matter, but using the GPIO source will hopefully bring it into L2 for more deterministic timing of the next control block. | |
|
No newline at end of file | ||
|
753 | cbArr[i].DEST_AD = PWM_BASE_BUS + PWM_FIF1; //write to the FIFO | |
|
No newline at end of file | ||
|
754 | cbArr[i].TXFR_LEN = DMA_CB_TXFR_LEN_YLENGTH(1) | DMA_CB_TXFR_LEN_XLENGTH(4); | |
|
No newline at end of file | ||
|
755 | cbArr[i].STRIDE = i/3; | |
|
No newline at end of file | ||
|
756 | cbArr[i].NEXTCONBK = virtToUncachedPhys(cbArrCached+i+1, pagemapfd); //have to use the cached version because the uncached version isn't listed in pagemap(?) | |
|
No newline at end of file | ||
|
757 | //copy buffer to GPIOs | |
|
No newline at end of file | ||
|
758 | cbArr[i+1].TI = DMA_CB_TI_SRC_INC | DMA_CB_TI_DEST_INC | DMA_CB_TI_NO_WIDE_BURSTS | DMA_CB_TI_TDMODE; | |
|
No newline at end of file | ||
|
759 | cbArr[i+1].SOURCE_AD = virtToUncachedPhys(srcArrayCached + i/3, pagemapfd); | |
|
No newline at end of file | ||
|
760 | cbArr[i+1].DEST_AD = GPIO_BASE_BUS + GPSET0; | |
|
No newline at end of file | ||
|
761 | cbArr[i+1].TXFR_LEN = DMA_CB_TXFR_LEN_YLENGTH(2) | DMA_CB_TXFR_LEN_XLENGTH(8); | |
|
No newline at end of file | ||
|
762 | cbArr[i+1].STRIDE = DMA_CB_STRIDE_D_STRIDE(4) | DMA_CB_STRIDE_S_STRIDE(0); | |
|
No newline at end of file | ||
|
763 | cbArr[i+1].NEXTCONBK = virtToUncachedPhys(cbArrCached+i+2, pagemapfd); | |
|
No newline at end of file | ||
|
764 | //clear buffer (TODO: investigate using a 4-word copy ("burst") ) | |
|
No newline at end of file | ||
|
765 | cbArr[i+2].TI = DMA_CB_TI_DEST_INC | DMA_CB_TI_NO_WIDE_BURSTS | DMA_CB_TI_TDMODE; | |
|
No newline at end of file | ||
|
766 | cbArr[i+2].SOURCE_AD = virtToUncachedPhys(zerosPageCached, pagemapfd); | |
|
No newline at end of file | ||
|
767 | cbArr[i+2].DEST_AD = virtToUncachedPhys(srcArrayCached + i/3, pagemapfd); | |
|
No newline at end of file | ||
|
768 | cbArr[i+2].TXFR_LEN = DMA_CB_TXFR_LEN_YLENGTH(1) | DMA_CB_TXFR_LEN_XLENGTH(sizeof(struct GpioBufferFrame)); | |
|
No newline at end of file | ||
|
769 | cbArr[i+2].STRIDE = i/3; //might be better to use the NEXT index | |
|
No newline at end of file | ||
|
770 | int nextIdx = i+3 < numSrcBlocks*3 ? i+3 : 0; //last block should loop back to the first block | |
|
No newline at end of file | ||
|
771 | cbArr[i+2].NEXTCONBK = virtToUncachedPhys(cbArrCached + nextIdx, pagemapfd); //(uint32_t)physCbPage + ((void*)&cbArr[(i+2)%maxIdx] - virtCbPage); | |
|
No newline at end of file | ||
|
772 | } | |
|
No newline at end of file | ||
|
773 | for (int i=0; i<cbPageBytes; i+=PAGE_SIZE) { | |
|
No newline at end of file | ||
|
774 | printf("virt cb[%i] -> phys: 0x%08x (0x%08x)\n", i, virtToPhys(i+(void*)cbArrCached, pagemapfd), virtToUncachedPhys(i+(void*)cbArrCached, pagemapfd)); | |
|
No newline at end of file | ||
|
775 | } | |
|
No newline at end of file | ||
|
776 | //source: http://virtualfloppy.blogspot.com/2014/01/dma-support-at-last.html | |
|
No newline at end of file | ||
|
777 | //cat /sys/module/dma/parameters/dmachans gives a bitmask of DMA channels that are not used by GPU. Results: ch 1, 3, 6, 7 are reserved. | |
|
No newline at end of file | ||
|
778 | //dmesg | grep "DMA"; results: Ch 2 is used by SDHC host | |
|
No newline at end of file | ||
|
779 | //ch 0 is known to be used for graphics acceleration | |
|
No newline at end of file | ||
|
780 | //Thus, applications can use ch 4, 5, or the LITE channels @ 8 and beyond. | |
|
No newline at end of file | ||
|
781 | //If using LITE channels, then we can't use the STRIDE feature, so that narrows it down to ch 4 and ch 5. | |
|
No newline at end of file | ||
|
782 | int dmaCh = 5; | |
|
No newline at end of file | ||
|
783 | //enable DMA channel (it's probably already enabled, but we want to be sure): | |
|
No newline at end of file | ||
|
784 | writeBitmasked(dmaBaseMem + DMAENABLE, 1 << dmaCh, 1 << dmaCh); | |
|
No newline at end of file | ||
|
785 | ||
|
No newline at end of file | ||
|
786 | //configure the DMA header to point to our control block: | |
|
No newline at end of file | ||
|
787 | dmaHeader = (struct DmaChannelHeader*)(dmaBaseMem + DMACH(dmaCh)/4); //must divide by 4, as dmaBaseMem is uint32_t* | |
|
No newline at end of file | ||
|
788 | printf("Previous DMA header:\n"); | |
|
No newline at end of file | ||
|
789 | logDmaChannelHeader(dmaHeader); | |
|
No newline at end of file | ||
|
790 | //abort any previous DMA: | |
|
No newline at end of file | ||
|
791 | //dmaHeader->NEXTCONBK = 0; //NEXTCONBK is read-only. | |
|
No newline at end of file | ||
|
792 | dmaHeader->CS |= DMA_CS_ABORT; //make sure to disable dma first. | |
|
No newline at end of file | ||
|
793 | usleep(100); //give time for the abort command to be handled. | |
|
No newline at end of file | ||
|
794 | ||
|
No newline at end of file | ||
|
795 | dmaHeader->CS = DMA_CS_RESET; | |
|
No newline at end of file | ||
|
796 | usleep(100); | |
|
No newline at end of file | ||
|
797 | ||
|
No newline at end of file | ||
|
798 | writeBitmasked(&dmaHeader->CS, DMA_CS_END, DMA_CS_END); //clear the end flag | |
|
No newline at end of file | ||
|
799 | dmaHeader->DEBUG = DMA_DEBUG_READ_ERROR | DMA_DEBUG_FIFO_ERROR | DMA_DEBUG_READ_LAST_NOT_SET_ERROR; // clear debug error flags | |
|
No newline at end of file | ||
|
800 | uint32_t firstAddr = virtToUncachedPhys(cbArrCached, pagemapfd); | |
|
No newline at end of file | ||
|
801 | printf("starting DMA @ CONBLK_AD=0x%08x\n", firstAddr); | |
|
No newline at end of file | ||
|
802 | dmaHeader->CONBLK_AD = firstAddr; //(uint32_t)physCbPage + ((void*)cbArr - virtCbPage); //we have to point it to the PHYSICAL address of the control block (cb1) | |
|
No newline at end of file | ||
|
803 | dmaHeader->CS = DMA_CS_PRIORITY(7) | DMA_CS_PANIC_PRIORITY(7) | DMA_CS_DISDEBUG; //high priority (max is 7) | |
|
No newline at end of file | ||
|
804 | dmaHeader->CS = DMA_CS_PRIORITY(7) | DMA_CS_PANIC_PRIORITY(7) | DMA_CS_DISDEBUG | DMA_CS_ACTIVE; //activate DMA. | |
|
No newline at end of file | ||
|
805 | ||
|
No newline at end of file | ||
|
806 | uint64_t startTime = readSysTime(timerBaseMem); | |
|
No newline at end of file | ||
|
807 | printf("DMA Active @ %llu uSec\n", startTime); | |
|
No newline at end of file | ||
|
808 | /*while (dmaHeader->CS & DMA_CS_ACTIVE) { | |
|
No newline at end of file | ||
|
809 | logDmaChannelHeader(dmaHeader); | |
|
No newline at end of file | ||
|
810 | } //wait for DMA transfer to complete.*/ | |
|
No newline at end of file | ||
|
811 | for (int i=1; ; ++i) { //generate the output sequence: | |
|
No newline at end of file | ||
|
812 | //logDmaChannelHeader(dmaHeader); | |
|
No newline at end of file | ||
|
813 | //this just toggles outPin every few us: | |
|
No newline at end of file | ||
|
814 | queue(outPin, i%2, startTime + 1000*i, srcArray, timerBaseMem, dmaHeader); | |
|
No newline at end of file | ||
|
815 | } | |
|
No newline at end of file | ||
|
816 | //Exit routine: | |
|
No newline at end of file | ||
|
817 | cleanup(); | |
|
No newline at end of file | ||
|
818 | printf("Exiting cleanly:\n"); | |
|
No newline at end of file | ||
|
819 | freeUncachedMemView(virtCbPage, cbPageBytes); | |
|
No newline at end of file | ||
|
820 | freeLockedMem(virtCbPageCached, cbPageBytes); | |
|
No newline at end of file | ||
|
821 | freeUncachedMemView(virtSrcPage, srcPageBytes); | |
|
No newline at end of file | ||
|
822 | freeLockedMem(virtSrcPageCached, srcPageBytes); | |
|
No newline at end of file | ||
|
823 | freeUncachedMemView(zerosPage, PAGE_SIZE); | |
|
No newline at end of file | ||
|
824 | freeLockedMem(zerosPageCached, PAGE_SIZE); | |
|
No newline at end of file | ||
|
825 | close(pagemapfd); | |
|
No newline at end of file | ||
|
826 | close(memfd); | |
|
No newline at end of file | ||
|
827 | return 0; | |
|
No newline at end of file | ||
|
828 | } | |
|
No newline at end of file | ||
|
829 | No newline at end of file |
General Comments 0
You need to be logged in to leave comments.
Login now