Processors
Intel® Processors, Tools, and Utilities
14639 Discussions

How to get the values of on die digital thermal sensors for Atom D510?

idata
Employee
2,936 Views

Hello experts,

I want to monitor DTS measurements for Atom D510 on QNX. Thanks to MSangalli, he gave me an example codes (lists as following) using MSR which I think it is for CORE series CPU. So there are some more technical details need to be comfirmed here.

1. what are the parameters for D510, 100C Tjunction_max? 0x19C for x86_msr_read() call?

2. how to get values for each core?

3. the sample codes can run OK. But the result prints that 100-th=100-84=16C, much different from BIOS monitoring result 58~64C. how to modify the codes for D510?

Any suggestions are greatly appreciated!!

Allen Chen

0 Kudos
1 Reply
idata
Employee
1,766 Views

The example codes list here.

/*

 

* msrsup.c

 

*

 

* Created on: 25/lug/2013

 

* Author: MSangalli

 

*

 

* NOTES ABOUT CPU TEMPERATURES:

 

* Intel defines a certain Tjunction temperature for the processor.

 

* This value is usually in the range between 85癈 and 105癈.

 

* In the later generation of processors, starting with Nehalem, the exact

 

* Tjunction Max value is available for software to read in an MSR.

 

* A different MSR contains the temperature data.

 

* The data is represented as a Delta in 癈 between current temperature and Tjunction.

 

* So the actual temperature is calculated like this 'Core Temp = Tjunction - Delta'

 

* The size of the data field is 7 bits.

 

* This means a Delta of 0 - 127癈 can be reported in theory.

 

* In fact the reported temperature can rarely go below 0癈 and in some cases

 

* (Core 2 - 45nm series) temperatures below 30?or even 40癈 are not reported.

 

*

 

* AMD processors report the temperature via a special register in the CPU's northbridge.

 

* Core Temp reads the value from the register and uses a formula provided by AMD

 

* to calculate the current temperature.

 

* The formula for the Athlon 64 series, early Opterons and Semprons (K8 architecture) is:

 

* 'Core Temp = Value - 49'.

 

* For the newer generation of AMD processors like Phenom, Phenom II, newer Athlons,

 

* Semprons and Opterons (K10 architecture and up), and their derivatives, there is a

 

* different formula:

 

* 'CPU Temp* = Value / 8'.

 

* CPU Temp is because the Phenom\Opteron (K10) have only one sensor per package,

 

* meaning there is only one reading per processor.

 

*

 

* VIA processors are capable of reporting the temperature of each core.

 

* The thermal sensor provides an absolute temperature value in Celsius, there is

 

* no need for any conversion or manipulation.

 

* The Tjunction or TjMax temperature on VIA chips is usually between 70 and 90C.

 

* 90C for the mobile and low power versions and 70C is for the desktop variants.

 

*/

 

# include

 

# include

 

# include

 

# include

 

# include

 

# include

 

# include

 

# include

 

# include

/*

 

* LOw WORD temperature into

 

*/

 

typedef struct x86_term_info

 

{

 

uint32_t th_sts: 1;

 

uint32_t th_sts_log: 1;

 

uint32_t prochot_forcepr: 1;

 

uint32_t prochot_forcepr_log: 1;

 

uint32_t out_of_spec_sts: 1;

 

uint32_t out_of_spec_sts_log: 1;

 

uint32_t th_threshold_status1: 1;

 

uint32_t th_threshold_status1_log: 1;

 

uint32_t th_threshold_status2: 1;

 

uint32_t th_threshold_status2_log: 1;

 

uint32_t reserved0: 6;

 

uint32_t dig_readout: 7;

 

uint32_t rsv1: 4;

 

uint32_t res_in_degrees_celsius: 4;

 

uint32_t rd_valid: 1;

 

uint32_t rsv2;

 

}X86_TERM_T;

typedef struct msr{

 

struct sigevent IntrEvent;

 

intrspin_t sLock;

 

int IntrId; // Int id

 

int msrOp; // Operation to do

 

volatile uint32_t reg_sel; // msr Register index

 

volatile uint64_t val64; // value to read/write

 

}MSR_T;

static MSR_T lv_msr;

 

static

 

const struct sigevent* msr_irq(void* area, int size)

 

{

 

/*

 

* rdmsr/wrmsr are privileged instruction that can be executed

 

* only in the kernel space, so use the interrupt to do the work.

 

*/

 

InterruptLock(&lv_msr.sLock );

 

{

 

switch(lv_msr.msrOp)

 

{

 

default:{;}break;

 

case 1:{

 

// Read MSR register

 

if ( lv_msr.reg_sel )

 

{

 

lv_msr.val64 = rdmsr( lv_msr.reg_sel );

 

lv_msr.reg_sel = 0;

 

}

 

}break;

case 2:{

 

// Write MSR register

 

if ( lv_msr.reg_sel )

 

{

 

wrmsr( lv_msr.reg_sel, lv_msr.val64 );

 

}

 

}break;

 

}

 

lv_msr.msrOp =0; //NOP

 

lv_msr.reg_sel=0;

 

}InterruptUnlock( &lv_msr.sLock );

 

return(&lv_msr.IntrEvent);

 

}

uint64_t x86_msr_read( uint32_t idx )

 

{

 

uint64_t res;

if(0 >= lv_msr.IntrId) return(-1);

// Set command

 

InterruptMask( 0, lv_msr.IntrId );

 

{

 

InterruptLock( &lv_msr.sLock );

 

{

 

lv_msr.reg_sel= idx;

 

lv_msr.msrOp =1;

 

}InterruptUnlock( &lv_msr.sLock );

 

}InterruptUnmask( 0, lv_msr.IntrId );

// Eventually, use a TimerTimeot here...

 

/*********************************************/

 

InterruptWait( 0, NULL );

 

/*********************************************/

// Read result

 

InterruptMask( 0, lv_msr.IntrId );

 

{

 

InterruptLock( &lv_msr.s...
0 Kudos
Reply