Seriously Confused

Hello.

I am trying to figure out how to use I/O with my BBB running Debian, but the more I try the more confused I get. For example: I try to read the analog inputs using information I find on the web. Per instructions, I enter

echo cape-bone-iio > /sys/devices/bone_capemgr.*/slots

which indeed adds something to slots.  Then the instructions say to enter 

cat /sys/devices/ocp.2/helper.11/AIN1

but I discover that there is no directory named "ocp.2" in /sys/devices, or anywhere else that I can
find.  There is an ocp.3, but it doesn't contain "helper.11" ...  and so on.

I keep searching for some sort of definitive guide to using the IO capabilities of the board, but have had no luck. There is nothing on software in the SRM, and memory-mapping to the registers described in the data sheet seems to be frowned upon.

Can anyone point me to an entry point into all these mysteries? Where do I go to find the definitive guide to reading the analog inputs under Debian, for example? What commands are available? Why would anyone want to use file IO to do simple GPIO operations when it is so much faster to just memory-map the GPIO registers?

Curt Carpenter <1cjcarpenter-fOdFMYwuEsI@public.gmane.org> writes:

I keep searching for some sort of definitive guide to using the IO
capabilities of the board, but have had no luck. There is nothing on
software in the SRM, and memory-mapping to the registers described in
the data sheet seems to be frowned upon.

I know of no definitive guide. There are some well written blog posts
but as with anything on the Internet, it's important to consider the
date it was published.

The bonescript analogRead module can handle this, so you could do all
this from the Cloud9 browser IDE. If you want to use javascript that is,
I prefer python (see next question).

Can anyone point me to an entry point into all these mysteries?
Where do I go to find the definitive guide to reading the analog
inputs under Debian, for example?

Anytime I've done ADC on the Bone I've used this python library:
GitHub - graycatlabs/PyBBIO: A Python library for Arduino-style hardware IO support on the Beaglebone.

The python snippet is something like this:

import Adafruit_BBIO.ADC as ADC
ADC.setup()
ADC.read(self.pin)

What commands are available? Why
would anyone want to use file IO to do simple GPIO operations when it
is so much faster to just memory-map the GPIO registers?

This question seems to arise quite often and there are a few "right"
answers. To me, directly using memory-map regions breaks down a certain
level of software and Linux abstractions. An analogous question,
perhaps, is: Why not just run everything as root? By using Linux from
userspace, you are sacrificing some of the performance but you gain the
ability to use a myriad of third-party libraries and your choice of
programming language.

You probably would get better performance if you made your own kernel
module for whatever you were trying to do, but that may not be the
easiest route if you just want to read an analog value.

Hope some of this helps,

Josh

Thank you for the detailed reply Joshua.

I’m still mystified by the documentation, and come to the BBB from OS-free environments where everything is done at the register level, and almost everything one needs to know is in the data sheet/TRM. I’d like to impose on you with one more question if I can
(this is not a rant! Trying to get organized).

I found (stumbled on) an article on reading the analog inputs on the web that works:

echo BB-ADC > /sys/devices/bone_capemgr.*/slots
cd /sys/bus/iio/devices/iio:device0
cat in_voltage0_raw

Am I correct in understanding that there is no documentation that would have pointed me to the /sys/bus/iio/devices/iio:device0
directory and given me some guidance on what it contained?

I have the feeling that the docs ARE there, I just haven’t located the mother ship yet :slight_smile:

I haven’t tried python or bonescript: sticking with C/C++ until I learn my way around the BBB first before I tackle the added complication of a new language. If I were to shift to python though, is there any particular doc I would read to learn how to do something like use the device tree and the A/Ds? If so, I might abandon C just in the interest of working on a stable, documented software platform.

Appreciate your help and advice.
Regards,
Curt

[-- text/plain, encoding 7bit, charset: UTF-8, 97 lines --]

I'm still mystified by the documentation, and come to the BBB from OS-free
environments where everything is done at the register level, and almost
everything one needs to know is in the data sheet/TRM. I'd like to impose
on you with one more question if I can
(this is not a rant! Trying to get organized).

I agree with you (previous questions as well) the documentation of the
BBB I/O is lacking in many ways, it's *very* difficult to get into it.

Seeing how some of the code works (e.g. Adafruit I/O libraries) I
think the people who wrote that code had the same problem! :slight_smile:

I found (stumbled on) an article on reading the analog inputs on the web
that works:

   echo BB-ADC > /sys/devices/bone_capemgr.*/slots
   cd /sys/bus/iio/devices/iio:device0
   cat in_voltage0_raw

... and that's the *real* raw value, not the pseudo-raw value that the
Adafruit libraries give you.

Am I correct in understanding that there is no documentation that would
have pointed me to the /sys/bus/iio/devices/iio:device0
directory and given me some guidance on what it contained?

Apart from the zillion page processor documentation I think you're
right.

I have the feeling that the docs ARE there, I just haven't located the
mother ship yet :slight_smile:

The 'mother ship' is google searching as far as I can tell, there is
no decent, high level overview that a reasonably proficient software
person can pick up and use.

I haven't tried python or bonescript: sticking with C/C++ until I learn my
way around the BBB first before I tackle the added complication of a new
language. If I were to shift to python though, is there any particular doc
I would read to learn how to do something like use the device tree and the
A/Ds? If so, I might abandon C just in the interest of working on a
stable, documented software platform.

I think you're making life harder for yourself using C/C++. I'm a
C/C++ programmer (30 or more years, now retired) but use Python on the
BBB and many other places. Python is a nice, regular, intelligible
language. Unless you need the absolute ultimate in speed it will do
all you want on the BBB. As someone else pointed out, to read the ADC
using Python you just do:-

> import Adafruit_BBIO.ADC as ADC
> ADC.setup()
> ADC.read(self.pin)
>

You have to install the Adafruit BBIO library first of course. The
documentation of the Adafruit libraries isn't all *that* comprehensive
but they're pretty simple so no problem really. As I pointed out
above though the code is a little odd in places, for example the 'raw'
value returned by the Adafruit library is simple the processed value
(which is in millivolts) divided by 1800 which isn't my idea of a raw
value!

Curt Carpenter <1cjcarpenter-fOdFMYwuEsI@public.gmane.org> writes:

Am I correct in understanding that there is no documentation that
would have pointed me to the /sys/bus/iio/devices/iio:device0
directory and given me some guidance on what it contained?

Ok. You enticed me to provide a more detailed answer :slight_smile: I started
thinking about the question, "How do I use the ADC on this board and the
answer can't be just: use python?" I'll try to point out some
assumptions and links to docs. I'm not an expert on this, so perhaps
there is a better way.

1.) You have to know that the linux kernel is the mechanism to provide
software interfaces to the hardware.

2.) The kernel does have documentation for most major
subsystems. Granted, some "documentation" is in the form of comments,
but it is there. If you downloaded the kernel or use the free electrons
site to search for "adc" you'd find this:
http://lxr.free-electrons.com/source/drivers/staging/iio/Documentation/overview.txt. This
is the root documentation on using the kernel's Industrial I/O subsystem
or IIO. If you root around in that directory, you'll find "the
definitive" guide to using this interface.

2.a.) The kernel documentation often assumes you are familiar with the
kernel :slight_smile: It's a bit circular I guess. There is a great book, Linux
Device Drivers, which is available for free:
Linux Device Drivers, Third Edition [LWN.net]. The kernel version is quite old now (2.6)
but the *basics* are helpful for understanding what's going on. Just
remember that it was a snapshot in time.

OK. So that's the IIO interface. But how do you know the BeagleBone has
the hardware to use it?

There a few pieces of knowledge you have to connect here. The first is
that one would expect a driver for TI's ADC for the AM335x to be in the
kernel. Some more searching through the sources reveals this:

That looks like a likely candidate. Then, we need a method to map this
driver to the hardware. The more generic question is, how does the
kernel know what hardware lies beneath it? From what I understand, this
is done with the *device tree.* So, you need to find the device tree
file that defines the use of this driver. This looks like it here:

But, that's a generic device tree for the AM3XX series, what about the
more specific BeagleBone black? More searching:
https://github.com/beagleboard/linux/search?p=2&q=am33xx.dtsi

From there you should see the mapping to the registers in the TRM.

I'm not familiar with the particular driver *at all*, so this may not be
the correct pairing. :slight_smile: However, this is the process that generally
works for me and I don't think it's too off base. If it is, hopefully
somebody will correct me here.

Josh

As a quick speed comparison on the BeagleBone Black.
If you program a GPIO line to just toggle up and down in a loop .

In Python, using the file system I/O, the line will toggle up and down at about 6 kHz.

If you program in C, under Debian, using a tight loop to toggle the line up and down
on memory mapped I/O, the line will toggle up and down at about 2.2 MHz.
Almost a 3 orders of magnitude improvement.

I have read, that in assembler on the PRU, you can get it to toggle at 200 MHz, another
two orders of magnitude.

So, if you are doing something where response time in the milliseconds is good enough
then Python is great. If you are teaching kids to program, then Python seems great.

If you are looking for response times in the microseconds, then
you need to be closer to the metal with something like C.

If you are looking for an example of a C I/O library for BBB GPIO,
and some off the peripherals, including the ADC, then look at:

https://github.com/VegetableAvenger/BBBIOlib

— Graham

Thank you for the link Graham – I think that library will be very useful as a guide, and I’ll try using it as my “point of entry” for a few weeks and see what progress I can make in parallel with exploring the other docs that Joshua has pointed me to. I note the author of the library relies a lot on mmap, which suits me – although I think I can understand the arguments for NOT using it from a software professional’s perspective.

It will be a while before I’m ready to tackle the PRU – and my 'scope is only useful up to 50MHz or so anyway :slight_smile: I don’t have any need to toggle anything at 200MHz – but the thought is pretty amazing.

Thanks again.
Curt

https://github.com/adafruit/adafruit-beaglebone-io-python/blob/master/source/c_adc.c

The adc source for bbio should be useful.

Keep in mind that these sysfs interfaces are incredibly slow compared to memory poking since each operation requires opening, reading/writing and closing the file. For example, with GPIO, you're limited to a few hundred khz (regardless of language since it's just file operations). With mmap and python, you can toggle at > 3Mhz. C a bit faster. Kernel, 12Mhz. There are python and closing libraries that handle all of the memory poking.

Also, check out libpruio. It will setup the pin muxing, and provides quick adc and GPIO support.

Thanks Brandon. Alas, the path used in the c_adc.c software just doesn’t seem to exist in the Debian I’m using – one of the big sources of confusion for me. I’m starting to think the only solution is to try to dig into the kernel source as Joshua suggests – but that sounds like it might take more years than I have left :slight_smile:

I’m not sure the kernel source would be beneficial. If you want to understand how the ADC works or get it going manually, with all the clock domain setup and whatnot, then read the reference manual. The kernel source will be doing all of this, in an abstracted and not so easy to understand way.

The driver/sysfs interface wont load up until the device tree overlay (that describes the ADC) is loaded. Is the BB-ADC overlay loaded? http://analogdigitallab.org/articles/using-adc-beaglebone-black