PRUdebug wrapper

I noticed here a considerable amount of PRU interest, I thought that I was the only one…

for those interested, I’ve posted to GitHub - gomer-grondin/prudebug_wrapper: wrapper for prudebug v.25 .. in perl WIP, a tool that I’ve used and tinkered with… it is far from polished, but I use it often.

will consider all inquiries for modification… or … it is simple enough for you to modify yourself.

the most formidable task to get it running is to install cr.yp.to/daemontools.html … this is an excellent tool written by DJB some time ago.

good luck
gomer

My py-uio library also has an example showing how it may be used to debug a PRU program: py-uio/debugging.py at master · mvduin/py-uio · GitHub
I’ve been meaning to integrate the breakpoint functionality into the library itself and also add support for getting debug info from ELF executables, but I haven’t gotten around to it yet.

BTW, daemontools is redundant nowadays, systemd and journald already provide the same functionality.

(py-uio also works on the AM572x (bbx15/bbai) and partially works on the new AI64, although some issues remain to be fixed there)

it may be as you say, but some old dogs stick with the old tricks. Are you sure that ALL features of daemontools are redundant? how about supervise actions? status commands?

perhaps you could post a solution using systemd and journald for comparison.

gomer

I haven’t looked at what your wrapper does in detail or what benefits it has over running a readline-enabled version of prudebug in a screen session, but the part for which you seem to be using daemontools is being able to feed commands to a running prudebug instance (which you can totally do with screen too btw!). Obviously the best way to handle that would be to modify prudebug itself to accept connections from a socket, handle commands from any of them, and print the reply to the same socket from which the command was received. This wouldn’t be difficult I think, but let’s instead look at how to do your pipe-trick with systemd.

Creating and managing the service

First there’s the question of whether we want a system service or a user service. In this case, assuming you’re using UIO (and not /dev/mem, ew) everything can run as the debian user so we’ll go with a user service.

Create the directory ~/.config/systemd/user if it doesn’t already exist and in it create the following two files:

prudebug.socket:

[Unit]
Description=PRU debugger control fifo

[Socket]
# %t = runtime directory (/run for system services, $XDG_RUNTIME_DIR for user services)
ListenFIFO=%t/prudebug/fifo
RemoveOnStop=yes

prudebug.service:

[Unit]
Description=PRU debugger

# make sure the fifo is created first
Requires=prudebug.socket
After=prudebug.socket

[Service]
ExecStart=/usr/local/bin/prudebug

StandardInput=socket
StandardOutput=journal

Tell your systemd user instance to reload its config with
systemctl --user daemon-reload
and then start your service with
systemctl --user start prudebug
or alternatively you can just start the socket unit with
systemctl --user start prudebug.socket
which will create the fifo:

@beaglebone:~$ ls -l $XDG_RUNTIME_DIR/prudebug/fifo
prw-r--r-- 1 debian debian 0 Jul 15 18:40 /run/user/1000/prudebug/fifo|

and then systemd will automatically start the prudebug service when anything is written to the fifo.

Note that stopping the prudebug service will not stop the socket unit, hence the service will be started again if anything is written to the fifo, which systemd will warn you about:

@beaglebone:~$ systemctl --user stop prudebug
Warning: Stopping prudebug.service, but it can still be activated by:
  prudebug.socket

If this is undesirable use
systemd --user stop prudebug.socket
instead (which will also stop the prudebug service because of its Requires dependency), or add
PartOf=prudebug.service
to the [Unit] section of prudebug.socket to automatically propagate stop/restart commands from prudebug to prudebug.socket (though systemctl will erroneously still give the warning, unfortunately).

Beware that by default when the last session of a user logs out, the user’s systemd instance is terminated hence so are the user services managed by it. If you don’t want that, enable “linger” mode for the user:
sudo loginctl enable-linger debian
Note that this will also cause the user’s systemd instance to be started at boot rather than at first login.

Auto-starting services

If you want the socket unit to automatically start when the user’s systemd instance is launched, add

[Install]
WantedBy=sockets.target

to prudebug.socket and then enable the unit with
systemctl --user enable prudebug.socket

If you want the prudebug service to auto-start use

[Install]
WantedBy=default.target

and systemctl --user enable prudebug

Beware however that if you’ve enabled linger-mode for the user as described above then this would cause these units to be started at boot just like system services, which is fine for the socket but with prudebug there might be a risk that it’s started too early, before the uio device is accessible.

I get the impression want to start prudebug on request rather than at boot so I won’t go into details on how to fix this problem, but if you want those details just ask.

Service output

In this example I’ve configured the StandardOutput of prudebug.service to go to journal, which you can monitor with journalctl, e.g.
journalctl --user-unit prudebug
or if you just want to capture the raw output in real-time, without any history:
journalctl -t prudebug -o cat -n0 -f

Alternatively you could ask systemd to send the output to file, e.g.:
StandardOutput=append:%t/prudebug/output
but beware that this never rotates, except at reboot since the location chosen here is in a tmpfs.

Using truncate: instead of append: would be better, to get a fresh output log each time prudebug is started, but unfortunately the systemd version in debian buster (v241) and bullseye (v247) are too old to support it, you’d need the one from bullseye-backports (v250) at a minimum. There’s an easy workaround however, just add
ExecStartPre=/bin/rm -f %t/prudebug/output
to the [Service] section.

Beware also that if rsyslogd is installed (which is the case on the IoT debian images) then it will log some (most? all?) stuff from journal to one or more files in /var/log/ based on how it’s configured. I personally always remove rsyslog to avoid unnecessary eMMC writes and because it is redundant.

Journal itself can be either persistent or kept in ram depending on whether /var/log/journal/ exists or not, but on the beagleboard images this directory doesn’t exist by default hence journal is just kept in ram. Configurable size limits are imposed in either case.

The netcat thing

It’s a complete mystery to me why you’re also using TCP sockets instead of just writing to the fifo directly from the perl script. Recreating this socket that forwards data to the fifo is something that can also be done fairly easily with systemd (and without need for netcat), but I’d like to know what its purpose is before putting any effort into that.

(Also, why on earth are you spawning netcat from the perl script instead of just using IO::Socket::INET to create a TCP socket?)

1 Like

[quote]I haven’t looked at what your wrapper does in detail.{/quote]

and yet you puke pablum about how you could do it better and how badly I did it.

“The proof of the pudding is in the EATING”… it is easy to describe your solution, how much simpler or better or elegant it is to the current !working model! … MUCH MORE DIFFICULT is to complete an alternative model that also works.

my challenge to you was to post a SOLUTION for comparison… instead, you merely point out alternative approaches, SOME of which MAY work.

The implementation that I posted does work, and it works NOW.

The details of your post are unworthy of further time

gomer

Jesus, chill dude, I just briefly mentioned some other possibilities in the general solution space at the start of my post, that does not invalidate your work. I perfectly well understand the value of something that works right now built using tools you happened to be familiar with.

I have not looked at the functionality of your project in detail yet because I was answering your specific question, hence I focussed on what you were using daemontools for. My assumption was that your question meant you were interested in learning how the functionality provided by systemd, which is an integral part of nearly every linux distro nowadays, can be leveraged to replace daemontools, which hasn’t been maintained in two decades. That’s why I spent the time on writing a detailed explanation for the specific use-case I identified in your project, making sure to test everything I said works on a beaglebone running the current default image. I did not offer a similar thing for the service that fowards data from TCP to the fifo because I do not understand its purpose, and I’m hesitant to offer a literal substitute for something I don’t understand since I might be missing some subtle requirement.

What I was offering is guidance on how to apply systemd to your specific needs, if you’re interested in that. If you’re not and prefer to stick with daemontools, that’s obviously perfectly fine too.