[LINUX] I want to disable interrupts on Raspberry Pi (≒ DI / EI)

background

On the Raspberry Pi, which is supposed to be used on Linux, the user's program naturally runs under the OS scheduler. Therefore, it is very difficult to write a time-strict program. To put it simply, I'm not good at processing something exactly at regular intervals. In such cases, timer interrupts or clock polling are used, but I think that there are many cases where you want to use the latter because of the low overhead and the simplicity of the context. At that time, various interrupts get in the way. I thought it would be nice if I could prohibit some simple temporary interrupts, and I tried various things, so I wrote an article. It is a Z80 DI / EI that is familiar to old men.

What you can do

I wrote a program (described later) that polls gettimeofday () and runs 100 us periodically. Here are the results (measured cycle) for the standard case and when interrupts are disabled. rpiint.png

how is it? It's obvious at a glance. If interrupts are disabled, it seems that various timing-critical controls can be performed. For example, Infrared remote control. (Note: Of course, disabling interrupts has many side effects. Minimize the disabling time.)

Overview of how to do it

According to the manual of SoC BCM2835 / 2837 of Raspberry Pi, there seems to be "interrupt disable register" and "interrupt enable register", so hit them directly. That is the familiar / dev / mem in GPIO tommap ().

  1. mmap () so that you can hit the physical address directly.
  2. Read the register and save the current setting information.
  3. Write all 1s to interrupt disable register to disable all interrupts.
  4. Do the necessary processing that is severe in time.
  5. Write the value saved in 2. to the interrupt enable register and return it to the initial state.

