概述
1)实验平台:正点原子MPSoC开发板
2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html
第十章PS SYSMON测量温度电压实验
系统监视器(System Monitors)是MPSOC中用来测量电压和温度的模块,能够将电压和温度信息提供给系统的其它部分,包括平台管理单元(PMU),实时处理单元(RPU)和应用处理单元(APU)。MPSOC中有两个SYSMON模块:PL端SYSMON模块和PS端SYSMON模块。
本章我们将使用PS端SYSMON模块,读取芯片的温度电压等信息。本章包括以下几个部分:
1010.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模块框图如下图所示:
图10.1.1 PS SYSMON模块框图
PS SYSMON监测的内部电压节点位于低功耗域和全功耗域,包含内部和IO缓冲区节点。PS中所有电压测量都是单极的,内部电压节点测量范围是03V或06V。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硬件设计
根据实验任务我们可以画出本次实验的系统框图,如下图所示:
图 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 Testrn");
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("rnEntering the SysMon Test. rn");
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.rn",
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. rn",
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. rn",
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. rn",
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. rnrnrn",
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通道,如下图所示:
图10.4.1 PS SYSMON传感器通道
通过查看ug1087手册可知,该通道物理地址为0x00FFA50804,而XSysMonPsu_GetAdcData()函数通过对第二和第三个参数计算,最终获取的就是物理地址为0x00FFA50804的VCC_PSINTLP通道的原始数据。程序第94行中,XSysMonPsu_RawToVoltage()函数对原始数据先乘以3再除以65536,公式详细讲解可参考ug580手册,如图10.4.2所示。其它通道的电压温度测量类似,这里不详细讲解。注意MIO通道电压计算公式和其它通道是不同的。
图10.4.2 电压计算公式
程序第96行调用SysMonPsuFractionToInt()函数,该函数将浮点型数据的小数部分转换成整数,函数定义如第125行至第135行所示。
10.5下载验证
首先我们将下载器与开发板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用USB连接线将USB_UART(开发板PS PORT)接口与电脑连接,用于串口通信。最后连接开发板的电源,给开发板上电。
打开Vitis Terminal终端,设置并连接串口。然后下载本次实验的程序,下载完成后,在下方的VITIS Terminal中可以看到应用程序每隔5秒打印一次芯片温度和电压等信息,如下图所示:
图 10.5.1 串口终端中打印的信息
从图 10.5.1中可以看到,串口终端能够正确打印温度和电压信息,说明本次实验在MPSOC开发板上面下载验证成功。
最后
以上就是微笑芒果为你收集整理的【正点原子FPGA连载】第十章PS SYSMON测量温度电压实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南第十章PS SYSMON测量温度电压实验的全部内容,希望文章能够帮你解决【正点原子FPGA连载】第十章PS SYSMON测量温度电压实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南第十章PS SYSMON测量温度电压实验所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复