AD9371 temperature reading

I added a debugfs option to read the internal temperature of the AD9371 based on the procedure outlined in the user guide:

MYKONOS_setupTempSensor()
MYKONOS_setAuxAdcChannel(), channel 16
MYKONOS_startTempMeasurement()
MYKONOS_readTempSensor
Here are the printk ouputs added for debug:

ad9371_debugfs_write() - temp cfg: dec 7, offset 0, override 0, window 15

MYKONOS_readTempSensor() - temp sensor code 20

ad9371_debugfs_write() - temp stat: code -83, winExceeded 0, winHiLo 0, valid 1

What am I missing in getting a meaningful temperature value?

Here is the diff for the linux source (needs cleanup, just proof of concept right now):

diff --git a/drivers/iio/adc/ad9371.c b/drivers/iio/adc/ad9371.c
index 9622e2eba09e..25c126775ed2 100644
--- a/drivers/iio/adc/ad9371.c
+++ b/drivers/iio/adc/ad9371.c
@@ -552,6 +552,7 @@ static int ad9371_setup(struct ad9371_rf_phy *phy)
    } else {
        dev_err(&phy->spi->dev, "Requesting device clock %u failed got %ld",
            mykDevice->clocks->deviceClock_kHz * 1000, dev_clk);
+       printk("%s() - %d\n", __func__, __LINE__);
        return -EINVAL;
    }

@@ -561,7 +562,10 @@ static int ad9371_setup(struct ad9371_rf_phy *phy)

    ret = clk_set_rate(phy->jesd_rx_clk, lane_rate_kHz);
    if (ret < 0)
+   {
+       printk("%s() - %d\n", __func__, __LINE__);
        return ret;
+   }

    lane_rate_kHz = mykDevice->obsRx->orxProfile->iqRate_kHz *
            mykDevice->obsRx->framer->M *
@@ -569,7 +573,10 @@ static int ad9371_setup(struct ad9371_rf_phy *phy)

    ret = clk_set_rate(phy->jesd_rx_os_clk, lane_rate_kHz);
    if (ret < 0)
+   {
+       printk("%s() - %d\n", __func__, __LINE__);
        return ret;
+   }

    lane_rate_kHz = mykDevice->tx->txProfile->iqRate_kHz *
            mykDevice->tx->deframer->M *
@@ -577,7 +584,10 @@ static int ad9371_setup(struct ad9371_rf_phy *phy)

    ret = clk_set_rate(phy->jesd_tx_clk, lane_rate_kHz);
    if (ret < 0)
+   {
+       printk("%s() - %d\n", __func__, __LINE__);
        return ret;
+   }

    /* Toggle RESETB pin on Mykonos device */

@@ -2485,6 +2495,45 @@ static ssize_t ad9371_debugfs_write(struct file *file,
            return ret;

        return count;
+   case DBGFS_DIE_TEMP:
+   {
+       mutex_lock(&phy->indio_dev->mlock);
+
+       //mykonosTempSensorConfig_t tcfg = { 7, 67, 1, 15 };
+       mykonosTempSensorConfig_t tcfg = { 7, 0, 0, 15 };
+#if 0
+       ret = MYKONOS_getTempSensorConfig(phy->mykDevice, &tcfg);
+       if ( ret != MYKONOS_ERR_GPIO_OK ) 
+               printk("%s() - %d ERR: %d\n", __func__, __LINE__, ret);
+#endif
+       printk("%s() - temp cfg: dec %d, offset %d, override %d, window %d\n", __func__, tcfg.tempDecimation, 
+                       tcfg.offset, tcfg.overrideFusedOffset, tcfg.tempWindow);
+
+       ret = MYKONOS_setupTempSensor(phy->mykDevice, &tcfg);
+       if ( ret != MYKONOS_ERR_GPIO_OK ) 
+               printk("%s() - %d ERR: %d\n", __func__, __LINE__, ret);
+
+       ret = MYKONOS_setAuxAdcChannel(phy->mykDevice, MYK_TEMPSENSOR);
+       if ( ret != MYKONOS_ERR_GPIO_OK ) 
+               printk("%s() - %d ERR: %d\n", __func__, __LINE__, ret);
+
+       ret = MYKONOS_startTempMeasurement(phy->mykDevice);
+       if ( ret != MYKONOS_ERR_GPIO_OK ) 
+               printk("%s() - %d ERR: %d\n", __func__, __LINE__, ret);
+       msleep( 10 );
+
+       mykonosTempSensorStatus_t tstat;
+       ret = MYKONOS_readTempSensor(phy->mykDevice, &tstat);
+       if ( ret != MYKONOS_ERR_GPIO_OK ) 
+               printk("%s() - %d ERR: %d\n", __func__, __LINE__, ret);
+       printk("%s() - temp stat: code %d, winExceeded %d, winHiLo %d, valid %d\n", __func__, tstat.tempCode,
+                       tstat.windowExceeded, tstat.windowHiLo, tstat.tempValid);
+       mutex_unlock(&phy->indio_dev->mlock);
+       if (ret < 0)
+           return ret;
+
+       return count;
+   }
    default:
        break;
    }
