IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> DE1-SoC软件实验(二)—— 点亮LED灯(头文件hwlib.h及socal/socal.h等的配置,及hps_0.h头文件的生成,解决soc_cv_av 没有声明) -> 正文阅读

[嵌入式]DE1-SoC软件实验(二)—— 点亮LED灯(头文件hwlib.h及socal/socal.h等的配置,及hps_0.h头文件的生成,解决soc_cv_av 没有声明)

第一部分

软件实验二是通过采用QSYS创建一个硬核工程,控制HPS端LED和KEY
由于只需要控制HPS端的外设,因此其实现方法和实验一是相同的,编写软件程序即可。

在软件实验二的程序中,通过C程序编写点亮LED灯的时候,包含如下的头文件,这些头文件的环境配置以及hps_0.h头文件的生成都是重点要学习的地方。其中hps_0.h头文件就是通过我们创建的硬核工程通过命令生成的。下面均会一 一讲述。

在这里插入图片描述

环境变量配置

首先上面这些库是 SoC EDS 软件提供的, DS-5 中默认并没有包含该库,所以如果不进行环境变量配置,直接在程序中包含这些文件, DS-5 会提示找不到文件,因此需要在工程中设置头文件包含路径。
方法如下:
在工程的基础上 鼠标右击选择 Properties在这里插入图片描述
首先进行hwlib.h的添加
根据安装的SOCEDS找到hwlib.h的路径

D:\intelFPGA\17.1\embedded\ip\altera\hps\altera_hps\hwlib\include

点击Add,输入路径,然后勾选 Add to all configurations 和 Add to all languages 选项, 然后点击 OK 即可,同样的方式可添加socal./hps.h头文件

D:\intelFPGA\17.1\embedded\ip\altera\hps\altera_hps\hwlib\include\soc_cv_av

最终得到如下:

在这里插入图片描述

hps_0.h头文件的生成

该头文件包含对 HPS 中各种外设地址信息进行了定义,该文件中的定义在进行虚拟地址映射时有用到。
在这里插入图片描述
此文件需要我们根据Qsys生成的硬件工程来生成。
当我们采用Qsys搭建完系统后,会生成如下的.sopcinfo文件
在这里插入图片描述
通过该文件即可生成hps_0头文件。
首先写一个sh脚本,其内容如下,"./soc_system.sopcinfo" \ 代表用qsys搭建的硬核工程的名字,根据自己的进行修改。

#!/bin/sh
sopc-create-header-files \
"./soc_system.sopcinfo" \  
--single hps_0.h \
--module hps_0

此时该工程文件夹下有了SH文件。
在这里插入图片描述
打开SOCEDS。定位到当前含有sopcinfo文件的目录下

cd "D:/intelFPGA/project/my_first_hps_fpga/fpga-rtl"

通过ls命令可查看,现在定位成功。

在这里插入图片描述
输入如下命令

 ./generate_hps_qsys_header.sh

出现如下结果,说明成功
在这里插入图片描述
回到该工程文件夹下可看到生成了hps_0.h头文件。
在这里插入图片描述
将hps_0.h头文件添加到C工程中即可。
在这里插入图片描述

环境配置完成,且有了hps_0.h头文件,那么代码无错误的情况下即可成功编译。

补充:解决soc_cv_av 没有声明

在这里插入图片描述
#include “hwlib.h” 前面直接添加

#define soc_cv_av

第二部分

实验目的

创建一个HPS_GPIO的软件工程,用该工程来控制HPS端的LED和KEY。其中LED和KEY均作为HPS端的外设,因此采用软件工程的方式来控制的方法和软件实验(一)中采用C程序来编写hello_fpga类似,也无需Quartusii工程,只编写C程序即可。

实验原理

