Success! Subscription added.
Success! Subscription removed.
Sorry, you must verify to complete this action. Please click the verification link in your email. You may re-send via your profile.
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
Community support is provided Monday to Friday. Other contact methods are available here.
Intel does not verify all solutions, including but not limited to any file transfers that may appear in this community. Accordingly, Intel disclaims all express and implied warranties, including without limitation, the implied warranties of merchantability, fitness for a particular purpose, and non-infringement, as well as any warranty arising from course of performance, course of dealing, or usage in trade.
For more complete information about compiler optimizations, see our Optimization Notice.