Community
cancel
Showing results for 
Search instead for 
Did you mean: 

Accessing hardware registers from user space programs

Accessing hardware registers from user space programs



MMU-less systems allow access to memory registers very easily, but the application code is then highly coupled to the system configuration: if the NIOS system is modified, and the hardware base address changed, the application must be recompiled. Worse, if the device is used in two different systems, it may be mapped at different addresses and the application must be compiled twice.

The purpose of this Wiki is to show how to manage hardware from user space, getting its base address thanks to a small driver. This one transmits the hardware base address thanks to mmap() routines.

As an example, we will use the small device "HR Timer" (see attached file) which increments a 32 bits counter at a given frequency. The parameter "COUNT_VALUE", with the default value 100000, gives a frequency of 1000 Hz for a system running at 100 MHz. The counter is reset to 0 at init time, but can be set later to a given value using a write access at the base address.

To access this device, one will use the driver "hrtimer.c".

This driver, see attached file "hrtimer.c", implements mainly the mmap() API.

The "userland" application has just to perform an open("/dev/hrtimer") to get a handdle on the device.

The mmap() system call then permits to get the physical address to use to access the device registers.

Some other Wiki give explanations (see ModuleProgramming) on how to add a driver to the kernel, but one have mainly to modify Makefile and Kconfig in the directory where the driver will be placed, for e.g. in linux-2.6/arch/nios2/drivers.

The following lines are added in Kconfig :

config NIOS2_HRTIMER

tristate "32 bits high-res timer"

default N

help

Say Y here if you use high-res timer

and this line in Makefile :

obj-$(CONFIG_NIOS2_HRTIMER) += hrtimer.o

Don't forget to set a device node in uClinux-dist/vendors/Altera/nios2/romfs_list.

Once the kernel has been completed with the driver, and regenerate, the userland program can access the hrtimer without read() nor ioctl(), using the simple code like:

#include <unistd.h>

#include <fcntl.h>

#include <sys/mman.h>


static volatile unsigned long* pHrTimer = 0;

static int hrtimerFd = -1;


/* init */

int HrTimerInit()

{

if ((hrtimerFd = open("/dev/hrtimer", O_RDWR)) != -1) {

pHrTimer = (unsigned long*)mmap(0, 4, PROT_READ | PROT_WRITE, MAP_SHARED, hrtimerFd, 0);

if (pHrTimer == MAP_FAILED)

return -1;

}

return hrtimerFd;

}


/* utilization */

int TickGet()

{

return *pHrTimer;

}


/* deInit */

int HrTimerEnd()

{

if (pHrTimer != MAP_FAILED)

munmap((void*)pHrTimer, 4);

if (hrtimerFd != -1)

close(hrtimerFd);

}

Downloads

Attachments
Version history
Revision #:
1 of 1
Last update:
‎06-21-2019 06:33 PM
Updated by:
 
Contributors