讀取cpu溫度的api 讀取CPU核心溫度

2021-10-13 09:14:36 字數 4387 閱讀 1055

最近在搞乙個讀取cpu溫度的驅動,網上翻了好多資料,可發現全是copy的,原稿也就兩三篇,可經實踐發現其中不乏錯誤與片面,讓人著實走彎路,燃起了我要總結一番的慾望。

這個驅動搞了乙個多星期,總算可以執行了,測試了幾台intel和amd的機器也都測試通過,測試對比用的是cpuid hwmonitor和core temp。

intel和amd的cpu中都有溫度感測器(dts),每個核心都有乙個,溫度就是由此獲取來的,多核cpu可以使用 setprocessaffinitymask api 來指定執行的cpu。

首先是利用cpuid來區分是intel型號還是amd型號,利用彙編和函式都可實現,考慮到64位系統不支援嵌入彙編,所以還是直接利用api函式就行。

cpuid其實就是對eax執行cpuid指令,返回資訊儲存在eax,ebx,ecx,edx中,令eax=0,可將cpu廠商資訊返回在ebx,ecx,edx中,

int cpuinfo[4];

__cpuid(cpuinfo,0);

intel資訊字串為genuineintel,amd為authenticamd,只判斷前4個字元就可以,只需與cpuinfo[1](ebx)比較就可得出型號。

接下來說如何獲取溫度,先從簡單的說起,intel實現起來比較簡單:

先以eax=0 執行 cpuid 檢測 eax 支援的最大命令數,如果小於6就肯定不支援dts。然後以eax=6 執行 cpuid,  然後測試 eax 第一位是否為1,如果為1表示cpu支援dts。

讀取dts:以 ecx=0x1a2 執行 rdmsr 指令, 測試 eax 的第30位是否為 1, 如果為 1 表示溫度計算的初始值為 85 度否則表示從100度開始計算,這個值稱為 tjunction.

eax=__readmsr(0x01a2)

然後以 ecx=0x19c 執行 rdmsr 指令,  eax 的 16-23 位為表示當前dts 值,當前溫度要以下面公式計算.

當前cpu溫度 = tjunction - dts

注意  signature 為 0x6f1, 0x6f0的 cpu dts 值直接代表當前溫度而不用tjunction 相減. 而 signature 小於等於 0x6f4 的 tjunction 一直為100。

amd溫度儲存在nb暫存器中,這是乙個熱感測暫存器。amd的cpu分為k8和k10,k8的溫度儲存在這個暫存器的23-14位,k10的在31-21位。

要訪問這個狀態暫存器,需要對pci進行讀寫。

先介紹倆個pci用到的暫存器,cf8h和cfch

cfch: 儲存配置空間的讀寫資料(config-data)

這兩個空間對應於pci橋路的兩個暫存器,當橋路看到cpu在區域性匯流排對這兩個 i/o空間進行雙字操作時,就將該i/o操作轉變為pci匯流排的配置操作。

溫度讀取

如果是k8的話,可以忽略低倆位,讀取23-16就可以了,當然也可以讀23-14,然後\4或者》2;

如果是k10的話,那就讀取31-21

如何判斷k8,k10

__cpuid(cpuinfo,1); //cpuid執行1,取出eax

t=cpuinfo[0];

family=((t>>20)&0xff) + ((t>>8)&0xf);

model=((t>>12)&0xf0) + ((t>>4)&0xf);

stepping=t&0xf;

如果family ==0xf 而除了

(((model == 4) && (stepping == 0)) ||

((model == 5) && (stepping <= 1)))

則為k8

如果family > 0xf,一般是g。那就是k10

溫度的計算公式

k8 temp = value - 49'.   49這個值需要修正的:if (model >= 0x69 && model != 0xc1 && model != 0x6c && model != 0x7c)  temp=value-49+21;

k10 temp = value / 8'.

31      24 23         16 15            11 10              8 7               2 1   0

| reserve | bus number | device number | function number | register number | 0 | 1/0 |

所以知道 bus number, device number, function number, register number後,可以這麼來構造配置空間位址暫存器

