1 Memory Organisation {#ChaMemory}
4 libpruio uses three blocks of memory to organize its data
6 -
PruIo::DInit : A memory block of variable size, allocated by
9 -
PruIo::DRam : A memory block of 2
x 8 kB, allocated by the kernel
12 -
PruIo::ERam : A memory block variable size (up to 8 MB), allocated by
13 the kernel driver uio_pruss.
15 These blocks are available after the constructor
PruIo::PruIo() call
16 and get destroyed in the destructor
PruIo::~
PruIo().
22 The
PruIo::DInit data block holds the
register context of the
23 subsystems. It gets allocated by the constructor
PruIo::PruIo(). Its
24 size is twice the size of all
register sets. This is
31 The pasm_init.p instructions prepares these structures
for each
32 subsystem and sets the member variables by the values read from the
33 registers. All structures are packed in a single data block that gets
34 stored in DRam. The constructor allocates memory and makes one copy of
35 the block starting at adress
PruIo::DInit and a second copy starting at
38 The first copy is used by the destructor
PruIo::~PruIo to restore the
39 original configuration. The second block is used
for customized
40 configurations and gets transfered back to the subsystem registers in
41 the call to
function PruIo::config(). The initialize member
function of
44 the data block sections:
46 | Pointer | Description |
47 | -----------------: | : -------------------------------------- |
48 |
PruIo::DInit | Start of initial block (=
AdcUdt::Init) |
49 |
AdcUdt::Init | Initial ADC configuration |
50 |
GpioUdt::Init (0) | Initial GPIO-0 configuration |
51 |
GpioUdt::Init (1) | Initial GPIO-1 configuration |
52 |
GpioUdt::Init (2) | Initial GPIO-2 configuration |
53 |
GpioUdt::Init (3) | Initial GPIO-3 configuration |
54 |
PruIo::BallInit | Initial CM-pad configuration (pinmuxing) |
55 |
PwmssUdt::Init (0) | Initial PWMSS-0 configuration |
56 |
PwmssUdt::Init (1) | Initial PWMSS-1 configuration |
57 |
PwmssUdt::Init (2) | Initial PWMSS-2 configuration |
58 |
PruIo::DConf | Start of custom block (=
AdcUdt::Conf) |
59 |
AdcUdt::Conf | Custom ADC configuration |
60 |
GpioUdt::Conf (0) | Custom GPIO-0 configuration |
61 |
GpioUdt::Conf (1) | Custom GPIO-1 configuration |
62 |
GpioUdt::Conf (2) | Custom GPIO-2 configuration |
63 |
GpioUdt::Conf (3) | Custom GPIO-3 configuration |
64 |
PruIo::BallConf | Custom CM-pad configuration (pinmuxing) |
65 |
PwmssUdt::Conf (0) | Custom PWMSS-0 configuration |
66 |
PwmssUdt::Conf (1) | Custom PWMSS-1 configuration |
67 |
PwmssUdt::Conf (2) | Custom PWMSS-2 configuration |
69 In order to minimize memory consumption libpruio may generate
70 uncomplete subsystem sets. In such a set only the first four member
71 variables are valid (DeAd, ClAd, ClVa, [REVISION, IDVER]). Such reduced
74 - when a subsystem should get ignored, that is its activate bit isn't
75 set in the parameter *Act* in the constructor call (member variable
78 - when a subsystem didn't wake up due to a hardware failure (member
79 variable `[REVISION | IDVER] = 0`).
81 After the constructor call also the member variable ClVa in the *Conf*
82 section is set to 0 (zero) for uncomplete sets. When you intent to
83 access the subsystems sets directly, you must check if the set is
84 complete, first. This is the case when member variable `ClVa = 2`.
86 \note It's forbidden to write to variables in an uncomplete subsystem
87 set. This can destroy the following set in the data block and may
88 result in non-revisible hardware damages.
94 The DRam area (data ram) is a fixed sized block of `2 * 8` kB,
95 allocated by the PRUSS kernel driver. The host (ARM) can access only
96 the first 8 KB block, but the PRU software may use both blocks in MM
97 mode in case of a great number of pre-trigger samples.
99 The
PruIo::DRam pointer (type
UInt32) gets initialized by the
100 constructor
PruIo::
PruIo() and points to the DRam of the used PRUSS.
101 This is DRam-0 when the PRU bit of parameter *Act* is cleared and
102 DRam-1 when the bit is set (the default).
104 The first value (
PruIo::DRam `[0]` is always used to report the state
105 of the PRUSS software. It contains either one of the message codes
106 defined in file pruio.hp or it contains the index of the
last stored
107 sample (in RB or MM mode).
109 The rest of the DRam area is used for exchanging parameters between the
110 host (ARM) and the PRU software. The context changes, depending on the
111 current operational state of libpruio.
114 Constructor {#SubSecMemCTOR}
117 Before the constructor loads and executes the pasm_init.p instructions,
118 it calls the constructors of the subsystem structures
AdcUdt,
GpioUdt
119 and
PwmssUdt. These initialize the DRam area with the adresses
for the
120 subsystems and their Control Module (CM) clock register. So before that
121 instructions the DRam area contains
123 | Value | Description |
124 | -------: | : ---------------------------------------- |
125 | DRam[1] | Start of the data block |
126 | DRam[2] | Base Adress of ADC subsystem registers |
127 | DRam[3] | Adress of the ADC clock register |
128 | DRam[4] | Base Adress of GPIO-0 subsystem registers |
129 | DRam[5] | Adress of the GPIO-0 clock register |
130 | DRam[6] | Base Adress of GPIO-1 subsystem registers |
131 | DRam[7] | Adress of the GPIO-1 clock register |
132 | DRam[8] | Base Adress of GPIO-2 subsystem registers |
133 | DRam[9] | Adress of the GPIO-2 clock register |
134 | DRam[10] | Base Adress of GPIO-3 subsystem registers |
135 | DRam[11] | Adress of the GPIO-3 clock register |
136 | DRam[12] | Base Adress of CM-pad registers |
137 | DRam[13] | Base Adress of PWMSS-0 subsystem registers |
138 | DRam[14] | Adress of the PWMSS-0 clock register |
139 | DRam[15] | Base Adress of PWMSS-1 subsystem registers |
140 | DRam[16] | Adress of the PWMSS-1 clock register |
141 | DRam[17] | Base Adress of PWMSS-2 subsystem registers |
142 | DRam[18] | Adress of the PWMSS-2 clock register |
144 In case of an inactive subsystem (configuration bit in parameter *Act*
145 cleared) the clock adress is set to 0 (zero) so that the PRU can still
146 read the subsystems identifier (REVISION, IDVER).
148 Otherwise the PRU reads the complete register context of the subsystem
149 and stores the context in the data block. When a block of subsystems
150 (ADC, 4xGPIO, CM, 3xPWMSS) is finished, the offset of the next block
151 gets written to the
last parameter. So after the pasm_init.
p
152 instructions, the DRam area contains the following information:
154 | Value | Description |
155 | --------: | : ----------------------------- |
157 | DRam[1] | Offset of ADC register block |
158 | DRam[3] | Offset of GPIO register block |
159 | DRam[11] | Offset of CM-pad register block |
160 | DRam[12] | Offset of PWMSS register block |
161 | DRam[18] | Length of complete data block |
162 | DRam[128] | Data block context |
164 The constructor
PruIo::
PruIo() generates two copies of the data block
165 in host memory (at
PruIo::DInit and
PruIo::DConf) and calls the
166 initialize() member functions of the subsystems (ie.
167 AdcUdt::initialize(),
GpioSet::initialize() ), where the pointers (ie.
168 AdcUdt::Init and AdcUdt::Conf) to the individual register sets (ie.
171 This method allows to extend libpruio by new subsystem code with
172 minimal adaption in the existing source.
175 config {#SubSecMemConfig}
178 The
function PruIo::config() uploads the customized configuration to
179 the subsystems and starts operation in the declared run mode. Before
180 the pasm_run.
p instructions get executed, the DRam area contains
182 | Value | Description |
183 | --------: | : ------------------------------- |
184 | DRam[1] | Start of the data block |
185 | DRam[2] | Number of samples AdcUdt::Samples |
187 | DRam[4] | Bit encoding mode AdcUdt::LslMode |
188 | DRam[5] | Timer value AdcUdt::TimerVal |
189 | DRam[128] | Conf data block context |
191 The PRU software reads these parameters and writes the configuration to
192 the subsystem registers. Then it prepares the DRam area as follows
194 | Value | Description |
195 | -------: | : ------------------- |
196 | DRam[0] | PRUIO_MSG_xxx |
197 | DRam[16] | 4xGpioArr (64 bytes) |
198 | DRam[32] | 3xPwmssArr (96 bytes) |
199 | DRam[56] | ADC data (38 bytes) |
201 The type of PRUIO_MSG_xxx depends on the required run mode. It's either
206 digital subsystems to the host. In IO and RB mode the PRU software
207 reads some registers and writes the context in to these arrays, where
208 the host (ARM) software can read them.
210 The field `Adc data` contains the subsystem adress of the ADC subsystem
211 (if enabled) and 17
UInt16 values for samples (the first is unused).
213 - In IO mode it contains the sampled data (AdcUdt::Value).
215 - In RB mode it's not used.
217 - In MM mode it contains the ring buffer for pre-trigger samples and
218 its size vary. Depending on the number of pre-trigger samples the
219 DRam areas of both PRUSS may be used.
221 Each array entry starts with the subsystem adress. In case of a
222 disabled subsystem the adress entry is 0 (zero) and the PRU software
223 skips this subsystem.
225 Furthermore the beginning of the DRam area is used to pass parameters
226 to the running PRU software
228 - Function
PruIo::rb_start()
229 | Value | Description |
230 | ------: | : ------------------------------- |
231 | DRam[1] | Number of samples AdcUdt::Samples |
232 | DRam[2] | Adress of ERam
PruIo::ERam |
233 | DRam[3] | Pre-trigger samples (= 0) |
234 | DRam[4] | Trigger specification (= RB mode) |
235 When running in RB mode the PRU software reports its
last write index
236 | Value | Description |
237 | ------: | : -------------------------------------------------------- |
238 | DRam[0] | Last write index `0 <=
i < AdcUdt::Samples * AdcUdt::ChAz` |
240 - Function
PruIo::mm_start()
241 | Value | Description |
242 | ------: | : ------------------------------- |
243 | DRam[1] | Number of samples AdcUdt::Samples |
244 | DRam[2] | Adress of ERam
PruIo::ERam |
245 | DRam[3] | Pre-trigger samples |
246 | DRam[4] | Trigger 1 specification |
247 | DRam[5] | Trigger 2 specification |
248 | DRam[6] | Trigger 3 specification |
249 | DRam[7] | Trigger 4 specification |
250 After performing a maesurement in MM mode the PRU software reports success
251 | Value | Description |
252 | ------: | ----------------- |
256 | Value | Description |
257 | ------: | : -------------------------------------- |
259 | DRam[2] | GPIO subsystem adress (+ &h100) |
260 | DRam[3] | Value for
GpioSet::CLEARDATAOUT register |
261 | DRam[4] | Value for
GpioSet::SETDATAOUT register |
262 | DRam[5] | Value for
GpioSet::OE register |
265 | Value | Description |
266 | ------: | : -------------------------------------- |
268 | DRam[2] | GPIO subsystem adress (+ &h100) |
269 | DRam[3] | Value for
GpioSet::CLEARDATAOUT register |
270 | DRam[4] | Value for
GpioSet::SETDATAOUT register |
272 - PRU command \ref
PRUIO_COM_PWM (set PWM frequency and duty cycle)
273 | Value | Description |
274 | ------: | : ----------------------------------------------------- |
276 | DRam[2] | PWMSS subsystem adress (+ &h200) |
282 and set frequency and duty cycle)
283 | Value | Description |
284 | ------: | : ---------------------------------------------------------- |
286 | DRam[2] | PWMSS subsystem adress (+ &h100) |
287 | DRam[3] | Value for
PwmssSet::CAP3 register (counter shadow) |
288 | DRam[4] | Value for
PwmssSet::CAP4 register (period shadow) |
290 - PRU command \ref
PRUIO_COM_CAP (switch PWMSS-CAP module in CAP mode)
291 | Value | Description |
292 | ------: | : ------------------------------------------------------ |
294 | DRam[2] | PWMSS subsystem adress (+ &h100) |
297 | Value | Description |
298 | ------: | : -------------------------------------------------------- |
301 \note PRU commands are valid in IO and RB mode. After a PRU command
302 execution the DRam[1] value gets set to 0 (zero). You must wait
303 for that zero value before you set a new command or write new
307 Destructor {#SubSecMemDTOR}
311 structure gets destroyed. It load the initial configuration data block
312 to the DRam and executes the configuration instruction on the PRU.
313 Therefor it prepares the DRam area as in the following table:
315 | Value | Description |
316 | --------: | : --------------------- |
317 | DRam[1] | Start of the data block |
318 | DRam[2] | Number of samples (= 0) |
319 | DRam[128] | Init data block context |
321 When the PRU finished successfully the DRam area contains
323 | Value | Description |
324 | ------: | : --------------- |
331 The ERam area (external memory) is the biggest memory block in use.
332 It
's allocated by the kernel driver when loaded. The default size is
333 256 kB (= 128 kSamples). libpruio uses the external memory in RB and MM
334 mode to store the ADC samples.
336 - In RB mode the size of the ring buffer is limited by the size of the
339 - And in MM mode the number of total samples (`= AdcUdt::Samples x
340 AdcUdt::ChAz`) must not be greater than the available number of
341 samples in the external memory.
343 The kernel driver allows to customize the size of the external memory.
344 This must be done at the first driver loading. Ie. execute (with admin
345 privileges) `modprobe uio_pruss extram_pool_sz=0x800000` to set the
346 maximum size of 8 MB (= 0x800000).
348 \note The kernel driver also gets loaded by a device tree overlay that
349 enables the PRUSS. Make sure that the above command gets executed
350 before the device tree overlay loads. (Or unload the kernel
351 driver by `modprobe -r uio_pruss` and reload again using the
#define PRUIO_COM_ADC
The command number to set a ADC-mask reconfiguration in IO mode.
#define PRUIO_COM_CAP
Command number to set a CAP module in input mode (IO, RB)
Main structure, binding all components together.
~PruIo()
Destructor to restore configurations and clear memory.
PruIo(BYVAL_AS_UInt16, BYVAL_AS_UInt8, BYVAL_AS_UInt32, BYVAL_AS_UInt8)
Constructor, initialize subsystems, create default configuration.
ULONG UInt32
32 bit unsigned integer data type
Structure for PWMSS subsystem features, containing all variables to handle the subsystems.
#define PRUIO_COM_PWM
Command number to set frequency and duty cycle for a PWM module (IO, RB)
Structure for ADC subsystem registers.
ANY_PTR ERam
Pointer to read PRU external ram.
Structure for Control Module, containing pad configurations.
#define PRUIO_MSG_CONF_OK
Message send after PruIo::config() when no mode is set (parameter Samp = 0).
Structure for ADC subsystem features, containing all functions and variables to handle the subsystem...
VAR p
The position of the 'x' character (if any).
UInt32 last[...]
The previous data of the channels.
BallSet_PTR Init
The subsystems register data at start-up (to restore when finished).
FUNCTION_CDECL_AS_ZSTRING_PTR initialize()
Initialize the register context after running the pasm_init.p instructions (private).
Structure for GPIO subsystem features, containing all functions and variables to handle the subsystem...
ANY_PTR DInit
Pointer to block of subsystems initial data.
#define PRUIO_MSG_IO_OK
Message send after PruIo::config() in IO mode.
#define PRUIO_MSG_MM_WAIT
Message send by PruIo::config() in RB and MM mode and after each call to PruIo::mm_start().
UDT for GPIO data, fetched in IO & RB mode.
FUNCTION_CDECL_AS_ZSTRING_PTR initialize()
Initialize the register context after running the pasm_init.p instructions (private).
Structure for GPIO subsystem registers.
FUNCTION_CDECL_AS_ZSTRING_PTR config(BYVAL_AS_UInt32, BYVAL_AS_UInt32, BYVAL_AS_UInt32, BYVAL_AS_UInt16)
Load configuration from host (ARM) to driver (PRU).
Structure for PWMSS subsystem registers.
#define PRUIO_MSG_INIT_OK
Message send after constructor PruIo::~PruIo.
BallSet_PTR Conf
The subsystems register data used by libpruio (current local data to be uploaded by PruIo::Config() )...
#define PRUIO_COM_GPIO_CONF
The command number to reconfigure a GPIO.
UInt32_PTR DRam
Pointer to access PRU DRam.
UDT for PWMSS data, fetched in IO & RB mode.
#define PRUIO_COM_GPIO_OUT
The command number to set a GPIO output state.
VAR mask
Steps 5 & 8 active (AIN4, AIN7).
VAR x
The header pin name.
USHORT UInt16
16 bit unsigned integer data type
#define PRUIO_COM_PWM_CAP
Command number to set frequency and duty cycle for a CAP module in PWM output mode (IO...