搜索
bottom↓
回复: 0

《ATK-DFPGL22G之FPGA开发指南_V1.0》第十章PS SYSMON测量温度电压实验

[复制链接]

出0入234汤圆

发表于 2023-4-11 09:13:32 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2023-4-11 16:00 编辑

1)实验平台:正点原子 DFZU2EG_4EV MPSoC开发板
2)购买链接:https://item.taobao.com/item.htm?&id=692368045899
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-340252-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子FPGA交流群:994244016 lQLPJxaFi2zaB4UWWrDAMgIsFEW2pwLb3abnwDMA_90_22.png
lQDPJxaFi2nfFizMjM0CbLCPlxn_FVheIQLb3aGrwFQA_620_140.jpg

lQLPJxaFi2nfFhLMkM0BXrDNvOUyeU_FPgLb3aGvQNIA_350_144.png


第十章PS SYSMON测量温度电压实验

系统监视器(System Monitors)是MPSOC中用来测量电压和温度的模块,能够将电压和温度信息提供给系统的其它部分,包括平台管理单元(PMU),实时处理单元(RPU)和应用处理单元(APU)。MPSOC中有两个SYSMON模块:PL端SYSMON模块和PS端SYSMON模块。
本章我们将使用PS端SYSMON模块,读取芯片的温度电压等信息。本章包括以下几个部分:
10.1简介
10.2实验任务
10.3硬件设计
10.4软件设计
10.5下载验证

10.1简介

PS SYSMON模块位于PS端低功耗域内,由VCC_PSAUX和VCC_PSADC供电。PS SYSMON能同时测量两个温度和几个固定的电压节点。AXI互联主机通过PS SYSMON和AMS寄存器组控制PS端SYSMON模块。
MPSOC中PS SYSMON和PL SYSMON模块都属于SYSMONE4结构,结构上存在很多相似处。也有许多不同点,例如采样率,参考电压,编程接口,电源域,温度传感器等。PS SYSMON模块框图如下图所示:
PS SYSMON测量温度电压实验472.png
图10.1.1 PS SYSMON模块框图

PS SYSMON监测的内部电压节点位于低功耗域和全功耗域,包含内部和IO缓冲区节点。PS中所有电压测量都是单极的,内部电压节点测量范围是0~3V或0~6V。PS内部有两个温度传感器,一个物理位置在RPU附近,另外一个在APU附近。在图10.1.1中,软件通过APB SLAVE接口配置PS SYSMON的寄存器。
PS和PL的SYSMON模块各自独立运行。运行模式包括单通道读模式,默认的序列模式和自动序列器模式,SYSMON通常以默认的序列模式运行。在默认模式下,可以通过CONFIG_REG寄存器将SYSMON配置成自定义序列。
单通道读模式一次只能测量一个通道的传感器信号。在使用单通道模式时,先向CONFIG_REG0寄存器[mux_channel]比特位写入通道序号,再将CONFIG_REG1寄存器[sequence_mode]比特位设置成单通道模式,然后等待EOC(end of conversion)中断,当中断触发时,读取相关测量寄存器。
自动序列器模式下,SYSMON模块可以一次或连续的对打开的通道列表进行顺序访问。模拟输入按照固定顺序进行时间多路复用,并且每次只有一路信号送给ADC输入。读取每个通道的测量值时,最大值和最小值都会被存储。测量值也可以在连续测量结果的平均值。
10.2实验任务
本章的实验任务是通过APB Slave接口,读取PS SYSMON测量的芯片温度、供电电压等信息,并通过串口打印出来。
10.3硬件设计
根据实验任务我们可以画出本次实验的系统框图,如下图所示:
PS SYSMON测量温度电压实验1232.png
图 10.3.1 系统框图

