cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Newbie
Newbie
10,298 Views
Registered: ‎08-23-2012

Linux mmap(): read data from physical DDR memory addresses -- Zynq System with eval. Board ZC702

Hello everybody,

 

I have a Problem with reading data from physical DDR memory addresses in Linux.

I have a custom Pcore which writes data direct to a ringbuffer in DDR. 

In a Baremetal Standalone System, I can read the right data out of memory.

Print out of the Baremetal System:

 

Hello World

78 56 34 12 79 56 34 12 7A 56 34 12 7B 56 34 12 78 56 34 12 79 56 34 12 7A 56 34 12 7B 56 34 12 78 56 34 12 79 56 34 12 7A 56 34 12 7B 56 34 12
...

...
78 56 34 12 79 56 34 12 7A 56 34 12 7B 56 34 12 78 56 34 12 79 56 34 12 7A 56 34 12 7B 56 34 12 78 56 34 12 79 56 34 12 7A 56 34 12 7B 56 34 12

78 56 34 12 79 56 34 12 7A 56 34 12 7B 56 34 12 78 56 34 12 79 56 34 12 7A 56 34 12 7B 56 34 12 78 56 34 12 79 56 34 12 7A 56 34 12 7B 56 34 12

 

If I run Linux on the System, and read out the data, every second int value stays clear.

 

Print out of the Linux System:

 

zynq> ./linux_empty_application_0.elf
/dev/mem opened.
Pcore mapped at address 0x40385000.
 Memory mapped at address 0x4047f000.

 79 56 34 12 00 00 00 00 7b 56 34 12 00 00 00 00 79 56 34 12 00 00 00 00 7b 56 34 12 00 00 00 00 79 56 34 12 00 00 00 00 7b 56 34 12 00 00 00 00

....

....
 79 56 34 12 00 00 00 00 7b 56 34 12 00 00 00 00 79 56 34 12 00 00 00 00 7b 56 34 12 00 00 00 00 79 56 34 12 00 00 00 00 7b 56 34 12 00 00 00 00
 79 56 34 12 00 00 00 00 7b 56 34 12 00 00 00 00 79 56 34 12 00 00 00 00 7b 56 34 12 00 00 00 00 79 56 34 12 00 00 00 00 7b 56 34 12 00 00 00 00
 
 zynq>

 

To read out the data from physical memory addresses, I have mapped a range from DDR memory into user space with mmap(...) function. Maybe someone can tell me where my fault is.

 

Please see my C Source Code below:

 

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>

#include "xaxi4_ms_SL_0.h"


#define MAP_SIZE 4096UL
#define MAP_MASK (MAP_SIZE - 1)

#define MAXBUF 1316

 

int main()
{
    int i=0;   
    int new=0;  
    int memfd, memfd2;


    void *mapped_base2, *mapped_dev_base2;
    void *mapped_base, *mapped_dev_base;
    off_t dev_base = 0x65800000; // base address of Pcore
    off_t dev_base2 = 0x30000000;  // startaddress of ringbuffer in DDR

    memfd = open("/dev/mem", O_RDWR | O_SYNC);
        if (memfd == -1) {
        printf("Can't open /dev/mem.\n");
        exit(0);
    }
    printf("/dev/mem opened.\n");
    memfd2 = open("/dev/mem", O_RDWR | O_SYNC);
        if (memfd == -1) {
        printf("Can't open /dev/mem.\n");
        exit(0);
    }



    // Map the PCore and the DDR memory


    mapped_base = (unsigned char *)mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, dev_base & ~MAP_MASK);
        if (mapped_base == (void *) -1) {
        printf("Can't map the memory to user space.\n");
        exit(0);
    }
     printf("Pcore mapped at address %p.\n", mapped_base);

     mapped_base2 = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED , memfd2, dev_base2 & ~MAP_MASK);
         if (mapped_base2 == (void *) -1) {
         printf("Can't map the memory to user space.\n");
         exit(0);
     }
      printf(" Memory mapped at address %p.\n", mapped_base2);




    mapped_dev_base = mapped_base + (dev_base & MAP_MASK);
    mapped_dev_base2 = (mapped_base2 + (dev_base2 & MAP_MASK));



    for(i=0;i<MAXBUF;i++)
      {
        *((unsigned char*)(mapped_dev_base2+i))=0x00;  // clear the ddr memory range

      }

*((unsigned int*)((mapped_dev_base)+XAXI4_MS_SL_0_ADDR_CTRL0_DATA)) = 0;     // 0: write Pattern from Pcore to DDR memory range
                                                                                // 1: read from Pcore Fifo and write to DDR memory range

    *((unsigned int*)((mapped_dev_base)+XAXI4_MS_SL_0_ADDR_AP_CTRL)) = 1;        // Start the transfer from Pcore to memory range
    while(1)
    {

        new=(((*((unsigned int*)((mapped_dev_base)+XAXI4_MS_SL_0_ADDR_AP_CTRL))) >> 1) & 0x1); //wait until transfer is done
        if(new==1)
        {
            break;
        }

    }

    for(i=0;i<MAXBUF;i++)
     {

        if((i%48)==0)
        {
            printf("\n\r ");
        }
        printf("%02x ",*((unsigned char*)(mapped_dev_base2+i))); //read out the date from memory range and print it

     }

    printf("\n\r ");

 // unmap the memory before exiting

    if (munmap(mapped_base, MAP_SIZE) == -1) {
        printf("Can't unmap memory from user space.\n");
        exit(0);
    }

    if (munmap(mapped_base2, MAP_SIZE) == -1) {
        printf("Can't unmap memory from user space.\n");
        exit(0);
    }

    close(memfd);
   close(memfd2);
    return 0;
}

 

 

Thanks in advance!

 

Christian Janczyk

 

0 Kudos
4 Replies
Highlighted
Observer
Observer
10,040 Views
Registered: ‎08-22-2012

 

Hi Christian,

 

I'm just getting started with a ZC702 and need to do exactly what you are doing - writing directly into DDR memory from the PL.  Would it be possible for you to outline what you need to do to generate the Pcore to achieve this?  I've only made a simple Pcore up to now.

 

Thanks,

 

Robin

 

0 Kudos
Highlighted
10,017 Views
Registered: ‎10-05-2010

Hello Guys,

We have a core called observer. This core writes to a ringbuffer which was allcoated by the kernel with the use of our driver.

The core has a dedicated axi lite link to the processing system (and thus to the RAM) and is master on the bus.

The kernel is notified per interrupt when the buffer is half full and full.

 

The buffer is accessed via usespace with mmap. A blocking read notifies the user space deamon when threre is new data (half full or full boundary).

 

I'll post the kernel driver in the attachement.

It works but I am right now on enhancing driver and core to have more flexibilty.

If you need the core please contact me per email: marco.hoefle(at)nanotronic.ch

 

 

 

0 Kudos
Highlighted
Visitor
Visitor
8,972 Views
Registered: ‎09-28-2013

We are having the same exact problem ... did you ever get a resolution?

 

0 Kudos
Highlighted
Visitor
Visitor
8,784 Views
Registered: ‎09-28-2013

FYI the problem for this was on the PL side, the FPGA guy was using an incorrect setting for the AXI memory writes which were 64 bits wide vs. the CPU reading memory which is 32 bit wide.

0 Kudos