Using PRU1 to configure ADC so PRU0 can use it

I have code working on PRU0 that reads two analog inputs. It all works, but we’re running out of memory for our program. So, I thought I could move the routine configuring the ADC to a program that runs only on PRU1. I will run that code to get the ADC configured and start the main code on PRU0. Once the code completes on PRU1 it doesn’t do anything else. Everything is written in C.

I’ve moved the ADC configuration code to a separate file to run on PRU1 and removed it from the file running on PRU0. Both files compile and appear to run. I can’t confirm this because our ARM code now thinks PRU0 is not running its code because, when it tries to query remoteproc configuration for confirmation, it fails.

Is what I’m trying to do even feasible? Can one PRU configure the ADC so the other one can use it?

You obviously can–pin configuration is the biggest sticking point. The BBB can reconfigure pins after boot while the BBBAI can’t. I don’t know if the BBBAI64 can or not.

But I would ask: why not just configure the ADC from Linux user space and then hand control over to PRU0? There’s no particular advantage to doing configuration on a PRU and there’s a lot of downsides.

I would be satisfied configuring the ADC from Linux space but I don’t know how to set things like number of steps, channels, and averaging in Linux space and haven’t found the references to help me learn how to do it. i think that would definitely be better

Do you know of any references or examples?

This is the onboard ADC on the BBB? I assumed this was an off-board thing.

The ADC inputs are part of the touchscreen controller, no? That’s Chapter 12 of the “AM335x and AMIC110 Sitara™ Processors Technical Reference Manual”.

You configure that the exact same way whether you are doing it from PRU0, PRU1 or the main processor. The registers should be identical as they don’t have local PRU mappings.

How are you currently configuring it?

Yes, we are using the on board TSC for the ADC.

I’ve become very familiar with the chapter on it in the TRM. :). It is actually a very flexible device and working well on this application.

I use three channels of it 0, 4 & 5. They are configured to be read in one shot mode in succession as steps 1, 2 and 3.
We have it average 8 readings I think. we may have backed down to four. i don’t have the code in front of me to confirm.

The Linux side should have access to the registers so I will investigate further.

Walter

Aw, crud. Right. mmap(). On Linux, you’re going to have to be root and hit the registers using mmap().

I have an old thread using mmap() on GPIO:
https://groups.google.com/g/beagleboard/c/tWYwpdXBDAY

And Mark Yoder has one here:
https://elinux.org/EBC_Exercise_11b_gpio_via_mmap

It doesn’t look like these work with the ADC device directly but do provide some good information for working with memory mapped devices directly. So I’ll dig into them more.

This is ironic as when I first started working with microcontrollers many, many years ago, it’s the primary way we programmed them. When I returned to this work a few years ago, that’s how I wanted to do everything. I wasn’t used to having the tools that make it all easier now. But I digress.

Quick thought, though. If the ADC configuration is persistent, I could conceivably use our existing code for the PRU0, load it as PRU0’s firmware, start PRU0 and let it run, stop PRU0 on completion, then change the firmware for PRU0 to our main control program and start that code. Then I wouldn’t have to use PRU1 at all. The big question is how persistent is the configuration of the ADC? Any idea?

You should be able to run the PRU0 twice and have the ADC state persist. The configuration of the ADC should persist fine unless something else comes along and resets it, powers down the L3 bus, etc.

One other thing that I tend to do since the PRUs are so small is that I create a command that does “read register” and “write register” so that I can send a complex chain of simple commands to the PRU–this lets a Linux program outside do a whole bunch of initialization and then kick off the PRU to do its bit. This can be particularly useful if you have to do lots of conditional waiting or complex calibration, for example.