如何读SPD 信息...(转自英布之剑的博客)

本文介绍了一个通过SMBus接口读取内存模块详细规格参数的程序实现,包括内存类型、工作频率、时序等关键信息。该程序能够识别不同类型的内存并获取其最大带宽、时钟周期及延迟等数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前接到过网友的询问,没有时间回复... 非常抱歉!真正创业的时候,才知道创来是如此不简单... 特别是再也没有这么多空余时间来钻研技术了...

还好,总是能收到网友讨论问题的邮件,让我偶尔还去看一下尘封以久的code, 或是再打开调试一下... 忙,没空写更多的费话,昨晚弄好code就睡了,贴一下出来...

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<dos.h>
#include<math.h>

//#define DEBUG

typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;

#define READ_SPD   0x01
#define WRITE_SPD 0x00

struct SPD
{
WORD MHz;
BYTE tRAS;
BYTE tRCD;
BYTE tCL;
BYTE tRP;
BYTE BL;
};

WORD SMB_Base=0;
SPD spd[3];

//----------------------------------------------------------
//Get SMBus Base address
//----------------------------------------------------------
WORD getSMBase()
{
    DWORD pciaddr;

    // bus:0 dev:31 fun:3, register:20h
    pciaddr = (1L << 31) + (0L << 16)+(31L << 11)+(3 << 8)+ (0x20 & 0xfc);

    asm{
        mov eax,pciaddr
        mov dx,0CF8h
        out dx,eax

        mov dx,0CFCh
        in eax, dx        //read SMB Base

        and ax, 0FFE0h
       }

    return _AX;
}

//----------------------------------------------------------
//Get SMBus Status
//----------------------------------------------------------
BYTE GetSMBusStatus()
{
    return inportb(SMB_Base+0x00);
}

//----------------------------------------------------------
//Check SMBus Ready or not
//----------------------------------------------------------
WORD SMBusReady()
{
     unsigned int m,n,s=0, check,i;

     for(i=0;i<0x80;i++)
     {
       //m=inportb(SMB_Base);     //read status
       m=GetSMBusStatus();
       delay(10);

       outportb(SMB_Base, m);
       delay(1);

       n=m;    //save

       m=m&0x02;                //BIT1:INTR is 1, ready
       if(m!=0)
       goto ret;

       m=n;    //restore

       m=m&0xbf;                //Bit6:INUSE_STS is 0, ready
       if(m==0)
       goto ret;

       m=n;    ///restore

       m=m&0x04;                //Bit2:DEV_ERR not 0, error
       if(m)
       break;
      }

      s=1;

ret:
   return(s);
}

//----------------------------------------------------------
// Check Byte Done Status
//----------------------------------------------------------
WORD CheckByteDone()
{
unsigned   int ss=0,st,i;

for(i=0;i<32;i++)
{
    st=inportb(SMB_Base);
    delay(1);

    st=st&0x80;        //Byte trans done...
    if(st)
      goto back;
    }
   ss=1;

back:
return(ss);
}

//----------------------------------------------------------
//Clear SMBus Status
//----------------------------------------------------------
void ClearSMBusStatus()
{
    outportb(SMB_Base+0x00, 0xFE);
}

//----------------------------------------------------------
//Set Slave Address
//----------------------------------------------------------
void SetSlaveAddress(BYTE flag)
{
    outportb(SMB_Base+0x04, 0xA0|flag);
}

//----------------------------------------------------------
//set command(index)
//----------------------------------------------------------
void SetCommand(BYTE index)
{
    outportb(SMB_Base+0x03, index);
}

//----------------------------------------------------------
//init Byte read
//----------------------------------------------------------
void InitByteRead()
{
    outportb(SMB_Base+0x02, 0x48);
}

//----------------------------------------------------------
//get data
//----------------------------------------------------------
BYTE GetData()
{
    return inportb(SMB_Base+0x05);
}

//----------------------------------------------------------
//read SM Bus
//----------------------------------------------------------
BYTE ReadSMBus(BYTE index)
{
int sts;
BYTE dat;

//set slave address
SetSlaveAddress(READ_SPD);
delay(1);

//set command
SetCommand(index);
delay(1);

//init block read
InitByteRead();
delay(1);

sts=SMBusReady();

if(sts!=0)
{
    return (0xff);
}

dat=GetData();
CheckByteDone();

#ifdef DEBUG
printf("\nData:%02x\n", dat);
#endif

return dat;
}

//----------------------------------------------
//BYTE to ns convert
//----------------------------------------------
float ByteToNs(BYTE dat)
{
   float ns=0.0, ns1=0.0, ns2=0.0;

    ns1=(float)(dat>>4);

    //ns2
    dat&=0x0f;

    if(dat<=9)
    {
      ns2=(float)(dat/10);
    }
    else if(dat==10)
    {
      ns2=0.25;
    }
    else if(dat==11)
    {
      ns2=0.33;
    }
    else if(dat==12)
    {
      ns2=0.66;
    }
    else if(dat==13)
    {
      ns2=0.75;
    }

    ns=ns1+ns2;
    return ns;
}

//----------------------------------------------
//BYTE to ns convert2
//----------------------------------------------
float ByteToNs2(BYTE dat)
{
   float ns=0.0, ns1=0.0, ns2=0.0;

    ns1=(float)(dat>>2);

    //ns2
    dat&=0x03;
    ns2=dat*0.25;    //0.0, 0.25, 0.50, 0.75

    ns=ns1+ns2;
    return ns;
}

//----------------------------------------------
// Show Memory Type
//----------------------------------------------
void ShowMemoryType(BYTE dat)
{
    switch(dat)
    {
      case 2:
        printf("EDO ");
        break;
      case 4:
        printf("SDRAM ");
        break;
      case 6:
        printf("DDR ");
        break;
      case 7:
        printf("DDR ");
        break;
      case 8:
        printf("DDR2 ");
        break;
      default:
        printf("UNKNOWN ");
        break;
    }
}

//----------------------------------------------------------
// Get Memory Capacity
//----------------------------------------------------------
WORD getMemCap(BYTE dat, BYTE rank)
{
WORD cap;

switch(dat)
{
    case 0x01:
      cap=1024*rank;
      break;
    case 0x02:
      cap=2048*rank;
      break;
    case 0x04:
      cap=4096*rank;
      break;
    case 0x08:
      cap=8192*rank;
      break;
    case 0x10:
      cap=16384*rank;
      break;
    case 0x20:
      cap=128*rank;
      break;
    case 0x40:
      cap=256*rank;
      break;
    case 0x80:
      cap=512*rank;
      break;
    default:
      cap=0;
    }

    return cap;
}

//----------------------------------------------------------
// Main Program
//----------------------------------------------------------
void main()
{
int sts=0, i=0;
BYTE dat;
float ns[3], tRP, tRCD, tRAS;
WORD MHz, cap;
BYTE rank=0,DDR=1,BL=0,CLX=0;

//--------------------------------------------
//get SMB Base
//--------------------------------------------
SMB_Base =getSMBase();

#ifdef DEBUG
printf("SMB_Base:%04X\n", SMB_Base);
#endif

//--------------------------------------------
//sure SMBus Ready first
//--------------------------------------------
sts=SMBusReady();

if(sts!=0)
{
    printf("SMBus not Ready0!\n");
    goto Exit;
}

//--------------------------------------------
//read Memory Type
//--------------------------------------------
dat=ReadSMBus(0x02);   //Byte 2

if (dat != 0xff)
{
printf("This DRAM is ");

    if (dat==6 || dat==7)
      DDR=1;
    else if (dat==8)
      DDR=2;

    ShowMemoryType(dat);
}
else
{
    printf("read SMB error1!\n");
    goto Exit;
}

//--------------------------------------------
//read SDRAM Cycle Time
//--------------------------------------------
dat=ReadSMBus(0x09); //Byte 9

if (dat != 0xff)
{
    ns[0]=ByteToNs(dat);
    MHz= (WORD)(1.0 /(ns[0]*pow(10,-9)) /1000000.0 * DDR+0.5);

    printf("%d,", MHz);
}
else
{
    printf("read SMB error2!\n");
    goto Exit;
}

//--------------------------------------------
//read Memory Rank information
//--------------------------------------------
dat=ReadSMBus(0x05); //Byte 5

if (dat != 0xff)
{
    dat&=0x07;
    rank=dat+1;

    printf("%d Rank,", rank);
}
else
{
    printf("read SMB error3!\n");
    goto Exit;
}

//--------------------------------------------
//read Memory Size Information
//--------------------------------------------
dat=ReadSMBus(0x1F); //Byte 31

if (dat != 0xff)
{
    cap=getMemCap(dat, rank);
    printf("%d MB\n", cap);
}
else
{
    printf("read SMB error4!\n");
    goto Exit;
}

printf("--------------------------------------------\n");

//-------------------------------------------
//read min Clock X-1, 2
//-------------------------------------------
dat=ReadSMBus(0x17);   //Byte 23

if (dat != 0xff)
{
    ns[1]=ByteToNs(dat);

    #ifdef DEBUG
    printf("%.2f", ns[1]);
    #endif
}
else
{
    printf("read SMB error5!\n");
    goto Exit;
}

dat=ReadSMBus(0x19);   //Byte 25

if (dat != 0xff)
{
    ns[2]=ByteToNs(dat);

    #ifdef DEBUG
    printf("%.2f", ns[2]);
    #endif
}
else
{
    printf("read SMB error6!\n");
    goto Exit;
}

for(i=0; i<3; i++)
{
if (ns[i]>0)
      spd[i].MHz = (WORD)(1.0 /(ns[i]*pow(10,-9)) /1000000.0 * DDR+0.5);
    else
      spd[i].MHz = 0;
}

//--------------------------------------------
//read tCL
//--------------------------------------------
dat=ReadSMBus(0x12); //Byte 18

if (dat != 0xff)
{
    if (dat|0xDF == 0xFF)
      CLX=5;
    else if (dat|0xEF == 0xFF)
      CLX=4;
    else if (dat|0xF7 == 0xFF)
      CLX=3;
    else if (dat|0xFB == 0xFF)
      CLX=2;

    #ifdef DEBUG
      printf("CLX=%d", CLX);
    #endif
}
else
{
    printf("read SMB error7!\n");
    goto Exit;
}

for(i=0; i<3; i++)
{
    spd[i].tCL = CLX-i;
}

//-------------------------------------------
//read Minimum Active to Precharge Time (tRAS)
//-------------------------------------------
dat=ReadSMBus(0x1E);    //Byte 30

if (dat != 0xff)
{
    tRAS=dat; //ns
}
else
{
    printf("read SMB error8!\n");
    goto Exit;
}

for(i=0; i<3; i++)
{
if (ns[i]>0)
      spd[i].tRAS=(BYTE)(tRAS/ns[i])+1;
    else
    spd[i].tRAS=0;
}

//-------------------------------------------
//read Minimum RAS to CAS Delay (tRCD)
//-------------------------------------------
dat=ReadSMBus(0x1D);   //Byte 29

if(dat != 0xff)
{
    tRCD=ByteToNs2(dat);

    #ifdef DEBUG
    printf("tRCD=%.2f", tRCD);
    #endif
}
else
{
    printf("read SMB error9!\n");
    goto Exit;
}

for(i=0; i<3; i++)
{
if (ns[i]>0)
      spd[i].tRCD=(BYTE)(tRCD/ns[i])+1;
    else
    spd[i].tRCD=0;
}

//-------------------------------------------
//read Minimum Row Precharge Time(tRP)
//-------------------------------------------
dat=ReadSMBus(0x1B);   //Byte 27

if(dat != 0xff)
{
    tRP=ByteToNs2(dat);

    #ifdef DEBUG
    printf("tRP=%.2f", tRP);
    #endif
}
else
{
    printf("read SMB error10!\n");
    goto Exit;
}

for(i=0; i<3; i++)
{
if (ns[i]>0)
      spd[i].tRP= (BYTE)(tRP/ns[i])+1;
    else
    spd[i].tRP= 0;
}

//-------------------------------------------
//read BL
//-------------------------------------------
dat=ReadSMBus(0x16);

if (dat != 0xff)
{
    if (dat|0x07 == 0x0F)
      BL=8;
    else if(dat|0x0B == 0x0F)
      BL=4;
}
else
{
    printf("read SMB error11!\n");
    goto Exit;
}

for(i=0; i<3; i++)
{
    spd[i].BL = BL;
}

//------------------------------------------
//Show result
//------------------------------------------
for(i=0;i<3;i++)
{
if (spd[i].MHz > 0)
{
      printf("%d MHz, tCL=%d, tRAS=%d, tRCD=%d, tRP=%d, tBL=%d\n", spd[i].MHz, spd[i].tCL, spd[i].tRAS, spd[i].tRCD, spd[i].tRP, spd[i].BL);
    }
}

Exit:
printf("Test End!\n");
}

