The following changes can be made to the ComfilePi to improve the the real-time performance of a program running on it.
performance
to keep the CPU's frequency constant
Run the following commands in a terminal to set the CPU governor to performance
to prevent the system from dynamically changing the CPU frequency.
sudo apt install cpufrequtils sudo cpufreq-set -g performance
Operating system utilities should report the frequency at 1.2GHz.
pi@raspberrypi:~ $ sudo cat /sys/devices/system/cpu/cpu[0-3]/cpufreq/cpuinfo_cur_freq 1200000 1200000 1200000 1200000 pi@raspberrypi:~ $ vcgencmd measure_clock arm frequency(48)=1200126000
First, add the isolcpus=3
kernel parameter to the /boot/cmdline.txt file. This will prevent Linux from allocating the 4th core to any processes. Reboot for the change to take effect. See the Linux kernel reference for isolcpus for more information.
Then use taskset
to have Linux run a program, in this case a program called test, on the 4th core. The program will have that core all to itself. See the taskset man page for more information.
sudo taskset -cp 3 `pidof test`
This will configure the process with FIFO scheduling, and increase its priority to the maximum. Other options are possible allowing one to tune the scheduling algorithm to their specific use case. See the chrt man page for more information.
sudo chrt -f -p `pidof test`
When using FIFO scheduling, it may help be necessary to disable realtime throttling.
sudo sh -c "echo -1 > /proc/sys/kernel/sched_rt_runtime_us"
However, this is a blunt instrument because it disables realtime throttling on all cores. Instead it may be best to introduce a sleep
along with a spin-wait for greater precision. For more information, refer to this description.
In this test, a program is created to output a 100µs alternating pulse (500kHz) on one of the ComfilePI's GPIO pins. The program uses the BCM2835 library.
#include <cstdio> #include <bcm2835.h> #define PIN 4 #define DELAY 100 int main() { if (!bcm2835_init()) { printf("bcm2835_init() failed\n"); exit(1); } bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP); for(;;) { bcm2835_gpio_write(PIN, HIGH); bcm2835_st_delay(bcm2835_st_read(), DELAY); bcm2835_gpio_write(PIN, LOW); bcm2835_st_delay(bcm2835_st_read(), DELAY); } }
Compile with…
gcc -O3 test.cpp -lbcm2835 -o test
An oscilloscope shows the pulse as physically generated by the ComfilePi.
While the real-time program is executing, a separate process is run to simulate browsing the web using the Chromium browser. The goal is to measure any disruption to the real-time process that may occur by an operator interacting with a user interface.
#!/bin/bash while true do chromium-browser http://comfiletech.com & sleep 15s killall chromium-browser sleep 5s done
Due to the CPU isolation configuration explained above, Linux will allocate the Chromium browser only to the first 3 cores.
An external data capture instrument is used to measure the consistency of the pulse. Any deviation from the 100µs, specified in the program's source code, is jitter. The jitter is recorded according to the number of times it occurs over the duration of the test.
The test is conducted under 3 configurations:
As can be seen in the chart above, the ordinary kernel, without any CPU isolation or real-time scheduling, operates with excessive jitter and would likely not be suitable for any real-time application. However, by taking a few measures to optimize a process for real-time performance, it is possible to reduce jitter potentially below 50µs which may be acceptable for some real-time use cases.
Although the real-time kernel can reduce jitter, it trades off overall performance throughput. Using the real-time kernel may cause the system to boot slower and run some applications with a mild performance penalty, but it will provide more deterministic behavior.