一、PIO的IP封装
1.在黄金参考工程的IP中找到预封装的IP:Qsys,双击进入。
2.在Platfrom Designer中搜索PIO,双击开始PIO_LED的封装
3.根据需求设置PIO的位宽和输入/输出端口;其中Bidir约等于inout接口,区别在于Bidir的输出端口时一位总线,inout的输出端口分为in_port和out_port。
4.将PIO接口的clk和reset端与系统时钟和复位相连。
5.将PIO_LED的S1端通过mm_bridge与PS端的axi接口相连,具体操作如下:
6.将PIO_LED的管道输出(即对输出端口命名),命名完成之后编译(点击Generate -> Generate HDL ->Generate),至此PIO_LED的IP封装完成,点击Finish退出。
二、PIO_LED的例化、引脚的绑定及黄金工程的编译
1.接上文,在黄金参考工程的IP中找到预封装的IP:Qsys,双击进入;点击Generate -> Show Instantiation Template,从例化中找到刚才封装的PIO_LED接口并复制。
2.复制完成后退出Platfrom Designer,开始在顶层例化封装的IP端口,具体流程如下图:
3.例化完成之后开始黄金工程的全编译,编译完成之后会生产.sof文件
三、软件编译环境搭建
1.用shell生成rbf文件
(1)打开开始——SoC EDS Command Shell
(2)切换到工程目录
(3)make dtb生成设备树
2.运行脚本生成rbf
运行output_files中的sof_to_rbf.bat文件生成rbf文件。每次运行完成之后要检查rbf生成时间,看是否为最新生成的。
3.生成新的hps_0头文件
4.将重新生成的.dtb文件和.rbf文件拷贝到sd卡上
四、搭建软件工程
1.SoC EDS Command Shell输入eclipse& 启动eclipse软件
2.设置工程路径
在此设计中我在黄金工程目录新建app目录用于存放目标程序。
3.新建C工程
4.新建C文件
5.编写soc_led.c代码
该段代码为初学时编写,肯能会有警告,但不影响程序功能正常执行
/*
* soc_led.c
*
* Created on: 2024年4月7日
* Author: ming1
*/
//gcc标准头文件
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
//HPS厂家提供的底层定义头文件
#define soc_cv_av //开发平台Cyclone V 系列
#include "hwlib.h"
#include "socal/socal.h"
#include "socal/hps.h"
//与用户具体的HPS 应用系统相关的硬件描述头文件
#include "hps_0.h"
#define HW_REGS_BASE (ALT_STM_OFST) //HPS外设地址段基地址
#define HW_REGS_SPAN (0x04000000) //HPS外设地址段地址空间 64MB大小
#define HW_REGS_MASK (HW_REGS_SPAN - 1) //HPS外设地址段地址掩码
#define LWSLAVES_STM_LEN (0x03200000) //HPS外设STM地址 50MB大小
static volatile unsigned long *led_pio_base = NULL;//led地址指针,volatile避免优化
//获得IP的slave接口的虚拟地址
int pio_virtual_addr_inst(int *virtual_base)
{
int fd;
void *stm_virtual_base;
//1.使能mmu 打开mem
//open int open(constchar*pathname,intflags,mode_t mode);
//函数参数:pathname:打开文件的路径名 flags:用来控制打开文件的模式 mode:用来设置创建文件的权限(rwx)。当flags中带有O_CREAT时才有效。
//返回值:调用成功时返回一个文件描述符fd 调用失败时返回-1,并修改errno
fd = open ("/dev/mem",(O_RDWR | O_SYNC));
if(fd == -1)
{
printf("ERROR: open is failed\n");
exit(0);
}
//2.映射那一段 映射stm的虚拟基地址
//mmap mmap(start, length, port, flags, fd, offsize)
//start:让操作系统选择映射区域的起始地址。NULL
//length:要映射的区域的长度。
//port:映射区域的保护方式.也可以是PROT_WRITE(写)、PROT_EXEC(执行)等。
//flags:映射的共享选项。
//fd:文件的描述符。
//offsize:文件映射的偏移量
stm_virtual_base = mmap (NULL, HW_REGS_SPAN, (PROT_READ | PROT_WRITE),
MAP_SHARED, fd, HW_REGS_BASE);
//成功执行时,startap()返回被映射区的指针,munmap()返回0;失败时,mmap()返回MAP_FAILED[其值为(void *)-1],munmap返回-1
if(stm_virtual_base == -1)
{
printf("ERROR: mmap is failed\n");
close(fd);
}
//3.stm + 50M + PIO_0_BASE
led_pio_base = stm_virtual_base + (LWSLAVES_STM_LEN + PIO_0_BASE);
//PIO_0_BASE为封装IP的hps_0.h的参数,可根据自己的IP封装具体修改
*virtual_base = stm_virtual_base;
return fd;
}
int main()
{
int fd;
int virtual_base;
int ret;
//获取mmu设备描述符 、获取stm虚拟地址 获取PIO IP虚拟地址
fd = pio_virtual_addr_inst(&virtual_base);
//灯闪烁
while(1){
*(led_pio_base + 0) = 0x0000000f; //低4位用于驱动4位LED,置1为LED点亮。
sleep(1);
*(led_pio_base + 0) = 0x00000000;
sleep(1);
}
//关闭mmu 解除stm后64M的空间
ret = munmap(&virtual_base, HW_REGS_SPAN);
if(ret == -1)
{
printf("ERROR: munmap is failed\n");
close(fd);
}
close(fd);
return 0;
}
6.设置环境,添加hps ip的头文件路径和CV的头文件
6.1 添加hps ip的头文件路径和CV的头文件
添加hps ip的头文件路径和CV的头文件,具体操作为:在File system中找到下图两个头文件路径,并添加进工程
头文件添加完成后如下图,添加完成后单击OK。
6.2 添加hps_0.h
7.编译soc_led.c代码,生成二进制文件
五、建立SSH调试
1.在eclipse里设置ssh
File->New-Other->Remote System Explorer下点击Connection->SSH Only
进入SSH Only之后,输入自己设置的cpu网关地址。具体操作如下:
2.切换到SSH视图
3.建立SSH连接
4.复制编译后的二进制文件到开发板工作路径
4.1 点击右上角的图标切换回C工程视图,复制二进制文件
4.2 点击右上角的图标切换回SSH视图,将复制的二进制文件粘贴到工作路径
5.运行SOC_LED并观察现象
选中工作路径opt,右键单击选择在当前目录运行终端;相关终端操作如下图: