BAR初始化第一步,即BAR_SCAN子函数了解完了,下面我们了解初始化第二步,即TSK_BUILD_PCIE_MAP函数。再次复习下BAR初始化步骤(在TSK_BAT_INIT任务里面其实是在模拟BIOS和驱动程序的操作,首先会对BAR寄存器进行赋值,然后会对BAR指向的设备内存进行IO或者mem映射,最后就是对设备的配置寄存器的参数写入。):
/************************************************************
Task : TSK_BAR_INIT Inputs : None Outputs : None Description : Initialize PCI core based on core's configuration. *************************************************************/ task TSK_BAR_INIT; begin TSK_BAR_SCAN; TSK_BUILD_PCIE_MAP; TSK_DISPLAY_PCIE_MAP; TSK_BAR_PROGRAM; end endtask // TSK_BAR_INIT复制代码 TSK_BUILD_PCIE_MAP源代码有点长,这里就不贴了。其主要目的就是执行存储器或I/O映射算法,并依据Endpoint需求分配Memory 32、Memory 64和I/O空间。具体来说,就是根据上一步TSK_BAR_SCAN得到的各个BAR的range变量,检查这些range,根据检查结果,判断每个BAR是否被使能、及其对应的映射结果(是MEM32啊还是MEM64啊,或者是I/O空间)。仿真的时候会将检查结果打印如下:注:函数TSK_BUILD_PCIE_MAP在检查正常的时候只会打印上图中的第一句;下面每个BAR空间的检查结果,是在调用函数TSK_DISPLAY_PCIE_MAP的时候打印的。
BAR空间初始化最后一步,看似就是将之前读回的BAR状态重新使用Type0配置写再写回去(
这里应该对应应用程序里的BAR空间基地址的产生,电脑开机扫描获取PCIe的各个BAR的信息,为它们分配地址空间,这里的Program应该是将分配好的地址空间基地址重新写回到BAR寄存器),比如对BAR0的写:
// Program BAR0
TSK_TX_TYPE0_CONFIGURATION_WRITE(DEFAULT_TAG, 12'h10, BAR_INIT_P_BAR[0][31:0], 4'hF); DEFAULT_TAG = DEFAULT_TAG + 1; TSK_TX_CLK_EAT(100);复制代码这个子函数还对其它BAR空间进行Type0配置写,个人觉得,其它BAR空间都Disable了,写不写都无所谓。值得注意的时候,该子函数最后还对PCI命令寄存器和PCIe器件控制寄存器进行了编程:
// Program PCI Command Register
TSK_TX_TYPE0_CONFIGURATION_WRITE(DEFAULT_TAG, 12'h04, 32'h00000003, 4'h1); DEFAULT_TAG = DEFAULT_TAG + 1; TSK_TX_CLK_EAT(100); // Program PCIe Device Control Register TSK_TX_TYPE0_CONFIGURATION_WRITE(DEFAULT_TAG, 12'h68, 32'h0000005f, 4'h1); DEFAULT_TAG = DEFAULT_TAG + 1; TSK_TX_CLK_EAT(1000);复制代码注意上述两次写和BAR0写的区别,比如最后一个参数为4‘h1,则表示只有最低字节被Enable了,即只需传递低8位即可。
了解完BAR空间的初始化,后面开始了解正常的PIO仿真,即存储器写和存储器读。
作者: coyoo, 来源:面包板社区
链接: https://mbb.eet-china.com/blog/uid-me-1010859.html
版权声明:本文为博主原创,未经本人允许,禁止转载!
文章评论(0条评论)
登录后参与讨论