Zing AXI总线Chipscope参考设计

来源:互联网 发布:淘宝卖家怎么免费提现 编辑:程序博客网 时间:2024/05/16 12:51

URL: http://xilinx.eetrend.com/article/4315?quicktabs_1=0

按键点灯设计 (使用14.3版本软件)

本参考设计基于Zing开发板。主要是熟悉ZYNQ器件开发及调试的基本步骤。主要包括,UART测试、采用PL端逻辑设计PS外设、AXI总线Chipscope调试、定时器中断设计、按键及点灯的设计。

一、建立工程:
1、 打开PlanAhead开始设计。

2、 点击Create New Project建立新的工程-> Next-> 填好项目名称和文件路径 Next -> RTL Project -> Next -> Next -> Next 直至界面:

3、 如图,选择Xilinx ZC702开发板 Next –> Finish

二、添加ARM处理器
1、点击Add sources ->选择Add or Create Embedded Sources -> Next ->Create Sub-Design -> 填入处理器名称 -> finish

2、弹出对话框,是否使用Base System Builder,选择Yes

3、默认采用AXI总线架构,点OK

4、默认选择Xilinx ZC702开发板,点Next

5、Remove GPIO_SW and LEDs_4Bits,点Finish

此时已添加和PS部分,并参照Xilinx ZC702开发板设计配置好外设、时钟、DDR内存等。

三、添加PL部分的外设,并连接到PS上
1、添加一个外部按键。点击IP Catalog-> 展开General Purpose IO菜单 ->双击AXI General Purpose IO

2、点击Yes -> 把Channel 1中的GPIO Data Channel Width改为1,点击OK,用PL部分逻辑实现一个板上按键。

4、 弹出对话框,是否把添加的IP连接到处理器总线上。默认选择,点OK。

5、此时在ZYNQ的菜单下可以看到,PS部分的GP0口被使能了。刚加入的GPIO IP连接到了处理器上。点击Address菜单可以看到给其分配了0x41200000地址。

6、同样的方法加入定时器IP。双击AXI Timer/Counter -> Yes -> OK -> OK

7、切换到Ports菜单,展开processing_system7_0,点击L to H: No Connection

8、把定时器的中断信号添加到右边,可以看到系统自动给其分配了中断号91,点击OK

四、使能PS部分的外设GPIO,并使用EMIO
1、切换到ZYNQ菜单,点击I/O Peripherals

2、把GPIO改为用EMIO,把位宽改为1。用EMIO实现一个板上按键。

3、切换到Ports菜单,把GPIO的管脚连接到外部。

五、添加Chipscope模块用来观察AXI总线上的信号。
1、在IP Catalog中找到Chipscope AXI Monitor IP,双击添加,点Yes,点OK。

2、双击添加Chipscope Intergrated Controller,点Yes,点OK。

3、切换到Bus Interfaces菜单。把MON_AXI连接到GPIO的S_AXI总线上,用于观测PL部分GPIO的总线信号。

4、切换到Ports菜单,把Chipscope_icon_0中的control0信号连接到Chipscope_axi_monitor_0的CHIPSCOPE_ICON_CONTROL信号上。

5、 点击DRC,检查设计中是否存在错误。至此EDK部分的完成。关闭EDK工具,转回到PlanAhead界面。

六、添加顶层文件,管脚约束,导出硬件至SDK中。
1、在Design Sources中找到处理器,点右键选择Create Top HDL自动生成顶层文件。

2、点击Add Sources,添加约束文件,Next-> Create File ->输入约束名称-> OK -> Finish

3、在Constraints中找到刚添加的约束文件,双击打开。按照Zing开发板的连接分配好管脚。PL部分的GPIO按键指定到PU1,PS部分GPIO按键指定到PU2。

4、点击Generate Bitstream生成PL部分的Bit文件。

5、待编译完成后,点击File ->Export -> Export Bitstream File,输入文件名,点击Save。导出PL部分的bit文件便于之后的设计。

6、点击File ->Export -> Export Hardware For SDK,勾选Launch SDK,点OK。

