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.

Linux/AM4378: ADC data out of order

Part Number: AM4378

Tool/software: Linux

I have an issue where I am setting up an IIO callback buffer for two different consumers.  When I only activate one the ADC data is always correct.  When activating the second the data is out of order sometimes.  I have verified that the data in the DMA buffer is out of order.  I would like to avoid the additional overhead of verifying that the DMA buffer is correct.  Any ideas?

ti-rt-linux-4.14.y branch

ti_am335x_adc.c

  • Hello Joshua,

    I am trying to get a better idea of your setup. You have a single buffer and two consumers, right? How are you activating your consumers? What exactly is your code doing?

    Regards,

    Nick

  • The setup is a device driver that is reading in a single channel from the ADC.  This is configured in the DTB.  There are two devices defined in the DTB using a total of 2 channels.  There are also 4 channels being used by the touchscreen.

    Previously the driver was reading a sample from the ADC in single shot mode using iio_read_channel_raw.  This was causing issues with the touchscreen so we switched to continuous mode.

    The driver now calls iio_channel_get_all_cb which is providing an iio_cb_buffer for each device.  This is working fine for both devices, until the devices are both reading at the same time.  When the second device starts the data coming out of the DMA sometimes starts at channel 2 and sometimes starts at channel 3.  I verified this by changing the DMA to transfer the entire FIFO value and read the ID tag.

  • Hello Joshua,

    I am still having trouble visualizing exactly what you are doing. Could you help me by posting:

    * The parts of your device tree involved

    * Terminal output of your iio devices (e.g., ls -al /sys/bus/iio/devices/iio\:device0/ )

    * Anything else that could be useful

    One thing to keep in mind is that the TSC / ADC driver is designed to allow the touchscreen and the ADC driver to access the same hardware without messing each other up. If you are writing your own driver, you might want to check out this overview of how the TI drivers interact: http://wiki.tiprocessors.com/index.php/Sitara_TSC_ADC_Driver_Overview 

    Regards,

    Nick

  • Here is a stripped down version of what we are attempting to do.  We are using the iio framework to get data from the iio device.  The device is started and stopped when requested by the user.  When only one of the two devices is started everything is fine.  Whenever the second device is started the data comes out of order between 30 and 70% of the time.  

    DTS:

    device1 {
    	status = "okay";
    	io-channels = <&am335x_adc 2>; /* am335x_adc[2] = AIN6 */
    	io-channel-names = "adc_channel_in";
    	...
    }
    device2 {
    	status = "okay";
    	io-channels = <&am335x_adc 3>; /* am335x_adc[3] = AIN7 */
    	io-channel-names = "adc_channel_in";
    	...
    }

    Device Probe:

    static int mydevice_probe(struct platform_device *pdev)
    {
    	struct my_device *mydevice;
    	...
    	mydevice->iio_cb_buff = iio_channel_get_all_cb(&pdev->dev, _ADC_callback, (void*) mydevice);
    	...
    }

    Start Running:

    void start(struct my_device *mydevice)
    {
    	iio_channel_start_all_cb(mydevice->iio_cb_buff);
    }

    Stop Running:

    void stop(struct my_device *mydevice)
    {
    	iio_channel_stop_all_cb(mydevice->iio_cb_buff);
    }

  • Hello Joshua,

    I apologize for the delay. I will have a response for you next week.

    Regards,

    Nick

  • Hello Joshua,

    It does not look like our AM335x ADC driver is capable of segregating samples from two different channels into two different buffers. The ADC IP has two FIFOs, one (FIFO0) for the touchscreen and one (FIFO1) for general ADC samples. When consumers enable more than one channel, the driver just enables all the requested channels and samples arrive to ADC FIFO1 which is picked up by DMA. There is no way to tell the DMA to look at the Tag and classify them into different buffers.

    It looks like you will need to look at the Tags in the sample to classify which samples are from channel 2 and which are from channel 3.

    Regards,

    Nick

  • I believe this implies that all data under continuous mode will not have a specific order as sent to IIO.  Essentially making continuous mode non-functional when enabling more than one channel.  Is that correct?

    Is there a recommended method for reading multiple channels of the ADC that doesn't require the large CPU load of polling them one at a time?

  • Hello Joshua,

    At this point in time, I do not have a single recommended method for reading multiple ADC channels.

    Do the channels always get sampled one after the other? e.g., you don't know if the buffer will start with channel 2 or channel 3. However, once you figure out which is which, will it always proceed like 2 3 2 3 2 3 2... etc? Perhaps that would allow you to reduce polling?

    There are other options. For example, using another core (like the PRU) to separate the ADC buffer data into two separate buffers. However, that would require additional development.

    FYI, I am on vacation the rest of this week. I will return next week.

    Regards,

    Nick