Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 8005

Advanced users • Re: Experimental RPi 6.12 kernel builds

$
0
0
Test #2 (PWM buzzer):

I have CM3, CM3+, CM4, and CM4S devices with an electro-mechanical buzzer. The buzzer is a cheap way to sound alarms and add audio feedback when a touchscreen screen is touched. It needs to be able to create a clean, consistent, beep using a PWM signal. Currently, on those devices I'm currently using pigpio, which uses a very clever DMA trick to produce a near perfect beep. But pigpio can't be used on the CM5. Although PIO would be the better choice, it would be convenient if I could use the same code on all compute module devices. Currently I can't, but maybe with PREEMPT_RT I can. Let's test.

Device
CM4S-Lite 1GB RAM

Configuration
isolcpus=domain,managed_irq,3 irqaffinity=0-2 rcu_nocbs=3 added to cmdline.txt

Control
Using pigpio to generated a 2kHz beep. The priority of the pigpio service was not changed, and CPU isolation was not utilized, as neither is necessary to achieve a nice clean beep. Even if the Chromium browser is launched, in an attempt to cause disturbance, the beep remains clean and consistent.

Code:

Code:

#include <pigpiod_if2.h>#include <thread> using namespace std; #define PIN 30 int main(){   auto instance = pigpio_start(NULL, NULL);    // 2000Hz   set_PWM_frequency(instance, PIN, 2000);    // 128/255 = 50% duty   set_PWM_dutycycle(instance, PIN, 128);    // play for 10 seconds   this_thread::sleep_for(chrono::milliseconds(10000));   set_PWM_dutycycle(instance, PIN, 0);    pigpio_stop(instance);    return 0;}
Audio:
https://drive.google.com/file/d/1yqyx9j ... drive_link

Experiment:
Using ligpiod to generated the 2kHz beep. Note that in this test, I'm employing both a sleep and a spinwait together to delay for the necessary 250us. I have observed in other experiments that this works best because waking up from sleep has unpredictable timing.

Procedure:
1. Start program with the command ./beep
2. About 5 seconds in, run sudo chrt -f -p 99 `pidof beep` && sudo taskset -cp 3 `pidof beep` to change the process's priority and run it on the isolated CPU.
3. About 10 seconds in, start the Chromium web browser in an attempt to introduce some disturbance.

Code:

Code:

#include <gpiod.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <errno.h>// GPIO chip and line settings#define GPIO_CHIP "gpiochip0"#define GPIO_LINE 30// Global variables for cleanupstruct gpiod_chip *chip = NULL;struct gpiod_line *line = NULL;void cleanup(int signum) {    if (line) {        gpiod_line_set_value(line, 0); // Set GPIO low        gpiod_line_release(line);    }    if (chip) {        gpiod_chip_close(chip);    }    printf("\nCleaned up and exiting.\n");    exit(0);}void spin_wait(int us) {    struct timespec start, current;    clock_gettime(CLOCK_MONOTONIC, &start);    long target_ns = us * 1000; // in nanoseconds    do {        clock_gettime(CLOCK_MONOTONIC, &current);    } while ((current.tv_sec - start.tv_sec) * 1000000000L + (current.tv_nsec - start.tv_nsec) < target_ns);}int main() {    // Set up signal handler for Ctrl+C    signal(SIGINT, cleanup);    // Open GPIO chip    chip = gpiod_chip_open_by_name(GPIO_CHIP);    if (!chip) {        perror("Failed to open GPIO chip");        return 1;    }    // Get GPIO line    line = gpiod_chip_get_line(chip, GPIO_LINE);    if (!line) {        perror("Failed to get GPIO line");        gpiod_chip_close(chip);        return 1;    }    // Request line as output    int ret = gpiod_line_request_output(line, "toggle_gpio", 0);    if (ret < 0) {        perror("Failed to request GPIO as output");        gpiod_line_release(line);        gpiod_chip_close(chip);        return 1;    }    // Toggle GPIO at 2kHz (500us period, 250us per state)    while (1) {        gpiod_line_set_value(line, 1); // Set high        usleep(150);                   // Wait 250us        spin_wait(100);        gpiod_line_set_value(line, 0); // Set low        usleep(150);                   // Wait 250us        spin_wait(100);    }    // Unreachable due to infinite loop, cleanup handled by signal    return 0;}
kernel8 Audio:
https://drive.google.com/file/d/1Kfv7EG ... drive_link

kernel8_rt Audio:
https://drive.google.com/file/d/15xOzX5 ... drive_link

Results
* There is a clear difference between pigpio and a pure software PWM. pigpio is much better.
* I don't notice much of a difference between kernel8 and kernel8_rt. Launching the chromium browser clearly adds disturbance even when using kernel8_rt.

Conclusion
* chrt, i.e. real-time scheduling is essential. Although not demonstrated in this post, taskset helps a little to reduce disturbance when the Chromium browser is launched.
* For software PWM on the CM4, kerne8_rt can't beat pigpio.
* I don't notice any significant difference between kernel8 and kernel8_rt for this specific use case if FIFO scheduling and CPU isolation are employed for both.

Statistics: Posted by JinShil — Thu Jun 05, 2025 11:36 pm



Viewing all articles
Browse latest Browse all 8005

Trending Articles