2

这是我的第一篇文章 :) 我正在使用 VxWorks 6.9 和 Intel Sandy Bridge 板。我想知道如何在我的应用程序中映射 PCIe 内存区域。PCIe 内存区域是图形内存的一部分,它的物理地址是 0x80000000。

我正在尝试使用不返回虚拟地址的 vmMap 函数。在这种情况下,我将虚拟地址设置为与物理地址相同的值,但我不知道这是否是好的行为。如何从物理地址获取虚拟地址?如果不存在函数,我必须使用什么虚拟地址?

当我在我的应用程序中映射了该区域时,我正在对该区域的访问进行调整。我正在尝试使用函数 vmStateSet 更改缓存状态,但只能设置 COPYBACK、WRITETHRU 和 DEFAULT(设置其他缓存值失败)。所有缓存状态的吞吐量都很低。在 Intel Sandybridge 中,可以将 MMU 设置为写入组合。我如何在 VxWorks 中做到这一点?

这是我到目前为止所尝试的:

int test_appli_pci (void) {
struct timeval      start, end;
uint64_t            time_us = 0;
VIRT_ADDR           buffer_virt_dest = ADDR_PHYS_GRAPHIC_PCI;
void*               buffer_virt_src = NULL;
int                 i;
int                 j;
UINT                state;
UINT                states[] = {MMU_ATTR_CACHE_OFF, MMU_ATTR_CACHE_COPYBACK, MMU_ATTR_CACHE_WRITETHRU, MMU_ATTR_CACHE_DEFAULT, MMU_ATTR_CACHE_GUARDED, MMU_ATTR_CACHE_COHERENCY};

/* Mapping on physical address */
if(vmMap(NULL, ADDR_PHYS_GRAPHIC_PCI, ADDR_PHYS_GRAPHIC_PCI, MWTEST_BUFFER_SIZE) == ERROR) {
    return -1;
}

/* Allocate buffer */
buffer_virt_src = (uint8_t*)malloc(MWTEST_BUFFER_SIZE);

/* bench depending on cache state */
for(i = 0; i < NELEMENTS(states); i++) {
    if(vmStateSet(NULL, ADDR_PHYS_GRAPHIC_PCI, MWTEST_BUFFER_SIZE, MMU_ATTR_CACHE_MSK, states[i]) == ERROR) {
        printf("set state %d error\n", i);
        continue;
    }
    vmStateGet(NULL, buffer_virt_dest, &state);
    printf("state: %x\n", state);

    /* memcpy */
    gettimeofday(&start, NULL);
    for(j = 0; j < NB_LOOP; j++) {
        memcpy((void*)buffer_virt_dest, buffer_virt_src, MWTEST_BUFFER_SIZE);
    }
    gettimeofday(&end, NULL);
    time_us = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
    printf("mean transfer time:%lld us, throughput:%lld MB/s\n", time_us / NB_LOOP, (MWTEST_BUFFER_SIZE * 1000000ull * NB_LOOP) / (1024 * 1024) / time_us);
}

/* free buffer */
free(buffer_virt_src);

return (0);
}

谢谢您的帮助 !!

4

0 回答 0