七、在SDK中设计软件程序。
1、进入到SDK界面,点击File -> New -> Application Project,输入软件工程名,选择Hello World,点Finish。建立了一个简单的在串口上打印Hello World的工程,并自动编译驱动库及程序。

2、展开Led目录下src菜单,双击Hellowrold.c打开文件。

3、用以下程序替换Helloword.c中的内容。点击保存,程序自动编译。
/*
* Copyright (c) 2009 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
/*
* helloworld.c: simple test application
*/
#include 
#include "platform.h"
#include "xil_types.h"
#include "xgpio.h"
#include "xtmrctr.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "xil_io.h"
#include "xil_exception.h"
#include "xscugic.h"
static XGpioPs psGpioInstancePtr;
extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES];
static int iPinNumber = 10;
XScuGic InterruptController; /* Instance of the Interrupt Controller */
static XScuGic_Config *GicConfig;/* The configuration parameters of the
controller */
static int InterruptFlag;
void print(char *str);
extern char inbyte(void);
void Timer_InterruptHandler(void *data, u8 TmrCtrNumber)
{
print("\r\n");
print("\r\n");
print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n");
print(" Inside Timer ISR \n \r ");
XTmrCtr_Stop(data,TmrCtrNumber);
// PS GPIO Writting
print("LED 'DS23' Turned ON \r\n");
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,1);
XTmrCtr_Reset(data,TmrCtrNumber);
print(" Timer ISR Exit\n \n \r");
print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n");
print("\r\n");
print("\r\n");
InterruptFlag = 1;
}
int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr)
{
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the ARM processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler,
XScuGicInstancePtr);
/*
* Enable interrupts in the ARM
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}
int ScuGicInterrupt_Init(u16 DeviceId,XTmrCtr *TimerInstancePtr)
{
int Status;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
* */
GicConfig = XScuGic_LookupConfig(DeviceId);
if (NULL == GicConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&InterruptController, GicConfig,
GicConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the Interrupt System
* */
Status = SetUpInterruptSystem(&InterruptController);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an
* interrupt for the device occurs, the device driver handler performs
* the specific interrupt processing for the device
*/
Status = XScuGic_Connect(&InterruptController,
XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR,
(Xil_ExceptionHandler)XTmrCtr_InterruptHandler,
(void *)TimerInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the device and then cause (simulate) an
* interrupt so the handlers will be called
*/
XScuGic_Enable(&InterruptController, XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR);
return XST_SUCCESS;
}
int main()
{
static XGpio GPIOInstance_Ptr;
XGpioPs_Config*GpioConfigPtr;
XTmrCtr TimerInstancePtr;
int xStatus;
u32 Readstatus=0,OldReadStatus=0;
//u32 EffectiveAdress = 0xE000A000;
int iPinNumberEMIO = 54;
u32 uPinDirectionEMIO = 0x0;
// Input Pin
// Pin direction
u32 uPinDirection = 0x1;
int exit_flag,choice,internal_choice;
init_platform();
/* data = *(u32 *)(0x42800004);
print("OK \n");
data = *(u32 *)(0x41200004);
print("OK-1 \n");
*/
print("##### Application Starts #####\n\r");
print("\r\n");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-1 :AXI GPIO Initialization
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xStatus = XGpio_Initialize(&GPIOInstance_Ptr,XPAR_AXI_GPIO_0_DEVICE_ID);
if(XST_SUCCESS != xStatus)
print("GPIO INIT FAILED\n\r");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-2 :AXI GPIO Set the Direction
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XGpio_SetDataDirection(&GPIOInstance_Ptr, 1,1);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-3 :AXI Timer Initialization
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xStatus = XTmrCtr_Initialize(&TimerInstancePtr,XPAR_AXI_TIMER_0_DEVICE_ID);
if(XST_SUCCESS != xStatus)
print("TIMER INIT FAILED \n\r");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-4 :Set Timer Handler
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XTmrCtr_SetHandler(&TimerInstancePtr,
Timer_InterruptHandler,
&TimerInstancePtr);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-5 :Setting timer Reset Value
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XTmrCtr_SetResetValue(&TimerInstancePtr,
0, //Change with generic value
0xf0000000);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-6 :Setting timer Option (Interrupt Mode And Auto Reload )
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XTmrCtr_SetOptions(&TimerInstancePtr,
XPAR_AXI_TIMER_0_DEVICE_ID,
(XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION ));
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-7 :PS GPIO Intialization
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
if(GpioConfigPtr == NULL)
return XST_FAILURE;
xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,
GpioConfigPtr,
GpioConfigPtr->BaseAddr);
if(XST_SUCCESS != xStatus)
print(" PS GPIO INIT FAILED \n\r");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-8 :PS GPIO pin setting to Output
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumber,uPinDirection);
XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumber,1);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-9 :EMIO PIN Setting to Input port
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XGpioPs_SetDirectionPin(&psGpioInstancePtr,
iPinNumberEMIO,uPinDirectionEMIO);
XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumberEMIO,0);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-10 : SCUGIC interrupt controller Intialization
//Registration of the Timer ISR
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
xStatus=
ScuGicInterrupt_Init(XPAR_PS7_SCUGIC_0_DEVICE_ID,&TimerInstancePtr);
if(XST_SUCCESS != xStatus)
print(" :( SCUGIC INIT FAILED \n\r");
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Step-11 :User selection procedure to select and execute tests
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
exit_flag = 0;
while(exit_flag != 1)
{
print(" SELECT the Operation from the Below Menu \r\n");
print("###################### Menu Starts ########################\r\n");
print("Press '1' to use NORMAL GPIO as an input (SW5 switch)\r\n");
print("Press '2' to use EMIO as an input (SW7 switch)\r\n");
print("Press any other key to Exit\r\n");
print(" ##################### Menu Ends #########################\r\n");
choice = inbyte();
printf("Selection : %c \r\n",choice);
internal_choice = 1;
switch(choice)
{
//~~~~~~~~~~~~~~~~~~~~~~~
// Use case for AXI GPIO
//~~~~~~~~~~~~~~~~~~~~~~~~
case '1':
exit_flag = 0;
print("Press Switch 'SW5' push button on board \r\n");
print(" \r\n");
while(internal_choice != '0')
{
Readstatus = XGpio_DiscreteRead(&GPIOInstance_Ptr, 1);
if(1== Readstatus && 0 == OldReadStatus )
{
print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\r\n");
print("SW5 PUSH Button pressed \n\r");
print("LED 'DS23' Turned OFF \r\n");
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,0);
//Start Timer
XTmrCtr_Start(&TimerInstancePtr,0);
print("timer start \n\r");
//Wait For interrupt;
print("Wait for the Timer interrupt to tigger \r\n");
print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\r\n");
print(" \r\n");
while(InterruptFlag != 1);
InterruptFlag = 0;
print(" ###########################################\r\n ");
print("Press '0' to go to Main Menu \n\r ");
print("Press any other key to remain in AXI GPIO Test \n\r ");
print(" ###########################################\r\n ");
internal_choice = inbyte();
printf("Select = %c \r\n",internal_choice);
if(internal_choice != '0')
{
print("Press Switch 'SW5' push button on board \r\n");
}
}
OldReadStatus = Readstatus;
}
print(" \r\n");
print(" \r\n");
break;
case '2' :
//~~~~~~~~~~~~~~~~~~~~~~~
//Usecase for PS GPIO
//~~~~~~~~~~~~~~~~~~~~~~~~
exit_flag = 0;
print("Press Switch 'SW7' push button on board \r\n");
print(" \r\n");
while(internal_choice != '0')
{
Readstatus = XGpioPs_ReadPin(&psGpioInstancePtr,
iPinNumberEMIO);
if(1== Readstatus && 0 == OldReadStatus )
{
print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\r\n");
print("SW7 PUSH Button pressed \n\r");
print("LED 'DS23' Turned OFF \r\n");
XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,0);
//Start Timer
XTmrCtr_Start(&TimerInstancePtr,0);
print("timer start \n\r");
//Wait For interrupt;
print("Wait for the Timer interrupt to tigger \r\n");
print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\r\n");
print(" \r\n");
while(InterruptFlag != 1);
InterruptFlag = 0;
print(" ###########################################\r\n ");
print("Press '0' to go to Main Menu \n\r ");
print("Press any other key to remain in EMIO Test \n\r ");
print(" ###########################################\r\n ");
internal_choice = inbyte();
printf("Select = %c \r\n",internal_choice);
if(internal_choice != '0')
{
print("Press Switch 'SW7' push button on board \r\n");
}
}
OldReadStatus = Readstatus;
}
print(" \r\n");
print(" \r\n");
break;
default :
exit_flag = 1;
break;
}
}
print("\r\n");
print("***********\r\n");
print("BYE \r\n");
print("***********\r\n");
cleanup_platform();
return 0;
}

八、采用JTAG模式调试程序。
1、按照下图,接好电源、JTAG电缆、UART口。模式管脚JS3、JS4、JS5、JS6、JS7的连接见图中所示,跳线均接2、3针。

2、点击Xilinx Tools -> Program FPGA,指定之前生成的PL部分下载文件,点击Program。

3、切换到Terminal 1串口调试工具,点击Settings,设置好串口,点击OK,串口自动连接。

4、在Project Explorer菜单下,选择软件工程,右键Run As -> Run configurations,点击Xilinx C/C++ ELF,按照图中选择需要Debug的工程,点击Run。

6、 在Terminal 1中出现如下打印信息:
##### Application Starts #####
SELECT the Operation from the Below Menu
###################### Menu Starts ########################
Press '1' to use NORMAL GPIO as an input (PU1 switch)
Press '2' to use EMIO as an input (PU2 switch)
Press any other key to Exit
##################### Menu Ends #########################

在键盘上输入1或2,此时开始做按键扫描。按照屏幕提示按下按键,DDP11灯熄灭,此时计数器开始计数。当计数器计满后产生中断,DDP11灯重新点亮。

九、在TF卡中启动程序,并用ChipScope观察AXI4总线信号。

1、切换至Console菜单,点击Terminate中断JTAG调试。

