Here's some feedback about the libpruio project. lejan wrote:
Dear TJF, I just wanted to thank you for sharing such a great library! I have been using this in C for a robotics project and this library really took the hassle out of a lot of the programming work. The Beaglebone is not as well supported as Arduino or Rasp Pi so your library is very much appreciated. Peter
Thanks, for the feedback! It seems that the major goal is reached.
libpruio is designed to provide faster, more flexible (customizable) and more easy (single source) access to the TI AM335x CPU subsystems, compared to the methods provided by the kernel. Its features in short
It's designed for BeagleBone boards with a type of TI AM335x CPU
and runs on all kernel versions above 3.8 (including 4.x, 5.x).
The TI AM335x CPU on Beaglebone hardware contains beside the main ARMv7 processor also two PRU subsystems. libpruio runs software on the host system (ARM) and in parallel on a Programable Realtime Unit SubSystem (PRUSS), either on PRU-0 or PRU-1 (the later is the default). Due to the PRU support the work load on the ARM is very low. Even complex controllers can operate at reasonable speed. The second PRU is free for any custom firmware, ie. a controller working in real-time, and using libpruio measurement configuration and data.
libpruio controls the following subsystems on the TI AM335x CPU
Therefor the user application (ARM) executes a sequence of these three steps
libpruio offers a set of API functions to do simple IO task at a reasonable speed. They may be inefficient in case of advanced requirements. Therefor libpruio allows direct access to all register configurations of the subsystems. This is for experts only. Further customization of the subsystems configuration for analog and digital lines can get done by adapting the subsystem registers before step 2.
libpruio supports three run modes. They differ in the priority of the timing of the ADC subsystem (restarts of the sequencer):
The run mode gets specified by parameter Samp
in the call to function PruIo::config()
Samp = 1
for IO mode, starting immediately, running endless.Samp > 1
for RB mode, starting by a call to function PruIo::rb_start(), running endless.Samp > 1
for MM mode, starting by a call to function PruIo::mm_start(), stopping after a single measurement is done.To stop an endless mode (IO or RB) call function PruIo::config() again. Or destroy the libpruio structure when done by calling the destructor PruIo::~PruIo().
Most digital lines of the TI AM335x CPU support several features and need to be configured before use (see section Pinmuxing for details). libpruio checks the pin configuration at run-time, and tries to adapt it if necessary.
libpruio supports multiple pinmuxing methods. Depending on the kernel version and the system configuration pinmuxing at run-time may require administrator privileges. The most advanced method is the loadable kernel module, described in section LKM. Or you can run your application with user privileges by making sure that digital lines are in the required state (configuration) before executing the code.
General Purpose Input Output is available by the GpioUdt member functions (in IO and RB mode, for all header pins). See section GPIO for further info.
Furthermore, multi lines can get accessed simultameously by direct access to the PRU interface (experts only).
Capture And Analyse a digital Pulse train is available by the member functions of class CapMod (in IO and RB mode). The frequency and duty cycle of a pulse train can get measured. See section CAP for further info.
A minimal frequency can get specified to limit the reaction time in case of no input.
Generating a Pulse Width Modulated output is available by the PwmMod member functions (in IO and RB mode). Therefor libpruio uses different subsystems: the PWM modules and the CAP modules in the PWMSS subsystems, as well as the TIMER [4-7]
subsystems. All modules are supported in a transparent API. See section PWM for further info.
Furthermore advanced features of the PWMSS subsystems can be used by direct access to the register configuration and PRU interface, ie. syncronizing multiple PWM outputs (experts only).
Generating a pulse train on output line[s]. The time period until the pulse starts and its duration gets specified. See section TIMER for details.
Reading and analysing signals from incremental Quadrature Encoder Pulse Trains. Those encoders generate pulses by two (mostly light barriers) sensors, scanning a regular grid (bar code), while both sensors are out of phase by 90 degrees. By analysing those signals, the position (angle) and the speed of the movement can get detected.
libpruio supports multiple measurement configurations:
The mode gets specified by the call to function QepMod::config(). See section QEP for further info.
In all run modes (IO, RB and MM) Analog Digital Converted input can get sampled by the AdcUdt member functions, controling the Touch Screen Controler and Analog to Digital Converter SubSystem (TSC_ADC_SS). It samples analog data on eight input lines (AIN-0 to AIN-7).
The ADC subsystem can use up to 16
step configurations (and an additional charge step) to perform a measurement. libpruio pre-configures steps 1
to 8
by default to sample lines AIN-0 to AIN-7.
The Beaglebone ADC subsystem samples 12 bit values in the range of 0
to 4095
. Most other devices (ie. like sound cards) use 16
bit encoding (in the range of 0
to 65535
) and the values cannot get compared directly. Therefor libpruio can left shift the samples internaly. By default the output is 16 bit encoded (range 0 to 65520).
In Ring Buffer (RB) mode the samples from the ADC subsystem continuously get stored in the external memory. The calling software has to make sure that only valid values get read. Therefor the value of PruIo::DRam [0]
contains the most recent write position (UInt32 index).
In order to run RB mode, specify the size of the ring buffer by the number of samples (> 1) in the call to PruIo::config() and then start measurement by calling function PruIo::rb_start(). Read samples as AdcUdt::Value[index] and make sure that index is always behind the counter PruIo::DRam [0]
(at the end of the ring buffer memory, the index counter jumps to 0 (zero)). Find examples in rb_file.bas (rb_file.c) or rb_oszi.bas.
In Measurement Mode (MM mode) the start of a measurement is either immediately, or the start can get triggered by up to four events. When the first event happens, the second trigger gets started, and so on. The last specified trigger starts the measurement.
A trigger event may be a digital line reaching a certain state or an analog line reaching a certain voltage. The voltage can get specified as an absolute voltage or as a difference related to the measured voltage at trigger start.
Post-triggers may delay the measurement start or the start of the next trigger for a certain time.
A pre-trigger can be used to start the measurement before the event happens. Only one pre-trigger is allowed, it's always the last trigger.
Call function
Pass the trigger specification[s] to function PruIo::mm_start() to activate them. Read the samples as AdcUdt::Value[index] and make sure that the index doesn't leave the range specified by the number of samples in the call to RruIo::config(). Find am exmple in file triggers.bas.
libpruio controls several subsystems, listed in section Operation. Each of these subsystems can either
To ignore a subsystem, clear its status bit in parameter Act when calling the constructor PruIo::PruIo(). Each subsystem gets controlled by its own status bit. When a system is set to be ignored, libpruio cannot access it. There's no configuration data and there's no reset to the initial state for the subsystem by the destructor PruIo::~PruIo().
By default all subsystems are active (not ignored). All active subsystems are enabled after the constructor call (unless the hardware fails). Check
2
if enabled),0
(zero) if wakeup failed).libpruio stores a complete set of configuration data for active subsystems and restores their state by the destructor when finished. Active subsystems can get enabled or disabled at run-time. Each call to function PruIo::config() can change a subsystem state.
0
(zero), before calling function PruIo::config(). Ie. set PruIo->PwmSS->Conf(2)->ClVa = 0
to switch off the third PWMSS subsystem (PWMSS-2).2
, before calling function PruIo::config() again. Ie. set PruIo->Adc->Conf->ClVa = 2
to enable the ADC subsystem.The libpruio package contains in folder src/config tools to create, compile and install device tree overlays.
In order to create a customized overlay adapt the source code, compile and execute it: