Xilinx-ZYNQ7000系列-学习笔记(5):设置EMIO并固化到QSPI

一、EMIO的设置

预先知识

MIO:多功能IO接口,属于Zynq的PS部分,在芯片外部有54个引脚。这些引脚可以用在GPIO、SPI、UART、TIMER、Ethernet、USB等功能上,每个引脚都同时具有多种功能,故叫多功能。

EMIO:扩展MIO,依然属于Zynq的PS部分,只是连接到了PL上,再从PL的引脚连到芯片外面实现数据输入输出

配置方法

1.创建Block块并添加ZYNQ系统IP核:

(1)由于要配置PL端的LED,所以要将EMIO的对勾选上

XILINX ZYNQ EMMC读写速率_固化


(2)由于后期要进行QSPI固化,所以这里要将QSPI也选上,并将下面都变为fast

XILINX ZYNQ EMMC读写速率_EMIO_02


XILINX ZYNQ EMMC读写速率_固化_03


(3)由于这里要点亮8盏LED灯,所以需要8位EMIO,这里将宽度设为8

这里要注意一下:只有当设置了EMIO范围内的管脚才能在SDK中使用,例如在这里定义了EMIO宽度为4,则在SDK中只能使用EMIO54,55,56,57。

XILINX ZYNQ EMMC读写速率_ZYNQ_04


(4)改变DDR型号

XILINX ZYNQ EMMC读写速率_固化_05


(5)完成更改,回到block design中看看,发现多出了GPIO_0。选中它将引脚引出。这里的GPIO_0对应EMIO。(做法:右键GPIO_0选make external)

XILINX ZYNQ EMMC读写速率_ZYNQ_06


(6)导出和生成顶层文件(这里不多介绍)

XILINX ZYNQ EMMC读写速率_固化_07


2.添加引脚约束文件:

所有PL端属于FPGA部分,所以必须添加XDC约束文件;而PS端是ARM部分,不用添加也可以。

XILINX ZYNQ EMMC读写速率_EMIO_08


注意这里的端口名称一定要和顶层文件中的定义端口名称一致。

XILINX ZYNQ EMMC读写速率_FSBL_09


3.导入到SDK:

生成bit流之后,导入到SDK中,切记如果有PL部分,一定要将bit流一起导入过去。

(1)file->export->export hardware

XILINX ZYNQ EMMC读写速率_EMIO_10


(2)file ->lauch SDK

XILINX ZYNQ EMMC读写速率_ZYNQ_11


4.建立工程:

(1)file->new->Application Project->(随便起个名字)建立好是这样的

XILINX ZYNQ EMMC读写速率_ZYNQ_12


(2)将代码输入到helloworld.c文件中,代码如下:

/*
 * main.c
 *
 *  Created on: 2018年7月30日
 *      Author: zxc
 */
#include "xgpiops.h"
#include "sleep.h"
#include "xparameters.h"