@@ -2551,6 +2600,7 @@ static int ad9371_register_debugfs(struct iio_dev *indio_dev)
    ad9371_add_debugfs_entry(phy, "bist_prbs_obs", DBGFS_BIST_PRBS_OBS);
    ad9371_add_debugfs_entry(phy, "bist_tone", DBGFS_BIST_TONE);
    ad9371_add_debugfs_entry(phy, "monitor_out", DBGFS_MONITOR_OUT);
+   ad9371_add_debugfs_entry(phy, "die_temperature", DBGFS_DIE_TEMP);

    for (i = 0; i < phy->ad9371_debugfs_entry_index; i++)
        d = debugfs_create_file(
diff --git a/drivers/iio/adc/ad9371.h b/drivers/iio/adc/ad9371.h
index dbbd4da798bd..408329ff0ddf 100644
--- a/drivers/iio/adc/ad9371.h
+++ b/drivers/iio/adc/ad9371.h
@@ -39,6 +39,7 @@ enum debugfs_cmd {
    DBGFS_BIST_PRBS_OBS,
    DBGFS_BIST_TONE,
    DBGFS_MONITOR_OUT,
+   DBGFS_DIE_TEMP,
 };

Parents
  • 0
    •  Analog Employees 
    on May 21, 2019 8:00 AM over 1 year ago

    Hey,

    Moved this question to "TES GUI & API Software Support AD9371/AD9375" forum.

    This is a question that is related to Mykonos API.

    Someone here will answer your question.

    Thanks

    Alex

  • 0
    •  Analog Employees 
    on May 22, 2019 4:47 AM over 1 year ago in reply to aardelean

    Please refer attached example temperature sensor C code

    .temperaturSensorExample.zip

  • Thanks for the sample code, but I still can't get it to work.  The sample code has two paths for calling MYKONOS_readTempSensor(), one doesn't set the aux adc channel and it is unclear what the decimation should be set to for the other path.  Looking through the linux driver, the ad9371_setup() function sets the adc decimation to 4, so I set the mykonosTempSensorConfig_t decimation to 4 and experimented w/ values for the other fields but nothing makes sense.  The valid field is set in the returned status.

  • 0
    •  Analog Employees 
    on Jun 12, 2019 7:35 AM over 1 year ago in reply to rrogers

    Please refer below example code. This you can try to run in TES python script or convert to equivalent c code.

    int loop = 5;

    //setting Monitor outputs
    //setting Monitor outputs
    byte ttt = 0x00;
    Link.fpgaWrite(0x100, 0x05000000); //disable ARM JTAG test mode
    Link.Mykonos.setupGpio(255, Mykonos.GPIO_MODE.GPIO_MONITOR_MODE, Mykonos.GPIO_MODE.GPIO_MONITOR_MODE,
    Mykonos.GPIO_MODE.GPIO_MONITOR_MODE, Mykonos.GPIO_MODE.GPIO_MONITOR_MODE,
    Mykonos.GPIO_MODE.GPIO_MONITOR_MODE);
    Link.Mykonos.setGpioMonitorOut(13, 255);
    Link.Mykonos.init_armGpioStructure(1, ref ttt, ref ttt, ref ttt, ref ttt, ref ttt, ref ttt, ref ttt,
    ref ttt, ref ttt, ref ttt, ref ttt, ref ttt, ref ttt, ref ttt, ref ttt, ref ttt);


    //before running this test the part shoudld be programmed.
    MykTempSensorConfig tempSensor = new MykTempSensorConfig();
    tempSensor.TempDecimation = 7;
    tempSensor.Offset = 0x40;
    tempSensor.OverrideFusedOffset = 1;
    tempSensor.TempWindow = 1;

    double AuxADC_CLK = 40000000.00; //40MHz
    double twoTopower = (double) Math.Pow(2, 23);


    double CalculationTime_s = (((1 * twoTopower) + 1.00)) / AuxADC_CLK;

    Debug.Print("Temp code calculation time : " + CalculationTime_s + " seconds");

    /* AUXADC setup */
    Debug.Print("Setting up AuxADC...");
    //read with and without the ADC and see the difference
    //Link.Mykonos.setupAuxAdc(1, 1);
    /* set AuxADC channel for temperature sensor */
    Link.Mykonos.setAuxAdcChannel(0x10);

    /* Start temperature sensor setup */
    MykTempSensorConfig readTempSensor = new MykTempSensorConfig();
    MykTempSensorStatus[] tempSensorRead = new MykTempSensorStatus[loop];
    for (int i = 0; i < loop; i++)
    {
    tempSensorRead[i] = new MykTempSensorStatus();
    }
    var watch = Stopwatch.StartNew(); /* stop watch to see the temperature sensor meas time*/

    Debug.Print("Start of loop ");
    Link.Mykonos.setupTempSensor(ref tempSensor);
    Link.Mykonos.getTempSensorConfig(out readTempSensor);


    /* wait for AUX ADC to settle */
    System.Threading.Thread.Sleep(1000);

    Link.Mykonos.radioOn();
    /* Loop to read temperature sensor single shot mode*/
    for (int i = 0; i < loop; i++)
    {
    tempSensorRead[i].TempValid = 0x00;
    watch = Stopwatch.StartNew();
    Link.Mykonos.startTempMeasurement();
    //read temperature for 6 seconds
    do
    {

    Link.Mykonos.readTempSensor(out tempSensorRead[i]);
    } while (tempSensorRead[i].TempValid == 0 && watch.ElapsedMilliseconds < (CalculationTime_s * 10000));

    watch.Stop();
    System.Threading.Thread.Sleep(1000);
    }
    for (int i = 0; i < loop; i++)
    {
    Debug.Print("temp temp valid = " + tempSensorRead[i].TempValid);
    Debug.Print("Temp Decimation = " + tempSensor.TempDecimation);
    Debug.Print("temp read = " + tempSensorRead[i].TempCode);
    Debug.Print("temp windowHiLo = " + tempSensorRead[i].WindowHiLo);
    Debug.Print("temp windowExceeded = " + tempSensorRead[i].WindowExceeded);
    Console.WriteLine("Time to runtempSensorRead: " + watch.ElapsedMilliseconds + "ms\n");
    }

  • Here's a c version I added to the linux driver.  Steps are pretty much the same as example above, but it returns crazy values around -85. 

    mykonosTempSensorStatus_t tstat = { 0 };
            mykonosTempSensorConfig_t tcfg = { 7, 0x40, 1, 1 };
            int i = 0;
    
            printk("%s() - START DIE TEMP READING...\n", __func__);
            printk("%s() - temp cfg (0x%x): dec %d, offset %d, override %d, window %d\n",
                            __func__, MYK_TEMPSENSOR, tcfg.tempDecimation,
                            tcfg.offset, tcfg.overrideFusedOffset, tcfg.tempWindow);
    
            ret = MYKONOS_setAuxAdcChannel(phy->mykDevice, MYK_TEMPSENSOR);
            if ( ret != MYKONOS_ERR_GPIO_OK )
                    printk("%s() - %d ERR: %d\n", __func__, __LINE__, ret);
    
            ret = MYKONOS_setupTempSensor(phy->mykDevice, &tcfg);
            if ( ret != MYKONOS_ERR_GPIO_OK )
                    printk("%s() - %d ERR: %d\n", __func__, __LINE__, ret);
    
            ret = MYKONOS_startTempMeasurement(phy->mykDevice);
            if ( ret != MYKONOS_ERR_GPIO_OK )
                    printk("%s() - %d ERR: %d\n", __func__, __LINE__, ret);
    
            tstat.tempValid = 0;
            while ( (tstat.tempValid == 0) && (i < 1000) )
            {
                msleep( 10 );
                i++;
    
                ret = MYKONOS_readTempSensor(phy->mykDevice, &tstat);
                if ( ret != MYKONOS_ERR_GPIO_OK )
                    printk("%s() - %d ERR: %d\n", __func__, __LINE__, ret);
    
                printk("> %d: temp stat: code %d, winExceeded %d, winHiLo %d, valid %d\n", i, tstat.tempCode,
                            tstat.windowExceeded, tstat.windowHiLo, tstat.tempValid);
            }
            ret = sprintf(buf, "DIE TEMP: %d\n", tstat.tempCode);

  • Ok, so I noticed temperature readback support was added to master (https://github.com/analogdevicesinc/linux/pull/432#event-2436465414), so I scrapped my changes and pulled in this update.  Still getting crazy values, in the range of -85.  Not sure what it could be at this point.

  • 0
    •  Analog Employees 
    on Jun 26, 2019 5:31 AM over 1 year ago in reply to rrogers

    Can you read the temperature through IIO GUI (DMM tab) and compare with your results?

Reply Children