I’ve almost always been told this is too hard a problem to solve, so why even try. I never really know how to respond to this reaction. Usually I respond to this type of quip with one of two assumptions: they’re a lazy person, I don’t know what I don’t know.
When this problem was first presented at work I was leaning in the direction of simply writing a realtime kernel to run, instead of the linux kernel, which would handle all the required hardware for the project. My will rapidly deflated following this option. I rather quickly realized the Pi isn’t quite like any other Single Board Computer (SBC) I had used up to this point.
One major difference on a pi from nearly all other platforms come from the fact that the main processor is one of the last components to be initialized. On the Pi the graphics “co” processor (GP) is the first peripheral to startup which loads external code and executes it. The graphics processor identifies which version of the Pi it is and selects the corresponding kernel binary from the /boot partition. Then after configuring the main processor the GP loads the kernel image into ram and starts the main CPU core at the entry point for the ELF binary it just copied into ram.
The problem wasn’t actually getting the system to take my custom kernel and load that. The problem arose when I needed to access the Broadcom SoC’s peripherals such as the GPIO ports. Another major consideration that led to abandoning this idea came when I realized we would be required to interface with a mobile app using with bluetooth or wifi. I wasn’t about to handcraft, or even borrow, a full TCP/IP stack, a full wifi driver, and a robust webserver all of which would have to run on a single core without real process management.
In the end I essentially stumbled upon a couple articles from several years ago (50 or so) involving dedicating entire cpu cores to a single process, or even a single thread in some cases when realtime, or “near-realtime” processing is required. Using a combination of SCHED_FIFO scheduling and sched_setaffinity
cpu affinity options I was able to dedicate one of the cores of the pi to the main GPIO thread under linux. This also required a change to the cmdline.txt file for isocpu config option (I think this stands for isolate cpu from scheduler) being set to reserve a couple cores for my realtime threads.
After doing both these steps I had one of my threads running as the only runnable thread for core 2. This thread manages the GPIO calls because reading them out regularly is essential for the correct debouncing of input signal there are no other threads in the system with a higher priority. The data is read into a buffer for later processing. The processing thread was spun-up using this same method on another core to handle the debouncing of the stored data. The final thread wasn’t run with such a high priority but it was run on a specific core. This means the linux scheduler can pre-empt, or pause my execution at any time. This final thread was responsible for making all the decisions based on the current system state.
This setup resulted in acceptable responsiveness for the application. What this wasn’t though was true realtime. I saw timing jitter on the order of tens of milli-seconds or around 10%. This wasn’t a massive deal for out usecase. If it had been I believe the issue lies with the library we used to manage the GPIO interface. If I were to do this over again I would manage the GPIO myself as I missed on my initial investigation the fact that the library does sampling at a configurable rate on its own. I probably didn’t need to duplicate that effort.
Thanks for the suggestions you have shared here. Something else I would like to state is that personal computer memory requirements generally increase along with other advancements in the technological innovation. For instance, when new generations of processors are introduced to the market, there is certainly usually a related increase in the dimensions preferences of both the computer system memory and also hard drive space. This is because the software program operated through these processors will inevitably surge in power to take advantage of the new technological know-how.
Arcano, I’m glad you brought that up. I think more recently given that we’re starting to slow down on the amount of compute a single node can have (at least on typical desktop processors) due to physical limitations so much that more of the periphery of compute advances at the same rate. This continual increase in storage space (sram, and persistent storage) is where most _innovation_ is able to progress. There are many algorithms that have space/time tradeoffs and prior to the slowing the progression with silicon processing the speed was always assumed to be not worth optimizing for because, “[just wait a year or two and it will run twice as fast]” was a common thought, whereas storage was expensive and slow. Now that processing improvements have slowed the speed can’t swept under the rug. This is also while the amount and speed of storage has continued to improve over the years to the point where programmers are now consider space the aspect to their programs which can be swept under the rug. Compute once, store forever type thinking is leading to the continually bloated and growing memory footprints of modern programs.