This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3358: TSC ADC

Part Number: AM3358
Other Parts Discussed in Thread: ADS1115

We have an prototype system using the BeagleBone Black which is based on the AM3358 SOC.
We are running Debian Linux Buster and write our code in C.

The application currently reads two channels of the ADC (TSC) with a PRU using C code.  The code sets up the ADC and then triggers the read.

We need to read a third channel but need to read it with C code running on the ARM section of the SOC.  Before putting a lot in to this, a) is this possible, b) will there be issues with conflicts and c) if so, what is the best practice for doing this, if indeed there is one. 

Thanks!

  • Hello Walter,

    It is tricky to directly share a single peripheral between different software instances (Linux, and PRU). The hardware is not designed to keep track of multiple software owners, so Linux and the PRU core could accidentally overwrite each other's settings, etc.

    Design discussion

    We actually had to solve a similar issue with the Linux drivers. The Linux touchscreen driver was not written to share a peripheral with any other software tasks, and neither was the ADC driver. But we have 8 ADC channels, and it was pretty common for customers to want to use 4-5 channels for resistive touchscreen, and the other channels for general ADC work. What we ended up doing was creating a single low-level driver that owned the ADC hardware (tscadc). The higher-level touchscreen (tsc) and adc drivers have to interact with the tscadc driver, and then the tscadc driver is the single owner who interacts with the ADC peripheral.

    The easiest option would probably be to do a similar concept for your Linux / PRU design. The simplest (but least optimized) design that occurs to me is to keep PRU as the ADC owner as you currently have, and then have Linux send an RPMsg to request the PRU to trigger an ADC read, and then the PRU sends the data back in another RPMsg message.

    There are a bunch of additional optimizations that could be done (e.g., develop a custom Linux driver to receive interrupts and send data faster and more efficiently than RPMsg), but that would represent additional development work for you. So let's not over-engineer a solution if it is not needed.

    Existing example from TI

    For future readers who are looking to get started with PRU/ADC development on AM335x, I do provide a basic example of the PRU core controlling the AM335x on-chip ADC in the PRU Software Support Package here:
    https://git.ti.com/cgit/pru-software-support-package/pru-software-support-package/tree/examples/am335x/PRU_ADC_onChip 

    I haven't touched that code in 7 years, so I cannot remember if I had to do anything fancy to clock the ADC peripheral while disabling the ADC in the Linux devicetree, or if the PRU code in init_adc was sufficient. Let me know if you have any feedback on that example based on your own experience.

    Usecase questions

    What kind of data throughput is needed for the ADC readings going to Linux? (i.e., how often will you want to trigger an ADC read, and how many ADC reads will you want to do at once?)

    Do you have latency requirements for how long it takes the ADC read to execute?

    Regards,

    Nick

  •   Thank you for this thorough and thoughtful response.   We have been using the PRU to read the ADC on this system in development for several years and it works very, very well.   To answer your question, we read it (call it sensor A) as fast as it possible continuously while the machine is operating.  We're analyzing a signal from a sensor to detect particles flowing by in a stream of fluid.  I have not checked the read rate lately as I don't do the the actual application programming anymore.   The ARM side would ideally read the second analog input at a very similar rate.   This input is the inverse of the output of sensor A.  The goal is to read it so that we can track what the baseline output is and adjust it if there is any drift.  It's a bit much to put in this thread.   But given your answer, I do think the best solution is probably to use a second I2C connected ADC to read this second analog input. It's not much of an issue as we have experience with a suitable I2C ADC (ADS1115).

    To your point about other readers, reading the TSC with the PRU works well and it's a powerful unit once you understand how it works.  The most important thing anyone can do first is read the technical reference manual sections on the TSC.  That's really helpful.

  • Thank you for your response Walter, I appreciate it!

    From a software development perspective, adding a separate ADC for Linux to own would definitely be the simpler option - then no need to worry about reads for the inverse of A, etc.

    However, if you need a shared timebase for your measurements so that you can associate sensorA measurement #X with ~(sensorA) measurement #X, that could be problematic. Especially if Linux is manually triggering reads, I would expect that it would sample the external ADC much more slowly than PRU with the on-chip ADC.

    If a shared timebase is needed, you may be able to just add the additional reads without impacting your current timing (assuming that the PRU core has idle time between reads). If you are only using one PRU core in your current design, you could keep one PRU core interacting with the ADC, and then program the other core to do data transfer with Linux, basic data processing of the ADC reads, etc.

    Regards,

    Nick