lighthouse
lighthouse

Reputation: 553

Best practice for realtime periodic task (< 1ms) with linux and multi core system

I am using a quad-core embedded computer with Linux as OS for controlling robot system.

Basically the project is multi-threaded, single-process program written in C++.
Here are some of the backgrounds and requirements;

The solution in my mind is combination of below.

Would it be a good practice for the application? Is there any other practice for more stable operation?

Upvotes: 3

Views: 1876

Answers (1)

SK-logic
SK-logic

Reputation: 9714

If you need your 1ms periodic process to have a very low jitter, you simply cannot rely on the system timers. Xenomai or not, jitter will be significant.

The only reasonable method is to do the following (it's a typical approach in both robotics and low latency finanical applications):

  • Isolate one CPU core (isolcpus=...)
  • Build kernel with NOHZ_FULL support, set up nohz_full for the isolated CPU core
  • Configure rcu_nocbs for this isolated core.
  • Use sched_setaffinity(...) to bind your process to your chosen isolated CPU
  • Use sched_setscheduler(...) to set SCHED_FIFO policy for this process (or any other real-time scheduling policy, it will tell the kernel to actually respec the NOHZ_FULL setting for this core).
  • You must only have ONE process running on that core
  • Do not use any system calls in that real-time process, system calls result in context switches and this is what you must avoid at all costs.
  • Use busy wait - spin all the time you need to wait for an even or a time period. Do not use system calls for sleeping. Your CPU load must always stay at 100%
  • Use lock-free communication between your real-time process and non-realtime supporting processes.
  • Be mindful of the DDR latency
  • Make sure that everything you do in your real-time process loop terminates before this 1ms timeout.

This way you will have a sub-microsecond jitter, as long as the other cores or devices in your system do not clog the bus too much.

Keep in mind that your I/O in this process must be entirely in user space. You should try to avoid using system calls to talk to the peripherals. It's possible in some cases if you can directly write to the control registers of the devices and use DMA to get the data out of them (i.e., just move the driver functionality from kernel to user space). More complicated if your peripherals rely on interrupts. An ideal implementation is if you're using an FPGA SoC (such as Xilinx Zynq UltraScale+, or Intel Cyclone V, etc.) - you can implement your own I/O peripherals that communicate via registers and DMA only and do not need interrupts.

Upvotes: 3

Related Questions