在图 10.3.1中,CPU作为AXI主机连接到SYSMON模块APB Slave接口,读取SYSMON模块采集的温度和电压数据,然后通过串口打印出来。
本次实验在《Hello World》实验中的最小系统上就可以完成,也就是说不需要额外配置PS端或者添加PL端的外设。
打开《hello_world》工程,另存为本次实验工程《ps_sysmon》,导出硬件设计(Hardware),具体步骤可以参照前面的实验,最后打开Vitis软件。
10.4软件设计
在VITIS软件中新建一个空的应用工程,应用工程名为“ps_sysmon”。然后为应用工程新建一个源文件“main.c”,我们在新建的main.c文件中输入本次实验的代码:
1   #include "xsysmonpsu.h"
2   #include "xparameters.h"
3   #include "xstatus.h"
4   #include "stdio.h"
5   #include "sleep.h"
6   
7   #define SYSMON_DEVICE_ID    XPAR_XSYSMONPSU_0_DEVICE_ID
8   #define printf xil_printf
9   
10  int    PS_SYSMON_Test(u16 SysMonDeviceId);
11  static int SysMonPsuFractionToInt(float FloatNum);
12  static XSysMonPsu SysMonInst;                          //PS SYSMON实例
13  
14  int main(void)
15  {
16      xil_printf("Run Sysmon Polled Test\r\n");
17  
18      PS_SYSMON_Test(SYSMON_DEVICE_ID);
19  
20      return XST_SUCCESS;
21  }
22  
23  int PS_SYSMON_Test(u16 SysMonDeviceId)
24  {
25      XSysMonPsu_Config *ConfigPtr;
26      u32 TempRawData;                              //温度         原始数据
27      u32 VccAuxRawData;                            //PS 辅助电压  原始数据
28      u32 VccIntRawData;                            //PS 内核电压  原始数据
29      u32 VCCO_PSIO0RawData;                        //Bank500电压  原始数据
30      u32 VCCO_PSIO1RawData;                        //Bank501电压  原始数据
31      float TempData;                               //温度
32      float VccAuxData;                             //PS 辅助电压
33      float VccIntData;                             //PS 内核电压
34      float VCCO_PSIO0Data;                         //Bank500电压
35      float VCCO_PSIO1Data;                         //Bank501电压
36      u64 IntrStatus;
37      XSysMonPsu *SysMonInstPtr = &SysMonInst;
38  
39      printf("\r\nEntering the SysMon Test. \r\n");
40  
41      ConfigPtr = XSysMonPsu_LookupConfig(SysMonDeviceId);
42      if (ConfigPtr == NULL) {
43          return XST_FAILURE;
44      }
45      XSysMonPsu_CfgInitialize(SysMonInstPtr, ConfigPtr,
46                  ConfigPtr->BaseAddress);
47  
48      XSysMonPsu_SetSequencerMode(SysMonInstPtr,
49              XSM_SEQ_MODE_SAFE, XSYSMON_PS);            //设置Sequence Mode为安全模式
50  
51      XSysMonPsu_SetAlarmEnables(SysMonInstPtr,          //关闭寄存器1中指定信号的警报
52              0x0, XSYSMON_PS);
53  
54      XSysMonPsu_SetAvg(SysMonInstPtr,
55              XSM_AVG_16_SAMPLES, XSYSMON_PS);           //设置采样16次后计算平均值
56  
57      XSysMonPsu_SetSeqAvgEnables(SysMonInstPtr,
58              XSYSMONPSU_SEQ_CH0_TEMP_MASK |             //使能Temp_LPD通道平均值测量
59              XSYSMONPSU_SEQ_CH0_SUP1_MASK |             //使能VCC_PSINTLP通道平均值测量
60              XSYSMONPSU_SEQ_CH0_SUP3_MASK |             //使能VCC_PSAUX通道平均值测量
61              XSYSMONPSU_SEQ_CH0_SUP6_MASK |             //使能VCCO_PSIO0通道平均值测量
62              XSYSMONPSU_SEQ_CH2_SUP7_MASK ,             //使能VCCO_PSIO1通道平均值测量
63              XSYSMON_PS);
64  
65      XSysMonPsu_SetSeqChEnables(SysMonInstPtr,
66              XSYSMONPSU_SEQ_CH0_TEMP_MASK |             //打开Temp_LPD通道
67              XSYSMONPSU_SEQ_CH0_SUP1_MASK |             //打开VCC_PSINTLP通道
68              XSYSMONPSU_SEQ_CH0_SUP3_MASK |             //打开VCC_PSAUX通道
69              XSYSMONPSU_SEQ_CH0_SUP6_MASK |             //打开VCCO_PSIO0通道
70              XSYSMONPSU_SEQ_CH2_SUP7_MASK ,             //打开VCCO_PSIO1通道
71              XSYSMON_PS);
72  
73      IntrStatus = XSysMonPsu_IntrGetStatus(SysMonInstPtr); //读中断状态寄存器
74      XSysMonPsu_IntrClear(SysMonInstPtr, IntrStatus);  //清除中断状态寄存器
75  
76      XSysMonPsu_SetSequencerMode(SysMonInstPtr,
77              XSM_SEQ_MODE_CONTINPASS, XSYSMON_PS);     //设定Sequence Mode为通道循环模式
78  
79      while ((XSysMonPsu_IntrGetStatus(SysMonInstPtr) & ((u64)XSYSMONPSU_ISR_1_EOS_MASK<<
80          32))!= ((u64)XSYSMONPSU_ISR_1_EOS_MASK<< 32));//等待EOS(end of sequence)发生
81  
82      while(1)
83      {
84      //从ADC数据寄存器读实时温度值
85      TempRawData = XSysMonPsu_GetAdcData(SysMonInstPtr,
86                              XSM_CH_TEMP, XSYSMON_PS);      //读Temp_LPD通道数据
87      TempData = XSysMonPsu_RawToTemperature_OnChip(TempRawData);
88      printf("The Current Temperature is %0d.%03d Centigrades.\r\n",
89                  (int)(TempData), SysMonPsuFractionToInt(TempData));
90  
91      //从ADC数据寄存器读VccInt电压值
92      VccIntRawData = XSysMonPsu_GetAdcData(SysMonInstPtr,
93                              XSM_CH_SUPPLY1, XSYSMON_PS);   //读VCC_PSINTLP通道数据
94      VccIntData = XSysMonPsu_RawToVoltage(VccIntRawData);
95      printf("The Current VCCINT is %0d.%03d Volts. \r\n",
96              (int)(VccIntData), SysMonPsuFractionToInt(VccIntData));
97  
98      //从ADC数据寄存器读VccAux电压值
99      VccAuxRawData = XSysMonPsu_GetAdcData(SysMonInstPtr,
100                             XSM_CH_SUPPLY3, XSYSMON_PS);   //读VCC_PSAUX通道数据
101     VccAuxData = XSysMonPsu_RawToVoltage(VccAuxRawData);
102     printf("The Current VCCAUX is %0d.%03d Volts. \r\n",
103             (int)(VccAuxData), SysMonPsuFractionToInt(VccAuxData));
104
105     VCCO_PSIO0RawData = XSysMonPsu_GetAdcData(SysMonInstPtr,
106                             XSM_CH_SUPPLY6, XSYSMON_PS);   //读Bank500电压
107     VCCO_PSIO0Data = XSysMonPsu_VccopsioRawToVoltage(VCCO_PSIO0RawData);
108     printf("The Current VCCO_PSIO0 is %0d.%03d Volts. \r\n",
109                 (int)(VCCO_PSIO0Data), SysMonPsuFractionToInt(VCCO_PSIO0Data));
110
111     VCCO_PSIO1RawData = XSysMonPsu_GetAdcData(SysMonInstPtr,
112                             XSM_CH_SUPPLY7, XSYSMON_PS);   //读Bank501电压
113     VCCO_PSIO1Data = XSysMonPsu_VccopsioRawToVoltage(VCCO_PSIO1RawData);
114     printf("The Current VCCO_PSIO1 is %0d.%03d Volts. \r\n\r\n\r\n",
115                 (int)(VCCO_PSIO1Data), SysMonPsuFractionToInt(VCCO_PSIO1Data));
116
117     //延时5s
118     sleep(5);
119     }
120
121     return XST_SUCCESS;
122 }
123
124 //将小数转换成整数
125 int SysMonPsuFractionToInt(float FloatNum)
126 {
127     float Temp;
128
129     Temp = FloatNum;
130     if (FloatNum < 0) {
131         Temp = -(FloatNum);
132     }
133
134     return( ((int)((Temp -(float)((int)Temp)) * (1000.0f))));
135 }
代码第14行至第21行,是程序的主函数,主函数比较简单,先输出打印信息“Run Sysmon Polled Test”,然后调用PS_SYSMON_Test()函数,该函数是在官方函数基础上修改而来。
在PS_SYSMON_Test()函数中,首先对SYSMON进行初始化,如程序第41行至第46行所示。通过调用XSysMonPsu_SetSequencerMode()函数,将SYSMON操作模式设置为默认模式(安全模式)。程序第54行至第55行,设置平均值的采样次数为16次。接下来是使能通道的平均值测量,即测量结果是采样16次后计算的平均值,如第57行至第63行所示,如果不打开通道的平均值测量,则测量结果是最后一次采样值。
程序第92行至第93行中,通过调用XSysMonPsu_GetAdcData()函数,读取Vcc_Int内核电压的原始数据。该函数中,第二个参数XSM_CH_SUPPLY1代表supply1通道,通过查看ug1085手册,supply1通道实际就是VCC_PSINTLP通道,如下图所示:
PS SYSMON测量温度电压实验7852.png
图10.4.1 PS SYSMON传感器通道

