PS: I need this for a quick and dirty hack for disabling the interrupts in user mode. I know you shouldn't do this, and it will mess up ethernet connections, timers etc., but it works
Well, most of the time. Sometimes I got a message "rcu_sched detected stalls on CPUs/tasks", or "NETDEV WATCHDOG: eth0 (socfpga-dwmac): transmit queue 0 timed out", so you really shouldn't do this for production software and instead write proper kernel drivers, but the system was still running, at least over the USB UART port. The source code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <stdint.h>
// the GIC starts at 0xfffec100, mmap can map only at 0x1000 boundaries
#define GIC_MAP 0xfffec000
#define GIC_SPAN 0x1000
int gic_fd;
void *gic_map;
void mmap_gic()
{
gic_fd = open("/dev/mem", O_RDWR | O_SYNC);
if (gic_fd == -1) {
printf("ERROR: could not open \"/dev/mem\"...\n");
exit(1);
}
gic_map = mmap(NULL, GIC_SPAN, PROT_READ | PROT_WRITE, MAP_SHARED, gic_fd, GIC_MAP);
if (gic_map == MAP_FAILED) {
printf("ERROR: mmap() failed...\n");
close( gic_fd );
exit(1);
}
}
void unmap_gic()
{
if (munmap( gic_map, GIC_SPAN ) != 0) {
printf("ERROR: munmap() failed...\n");
}
close( gic_fd);
}
void enable_interrupts()
{
*((uint32_t*) (gic_map + 0x100)) = 1;
}
void disable_interrupts()
{
*((uint32_t*) (gic_map + 0x100)) = 0;
}
int main(int argc, char **argv)
{
// memory map the GIC region
mmap_gic();
// disable interrupts
// you can't use printf etc. when interrupts are disabled
disable_interrupts();
// do something
// enable interrupts again
enable_interrupts();
// unmap GIC region and close handle
unmap_gic();
return( 0 );
}
At the comment "// do something" you can write any code that don't use interrupts (so no printf and probably many other system calls), for example bit banging some GPIO pins with direct register access, without being interrupted by the task scheduler or other interrupts. Tested with the image "Linux Console (kernel 4.5)", version 1.3, 2018-03-15 from
this page. No hwlib.h or socal.h etc. required, you can even compile it on the system itself. I could use it to access an Avalon memory mapped VHDL component I wrote with qsys, and accessing the registers with some calculations and accessing the SDRAM in a loop needed always about 15 us, without much variation. When the interrupts were running, sometimes the loop time was nearly a millisecond and it fluctuated a lot, depending on the number of loops and the rest of the system.