And this is all. In terms of Z80, 2-3 is DI and 5 is ʻEI`.

Code example

The code used to create the data for the graph above. Please change the part of #define PERI_BASE PI? _PERI_BASE according to your Raspberry Pi.

#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/time.h>

#define BLOCK_SIZE (4 * 1024)
#define PI2_PERI_BASE 0x3f000000
#define PI1_PERI_BASE 0x20000000
#define PERI_BASE PI1_PERI_BASE // Raspberry 0/1 or 2/3

//Specified time(us)Wait by polling
inline static void waitUs(struct timeval tv_zero, int until_us) {
  struct timeval tv;
  int us;

  while (1) {
    gettimeofday(&tv, NULL);
    us = (tv.tv_sec - tv_zero.tv_sec) * 1000000 + (tv.tv_usec - tv_zero.tv_usec);
    if (us >= until_us) break;
  }
}


int main() {
  int mem_fd;
  char *map;
  int i;
  int us_next;
  struct timeval tv0, tv1;
  int dt[10000];
  int irq1, irq2, irq3;   //Let's save interrupt information(Finally write back to irqen)

  volatile unsigned int *irqen1;
  volatile unsigned int *irqen2;
  volatile unsigned int *irqen3;
  volatile unsigned int *irqdi1;
  volatile unsigned int *irqdi2;
  volatile unsigned int *irqdi3;

  if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0) return -1;
  map = (char*) mmap(NULL,
		     BLOCK_SIZE,
		     PROT_READ | PROT_WRITE,
		     MAP_SHARED,
		     mem_fd,
		     PERI_BASE + 0xb000
		     );
  if (map == MAP_FAILED)  return -1;
  irqen1 = (volatile unsigned int *) (map + 0x210);
  irqen2 = (volatile unsigned int *) (map + 0x214);
  irqen3 = (volatile unsigned int *) (map + 0x218);
  irqdi1 = (volatile unsigned int *) (map + 0x21c);
  irqdi2 = (volatile unsigned int *) (map + 0x220);
  irqdi3 = (volatile unsigned int *) (map + 0x224);

  gettimeofday(&tv0, NULL);
  irq1 = *irqen1;
  irq2 = *irqen2;
  irq3 = *irqen3;
  //Disable all interrupts on the following 3 lines
  *irqdi1 = 0xffffffff;
  *irqdi2 = 0xffffffff;
  *irqdi3 = 0xffffffff;
  
  for (i = 0, us_next = 100; i < 10000; i++, us_next += 100) {
    waitUs(tv0, us_next);
    gettimeofday(&tv1, NULL);
    dt[i] = (tv1.tv_usec - tv0.tv_usec) + (tv1.tv_sec - tv0.tv_sec) * 1000000;
  }
  //Restore the interrupt enable flag on the following three lines.
  *irqen1 = irq1;
  *irqen2 = irq2;
  *irqen3 = irq3;
  //Result display
  for (i = 1; i < 10000; i++) {
    printf("%d\n", dt[i] - dt[i - 1]);
  }
  return 0;
}


Recommended Posts

I want to disable interrupts on Raspberry Pi (≒ DI / EI)
I want to run the Python GUI when starting Raspberry Pi
I want to use Linux on mac
How to install NumPy on Raspberry Pi
I want to develop Android apps on Android
I installed OpenCV-Python on my Raspberry Pi
Note: I want to do home automation with Home Assistant + Raspberry Pi + sensor # 1
I want to do pyenv + pipenv on Windows
I want to log file I / O on Linux
Connect to MySQL with Python on Raspberry Pi
I have a question. Unable to make protocol buffers on raspberry pi 3 modelB.
pigpio on Raspberry pi
Cython on Raspberry Pi
I want to develop an Android application on Android (debugging)
I want to find a popular package on PyPi
I want to AWS Lambda with Python on Mac!
I want to use OpenJDK 11 on Ubuntu Linux 18.04 LTS / 18.10
Output to "7-segment LED" using python on Raspberry Pi 3!
I want to restart CentOS 8 on time every day.
I want to do Wake On LAN fully automatically
I want to be notified of the connection environment when the Raspberry Pi connects to the network
Introduced python3-OpenCV3 to Raspberry Pi
Introducing PyMySQL to raspberry pi3
I want to solve Sudoku (Sudoku)
I want to announce my graduation thesis on IPython Notebook
I tried to automate [a certain task] using Raspberry Pi
Introduced pyenv on Raspberry Pi
Use NeoPixel on Raspberry Pi
Install OpenCV4 on Raspberry Pi 3
Install TensorFlow 1.15.0 on Raspberry Pi
I sent the data of Raspberry Pi to GCP (free)
About the error I encountered when trying to use Adafruit_DHT from Python on a Raspberry Pi
I want to use shortcut translation like DeepL app on Linux
I tried to automate the watering of the planter with Raspberry Pi
I made a web server with Raspberry Pi to watch anime
Use python on Raspberry Pi 3 to illuminate the LED (Hello World)
How to play music (wav / mp3) files on Raspberry Pi python
Run Polyglot on Raspberry Pi to perform morphological analysis in English
Port FreeRTOS to Raspberry Pi 4B
Testing uart communication on Raspberry Pi
MQTT on Raspberry Pi and Mac
raspberry pi 4 centos7 install on docker
Install ghoto2 on Raspberry Pi (memo)
Output from Raspberry Pi to Line
Try using ArUco on Raspberry Pi
OpenCV installation procedure on Raspberry Pi
I want to scrape images to learn
I want to do ○○ with Pandas
Power on / off Raspberry pi on Arduino
Detect switch status on Raspberry Pi 3
I want to copy yolo annotations
Install OpenMedia Vault 5 on Raspberry Pi 4
I want to debug with Python
L Chika on Raspberry Pi C #
[Raspberry Pi] Changed Python default to Python3
Build wxPython on Ubuntu 20.04 on raspberry pi 4
I want to tweet on Twitter with Python, but I'm addicted to it
Use python on Raspberry Pi 3 to light the LED with switch control!
I want to display an image on Jupyter Notebook using OpenCV (mac)
I tried to make a traffic light-like with Raspberry Pi 4 (Python edition)
I connected the thermo sensor to the Raspberry Pi and measured the temperature (Python)