cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Explorer
Explorer
178 Views
Registered: ‎09-19-2018

How to write in the memory from a Petalinux application ?

Jump to solution

Hi,

I'm learning how the AXI interface works and I've created a simple design with AXI Lite and memory mapped registers just to transfer data from PS to PL.

For this, I've created an AXI4 peripheral using: Tools -> Create and Package IP -> Create a new AXI4 peripheral ...

This IP has 5 registers of 32 bits each. According to the address editor, the memory starts at 0x43C0_0000 and end at 0x43C0_FFFF (range 64k).

As a first test, I have connected these registers to the LEDs and added some logic like: if register X contains the data Y, then LED1 turns on, ...

Now what I am looking for is some example code to create the application in C / C ++ in the SDK to be run on the Petalinux.

So, I have two questions:

1- Is it necessary to add this AXI peripheral to the device tree ?

2- I've read others threads talking about 2 kind of device drivers to write in the memory: /dev/mem and UIO (uio_pdrv_genirq). Is there any simple guide/sample code to understand how to build this simple application using any of these drivers? 

Thanks in advance.

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Scholar
Scholar
152 Views
Registered: ‎05-28-2013

To start out, you can just use the existing "devmem" command, this should already exist in your PetaLinux environment. The usage is:

devmem 0x43c00000                # read the first register
devmem 0x43c00004 32 0x12345678  # write the 2nd register with 0x12345678

The "devmem" program actually uses "/dev/mem" to perform the access. Note the address should always be a multiple of 4, since your registers are 32-bits wide.

There is quite a lot of overhead to launching a new program each time, just to do a single 32-bit read or write. If this becomes an issue, you replace devmem with your own program. It would be the same as devmem, but it keeps running, performing many read/write operations, until you decide to exit. This way the overhead occurs only once on startup, not on each read/write.

To answer the questions:

1- Maybe later on, but for now, not needed.

2- The /dev/mem option has been described above. A UIO driver gives much the same memory-mapped access, plus it allows you to "receive" an interrupt userspace (as opposed to in a true kernel driver). There are minor differences in how addressing works, but functionally the only difference is interrupt handling.

Those are both just scratching the surface. A "real" driver in the kernel has access to many more features, and generally provides an abstraction, so that userspace code does not need to know any details about your 32-bit register details. Rather it should provide "functions" such as "send a message" or "read sensor x" for example. You can revisit this much later, for now, I'd recommend starting with simple devmem.

View solution in original post

3 Replies
Highlighted
Scholar
Scholar
153 Views
Registered: ‎05-28-2013

To start out, you can just use the existing "devmem" command, this should already exist in your PetaLinux environment. The usage is:

devmem 0x43c00000                # read the first register
devmem 0x43c00004 32 0x12345678  # write the 2nd register with 0x12345678

The "devmem" program actually uses "/dev/mem" to perform the access. Note the address should always be a multiple of 4, since your registers are 32-bits wide.

There is quite a lot of overhead to launching a new program each time, just to do a single 32-bit read or write. If this becomes an issue, you replace devmem with your own program. It would be the same as devmem, but it keeps running, performing many read/write operations, until you decide to exit. This way the overhead occurs only once on startup, not on each read/write.

To answer the questions:

1- Maybe later on, but for now, not needed.

2- The /dev/mem option has been described above. A UIO driver gives much the same memory-mapped access, plus it allows you to "receive" an interrupt userspace (as opposed to in a true kernel driver). There are minor differences in how addressing works, but functionally the only difference is interrupt handling.

Those are both just scratching the surface. A "real" driver in the kernel has access to many more features, and generally provides an abstraction, so that userspace code does not need to know any details about your 32-bit register details. Rather it should provide "functions" such as "send a message" or "read sensor x" for example. You can revisit this much later, for now, I'd recommend starting with simple devmem.

View solution in original post

Highlighted
Advisor
Advisor
143 Views
Registered: ‎01-28-2008

Hi @shairva 

  Adding to @rfs613 's insightful response, the other benefit of using UIO vs. /dev/mem besides interrupts, is removing the hard-coded offsets in the code, and leave them in the BSP, i.e. device tree. This may not be important for a one-off application but makes the code more portable for modifications and future projects.

  I've written recently on my blog about userspace memory I/O along with some example code.

Thanks,

-Pat

 

Give kudos if helpful. Accept as solution if it solves your problem.
https://tuxengineering.com/blog

0 Kudos
Highlighted
Moderator
Moderator
95 Views
Registered: ‎09-12-2007
0 Kudos