Commit b1948b13 authored by Konstantin Luebeck's avatar Konstantin Luebeck

Completed section on 'Software for the Zynq PS'.

parent 842c82df
......@@ -297,3 +297,264 @@ To bring the custom AXI4 IP with the block diagram to the Zynq PL you have to sy
5. Lastly, when the bitstream generation is finished you can look at the reports to see if all contraints are fulfilled. Choose _View Reports_ and click OK. (However, this is not necessary here since the design is very simple).
![view reports](./images/synthesis_and_implementation05.png "view reports")
## Software for the Zynq PS
To program the Zedboard and talk to it via UART you have to connect it to the power supply and connect two USB cables from your computer to the following USB ports on the Zedboard.
![zedboard connection](./images/zedboard01.jpg "zedboard connection")
Make sure your Zedboard is turned on. If the green _POWER_ led is on the Zedboard is turned on.
![zedboard led](./images/zedboard02.jpg "zedboard led")
The C program which will be transferred to the Zynq PS will initiate an AXI4 read/write burst transaction over the AXI4-Lite slave interface of your custom AXI4 IP and afterwards it will verify the result.
1. You have to export the hardware configuration to the Xilinx SDK. Go to _Menu -> File -> Export -> Export Hardware ..._.
![menu export hardware](./images/software01.png "menu export hardware")
2. Check _Include bitstream_ and click _OK_.
![export hardware](./images/software02.png "export hardware")
3. To launch the Xilinx SDK go to _Menu -> File -> Launch SDK_
![lauch sdk](./images/software03.png "lauch sdk")
4. When the Xilinx SDK is ready create a new project by going to _Menu -> File -> New -> Application Project_.
![new application project](./images/software04.png "new application project")
5. Choose a _Project name_ and leave all other parameters at their default value and click on _Next >_. The _Project name_ in this tutorial is _axi4\_pl\_interrupt\_generator\_test_.
![project name](./images/software05.png "project name")
6. Choose _Hello World_ under _Available Templates_ and click on finish. This creates a simple Hello World program for the Zynq PS.
![hello world](./images/software06.png "hello world")
7. After the project was successfully created open `helloworld.c` under _Project Explorer -> _axi4\_pl\_interrupt\_generator\_test -> src -> helloworld.c_
![helloworld.c](./images/software07.png "helloworld.c")
8. Replace the Hello World C code with:
```c
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xbasic_types.h"
#include "xscugic.h"
#include "xil_exception.h"
#define INTC_INTERRUPT_ID_0 61 // IRQ_F2P[0:0]
#define INTC_INTERRUPT_ID_0 62 // IRQ_F2P[1:1]
// instance of interrupt controller
static XScuGic intc;
// address of AXI PL interrupt generator
Xuint32* baseaddr_p = (Xuint32*) XPAR_AXI4_PL_INTERRUPT_GENERATOR_0_S00_AXI_BASEADDR;
int setup_interrupt_system();
void isr0 (void *InstancePtr);
void isr1 (void *InstancePtr);
void nops(unsigned int num) {
int i;
for(i = 0; i < num; i++) {
asm("nop");
}
}
int main()
{
init_platform();
xil_printf("== START ==\n\r");
// set interrupt_0/1 of AXI PL interrupt generator to 0
*(baseaddr_p+0) = 0x00000000;
*(baseaddr_p+1) = 0x00000000;
xil_printf("Checkpoint 1\n\r");
// set interrupt_0/1 of AXI PL interrupt generator to 1
*(baseaddr_p+0) = 0x00000001;
*(baseaddr_p+1) = 0x00000001;
xil_printf("Checkpoint 2\n\r");
// read interrupt_0/1 of AXI PL interrupt generator
xil_printf("slv_reg0: 0x%08x\n\r", *(baseaddr_p+0));
xil_printf("slv_reg1: 0x%08x\n\r", *(baseaddr_p+1));
// set interrupt_0/1 of AXI PL interrupt generator to 0
*(baseaddr_p+0) = 0x00000000;
*(baseaddr_p+1) = 0x00000000;
xil_printf("Checkpoint 3\n\r");
// read interrupt_0/1 of AXI PL interrupt generator
xil_printf("slv_reg0: 0x%08x\n\r", *(baseaddr_p+0));
xil_printf("slv_reg1: 0x%08x\n\r", *(baseaddr_p+1));
xil_printf("Checkpoint 4\n\r");
// setup and enable interrupts for IRQ_F2P[1:0]
int status = setup_interrupt_system();
if (status != XST_SUCCESS) {
return XST_FAILURE;
}
xil_printf("Checkpoint 5\n\r");
nops(1000);
// set interrupt_0 of AXI PL interrupt generator to 1 (isr0 will be called)
*(baseaddr_p+0) = 0x00000001;
xil_printf("Checkpoint 6\n\r");
nops(1000);
// set interrupt_1 of AXI PL interrupt generator to 1 (isr1 will be called)
*(baseaddr_p+1) = 0x00000001;
// disable interrupts for IRQ_F2P[1:1]
XScuGic_Disable(&intc, INTC_INTERRUPT_ID_1);
xil_printf("Checkpoint 7\n\r");
nops(1000);
// set interrupt_0 of AXI PL interrupt generator to 1 (isr0 will be called)
*(baseaddr_p+0) = 0x00000001;
xil_printf("Checkpoint 8\n\r");
nops(1000);
// set interrupt_1 of AXI PL interrupt generator to 1
// (isr1 wont be called since interrupts for IRQ_F2P[1:1] are disabled)
*(baseaddr_p+1) = 0x00000001;
xil_printf("== STOP ==\n\r");
cleanup_platform();
return 0;
}
// interrupt service routine for IRQ_F2P[0:0]
void isr0 (void *InstancePtr) {
xil_printf("isr0 called\n\r");
*(baseaddr_p+0) = 0x00000000;
}
// interrupt service routine for IRQ_F2P[1:1]
void isr1 (void *InstancePtr) {
xil_printf("isr1 called\n\r");
*(baseaddr_p+1) = 0x00000000;
}
// sets up the interrupt system and enables interrupts for IRQ_F2P[1:0]
int setup_interrupt_system() {
int result;
XScuGic *intc_instance_ptr = &intc;
XScuGic_Config *intc_config;
// get config for interrupt controller
intc_config = XScuGic_LookupConfig(XPAR_PS7_SCUGIC_0_DEVICE_ID);
if (NULL == intc_config) {
return XST_FAILURE;
}
// initialize the interrupt controller driver
result = XScuGic_CfgInitialize(intc_instance_ptr, intc_config, intc_config->CpuBaseAddress);
if (result != XST_SUCCESS) {
return result;
}
// set the priority of IRQ_F2P[0:0] to 0xA0 (highest 0xF8, lowest 0x00) and a trigger for a rising edge 0x3.
XScuGic_SetPriorityTriggerType(intc_instance_ptr, INTC_INTERRUPT_ID_0, 0xA0, 0x3);
// connect the interrupt service routine isr0 to the interrupt controller
result = XScuGic_Connect(intc_instance_ptr, INTC_INTERRUPT_ID_0, (Xil_ExceptionHandler)isr0, (void *)&intc);
if (result != XST_SUCCESS) {
return result;
}
// enable interrupts for IRQ_F2P[0:0]
XScuGic_Enable(intc_instance_ptr, INTC_INTERRUPT_ID_0);
// set the priority of IRQ_F2P[1:1] to 0xA8 (highest 0xF8, lowest 0x00) and a trigger for a rising edge 0x3.
XScuGic_SetPriorityTriggerType(intc_instance_ptr, INTC_INTERRUPT_ID_1, 0xA8, 0x3);
// connect the interrupt service routine isr1 to the interrupt controller
result = XScuGic_Connect(intc_instance_ptr, INTC_INTERRUPT_ID_1, (Xil_ExceptionHandler)isr1, (void *)&intc);
if (result != XST_SUCCESS) {
return result;
}
// enable interrupts for IRQ_F2P[1:1]
XScuGic_Enable(intc_instance_ptr, INTC_INTERRUPT_ID_1);
// initialize the exception table and register the interrupt controller handler with the exception table
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, intc_instance_ptr);
// enable non-critical exceptions
Xil_ExceptionEnable();
return XST_SUCCESS;
}
```
9. Program the Zynq PL with the previously generated bitstream by going to _Menu -> Xilinx Tools -> Program FPGA_.
![menu program fpga](./images/software08.png "menu program fpga")
10. Click on _Program_.
![program fpga](./images/software09.png "program fpga")
11. The Zynq PS will write the content of all `xil_printf("...");` statments to the UART.
On Linux you can connect to the UART of the Zedboard with the following `picocom` command:
```bash
picocom /dev/ttyACM0 -b 115200 -d 8 -y n -p 1
```
12. After you programed the Zynq PL you can and connected to the UART you can build and run the Program on the Zynq PS by clicking on ![build](./images/software10.png "build") and then on ![run](./images/software11.png "run").
13. Choose _Lauch on Hardware (System Debugger)_ and click on _OK_.
![run on hardware](./images/software12.png "run on hardware")
14. You should see the following output in `picocom`:
```
== START ==
Checkpoint 1
Checkpoint 2
slv_reg0: 0x00000001
slv_reg1: 0x00000001
Checkpoint 3
slv_reg0: 0x00000000
slv_reg1: 0x00000000
Checkpoint 4
Checkpoint 5
isr0 called
Checkpoint 6
isr1 called
Checkpoint 7
isr0 called
Checkpoint 8
== STOP ==
```
You can leave `picocom` with [CTRL]+[A] [CTRL]+[Q].
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment