hzeller / rpi-rgb-led-matrix

Controlling up to three chains of 64x64, 32x32, 16x32 or similar RGB LED displays using Raspberry Pi GPIO
GNU General Public License v2.0
3.67k stars 1.17k forks source link

CPU usage / call CreateMatrixFromOptionscreate twice? #708

Closed oischinger closed 5 years ago

oischinger commented 5 years ago

I noticed that the CPU usage of my executable is quite high even if I don't use the matrix so I was wondering if I could just stop/delete the matrix and create it later again. Unfortunately this does not seem to work.

Calling rgb_matrix::CreateMatrixFromOptions a second time results in the error "Must run as root to be able to access /dev/mem". Setting runtime_opt.do_gpio_init = false results in a segfault sometime later.

Is there a way to achieve what I want to do here: In the end my executable is a daemon that listens for mqtt messages and displays something for a couple of seconds and then idles again until the next message arrives.

hzeller commented 5 years ago

The CPU usuage is because it constantly pushes pixesl to the matrix (even if they are black). Usually, this is nothing really to worry about as you use the Raspberry Pi for this very specific purpose; so unless you need that one core for a very calculation-intensive things, I'd say don't worry about it.

Anyway, if you really want to restart, you can do that and call delete on the matrix to stop things and re-create it with rgb_matrix::CreateMatrixFromOptions() as you do now.

The issue you are seeing Must run as root to be able to access /dev/mem" is because by default the matrix creation drops the root privileges the first time so that it is safer security-wise after the matrix is created (which is probably a good idea if you are running this as a network service). But if you want to re-create the matrix later, you need to make sure that privileges are not dropped.

You can do this by supplying the --led-no-drop-privs command line option, or set the field drop_privileges in the RuntimeOptions to 0 (switch drop privileges off) or -1 (to prevent toggling this option with a command line flag).

I think the do_gpio_init = false idea you tried won't work right now because of some other internal initialization sequencing, that I have to look into (but you still would need want root access as the thread initialization wants to switch to realtime priority).

So TL;DR: either (a) don't worry about the CPU use or (b) don't drop privileges.

oischinger commented 5 years ago

I forgot about the drop-privileges thing. I believe the best way is option a). In the end I don't care about a single core being used by the matrix on my raspberry pi 3 and if the privileges are dropped right after the matrix creation it's the most secure way I guess.

Closing the issue. Thanks for your feedback and your great work on this project.

hzeller commented 5 years ago

Anyway, I now also fixed that it is possible to use do_gpio_init = false (where I mention the internal sequencing not working properly), so you only have to initialize GPIO once, then could re-use it later:

runtime_opt.do_gpio_init = false;

GPIO gpio;
gpio.Init();

// ...
RGBMatrix *matrix = rgb_matrix::CreateMatrixFromOptions(matrix_options, runtime_opt);
matrix->SetGPIO(&gpio, true);  // Need to explicitly set GPIO, because do_gpio_init is false
// do something with it
delete matrix;  // not needed anymore.

// later, re-initialize ...
matrix = rgb_matrix::CreateMatrixFromOptions(matrix_options, runtime_opt);
matrix->SetGPIO(&gpio, true);

This would at least make it possible that the GPIO can be re-used, even if you drop privileges.

However, if you do drop privileges, the new thread can't be set to realtime priority, so it is still not really what you want, as the quality will be less.