官方例程为,通过驱动程序控制PL端LED灯周期闪烁。
需要配置对LED灯的控制逻辑,该控制逻辑通过ip核封装。

其中,对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端逻辑进行闪烁了。

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

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