-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME
354 lines (278 loc) · 15.7 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
PRUSS-EndToEnd-PWM Version 0.60
(C) Copyright 2016 by Christopher C. Mills:
This program is distributed under the terms of the GNU General Public
License v3 (GPLv3). A copy of this lisence is included with this archive.
THIS PROGRAM HAS VERY LIMITED TESTING - USE AT YOUR OWN RISK.
INTRODUCTION
--------------------------------------------------------------------------------
This is a demonstration program of the PRU Subsystem (PRUSS) on the BeagleBone
Black Rev C (BBB). It is inspired by an interest in the BBB, the PRUSS, and in
particular by Derek Molloy's excellent introduction to the BBB: "Exploring
BeagleBone." Hopefully, this project is a useful supplement to the examples
found in this book. As such a supplement, it assumes the following of the user:
1) Introductory competence with coding and manipulating the BBB. This could
possibly be through the excellent book "Exploring BeagleBone" by Derek
Molloy (as was the case of myself) and its accompanying web site.
2) Experience compiling and loading device tree overlays.
3) Competence in the C language.
4) Comfort with learning and developing in the PRUSS assembly language
using the PASM assembler.
5) Some Linux experience (the more the better, but the Molloy intro is
adequate).
6) An introductory understanding of the uio_pruss kernel module, including
how to access its external memory buffer (DDR) parameters via the /sys
filesystem. (See Molloy and his book's web page for his chapter 13.)
7) Access to a PWM source device that can produce a 3.3V pulse. (More on this
below)
8) An interest in understanding and coding the PRUSS on the BBB.
USEFUL RESOURCES
--------------------------------------------------------------------------------
- "Exploring BeagleBone" by Derek Molloy (and its accompanying web site)
- Texas Instruments "AM335X Sitara Processors" (Rev. L)
- Texas Instruments "AM335X PRU-ICSS Reference Guide" (Rev. A)
- The am335x-pru-package on Github (source code and docs a great reference)
- prudebug-bbb on Github (A PRUSS debugger authored by Steven Anderson and
improved by myself, Christopher C. Mills-- improvements ongoing)
DESCRIPTION
--------------------------------------------------------------------------------
This is a demonstration of the PRUSS operating in the framework of an end-to-end
application. The intent is to go one step beyond a simple demonstation of the
PRUSS by using a TCP/IP client to download data via a server running on the
BeagleBone Black that also manages the PRUSS. It intentionally doesn't attempt
to do anything too fancy so as to remain reasonably easy to understand. The
PRUSS captures data from an input pin attached to a pulse width modulator (PWM)
source. A sample by the PRUSS consists of a pair of 32 bit words: one holding a
high count, and the other holding a low count of a single pulse.
IMPORTANT: To run the program, it is necessary to have access to a PWM
generator of some sort, configured for a BBB *safe* input voltage
(3.3V). There is a function generator kit called the "FG085 miniDDS
Function Generator" available from multiple sources (needs to be
built and has a maximum frequency for PWM of around 10KHz). However,
another BBB, a microcontroller, or a user-built circuit could
provide the source. These latter approaches could have the added
advantage of running at a much higher frequency (10MHz or greater).
This PWM source is assumed to exist for this code and further
details about configuring this source is beyond the scope of the
information in this demo.
There are a couple of useful things demonstrated in this project:
- PRU-to-PRU interrupts
- Use of the PRUSS Scratchpad register bank on the broadside bus to rapidly
exchange data between PRUs, circumventing the need to use slow Shared
Memory.
The use of PRU-to-PRU interrupts and the scratchpad are not documented in
Molloy. Both of these may be useful in extracting every ounce of speed out of
the PRUSS. This project is a good starting point to test PRUSS throughput.
Device Tree Overlay:
The device tree overlay file, PWM-PRU-ETE.dts, used on this project is
derived from the one Molloy uses in the Chapter 13 ADC example (on the
web). It has two added outputs from that example; one was added to PRU 1
for debugging its operation with a scope. However, only the one input on
PRU 0 is used in this project. The other outputs were left available to
be used for future expansion or for debugging with a scope.
Also, note that HDMI needs to be disabled for this example. See Molloy
for details on how to go about doing this. Check out his web site for
updated details on this topic.
In addition to a Makefile, a PASM header file, and a device tree overlay and
its build script, this demonstration consists primarily of four modules:
pruss-ete.c (server and PRUSS manager)
client-ete.c (client compilable on any system including the BBB)
data-pru0.p (PRU 0 code for PWM sample capturing)
ddr-pru1.p (PRU 1 code for dumping samples to DDR)
There is also included a Windows client written under the .NET framework in C#.
This can be used in place of the client above:
win-client-ete.cs (requires a platform running .NET)
The DDR buffer is setup by the uio_pruss kernel module. This module is loaded by
default upon BBB boot and this buffer (called External RAM by uio_pruss
nomenclature) should be of adequate size by default for this demo. Molloy
describes how to expand this on his Chapter 13 web page if that is desired.
The following describes the role in a bit more detail of each of the above
four modules:
pruss-ete:
1) Determines DDR buffer size and calculates sample count based on this.
2) Determines DDR buffer physical address.
3) Configures the PRUSS.
4) Writes the DDR buffer parameters into PRUSS Shared Memory.
5) Starts the PRUSS (PRU 1, then PRU 0).
6) Waits for PRUSS sampling to complete.
PRU 1:
1) Waits for an interrupt from PRU 0 signalling that a
pulse-width sample is ready in the scratchpad.
2) When interrupt is received, transfers scratchpad
data (the sample) to its register file.
3) Writes the sample from its registers to the next location in the DDR
buffer.
4) Decrements the sample count and halts if 0, after triggering a host
interrupt signalling completion.
5) Otherwise, it goes back to (1) above and repeats.
PRU 0:
1) Syncs itself to the first high-going pulse.
2) Counts from 0 (count tick duration undetermined) until pulse goes
low.
3) Counts from 0 until pulse goes high.
4) Passes counts into scratchpad bank.
5) Triggers interrupt to PRU 1.
6) Decrements the sample count and halts if 0.
pruss-ete (continues):
7) Receives interrupt from PRU 1 signaling completion.
8) Shuts down the PRUSS.
9) Sets itself up as a TCP server and waits for a connection. The
port was passed on the command line.
10) Immediately upon connection established by the client (client-ete) it
sends the DDR buffer size to the client.
11) Waits for a "GO" string from the client.
12) Upon receipt of the "GO" string, dumps the DDR buffer to the
TCP stream.
13) It then shuts down.
client-ete or win-client-ete:
1) Connects to the server: Its port was passed on its command line.
2) Immediately reads the stream for the sample data size.
3) Upon receipt of the size, sends a "GO" string to the server.
4) Reads the resulting stream of data from the server-- formatting it
and outputting it to a file.
5) It then shuts down.
Things to note about this operation:
1) PRU 0 counts its samples by counting pairs of high/low transitions on its
input pin. No input, no count and so the PRUSS operation never completes.
2) Likewise, PRU 1 decrements its sample count by counting interrupts from
PRU 0, so no input to PRU 0 means it will hang also, never interrupting
the pruss-ete module, which will then also hang.
3) The sample count used is derived from how big the DDR buffer is: the
bigger the buffer, the greater the sample count:
sample count = buffer size/8
4) Beware: how long it takes to complete not only depends on the number of
samples but the frequency of the PWM. If a slow frequency PWM is used the
sampling could take a long time.
5) The fastest PWM frequency is undetermined as of this writing, but in
theory this code could support a pretty high frequency PWM (say 10Mhz or
more). This module is designed to test this throughput. For initial
testing, I used a 38 micro secs (~26KHz) pulse width. (As of this
writing a test to determine highest throughput of this code is planned,
but has not yet been performed.)
6) A quirk of operation is that the client should *not* be started until
the server has finished the PRUSS operation and has configured itself as
a TCP server waiting on a port. The reason for this annoyance was to
keep the handshaking between client and server to a minimum to keep
the code reasonably easy to follow.
Practical Use:
Although not intended as such by any stretch of the imagination, this code
could actually be useful to gather stats on a PWM device. This could be
useful, for instance, to determine the severity of jitter. You could:
1) Run the server on a PWM source.
2) Run the client on a Windows PC and connect to the server to dump the data.
3) Analyze the data in a spreadsheet for variance or graph the deviations
against time.
BUILD
--------------------------------------------------------------------------------
1) Compile and install the device tree overlay supplied (PWM-PRU-ETE) with the
following command in the project directory:
./build-pwm-dts
This will result in the file
PWM-PRU-ETE-00A0.dtbo
which can then be installed in the usual manner. Installation of this dto
as well as the unloading of any competing dtos is beyond the scope of
these instructions.
2) Be certain to test that this device tree overlay is installed and that the
pins are configured as expected. (See Molloy for further description)
3) Run:
make
in the project directory to create both the client and server executables.
Note: the client can be compiled on another system if desired. Its gcc
parameters can be determined from the Makefile.
The make will produce the following two executables:
pruss-ete (the server and PRUSS manager)
client-ete (the downloading client)
It will also produce the PRU binaries:
data-pru0.bin (PRU 0 PWM sampling code)
ddr-pru1.bin (PRU 1 DDR buffering code)
Note: This module must be linked to the prussdrv library which is installed
on the BBB via the am335x_pru_package. Because of this, no action
probably needs to be taken to ensure the project's Makefile runs. If
there is a problem, load the package via apt-get. This package is also
available for download on Github.
WINDOWS CLIENT BUILD
--------------------------------------------------------------------------------
If you prefer to run the client from a Windows PC, you can try out the C# .NET
Console Application provided. It has been compiled under Visual Studio 2010
Professional as well as Visual Studio Commumity 2015 using Target framework
3.5. or 4.5.
INSTALLATION
--------------------------------------------------------------------------------
Other than the device tree overlay described above, no install is required
USAGE
--------------------------------------------------------------------------------
Note: The server (pruss-ete) must be run with root privileges.
1) Safely configure a PWM source and connect it to P9.28 (double check the pin
configuration and source voltage if you care about your BBB!)
2) Run:
pruss-ete <port number>
where <port number> is any desired unused port (maybe arbitrarily 51717).
The server will print a series of informational and status messages.
3) Wait for the PRUSS work to complete and the TCP server to start. This will
be indicated by the message:
Starting the server...
4) When the server has indicated that it has started, start the client with:
client-ete <hostname or ip> <port number>
where the port number is the same as for the server. If using the Windows
client, it can be started similarly with:
win-client-ete <hostname or ip> <port number>
5) The client and server should quickly complete and shutdown, again, after
displaying a series of informational and status messages.
6) Check for the file
tcpcap.dat
in the client's startup folder.
TESTING
--------------------------------------------------------------------------------
Initial development was done using the FG085 miniDDS Function Generator. It was
run at a speed on the order of 10KHz.
The following is an account of a more robust test setup used to test the code
after development had been completed:
For the test set up a simple pulse generator, using a ChipKit MAX32
Microcontroller board and a mixture of C and assembly to exploit the high
speed I/O toggling capability of the Microchip PIC32MX795F512H (80MHz), was
used. This allowed generating pulses as short as 60 nanoSeconds. The limits of
the system were close to being tested.
The table below shows the results of capturing pulse trains using a variety of
values:
| | Sample
| (Duty Cyc) | Counts
Pulse Duration | (Frequency) |(in Hex)
---------------------------------------
| |
(-ve) 3960 nS | (33%) | 0000018C
(+ve) 1950 nS | (169 KHz) | 000000C5
| |
(-ve) 465 nS | (42%) | 0000002E
(+ve) 335 nS | (1.25 MHz) | 0000001E
| |
(-ve) 61.5 nS | (50%) | 00000006
(+ve) 61.5 nS | (8.1 MHz) | 00000003
DISCUSSION
--------------------------------------------------------------------------------
The aim of this project was to keep the code from being obscure, while
demonstrating a "complete" system involving the PRUSS that may have a hint of
being practical. It is probably possible to finetune the PRUSS code to be
faster or more accurate. For instance, the high counts have a systematic error
that reduces their counts (likely by a fixed amount) as a result of all the
testing overhead, and data transfer. The BeagleLogic project claims operating
speeds of up to 100MHz, 2 orders of magnitude faster than the above results.
Addressing these issues to improve performance is likely to complicate the code
in a manner that would make it less digestable. Consequently, such
optimizations were avoided on this project. Instead, the principle idea has
been to provide a starting point for investigating these kinds of
optimizations. It is up to the user to explore further efficiency
possibilities. Some of these may include:
-- Cycle counting blocks of code using the PRUSS resources supporting this.
(See the PRUSS documentation for use of the cycle and stall count
registers.)
-- Exploring alternative algorithms.
-- Using scratchpad PRU-to-PRU signalling rather than an interrupt to
combine signalling and data transfer in one step via the single cycle
broadside bus instructions (XIN, XOUT).
In addition, on the Linux/C side improvements in buffering could be achieved by
writing a custom kernel module which, among other things, could dramatically
improve buffer size. (Derek Molloy is in the process of completing a four part
series on the web for doing just this.)
CONTRIBUTORS
--------------------------------------------------------------------------------
Christopher C. Mills ---- Linux C and PRUSS source modules; design
Ram Radhakrishnan ------- PWM circuit, Windows C client; design