<think>好的,我现在需要帮助用户解决关于spdlog.lib的问题。首先,用户询问的是spdlog.lib的使用方法或下载地址。根据用户提供的引用内容,我需要整理相关信息,并确保回答准确且符合格式要求。 首先,查看用户提供的引用内容。引用[1]提到替换libspdlog.a文件,这可能与编译后的静态库有关,但用户需要的是.lib文件,通常是Windows下的静态库。引用[4]提到了使用VS2019编译生成安装包,可能涉及生成.lib文件。引用[5]则指向GitHub项目地址,这里可能有相关的文档或构建说明。 接下来,我需要确认spdlog.lib的生成方法。通常,在Windows环境下使用CMake构建项目时,选择正确的生成器(如Visual Studio)会生成.lib文件。引用[2]和[4]提到使用CMake和VS2019进行编译,这可能是关键步骤。需要指导用户如何通过CMake配置项目,生成解决方案文件,然后用VS编译,从而得到spdlog.lib。 关于下载地址,引用[4]提到了一个优快云的链接,但用户可能需要官方来源。GitHub仓库(引用[3]、[5])是官方地址,用户应从这里获取代码,而不是第三方链接。需要建议用户从GitHub克隆代码并自行编译,以确保版本正确和安全。 使用方法方面,用户可能需要包含头文件和链接.lib库。引用[2]提到头文件路径设置为${STAGING_DIR}/include/,而.lib文件需要添加到链接器选项中。需要指导用户在项目中配置包含目录和库目录,并添加spdlog.lib作为依赖。 同时,用户可能遇到的常见问题包括链接错误或找不到库文件,如引用[1]中的错误,提示替换libspdlog.a,这可能是因为路径设置不正确。需要提醒用户检查库文件路径是否正确,并在编译时确保生成的是正确的.lib文件。 最后,生成相关问题需要考虑用户可能的后续疑问,比如编译问题、配置示例或与其他库的集成。这些问题可以帮助用户更深入地了解spdlog的使用和故障排除。</think>### spdlog.lib 相关使用说明 #### 1. 获取spdlog.lib文件 - **官方源码编译**(推荐): 1. 克隆GitHub仓库:`git clone https://github.com/gabime/spdlog` [^3][^5] 2. 使用CMake生成工程文件: ```bash cd spdlog mkdir build && cd build cmake .. -DCMAKE_INSTALL_PREFIX=你的安装路径 ``` 3. 使用Visual Studio打开生成的`spdlog.sln`,编译**Release x64**模式,生成`spdlog.lib`[^4] 4. 编译完成后,在`build`目录下查找生成的库文件 - **预编译包下载**: 部分第三方平台提供预编译版本(如优快云),但建议优先使用官方源码编译以保证兼容性。 #### 2. 使用spdlog.lib - **项目配置**: 1. **头文件包含**:添加spdlog头文件目录到项目包含路径: ```cmake include_directories(${SPDLOG_DIR}/include) # CMake示例[^2] ``` 2. **库文件链接**:将`spdlog.lib`所在目录添加到库搜索路径,并链接库: ```cmake link_directories(${SPDLOG_DIR}/lib) target_link_libraries(你的项目名 spdlog) ``` - **代码调用示例**: ```cpp #include "spdlog/spdlog.h" int main() { auto logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt"); logger->info("成功加载spdlog.lib!"); return 0; } ``` #### 3. 常见问题解决 - **链接错误**:若出现类似`无法找到spdlog.lib`错误,检查: 1. 库文件路径是否正确添加到项目属性 2. 编译平台(x86/x64)是否与项目配置一致 3. 确保编译时选择**静态库**生成选项(若需动态库则生成`.dll`) - **性能优化**:可通过`SPDLOG_COMPILED_LIB`宏定义强制使用预编译库提升性能[^5]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值