在C程序中,我们要采用虚拟地址映射的方式,来控制LED和KEY。其中用到的是Linux内核memory_mapped device(内存映射设备)驱动访问GPIO控制器的寄存器,这些被驱动的寄存器就相当于LED和KEY的I/O接口。在映射的时候我们就需要知道I/O的方向以及写入读出值。(也就是需要知道I/O端口是输入输出,同时输入的是多少,输出的是多少)

HPS GPIO的原理

下图为GPIO例程的方块图,LED和KEY都是连接到DE1-SoC HPS部分的GPIO控制器上的,同时采用memory_mapped device来驱动访问GPIO控制器的寄存器,从而实现GPIO的控制行为在这里插入图片描述
如下是GPIO的接口方块图。可看到HPS提供了三个通用I/O接口模块,GPIO 0、GPIO 1、GPIO 2在这里插入图片描述
前面提到GPIO控制器通过驱动访问GPIO控制器的寄存器,来实现I/O控制,那么下面就展示了对应的寄存器组所控制的I/O引脚的行为。

  • 采用三种32位寄存器来实现引脚方向以及写入写出的控制:
  1. GPIO1_SWPORTA_DDR:配置IO引脚方向 (通过该寄存器组来控制输出高低电平,其中高电平1为输出,低电平0为输入)
  2. GPIO1_SWPORTA_DR : 写数据到输出引脚(如果写入1,则输出高电平,写入0,输出低电平)——相当于LED接收的是0还是1
  3. GPIO1_EXT_PORTA : 从输入引脚读数据(读出来的数据为1,则高电平,为0,低电平)——相当于从KEY读到的数据是0还是1

由此确定了输入输出,并知道了输入引脚和输出引脚的值,那么我们就能知道,输入KEY和输出LED的状态是0还是1。

  • 如下是GPIO寄存器地址映射表:
    其中GPIO 0 控制器的寄存器映射到基地址0xFF708000,共4KB寻址空间。GPIO 1 和 GPIO 2 同理。
    在这里插入图片描述

软件API

分析完原理后,我们就要采用软件的方式来完成地址映射。可以通过如下软件API访问GPIO控制器的寄存器。(所用到的函数)
在这里插入图片描述
还可使用如下MACR0访问寄存器:(宏定义)
在这里插入图片描述
若想要使用上面的函数,那么就要包含如下的头文件:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "hwlib.h"
#include "socal/socal.h"
#include "socal/hps.h"
#include "socal/alt_gpio.h"

LED和KEY控制

如下为HPS的KEY和LED的引脚分配,分别连接到54和53,由GPIO1控制器控制,另外该控制器还控制29~57
在这里插入图片描述
在GPIO1控制器中可看到,其中Bit-24,Bit-25分别控制LED和KEY。因此,我们即可通过控制前面介绍的三种32位的寄存器组(GPIO1_SWPORTA_DDR、GPIO1_SWPORTA_DR、GPIO1_EXT_PORTA )中相应的Bit-24,Bit-25来分别控制LED和KEY的方向,以及写入和读取。
在这里插入图片描述

具体代码分析

采用宏定义的方式来控制LED和KEY的方向,以及LED的输出状态

#define USER_IO_DIR     (0x01000000) //LED引脚为输出引脚
#define BIT_LED         (0x01000000) //点亮LED
#define BUTTON_MASK     (0x02000000) //

GPIO1_SWPORTA_DDR寄存器组可设置IO引脚方向,alt_setbits_word 设定寄存器的指定位为1,如下语句是配置LED引脚为输出引脚

alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DDR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), USER_IO_DIR ); 

ALT_GPIO1_SWPORTA_DR寄存器组是写数据到输出引脚,alt_setbits_word 设定寄存器的指定位为1,如下语句是点亮LED

alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), BIT_LED ); 

alt_clrbits_word设定寄存器的指定位为0

alt_clrbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), BIT_LED );

ALT_GPIO1_EXT_PORTA寄存器组是从输入引脚读数据,从而检查KEY是0还是1,(按下还是释放)