2、点击File –> New -> Application Project,输入工程名,点Next。选定ZYNQ FSBL,点Finish。此时自动生成ZYNQ的初始化文件。

3、点击Xilinx Tools -> Create Boot Image,点击上面的Browse指定刚才编译完成FSBL ELF文件,点击Add加入PL部分的配置bit文件,点击Add加入软件编译后的文件ELF。点击下面的Browse,指定文件输出的路径,点击Create Image。生成TF卡启动文件。

4、在生成文件的路径中找到生成的文件。把其中的BIN文件的文件名改为BOOT。从PC中拷贝至TF卡中。

5、如图所示连在开发板中,接好电源、UART线。模式管脚JS3、JS4、JS5、JS6、JS7,除JS5、JS6接1、2针外,其他接2、3针。在SDk的Terminal 1中连接好串口。之后打开电源。

6、在调试终端中出现和之前相同的打印信息。证明ZYNQ正常启动。
7、确认JTAG电缆已接好。在PlanAhead中点击Launch Chipscope Analyzer运行Chipscope工具。

8、 点击左上角的Open Cable/Search JTAG Chain,在JTAG链上找到两个Device。点OK。

9、 点击File -> Import -> Select New File,从下图所示的路径中找到CDC文件并加入。点OK。

10、 在Trigger Setup菜单中,设置触发条件,把M1:MON_AXI_ARADDRCONTROL下的MON_AXI_ARVALID改为1。Position改为512。Trigger Condition Equation改为M1。

11、 点击Apply Settings And Arm Trigger,开始采样。可以看到由于此时AXI读总线上没有信号,故无法触发采样。

12、 切换至SDK的Terminal 1中,在键盘上输入1。此时ARM开始读GPIO的按键,Chipscope中采样到波形。可以根据此波形熟悉AXI总线协议。


0 0
原创粉丝点击