AR# 64980

SDK — 如何使用 HSI 为定制 IP 创建驱动程序

描述

我如何使用 HSI 为定制 IP 创建驱动程序?

解决方案

本答复记录主要介绍如何使用 HSI 工具来创建一个定制驱动程序,使 xparameters.h 文件驻留在 SDK 中。

第 1 步:在 IP 打包器中创建 IP

在以下实例中创建一个简单的 AXI 从 IP 并连接至 MPSoC 器件:



默认情况下,IP 打包器为 IP 生成一个简单的驱动程序,以便在硬件导出至 SDK 时,将该驱动程序打包在硬件平台中。

步骤 2: 使用 HSI 探索硬件设计

可以使用 HSI 检查导出的硬件设计(HDF 文件),因此可以在驱动程序生成 Tcl 中使用该工具根据设计对其进行定制。

启动 SDK shell 并调用 HSI 获得命令提示符。

$ hsi
****** hsi v2018.2 (64-bit)
  **** SW Build 2258646 on Thu Jun 14 20:02:38 MDT 2018
    ** Copyright 1986-2018 Xilinx, Inc. All Rights Reserved.

hsi%

  • 打开 HW 设计:

hsi% open_hw_design system.hdf
INFO: [Hsi 55-1698] elapsed time for repository loading 1 seconds
open_hw_design: Time (s): cpu = 00:00:10 ; elapsed = 00:00:12 . Memory (MB): peak = 519.324 ; gain = 194.016 ; free physical = 10326 ; free virtual = 350695
design_1_wrapper

  • 在设计中检查 IP:

hsi% get_cells *
myip_0 ps8_0_axi_periph rst_ps8_0_99M zynq_ultra_ps_e_0 psu_axi_interconnect_0 psu_coresight_0 psu_acpu_gic psu_rcpu_gic psu_r5_tcm_ram_global psu_r5_tcm_ram_0 psu_ocm_ram_0 psu_ocm psu_r5_1_btcm psu_r5_1_btcm_global psu_r5_1_atcm psu_r5_1_atcm_global psu_r5_0_btcm_lockstep psu_r5_0_btcm psu_r5_0_btcm_global psu_r5_0_atcm_lockstep psu_r5_0_atcm psu_r5_0_atcm_global psu_bbram_0 psu_pmu_ram psu_pmu_iomodule psu_pmu_global_0 psu_mbistjtag psu_rsa psu_efuse psu_csu_wdt psu_csudma psu_smmu_gpv psu_fpd_gpv psu_cci_gpv psu_fpd_slcr_secure psu_fpd_slcr psu_smmu_reg psu_cci_reg psu_fpd_xmpu_cfg psu_apu psu_gdma_7 psu_gdma_6 psu_gdma_5 psu_gdma_4 psu_gdma_3 psu_gdma_2 psu_gdma_1 psu_gdma_0 psu_fpd_xmpu_sink psu_dpdma psu_gpu psu_dp psu_apm_5 psu_serdes psu_siou psu_afi_5 psu_afi_4 psu_afi_3 psu_afi_2 psu_afi_1 psu_afi_0 psu_crf_apb psu_pcie_dma psu_pcie_low psu_pcie_high1 psu_pcie_high2 psu_pcie psu_pcie_attrib_0 psu_sata psu_apm_0 psu_ddr_qos_ctrl psu_ddr_phy psu_ddr_xmpu5_cfg psu_ddr_xmpu4_cfg psu_ddr_xmpu3_cfg psu_ddr_xmpu2_cfg psu_ddr_xmpu1_cfg psu_ddr_xmpu0_cfg psu_adma_7 psu_adma_6 psu_adma_5 psu_adma_4 psu_adma_3 psu_adma_2 psu_adma_1 psu_adma_0 psu_ocm_xmpu_cfg psu_rtc psu_ams psu_apm_2 psu_apm_1 psu_usb_0 psu_usb_xhci_0 psu_lpd_xppu_sink psu_afi_6 psu_rpu psu_lpd_xppu psu_crl_apb psu_lpd_slcr_secure psu_lpd_slcr psu_ipi_0 psu_ipi_1 psu_ipi_2 psu_ipi_3 psu_ipi_4 psu_ipi_5 psu_ipi_6 psu_ctrl_ipi psu_message_buffers psu_iou_s psu_iou_scntrs psu_iou_scntr psu_iousecure_slcr psu_iouslcr_0 psu_r5_ddr_0 psu_ddr_0 psu_ddr_1 psu_ddrc_0 psu_sd_1 psu_wdt_0 psu_wdt_1 psu_ttc_3 psu_ttc_2 psu_ttc_1 psu_ttc_0 psu_qspi_0 psu_ethernet_3 psu_gpio_0 psu_can_1 psu_i2c_1 psu_i2c_0 psu_uart_1 psu_uart_0 psu_qspi_linear_0 psu_cortexa53_0 psu_cortexa53_1 psu_cortexa53_2 psu_cortexa53_3 psu_cortexr5_0 psu_cortexr5_1 psu_pmu_0

  • 获得 IP 属性

 list_property [get_cells myip_0]
ADDRESS_TAG CLASS CONFIG.C_INTR_ACTIVE_STATE CONFIG.C_INTR_SENSITIVITY CONFIG.C_IRQ_ACTIVE_STATE CONFIG.C_IRQ_SENSITIVITY CONFIG.C_NUM_OF_INTR CONFIG.C_S00_AXI_ADDR_WIDTH CONFIG.C_S00_AXI_BASEADDR CONFIG.C_S00_AXI_DATA_WIDTH CONFIG.C_S00_AXI_HIGHADDR CONFIG.C_S_AXI_INTR_ADDR_WIDTH CONFIG.C_S_AXI_INTR_BASEADDR CONFIG.C_S_AXI_INTR_DATA_WIDTH CONFIG.C_S_AXI_INTR_HIGHADDR CONFIG.Component_Name CONFIG.EDK_IPTYPE CONFIGURABLE DRIVER_MODE HIER_NAME IP_NAME IP_TYPE IS_HIERARCHICAL IS_PL NAME PRODUCT_GUIDE SLAVES VLNV

  • 获得 IP 引脚

get_pins -of_objects [get_cells myip_0]
s00_axi_awaddr s00_axi_awprot s00_axi_awvalid s00_axi_awready s00_axi_wdata s00_axi_wstrb s00_axi_wvalid s00_axi_wready s00_axi_bresp s00_axi_bvalid s00_axi_bready s00_axi_araddr s00_axi_arprot s00_axi_arvalid s00_axi_arready s00_axi_rdata s00_axi_rresp s00_axi_rvalid s00_axi_rready s00_axi_aclk s00_axi_aresetn irq s_axi_intr_awaddr s_axi_intr_awprot s_axi_intr_awvalid s_axi_intr_awready s_axi_intr_wdata s_axi_intr_wstrb s_axi_intr_wvalid s_axi_intr_wready s_axi_intr_bresp s_axi_intr_bvalid s_axi_intr_bready s_axi_intr_araddr s_axi_intr_arprot s_axi_intr_arvalid s_axi_intr_arready s_axi_intr_rdata s_axi_intr_rresp s_axi_intr_rvalid s_axi_intr_rready s_axi_intr_aclk s_axi_intr_areset

  • 获得 IP 时钟引脚

get_pins -of_objects [get_cells myip_0] -filter TYPE==clk

s00_axi_aclk_axi_intr_aclk

  • 获得引脚属性

list_property [get_pins s00_axi_aclk]
CLASS CLK_FREQ DIRECTION INTERFACE IRQID IS_CONNECTED LEFT NAME RIGHT SENSITIVITY TYPE

  • 获得引脚属性值

get_property CLK_FREQ [get_pins s00_axi_aclk]
99990000

  • 检查中断引脚是否连接至任何中断控制器

hsi% set int_pin [get_pins -of_objects [get_cells myip_0] -filter TYPE==INTERRUPT]
irq
hsi% set intc_type [:hsi::utils::get_connected_intr_cntrl myip_0 $int_pin]

了解更多有关 HSI 命令的信息,请查看 (UG1138)


第 3 步:更新驱动程序 Tcl 文件

将硬件平台驱动程序中的自定义 IP 的 Tcl 脚本修改为开发流程。 

在驱动程序中所做的更改仅适用于基于硬件项目生成的 BSP,但一旦稳定,这些更改可导出至在 Vivado 中创建的 IP 库中。

proc generate {drv_handle} {
        xdefine_include_file $drv_handle "xparameters.h" "myip" "NUM_INSTANCES" "DEVICE_ID"  "C_S00_AXI_BASEADDR" "C_S00_AXI_HIGHADDR"

        #Custom Diver handler
        set periph_name [get_property IP_NAME [get_cells  $drv_handle]]
        set found [string first $periph_name $drv_handle]
        if {$found != -1} {
                set ip_name [string toupper [string range $drv_handle $found [string length $drv_handle]]]
        } else {
                set ip_name [string toupper $drv_handle]
        }

        set file_handle [::hsi::utils::open_include_file xparameters.h]
        puts $file_handle "/* This is from the custom addition $ip_name */"

        set clk_pins [get_pins -of_objects [get_cells $drv_handle] -filter TYPE==clk]
        for {set i 0} {$i < [llength $clk_pins]} {incr i} {
                set clk_freq [get_property CLK_FREQ [lindex $clk_pins $i]]
                set clk_name [string toupper [get_property NAME [lindex $clk_pins $i]]]
                puts $file_handle "\#define XPAR_${ip_name}_${clk_name} $clk_freq"
        }

        set int_pin [get_pins -of_objects [get_cells $drv_handle] -filter TYPE==INTERRUPT]
        set intc_periph_type [::hsi::utils::get_connected_intr_cntrl myip_0 $int_pin]
        if {$intc_periph_type != ""} {
                puts $file_handle "\#define XPAR_${ip_name}_INTERRUPT_CONNECTED 1"
        } else {
                puts $file_handle "\#define XPAR_${ip_name}_INTERRUPT_CONNECTED 0"
        }

        close $file_handle
}


Tcl 脚本中的定制代码可执行以下操作:


  • 打开 xparameters.h 文件
  • 使用 drv_handler 查找 IP 名称。如果该 IP 位于一个子块中,则只使用驱动程序名称。
  • 获取定制 IP 中的所有时钟引脚,并将这些引脚输出至报头文件
  • 检查定制 IP 中的中断是否连接,并将其输出至报头文件
  • 关闭报头文件

步骤 4: 测试 BSP

一旦 Tcl 脚本就绪,就可以创建一个 BSP 项目来检查定制 IP 的驱动程序是否生成了属性。




BSP 的 xparameters.h 文件包含自定义值:


/* This is from the custom addition MYIP_0 */
#define XPAR_MYIP_0_S00_AXI_ACLK 99990000
#define XPAR_MYIP_0_S_AXI_INTR_ACLK 99990000
#define XPAR_MYIP_0_INTERRUPT_CONNECTED 1


第 5 步:整合到 Vivado 库中

要将定制驱动程序整合在 Vivado 库中,只需将 Tcl 脚本复制到存储 IP 的 ip_repo 文件夹中即可。

这将触发 Vivado 中的 IP 更改,因此更新设计,可整合新驱动程序。 

通过这种方式,每次使用定制 IP 导出硬件时都会使用新脚本。

链接问答记录

主要问答记录

Answer Number 问答标题 问题版本 已解决问题的版本
66297 SDK - 设计助手 N/A N/A
AR# 64980
日期 08/20/2018
状态 Active
Type 解决方案中心
Tools