2

This is my first post :) I am using VxWorks 6.9 and an Intel Sandy Bridge board. I would like to know how to map a PCIe memory area in my application. The PCIe memory area is a part of the Graphic memory and it's physical address is 0x80000000.

I’m trying with the vmMap function which doesn’t return the virtual address. In that case, I set the virtual address with the same value than the physical address but I don’t know if it’s the good behavior. How can I get the virtual address from the physical address? If no function exists, what’s virtual address I have to use?

When I’ve mapped the area in my application, I’m benching the access to this area. I’m trying to change the cache state with the function vmStateSet but only COPYBACK, WRITETHRU and DEFAULT can be set (setting other cache values fail). I’ve got a low throughput for all cache states. In Intel Sandybridge, it is possible to set the MMU to write combining. How can I do it in VxWorks?

This is what I have tried so far:

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);
}

Thank you for your help !!

  • AFAIK, WindRiver's manual is not public. I guess, if you have access to VxWorks OS+toolkit, the manual should also be available to you. Look for "PCI mapping" or Memory-mapped I/O in the manual. – Alexey Polonsky Mar 11 '14 at 18:30
  • The information you need is in the "vxworks programmers guide" the only docs I can find online are for vxworks 5.5, and if I recall correctly this area has changed a bit in vxworks 6.x... – Chris Desjardins Mar 12 '14 at 07:48
  • I already read programmers guide many times. I may be missing some understanding concepts but I still think it's either not detailed enough with good examples for MMU using or the library functions provided are not complete... My first concern is to map the PCIe area and get a good throughput when I call a mempcy. In Linux, we use a lot ioremap_wc which offers some good performances but what about in VxWorks ? Thanks for helping me, I think that working with VxWorks is difficult because of its privacy. – user3407317 Mar 12 '14 at 08:41
  • Agreed if vxworks was more open it would be easier, but another thing to look at is to grep the source code for examples of vmMap. I am sure there are some drivers that use it. – Chris Desjardins Mar 12 '14 at 17:29

0 Answers0