通过查看ug1087手册可知,该通道物理地址为0x00FFA50804,而XSysMonPsu_GetAdcData()函数通过对第二和第三个参数计算,最终获取的就是物理地址为0x00FFA50804的VCC_PSINTLP通道的原始数据。程序第94行中,XSysMonPsu_RawToVoltage()函数对原始数据先乘以3再除以65536,公式详细讲解可参考ug580手册,如图10.4.2所示。其它通道的电压温度测量类似,这里不详细讲解。注意MIO通道电压计算公式和其它通道是不同的。
PS SYSMON测量温度电压实验8210.png
图10.4.2 电压计算公式

程序第96行调用SysMonPsuFractionToInt()函数,该函数将浮点型数据的小数部分转换成整数,函数定义如第125行至第135行所示。
10.5下载验证
首先我们将下载器与开发板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用USB连接线将USB_UART(开发板PS PORT)接口与电脑连接,用于串口通信。最后连接开发板的电源,给开发板上电。
打开Vitis Terminal终端,设置并连接串口。然后下载本次实验的程序,下载完成后,在下方的VITIS Terminal中可以看到应用程序每隔5秒打印一次芯片温度和电压等信息,如下图所示:
PS SYSMON测量温度电压实验8549.png
图 10.5.1 串口终端中打印的信息

从图 10.5.1中可以看到,串口终端能够正确打印温度和电压信息,说明本次实验在MPSOC开发板上面下载验证成功。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-6 14:58

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表