int main()
{
    XGpioPs gpioStruct;
    XGpioPs_Config *gpioConfig;
    int pinNum1 = 54;
    int pinNum2 = 55;
    int pinNum3 = 56;
    int pinNum4 = 57;
    int pinNum5 = 58;
    int pinNum6 = 59;
    int pinNum7 = 60;
    int pinNum8 = 61;

    u32 pinDirection = 1;   //1表示输出, 0表示输入
    s32 xStatus;

    print("hello\n");

    //初始化MIO
    //通过gpio的device_ID获取GPIO寄存器的基地址
    gpioConfig = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
    if(gpioConfig == NULL)  //若指针为空,说明没有找到对应的设备或者FPGA底层未进行配置
    {
        print("Can not lookup gpioConfig!!!\n");
        return XST_FAILURE;
    }

    //初始化GPIO
    xStatus = XGpioPs_CfgInitialize(&gpioStruct, gpioConfig, gpioConfig->BaseAddr);
    if(xStatus != XST_SUCCESS)
    {
        print("PS MIO GPIO Initialize failed!!!\n");
    }
    else
    {
        print("PS MIO GPIO Initialize successed!!!\n");
    }

    //设置GPIO的引脚以及输入输出模式
    XGpioPs_SetDirectionPin(&gpioStruct, pinNum1, pinDirection);

    //设置GPIO的输出使能
    XGpioPs_SetOutputEnablePin(&gpioStruct, pinNum1, 1);

    XGpioPs_SetDirectionPin(&gpioStruct, pinNum2, pinDirection);

    //设置GPIO的输出使能
    XGpioPs_SetOutputEnablePin(&gpioStruct, pinNum2, 1);
    XGpioPs_SetDirectionPin(&gpioStruct, pinNum3, pinDirection);

    //设置GPIO的输出使能
    XGpioPs_SetOutputEnablePin(&gpioStruct, pinNum3, 1);


    XGpioPs_SetDirectionPin(&gpioStruct, pinNum4, pinDirection);

    //设置GPIO的输出使能
    XGpioPs_SetOutputEnablePin(&gpioStruct, pinNum4, 1);
    XGpioPs_SetDirectionPin(&gpioStruct, pinNum5, pinDirection);

    //设置GPIO的输出使能
    XGpioPs_SetOutputEnablePin(&gpioStruct, pinNum5, 1);
    XGpioPs_SetDirectionPin(&gpioStruct, pinNum6, pinDirection);

    //设置GPIO的输出使能
    XGpioPs_SetOutputEnablePin(&gpioStruct, pinNum6, 1);
    XGpioPs_SetDirectionPin(&gpioStruct, pinNum7, pinDirection);

    //设置GPIO的输出使能
    XGpioPs_SetOutputEnablePin(&gpioStruct, pinNum7, 1);
    XGpioPs_SetDirectionPin(&gpioStruct, pinNum8, pinDirection);

    //设置GPIO的输出使能
    XGpioPs_SetOutputEnablePin(&gpioStruct, pinNum8, 1);

    while(1){
        XGpioPs_WritePin(&gpioStruct, pinNum1, 1);   //给高电平
        usleep(1000*500);

        XGpioPs_WritePin(&gpioStruct, pinNum2, 1);   //给高电平
        usleep(1000*500);

        XGpioPs_WritePin(&gpioStruct, pinNum3, 1);   //给高电平
        usleep(1000*500);

        XGpioPs_WritePin(&gpioStruct, pinNum4, 1);   //给高电平
        usleep(1000*500);

        XGpioPs_WritePin(&gpioStruct, pinNum5, 1);   //给高电平
        usleep(1000*500);

        XGpioPs_WritePin(&gpioStruct, pinNum6, 1);   //给高电平
        usleep(1000*500);

        XGpioPs_WritePin(&gpioStruct, pinNum7, 1);   //给高电平
        usleep(1000*500);

        XGpioPs_WritePin(&gpioStruct, pinNum8, 1);   //给高电平
        usleep(1000*500);

    }
    return 0;
}

(3)由于数据中带有PL部分,所以我们需要将这两个选项也选上。

XILINX ZYNQ EMMC读写速率_EMIO_13


烧进去程序以后我们会发现灯循环点亮。

二、程序的固化处理

要想了解板子的启动详细步骤与说明请参考


不废话,直接开始固化过程:

(1)进入SDK 开发环境后,点击菜单 File -> New -> Application Project。

XILINX ZYNQ EMMC读写速率_固化_14


(2)仅在 Project name: 输入 fsbl,Hardware Platform 需要选择system_wrapper_hw_platform_0。

next,选择 Zynq FSBL 模板

XILINX ZYNQ EMMC读写速率_FSBL_15


(3)右键你自己的工程文件选择Board Support Package Setting,选择xilffs和xilrsa加入,点击OK。

XILINX ZYNQ EMMC读写速率_zedboard_16


(4)在工程目录下新建boot文件夹,用来存储BOOT文件。

XILINX ZYNQ EMMC读写速率_ZYNQ_17


(5)点击Xilinx Tools->Creat Boot Image选择bif和BIN文件的输出位置为你刚才设定的文件夹。

XILINX ZYNQ EMMC读写速率_zedboard_18


(6)在Boot image partitions中点击Add,依次添加fsbl文件、bit文件和应用程序.elf文件。这里要说明一下三个文件:

1.FSBL文件夹中的elf文件,从而将fsbl启动任务添加进去。
2.你的工程文件夹中的bit文件,从而将PL部分添加进去。
3.你的工程文件夹中的elf文件,从而将SDK中的控制逻辑加进去。

XILINX ZYNQ EMMC读写速率_ZYNQ_19


(7)点击Creat Image后,会在boot文件夹下生成.bif文件和.bin文件。

XILINX ZYNQ EMMC读写速率_EMIO_20


(8)(这一步为选做),有些板子可以直接下载BOOT文件,但是有些需要生成MCS文件,接下来是将BOOT文件转为MCS文件。

XILINX ZYNQ EMMC读写速率_FSBL_21


(9)把.mcs镜像文件烧写入Flash中。

XILINX ZYNQ EMMC读写速率_EMIO_22


(10)选择镜像文件,点击Program。

XILINX ZYNQ EMMC读写速率_固化_23