Author Topic: Beaglebone Black, how to export peripheral at boot, or as a regular user?  (Read 3210 times)

0 Members and 1 Guest are viewing this topic.

Offline JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
TL;DR: At the bottom

Hi,
It's august and there isn't much to develop at work so i started working again on an idea i had been toying with for some time: to build an automated test machine for our products.

I've put together all the reasonable requirements and most if not all the unreasonable and i'm confident i can do this. It's actually not the first tester i design/build but this time i want it to be Definitive in the sense that it can be expanded in the future.

As the brain of the whole thing i'm going to use a Beaglebone Black i bought a couple of years ago for this very purpose because
- I don't have to design the ADC/DAC structure around it, it's already in there -so no need to debug usb stacks or to use very slow uart links-
- builtin networking and graphics
- the PRUs, because i'll need pattern generators and a ways to send/receive data in non-common protocols. This saves me the pain of dealing with a dedicated decoder/encoder chip (which i can do, but if i don't need to, better.)
- The PRUs will also let me implement  >1 pic programmers, without having to deal with the shitty production programmers we have.. they were good until we needed updates to support new pics. We are back on using several pickits.

So, in the past few days i dug out the BBB and after a number of tries with different images installed the latest available. I had to go on to the process of updating kernel and bootloader several times but now i have a truly up to date board.
This is good, because i found that the newer ways to control the hardware are much less confusing and convoluted.
This is bad, because almost all the documentation out there is for older kernels. It took me litterally days to figure out how to enable the pwm.
Also, i have the Exploring Beaglebone Black book, which i found very helpful as i went from ZERO linux experience to a bit of linux experience and once i figured out how to adapt the old ways to the new ones i was able to run all the examples.

I've come to a point where i have configured almost every pin i'll need, i can begin writing the first draft of an application that can run a test (without graphical interface, that will be developed on its own. Interface will call the test program, in case i decide to drop the GUI completely at some point)
but there are some issues i can't get around with, basically for my lack of knowledge of the whole linux thing. I hope that you can help me see the light

SO TO THE QUESTIONS
At this point i'm able to run a script to configure the pins as needed (config-pin command) and i can do that as a regular user.
However, i have to first enable the peripherals (like, as root, echo 0 > export in pwmchip1)
Question 1: How can i export/enable all the peripherals i need at boot?I figure that once they are enabled i can just run different script to map different pinouts. I'm not sure because on the web there are different ways for different kernels and i don't know what is the current way to do it.
Question 2: There is also another issue, the paths to many of the peripherals is different at every boot. Actually, it's the same up to a point. For example now PWM0 control is located at this path
Code: [Select]
/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip1but at the next boot it could be at
Code: [Select]
/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip4
I'm sure that there's a way to write a script that just enters the folder, as there is only one but i don't know how to do it. A good resource on writing bash scripts for the script rookie?
Question 3: The only (safe) way i know that writes/reads the peripherals is by writing/reading the associated files, my program should also be aware of the path. Would it be a good idea to also create symbolic links to the peripherals so my program just refers to those paths?
Also, is there a better and or faster (but still safe) way to access the peripherals? I know i can directly access the memory but i read this could lead to nasty issues when another process also wants to access the same resource.

Question 4: Obviously i need to be root in order to read/write the peripherals. sigh. However i tested and with chmod i can make it so i can access the files as a regular users. Naturally i have to do it at every boot. Would it be good or bad practice? Is there a better way?

Thank you for any help..
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6264
  • Country: fi
    • My home page and email address
  • Use an init script.  The details depend on whether you use SystemD or something else.  For SysV init, it's just dropping that script into /etc/init.d/, and adding symlinks to it from the relevant /etc/rc?.d/ directories.
  • Maybe Bash Beginners Guide? Dunno.
  • Let udev do it, by creating the necessary rules.
  • No, you don't.  udev can do it for you, and you are almost certainly already using udev.
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6264
  • Country: fi
    • My home page and email address
For udev rules, I think the guide at Debian Wiki is a good one for initial description; then see the udev man page.