ioaddr = 0x80000000+bus*0x10000 +(device*8)*0x100 + ufunction&0x07 + register number&~3;

為什麼需要0x80000000呢,因為

當cpu發出對i/o空間cfch的操作時,pci橋路將檢查配置空間位址暫存器cf8h的31位。如果為1,就在pci匯流排上產生乙個相應的配置空

間讀或寫操作,0x80000000就是使配置空間位址暫存器為1。

經過上面的討論後,可以寫成

#define deviceslot(udevice, ufunction) ((((udevice)&0x1f)<<3)|((ufunction)&0x07))

#define getdevice(ubus,uslot,uaddress) (0x80000000l |((ubus&0xff)<<16)|(uslot<<8)|(uaddress&~3));

這樣知道 ubus, udevice, ufunction, uaddress後就可以通過io指令來讀寫了。

對於k8, uaddress為0xe4,對於k10 uaddress為0xa4

怎樣獲取ubus, udevice, ufunction從上面知道getdevice需要 ubus, udevice, ufunction的。

可以掃瞄pci匯流排來獲取,對於amd k8來說,裝置id為0x1103,對於k10來說,裝置id為0x1203。 二者的ufunction都為3.

通過掃瞄pci匯流排,匹配裝置id來獲取。

bool get_bus_dev( int devieid,int *bus, int *dev ) //遍歷pci得到bus和dev

ulong bus;

ulong dev;

ulong func=3; //k8 k10 fun為3

unsigned long size;

pci_common_config pciconfig;

pci_slot_number slotnumber;

for(bus = 0; bus <= 255; ++bus)

for(dev = 0; dev <= 31; ++dev)

slotnumber.u.asulong = 0;

slotnumber.u.bits.devicenumber = dev;

slotnumber.u.bits.functionnumber = func;

rtlzeromemory(&pciconfig, sizeof(pci_common_config));

size = halgetbusdata(pciconfiguration,

bus,

slotnumber.u.asulong,

&pciconfig,

pci_common_hdr_length); //api函式

if (size==pci_common_hdr_length)

if ( devieid==pciconfig.deviceid )

*bus=bus;

*dev=dev;

dbgprint("bus:%d \n",bus);

dbgprint("dev:%d \n",dev);

return true;

return false;

然後進行io讀寫就可以獲取溫度了,k8:

static once =1;

if (once)

int bus,dev,slot;

if ( !get_bus_dev(0x1103,&bus,&dev) )

dbgprint("獲取bus、dev失敗! \n");

return;

slot=deviceslot(dev,0x3);  //上面定義的巨集

io_addre=getdevice(bus,slot,0xe4);  //上面定義的巨集

once=0;

_outpd(0xcf8,io_addre);//埠讀寫

cputemp=_inpd(0xcfc);//埠讀寫

cputemp=(cputemp>>16)&0xff;

cputemp=cputemp - g_offset;//g_offset為49-21

dbgprint("cputemp: %d \n",cputemp);

讀取cpu溫度的api 獲取CPU的溫度的方法

獲取 cpu的溫度的方法 在記憶體配置較低的計算機中 比如記憶體 32mb windows 98第二版 cpu的占有率是較高的,一般能夠達到 50 這可能是由於系統 需要cpu 進行許多的運算模擬來彌補資源的不足。下面是收集獲取 cpu溫度的方法,歡迎閱讀。作為乙個系統級程式設計師或者程式設計愛好者...

3288讀取cpu溫度失敗問題

rk3288使用tsadc temperature sensor adc 來測量cpu溫度,支援兩種模式 使用者自定義模式 主動控制讀取溫度.自動模式 自動檢測溫度,達到閥值就自動報告.dts配置如下 tsadc tsadc tsadc ff280000 用指令讀取cpu溫度 cat sys cla...

esp8266讀取溫度

使用esp8266模組獲取天氣的at指令設定方法 1 使用串列埠傳送指令at cwmode 1設定模組wi fi應用模式為station模式 2 傳送指令at rst重啟模組使應用模式更改生效 3 傳送指令at cwjap ssid pwd 連線ap 4 傳送指令at cipmux 0設定模組為單路...