DE-10开发板 FPGA SOC学习(六)在HPS上添加一个uart模块IP

本文介绍了如何在DE-10开发板上添加UART模块,配置好波特率并实现自定义IP的读写功能。通过修改顶层代码,实现在HPS上与外部设备的串口交互,包括发送、接收字符串和字符。重点讲解了硬件接口配置和软件接口设计,以及关键函数的实现。
摘要由CSDN通过智能技术生成

在上一次学习的基础上,添加uart 模块IP,,同时测试上次的自定义IP的读数据功能

1.硬件设计

1.1.添加uart

在IP Catalog中搜索uart选择下图的IP。
在这里插入图片描述
配置如下图:偶校验、8bit数据、1bit停止位、115200波特率。
在这里插入图片描述
连线与pio基本一致,这里需要将rx和tx供给外部连接。然后将irq与HPS组件的f2h_irq0相连。
在这里插入图片描述
最后生成新的qsys系统保存。

1.2.顶层代码修改

打开顶层代码,添加uart的接收发送接口。
在这里插入图片描述
soc_system例化部分
在这里插入图片描述
编译生sof文件再转换成rbf文件复制到sd卡中。

软件设计

首先根据DE-10开发板 FPGA SOC学习(三)熟悉SOC开发流程的2.3.1.生成新的硬件头文件hps_o.h
然后修改DE-10开发板 FPGA SOC学习(五)在HPS上自定义Avalon总线组件实验中的main函数代码
在这之前需要了解一下altera的uart核的寄存器配置
《Embedded Peripherals IP User Guide》手册中有介绍,直接取intel官网搜索下载即可。

#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"
#include "hps_0.h"
#include <string.h>
#define HW_REGS_BASE ( ALT_STM_OFST )
#define HW_REGS_SPAN ( 0x04000000 )
#define HW_REGS_MASK ( HW_REGS_SPAN - 1 )
#define LED_CTRL_DATA 0x01 //定义led的相对地址,对应硬件自定义IP时,在地址为1时对LED进行读写。

//uart字符打印函数
void uart_putc(char c ,unsigned long *h2p_lw_uart_addr)
{
	unsigned short uart_status; //状态寄存器值
	do{
		uart_status = *(h2p_lw_uart_addr + 2);//读取状态寄存器
	}while(!(uart_status & 0x40)); //等待状态寄存器 bit6(trdy)为 1
	
	*(h2p_lw_uart_addr + 1) = c; //发送一个字符
}
//uart字符串打印
void uart_printf(char *str ,unsigned long *h2p_lw_uart_addr)
{
	while(*str != '\0')//检测当前指针指向的数是否为空字符
	{
		uart_putc(*str ,h2p_lw_uart_addr); //发送一个字符
		str++; //字符串指针+1
	} 
}

//串口字符接收函数
int uart_getc(unsigned long *h2p_lw_uart_addr) {
	unsigned short uart_status; //状态寄存器值
	do {
	uart_status = *(h2p_lw_uart_addr + 2); //读取状态寄存器
	} while (!(uart_status & 0x80)); //等待状态寄存器 bit7(rrdy)为 1
	return *(h2p_lw_uart_addr + 0);//读取一个字符并作为函数返回值返回 
}
//串口字符串接收函数
int uart_scanf(char *p,unsigned long *h2p_lw_uart_addr) {
	int cnt = 0; //接收个数计数器
	while (1) {
		*p = uart_getc(h2p_lw_uart_addr); //读取一个字符的数据
		cnt++;
		if (*p == '\n') //判断数据是否为换行
			return cnt; //换行则停止计数,返回当前接收的字符个数
		else
			p++; //接收指针增 1 
	} 
}
int main() {

	void *virtual_base;
	int fd;
	int loop_count;
	int led_direction;
	int led_mask;
	int led_temp;
	int i;
	unsigned long *h2p_lw_led_addr;
	unsigned long *h2p_lw_uart_addr;
	// 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
	//打开MPU
	if( ( fd = open( "/dev/mem", ( O_RDWR | O_SYNC ) ) ) == -1 ) {
		printf( "ERROR: could not open \"/dev/mem\"...\n" );
		return( 1 );
	}
	//将外设地址段映射到用户空间
	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 );
	}
	
	h2p_lw_led_addr=virtual_base + ( ( unsigned long  )( ALT_LWFPGASLVS_OFST + MY_LED_0_BASE ) & ( unsigned long)( HW_REGS_MASK ) );//led地址
	h2p_lw_uart_addr=virtual_base + ( ( unsigned long  )( ALT_LWFPGASLVS_OFST + UART_0_BASE ) & ( unsigned long)( HW_REGS_MASK ) );//uart地址
	// toggle the LEDs a bit
    *(h2p_lw_uart_addr + 4) = (int) (UART_0_FREQ / UART_0_BAUD + 0.5);//设置波特率115200
	loop_count = 0;
	led_mask = 0x01;
	led_direction = 0; // 0: left to right direction
	char rx_buf[128] = { 0 }; //定义一个 128 字节的接收数组
	memset(rx_buf, 0, 128); //清除数组中内容
	char c[20];
	while( loop_count < 60 ) {
		// control led
		*(h2p_lw_led_addr+LED_CTRL_DATA ) = led_mask; //对LED端口赋值
		led_temp = *(h2p_lw_led_addr);//读取LED端口数据,因为我把读地址设置为了0,所有读数据的地址发生了改变
		printf("led_mask:%d  led_temp:%d\n",led_mask,led_temp);
		// wait 100ms
		sprintf(c,"%d",led_temp);//将int数据转换成字符数据
		uart_printf(&c[0],h2p_lw_uart_addr);//打印读入的数据

		usleep( 100*1000 );
		
		// update led mask
		if (led_direction == 0){
			led_mask <<= 1;
			if (led_mask == (0x01 << (7-1)))
				 led_direction = 1;
		}else{
			led_mask >>= 1;
			if (led_mask == 0x01){ 
				led_direction = 0;
				loop_count++;
			}
		}
		
		uart_scanf(&rx_buf[0],h2p_lw_uart_addr); //接收一行数据到 rx_buf 中
		for (i = 0; rx_buf[i]!='\0'; i++)  
		{    
			printf("%c", rx_buf[i]);  
		}   
		printf("\n%s\n",rx_buf);
			
		//printf("%s",rx_buf); //打印当前接收到的字符串内容
		uart_printf(&rx_buf[0],h2p_lw_uart_addr);//通过串口调试助手,发送数据到FPGA
		
		
	} // while
	// clean up our memory mapping and exit
	if( munmap( virtual_base, HW_REGS_SPAN ) != 0 ) {
		printf( "ERROR: munmap() failed...\n" );
		close( fd );
		return( 1 );
	}

	close( fd );

	return( 0 );
}

最后生成可执行文件复制到sd卡中。
结果验证部分在之前的实验中已经做过,不再赘述。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值