Creating Apps for Custom Hardware in Petalinux

In this post we will create an application in C that controls the hardware we created in a previous one. The application reads via polling the buttons value and propagates it to the counter interface. Then according to the buttons pressed, the counter functions as described in the previous post. The counter output is finally written at the leds interface.


Lets now explain how the code works.

#define BUTTONS_BASE_ADDR      0x41210000
#define LEDS_BASE_ADDR              0x43C00000
#define GRAY_BASE_ADDR              0x43C10000

First of all, we must define the addresses of the peripherals interface. These addresses are set from the Vivado project when we create the peripherals.

void             *ptr_buttons, *ptr_gray, *ptr_led;
unsigned    page_addr_buttons, page_addr_gray, page_addr_led;
unsigned    page_offset_buttons, page_offset_gray,page_offset_led;
unsigned    page_size = sysconf(_SC_PAGESIZE);

After that, we declare the above variables in order to communicate with the peripherals.

page_addr_buttons      = (BUTTONS_BASE_ADDR & ~(page_size-1));
page_offset_buttons   = BUTTONS_BASE_ADDR – page_addr_buttons;

page_addr_gray            = (GRAY_BASE_ADDR & ~(page_size-1));
page_offset_gray    = GRAY_BASE_ADDR – page_addr_gray;

page_addr_led        = (LEDS_BASE_ADDR & ~(page_size-1));
page_offset_led        = LEDS_BASE_ADDR – page_addr_led;

int    fd;

fd = open(“/dev/mem”,O_RDWR);

We open a file descriptor which is essential for mapping the peripheral physical address to a virtual one. Here is how the mapping is done using the mmap function

ptr_buttons = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (BUTTONS_BASE_ADDR & ~(page_size-1)));

ptr_gray     = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (GRAY_BASE_ADDR & ~(page_size-1)));

ptr_led     = mmap(NULL, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, (LEDS_BASE_ADDR & ~(page_size-1)));

Now, in order to read from a peripheral(for example the buttons) we use the following command:

counter = *((unsigned *)(ptr_gray+page_offset_gray+4));

The +4 offset in the command is because in the gray counter module in the vivado project the output of the module is stored in the slv_reg1(for example if we wanted to access the slv_reg3 we would have to use a +12 offset).

Now in order to write we simply use this command:

*((unsigned *)(ptr_led+page_offset_led)) = counter;


In order to write an application which control the custom designed peripherals you have to know the physical address of them and map it to a virtual one. Then use these virtual addresses and offsets in a simple command to read and write to those peripherals.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s