Essentially, you'll need to first find out a way to detect the particular device reliably, using matches.  For example,
KERNEL=="gpio*", SUBSYSTEM=="gpio", ACTION=="add"
matches when the kernel finds a GPIO device.  Then, you can add one or more keys, like NAME, OWNER, GROUP, SYMLINK, or RUN to get the desired effect.  For example, Adafruit uses PROGRAM=path-to-script to execute a script that changes the ownership and mode of the related device nodes on Beaglebones; they really should use, RUN{program}+=path-to-script instead, because PROGRAM is intended for probes; a matching rule (returning zero to match, nonzero to not match).

Fortunately, in /sys/, for each device you can see the udev settings because the kernel exports a pseudofile named uevent.  In particular, I think you'll find /sys/class/pwm/pwmchip*/uevent that correspond to the PWM devices, and adding suitable matching rules with GROUP:=groupname, SYMLINK+=/dev/pwm-name should do what you want.

« Last Edit: August 03, 2019, 10:43:47 am by Nominal Animal »
 

Offline JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
thanks for answering. The problem with /sys/class/ is the one i mentioned in my previous post: the hardware peripheral corresponding to pwmchip* can be different at each boot. For example some times pwmchip1 corresponds to hardware pwm0, sometimes to hardware pwm2, sometimes it isn't even present, in his place you have pwmchip4.

Wouldn't this mean that if my program were to look for that particular path at one boot it would control the correct PWM, the next boot a different pwm and the boot after it would control nothing and maybe crash?

This is why i thought i should go with /sys/devices/ instead, because the path is consistent up to that point... And me creating links at boot just because it's not the program anymore that has to check the addresses but can work assuming they are always right
or is there something i'm still not understanding?
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
That sounds like a weird issue in your Linux distribution, but with udev you can match on any attributes from the root to the leaf of the device tree. The command "udevadm info --query=all --attribute-walk --path=<sysfs path to device>" will print all attributes in the hierarchy of the device. I assume that eg. the "48300200.pwm" comopnent uniquely identifies the peripheral by its memory address.

Udev can also create symlinks for you. The only issue is that if you're writing something that's supposed to run on boot, you have to delay it until after udev has done its job. Systemd has a "systemd-udev-settle" service you can use, dunno the best way to to it with other inits.
« Last Edit: August 03, 2019, 12:25:52 pm by andersm »
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6264
  • Country: fi
    • My home page and email address
JPortici, could you post your kernel version, uname -a ?

I'm not exactly sure which part of the path is the device, as I don't have a Beagle*, but the output of I guess
Code: [Select]
for D in /sys/devices/platform/ocp/*/*/pwm/pwmchip? ; do printf '\n%s:\n' "$D" ; udevadm info --query=all --attribute-walk "--path=$D" ; done
basically expanding on what andersm suggested, might show how to tell the difference.  The numbering itself might be a probing quirk in the kernel, and the device nodes still have uniquely identifying information that can be used to generate reliable persistent symlinks.
« Last Edit: August 03, 2019, 12:46:58 pm by Nominal Animal »
 

Offline JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3461
  • Country: it
Code: [Select]
debian@beaglebone:/sys/class/pwm$ uname -a
Linux beaglebone 4.14.108-ti-r113 #1 SMP PREEMPT Wed Jul 31 00:01:10 UTC 2019 armv7l GNU/Linux

I have actually retried booting a couple of times, but the pwm assignment haven't changed. Could it be that it was an issue with older kernels? because i do remember a guy metioning that behaviour in a video tutorial.
If it was and it's not anymore, good for me, i can probably just use an init.d script to configure everything
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6264
  • Country: fi
    • My home page and email address
The behaviour stabilized in 4.11, if I recall correctly; and even had a different path before that (based on various github repos involving BBB GPIOs, like the Adafruit one).

If there is only one pwmchipN device at run time, you can always add something like
Code: [Select]
ln -sf /sys/devices/platform/ocp/*.epwmss/*.pwm/pwm/pwmchip[0-9] /dev/bbb-pwm
as an init script, to generate/refresh the symlink.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf