PS端与PL端交互学习_20260318

官方例程学习

官方例程为,通过驱动程序控制PL端LED灯周期闪烁。

需要配置对LED灯的控制逻辑,该控制逻辑通过ip核封装。

alt text

其中,对LED状态控制的输出信号,由slv_reg0寄存器控制,PS端可以通过驱动程序,对该寄存器进行写入操作,将设定的值写入寄存器中对应控制LED灯状态的位置,从而控制LED灯当前状态。

ip核中,默认对该寄存器的控制通过外部输入,需要拉高写使能信号后对寄存器输入值。

	    if (slv_reg_wren)
	      begin
	        case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
	          2'h0:
	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
	                // Respective byte enables are asserted as per write strobes 
	                // Slave register 0
	                slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
	              end  
                ···

因此,驱动程序中,需要对相关寄存器写入控制的值。

AxiData_0 = ioremap(AxiUserGpio_data->reg_value[1] + AxiUserGpio_data->addr_width *
 0, AxiUserGpio_data->addr_width);
for (i = 0; i < 12; i++) 
{ 
    writel(i % 4, AxiData_0);  
    ssleep(1); 
} 

之后配置linux系统,在开发板上应用驱动程序后,PL端LED灯可以根据驱动程序输入的值,进行对应的闪烁。

官方例程修改

参考上述内容,对官方例程进行了修改。

在25.axiusergpio中,LED灯通过驱动程序axi_user_gpio.ko控制LED闪烁。
现在将程序修改为,通过PL端IP核控制LED灯闪烁,驱动程序同步读取LED灯的当前状态。

创建新工程项目my_led_ctrl。工程中具体控制LED灯闪烁的相关逻辑略。

与PS端交互,调用的是slv_reg0寄存器。因此,将LED灯的状态赋值给该寄存器。

    always @(posedge S_AXI_ACLK) begin
        if (!S_AXI_ARESETN)
            slv_reg0 <= 0;
        else
            slv_reg0 <= {30'b0, led_state};  // 将 led_state 放入低2位,其余位清零
    end

由于我们不想通过驱动程序修改该寄存器的值,因此,原来程序中写使能控制逻辑需要注释掉。

驱动程序选择读取值。

AxiData_0 = ioremap(AxiUserGpio_data->reg_value[1] + AxiUserGpio_data->addr_width *
 0, AxiUserGpio_data->addr_width);
while (1) 
{   
    printk(KERN_CRIT "AxiData_0:%#X\n", readl(AxiData_0));
    ssleep(1); 
} 

此时,将linux系统存进tf卡并启动开发板后,不需要装载驱动程序,LED灯就已经按照PL端逻辑进行闪烁了。
alt text

装载驱动程序后,可以每隔一秒输出当前LED灯的状态。 alt text


本文章使用limfx的vscode插件快速发布