Search by Tags

SoC Temperature Readout (WinCE)


Article updated at 02 Feb 2018
Compare with Revision

This article demonstrates how to read Colibri/Apalis internal Soc temperature.

Colibri PXAxxx

PXAxxx processors do not have internal temperature sensors. External temperature sensor must be added to the carrier board if temperature measurements are required.

Colibri/Apalis Txx

To measure Temperature of Soc on Colibri T20, T30 and Apalis T30 module use following C code:

#include <windows.h>
/// Temperature zone
typedef enum
    NvRmTmonZoneId_Module = 1,  ///< specifies the temperature sensor located on the module, away from the CPU.
    NvRmTmonZoneId_Core   = 2,  ///< specifies the temperature sensor measuring the CPU core voltage
} NvRmTmonZoneId;
/// NvError NvRmDiagGetTemperature(NvRmDeviceHandle pHandle, NvRmTmonZoneId ZoneId, DWORD* pTemperatureC);
/// Read a temperature from the on-module temperature sensor
/// @param[in]  pHandle         not required. Always set to 0
/// @param[in]  ZoneId          specifies which temperature sensor to read
/// @param[out] pTemperatureC   measured temperature in degree C
/// @return                     0 indicates success, any other value indicates an error
typedef DWORD (*PFNNvRmDiagGetTemperature)(DWORD, NvRmTmonZoneId, DWORD*);
PFNNvRmDiagGetTemperature NvRmDiagGetTemperature;
/// Demo function to read the temperatures on Tegra modules
/// To keep the code simple, there is no error handling implemented.
int _tmain(int argc, _TCHAR* argv[])
    HMODULE hMod;
    DWORD   moduleTemperature;
    DWORD   cpuTemperature;
    // evaluate function pointers
    NvRmDiagGetTemperature  = (PFNNvRmDiagGetTemperature)GetProcAddress(hMod, L"NvRmDiagGetTemperature");
    // read temperatures
    NvRmDiagGetTemperature(0, NvRmTmonZoneId_Module, &moduleTemperature);
    NvRmDiagGetTemperature(0, NvRmTmonZoneId_Core,   &cpuTemperature);
    return 0;

In C# the following code can be used:

// definition of the native code call
public static extern UInt32 NvRmDiagGetTemperature(UInt32 pHandle, UInt32 ZoneId, out UInt32 TemperatureC);
// To actually read the temperature:
    UInt32 retVal;
    UInt32 tempModule;
    UInt32 tempCpu;
    retVal = NvRmDiagGetTemperature(0, 1, tempModule);    
    retVal = NvRmDiagGetTemperature(0, 2, tempCpu);

Colibri VFxx

To measure temperature of Soc on Colibri VF50, VF61 module use following code:

#include <windows.h>
#include "winioctl.h"
#define ADC_AVG_32      3
#define ADC_MODE_10BIT  1 
typedef struct
    BYTE        channel;                                // ADC channel used
    BOOL        useaverage;
    BOOL        avgsamples;                             // Number of samples to be averaged to get value
    BOOL        mode;                                   // ADC mode 8, 10, 12 bit mode
typedef struct
    DWORD       vTemp25;                                // V_Temp value at 25 'C at VDD 3.3V see ADC electrical characteristic in datasheet
    float       slopeCoefficient;                       // temperature slope value used to calculate temperature see datasheet
    BYTE        channel;                                // temperature sensor connected to 26 channel of adc
int wmain()
    HANDLE      adc0            =   NULL;               // handle to adc device
    ADC_READ    adcRead;                                // ADC configuration 
    TEMPERATURE_SENSOR tempSensor;                      // Internal temperature sensor configuration
    DWORD       adcValue        =   0;                  // variable to get adc value
    DWORD       returned        =   0;                  // variable holds number of bytes returned by DeviceIoControll      
    float       temperature     =   0;                  // variable to hold temperature reading
    DWORD       error           =   0;                  // error value used by Getlasterror to return error          =   26;                 // Temperature sensor channel
    tempSensor.slopeCoefficient =   1.8;                // temp slope to calculate value
    tempSensor.vTemp25          =   721;                // VTemp at 25 'C
    adcRead.useaverage          =   TRUE;   
    adcRead.avgsamples          =   ADC_AVG_32;         // 32 samples averaged                                      
    adcRead.mode                =   ADC_MODE_10BIT;     // ADC used in 10 bit mode             =; // adc_channel 26 connected to internal temperature sensor
    // provide handle to adc0
        printf("GetLastError %x\r\n", GetLastError());
        printf("ERROR - opening ADC0\r\n");
        return -1;
    // get adc value at channel 26(temperature sensor)
    if(!DeviceIoControl(adc0, IOCTL_ADC_READ, &adcRead, sizeof(ADC_READ), &adcValue, sizeof(DWORD), &returned, NULL))
        printf("GetLastError %x\r\n", GetLastError());
        printf("ERROR - Reading ADC value at channel %d\r\n",;
        return -1;
    temperature = 25 - ((adcValue*3.22 - tempSensor.vTemp25)/tempSensor.slopeCoefficient);// calculation to obtain temperature
    printf("Temperature is %2.2f 'C\r\n", temperature);
    printf("Press Enter to exit \r\n");
    return 0;

Colibri/Apalis iMX6

This code can be used to read SOC temperature on iMX6-based modules

#include "windows.h"
#include "mapmem.h"
int _tmain(int argc, _TCHAR* argv[])
	// Init map mem lib
	HANDLE maphandle=Map_Init();
	// we need to map the OCOTPANA1 fuse to read calibration values
	volatile DWORD* ocotpana1;
	// split the value into room temperature (25C) value, hot value and hot reference temp
	DWORD roomcount,hotcount,hottemp;
	// map the TEMPMON registers (TEMPSENSE0 and TEMPSENSE1, both have separate registers to set,clear and toggle bits)
	volatile DWORD *tempsense0,*tempsense1;
	volatile DWORD *tempsense0set,*tempsense0clr,*tempsense0tog;
	volatile DWORD *tempsense1set,*tempsense1clr,*tempsense1tog;
	// disable auto updates
	//set alarm to max value (we are not using the interrupt)
	// power-on sensor
	// measure
	for (;;)
		// clears start flag
		// start
		// wait until measured value is valid
		while (!(*tempsense0 & 0x00000004))
		// calculate temperature in Celsius
		DWORD tempcount=(*tempsense0 >> 8) & 0x00000FFF;
		DWORD tmeas=(DWORD)((double)hottemp-(tempcount-hotcount)*((hottemp-25.0)/(roomcount-hotcount)));
		// print it out
		_tprintf(TEXT("Temperature: %d\r\n"),tmeas);
		RETAILMSG(1,(TEXT("Temperature: %d\r\n"),tmeas));
		// wait a second before doing a new measurement
	return 0;

Download projects

You can download demo source code for Apalis/Colibri Txx from here, for Colibri VFxx from here and for Apalis/Colibri iMX6 from here.