alt_read_word( ( virtual_base + ( ( uint32_t )(  ALT_GPIO1_EXT_PORTA_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ) );

点亮LED的完整代码

如下是教材中提供的KEY控制LED的C程序:(根据错误提示进行一定修改),这部分采用DS-5软件来进行工程创建,并创建c文件。

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define soc_cv_av
#include "hwlib.h"
#include "socal/socal.h"
#include "socal/hps.h"
#include "socal/alt_gpio.h"

#define HW_REGS_BASE ( ALT_STM_OFST )
#define HW_REGS_SPAN ( 0x04000000 )
#define HW_REGS_MASK ( HW_REGS_SPAN - 1 )

//采用宏定义的方式来控制LED和KEY的方向,以及LED的输出状态
#define USER_IO_DIR     (0x01000000)  
#define BIT_LED         (0x01000000)
#define BUTTON_MASK     (0x02000000)

int main(int argc, char **argv) {

	void *virtual_base;
	int fd;
	uint32_t  scan_input;
	int i;
	// map the address space for the LED registers into user space so we can interact with them.
	// we'll actually map in the entire CSR span of the HPS since we want to access various registers within that span
	//打开内存映射设备
	if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
		printf( "ERROR: could not open \"/dev/mem\"...\n" ); 
		return( 1 );
	}
//采用mmap函数,将LED寄存器的地址空间映射到用户空间
	virtual_base = mmap( NULL, HW_REGS_SPAN, ( PROT_READ | PROT_WRITE ), MAP_SHARED, fd, HW_REGS_BASE ); 

	if( virtual_base == MAP_FAILED ) {
		printf( "ERROR: mmap() failed...\n" );
		close( fd );
		return( 1 );
	}
	// initialize the pio controller
	// led: set the direction of the HPS GPIO1 bits attached to LEDs to output
	//GPIO1_SWPORTA_DDR设置IO引脚方向,配置LED引脚为输出引脚
	alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DDR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), USER_IO_DIR ); 
	printf("led test\r\n");
	printf("the led flash 2 times\r\n");
	//GPIO1_SWPORTA_DR 写数据到输出引脚,目的是用来点亮LED
	for(i=0;i<2;i++)
	{
	//alt_setbits_word是设定指定寄存器指定位为1
		alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), BIT_LED );  
		usleep(500*1000);
    //alt_clrbits_word是设定指定寄存器指定位为0
		alt_clrbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), BIT_LED );
		usleep(500*1000);  
	}
	printf("user key test \r\n");
	printf("press key to control led\r\n");
	//alt_read_word从指定寄存器读取一个值
	while(1){ 
		scan_input = alt_read_word( ( virtual_base + ( ( uint32_t )(  ALT_GPIO1_EXT_PORTA_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ) );	 //GPIO1_EXT_PORTA是用来从输入引脚读数据
		//usleep(1000*1000);
		if(~scan_input&BUTTON_MASK)
			alt_setbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), BIT_LED );
		else    
		    alt_clrbits_word( ( virtual_base + ( ( uint32_t )( ALT_GPIO1_SWPORTA_DR_ADDR ) & ( uint32_t )( HW_REGS_MASK ) ) ), BIT_LED );
	}
	// clean up our memory mapping and exit
	//munmap清除内存映射
	if( munmap( virtual_base, HW_REGS_SPAN ) != 0 ) { 
		printf( "ERROR: munmap() failed...\n" );
		close( fd ); //关闭设备驱动
		return( 1 );
	}
	close( fd );
	return( 0 );
}

上板测试,成功点亮LED

头文件问题解决之后,编译C程序,然后生成可执行文件,将可执行文件拷贝到SD卡,然后上板并进行串口终端调试,即可完成在DE1-SOC开发板点亮LED,其具体步骤和实验一的hello_fpga是一样的。
已上板测试,按压开关,即可点亮LED。
在这里插入图片描述

参考:
环境变量配置
头文件的生成

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 17:58:47  更:2022-04-18 18:02:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:29:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码