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条评论)
登录后参与讨论