当前位置:   article > 正文

Zynq-PS-SDK(6) 之 AXI GPIO_sdk怎么控制axi

sdk怎么控制axi

目录

1、Block Design

2、Generate top level

3、Add constraints & Bitstream

4、Export Hardware

5、Software driver

5.1、Datasheet

5.2、Code


 

前面说过 PS 端可以使用 EMIO 来映射 IO,进而使用到 PL 端的 IO 口,另外一种办法就是使用 AXI 总线互联,在 PL 端实现一个逻辑,通过 AXI 总线进行配置和访问,这里先以一个最简单的 IO 控制为例;

板端 PS 有2个 LED 的 IO,PL 端有 4 个 LED 的 IO 和按键 IO,初步打算 IO 的分配如下,这样就可以覆盖到每种用法:

这里我们关心 AXI GPIO 一行,EMIO 和 MIO 的部分在前面的《Zynq-PS-SDK 之 EMIO 使用》 和 《Zynq-PS-SDK 之 MIO 使用》中已经描述,不在多说;

 

1、Block Design

Xilinx 的 Vivado 软件集成了相关的 IP,我们只需要在 PL 端新增 AXI GPIO 的 IP 即可,这里我们新增两个 AXI GPIO,一个作为控制 LED,另一个作为控制 Key 产生中断;

如图所示,Zynq 的 PS 端使用到了一个 M_AXI_GP0 的资源(红色),连接到一个 AXI Interconnect 互联单元,互联单元连接了 axi_gpio_0 和 axi_gpio_1;

配置 AXI GPIO 端口,一个为输入,一个为输出,位宽都是 1b;

block design 连接完成后(点击 Run Connection Automation),点击 Optimize Routing 可以优化布局;

2、Generate top level

保存 block design,然后【Generate Output Products】:

【Generate Output Products】这样就会生成顶层文件:

./Zynq7020_PS.srcs/sources_1/bd/design_1/hdl/design_1_wrapper.v

 

3、Add constraints & Bitstream

此刻,我们需要为我们定义的管脚进行约束,打开 design_1_wrapper.v

这个就是顶层的管脚名字,对应到原理图中,进行管脚 xdc 的约束:

  1. # PL EMIO LED
  2. set_property PACKAGE_PIN M14 [get_ports {pl_led1_emio_tri_io[0]}]
  3. set_property IOSTANDARD LVCMOS33 [get_ports {pl_led1_emio_tri_io[0]}]
  4. # PL AXI GPIO LED
  5. set_property PACKAGE_PIN M15 [get_ports {pl_led2_axi_tri_o[0]}]
  6. set_property IOSTANDARD LVCMOS33 [get_ports {pl_led2_axi_tri_o[0]}]
  7. # PL Input Interrupt
  8. set_property PACKAGE_PIN N15 [get_ports {pl_key_input_tri_i[0]}]
  9. set_property IOSTANDARD LVCMOS33 [get_ports {pl_key_input_tri_i[0]}]

约束完成后,生成 bitstream;

 

4、Export Hardware

生成完 Bitstream 后,硬件部分就完成了,接下来导出硬件:【File】->【Export】->【Export Hardware】:

导出硬件的时候,记得勾选 【Include bitstream】:

此刻,硬件部分就完成了;

 

5、Software driver

5.1、Datasheet

硬件弄完后,由于我们增加了 AXI GPIO,所以在系统信息中看得到:

我们展开 axi_gpio_0,可以看到 axi_gpio_0 的寄存器地址,以及相关的偏移:

针对 Xilinx 的 AXI GPIO 相关的内容,可以参考 Xilinx 方法的 AXI GPIO 的 IP 说明:PG144

可以看到,每一个 AXI GPIO IP 可以配置 2 路 GPIO,每一路的宽度为 WIDTH,我们这里就是 32;

寄存器的说明如下:

我们这里,只是用了 GPIO 的输出功能,

GPIO_DATA 寄存器描述为:

 

GPIOX_TRI 寄存器描述为(也就是配置输出还是输入):

 

GIER 是中断控制,这个 AXI GPIO IP 的全局中断控制:

 

IPIER 也是中断控制,可以理解为,GPIO 和 GPIO2 单独的控制:

 

IPISR 是中断状态:

 

5.2、Code

OK,现在知道了这个 IP 的寄存器用法和绝对地址,而且硬件也 Ready了,那么咱们就可以动起来了,代码上:

  1. XGpioPs Gpio;
  2. #define RD_32BIT_REG(addr) (*(volatile uint32_t *)(addr))
  3. #define WR_32BIT_REG(addr, value) (*(volatile uint32_t *)(addr)) = (value)
  4. #define STEPH_MIO_0 0
  5. #define STEPH_MIO_1 13
  6. #define STEPH_EMIO_0 54
  7. #define STEPH_EMIO_1 55
  8. #define STEPH_EMIO_2 56
  9. #define STEPH_EMIO_3 57
  10. #define MIO_OUTPUT 1
  11. #define MIO_INPUT 0
  12. #define MIO_OUTPUT_EN 1
  13. #define MIO_OUTPUT_DIS 0
  14. /* Accroding to the system.hdf file axi_gpio_0 */
  15. #define AXI_GPIO_0_BASE_ADDR 0x41200000
  16. #define GPIO_DATA_OFFSET 0x00
  17. #define GPIO_TRI_OFFSET 0x04
  18. #define GPIO_2_DATA_OFFSET 0x08
  19. #define GPIO_2_TRI_OFFSET 0x0C
  20. #define GIER_OFFSET 0x11C
  21. #define IP_ISR_OFFSET 0x120
  22. #define IP_IER_OFFSET 0x128
  23. static void Steph_AXI_GPIO_Init(void)
  24. {
  25. // Set as output
  26. WR_32BIT_REG(AXI_GPIO_0_BASE_ADDR + GPIO_TRI_OFFSET, 0x00);
  27. }
  28. static void Steph_AXI_LED_On(void)
  29. {
  30. WR_32BIT_REG(AXI_GPIO_0_BASE_ADDR + GPIO_DATA_OFFSET, 0x00);
  31. }
  32. static void Steph_AXI_LED_Off(void)
  33. {
  34. WR_32BIT_REG(AXI_GPIO_0_BASE_ADDR + GPIO_DATA_OFFSET, 0x0F);
  35. }
  36. uint32_t Steph_LEDInit(void)
  37. {
  38. XGpioPs_Config *ConfigPtr = NULL;
  39. int Status = XST_SUCCESS;
  40. ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
  41. if(!ConfigPtr)
  42. {
  43. xil_printf("XGpioPs_LookupConfig Error.\r\n");
  44. return XST_FAILURE;
  45. }
  46. Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr,
  47. ConfigPtr->BaseAddr);
  48. if (Status != XST_SUCCESS) {
  49. xil_printf("XGpioPs_CfgInitialize Error.\r\n");
  50. return XST_FAILURE;
  51. }
  52. // For MIO
  53. XGpioPs_SetDirectionPin(&Gpio, STEPH_MIO_0, MIO_OUTPUT);
  54. XGpioPs_SetDirectionPin(&Gpio, STEPH_MIO_1, MIO_OUTPUT);
  55. XGpioPs_SetOutputEnablePin(&Gpio, STEPH_MIO_0, MIO_OUTPUT_EN);
  56. XGpioPs_SetOutputEnablePin(&Gpio, STEPH_MIO_1, MIO_OUTPUT_EN);
  57. xil_printf("Steph_LED MIO Initialize Finished...\r\n");
  58. // For EMIO
  59. XGpioPs_SetDirectionPin(&Gpio, STEPH_EMIO_0, MIO_OUTPUT);
  60. XGpioPs_SetOutputEnablePin(&Gpio, STEPH_EMIO_0, MIO_OUTPUT_EN);
  61. xil_printf("Steph_LED EMIO Initialize Finished...\r\n");
  62. Steph_AXI_GPIO_Init();
  63. xil_printf("Steph_LED AXI GPIO Initialize Finished...\r\n");
  64. return Status;
  65. }
  66. void LED_OFF(uint32_t pin)
  67. {
  68. XGpioPs_WritePin(&Gpio, pin, 0x1);
  69. }
  70. void LED_ON(uint32_t pin)
  71. {
  72. XGpioPs_WritePin(&Gpio, pin, 0x0);
  73. }

 

相关代码和工程在 gitee 持续更新:

https://gitee.com/stephenzhou-tech/Zynq7020_PS

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/830490
推荐阅读
相关标签
  

闽ICP备14008679号