Torizon kernel module pwm-beeper

Hi all!

We would like to upgrade our system from BSP 2.8 to latest Torizon. One core feature of our product is giving acoustic feedback to the user through a buzzer that is soldered onto our inhouse carrier board. To enable the PWM beeper we added CONFIG_INPUT_PWM_BEEPER=y to the kernel config in BSP 2.8.
How can we achieve this with Torizon (TorizonCore Upstream 5.7.0+build.17) and the Torizoncore Builder without actually having to modify the kernel build itself?

Best regards

Hi @bgo ,

You can use TorizonCore Builder to create a custom TorizonCore image with the PWM beeper driver as an external Kernel Module. Try following Approach 1 from this article: Building External Kernel Modules With Torizon | Toradex Developer Center.

In your case the contents of source-dir should be:

obj-m := pwm-beeper.o

SRC := $(shell pwd)

all:
	$(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules

clean:
	$(MAKE) -C $(KERNEL_SRC) M=$(SRC) clean

Then create tcbuild.yaml following the article, run torizoncore-builder build and your custom image should be created with the kernel module included.

Let me know if this helps you.

Best regards,
Lucas Akira

Hi @lucas_a.tx ,

Thank you for your guidance!
I was able to add the pwm-beeper kernel module (lsmod shows it in the list) - though I am still struggling to get our beep up working with Torizon. Maybe you can help me again?
I converted our device tree into a device tree overlay for the apalis imx6q and currently it looks like follows:

/dts-v1/;
/plugin/;


//#include "imx6q-pinfunc.h"
#include "../dts-arm32/imx6q-pinfunc.h"
#include <dt-bindings/clock/imx6qdl-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>

/ {
        compatible = "toradex,apalis_imx6q";

        gpio-keys {
                compatible = "gpio-keys";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_gpio_keys>;
        };


        beeper: beeper@0 {
                compatible = "pwm-beeper";
                pwms = <&pwm1 0 5000000 0>;
        };

};

&can1 {
        status = "okay";
};

&can2 {
        status = "okay";
};

&i2c1 {
        status = "okay";

        polytouch: edt-ft5x06@38 {
                compatible = "edt,edt-ft5x06";
                reg = <0x38>;
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_edt_ft5x06>;
                interrupt-parent = <&gpio2>;
                interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
                reset-gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;
                wake-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>;
           };

           pcie-switch@58 {
                   compatible = "plx,pex8605";
                   reg = <0x58>;
           };

};

/*
 * DDC_I2C: I2C2_SDA/SCL on MXM3 205/207
 */
&i2c2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";


        /* XXX
         * Both RTCs are disabled by default, and re-enabled in U-Boot
         * based on the detected boardrevison */

        /* M41T0M6 real time clock on carrier board */
        rtc_i2c: rtc0@68 {
                 compatible = "st,m41t00";
                 reg = <0x68>;
                 status ="disabled";
        };

        /* M41T83 rtc on carrier board since revision 6 */
        rtc_i2c_2: rtc1@68 {
                   compatible = "st,m41t83o";
                   reg = <0x68>;
                   status ="disabled";
        };

};

&iomuxc {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_apalis_gpio3
                &pinctrl_apalis_gpio5 &pinctrl_apalis_gpio6
                &pinctrl_apalis_gpio7 &pinctrl_apalis_gpio8>;

        //touchpanel
        pinctrl_edt_ft5x06: edt-ft5x06grp {
                fsl,pins = <MX6QDL_PAD_NANDF_D4__GPIO2_IO04     0x1b0b0
                            MX6QDL_PAD_NANDF_D5__GPIO2_IO05     0x1b0b0
                            MX6QDL_PAD_NANDF_D7__GPIO2_IO07     0x1b0b0>;
        };

        //gpio {
                pinctrl_apalis_gpio5: apalis_gpio5 {
                        fsl,pins = <
                                MX6QDL_PAD_NANDF_RB0__GPIO6_IO10        0x1b0a8
                        >;
                };
                pinctrl_apalis_gpio6: apalis_gpio6 {
                        fsl,pins = <
                                MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09       0x1b0a8
                        >;
                };
                pinctrl_apalis_gpio7: apalis_gpio7 {
                        fsl,pins = <
                                MX6QDL_PAD_GPIO_2__GPIO1_IO02           0x1b0a8
                        >;
                };
                pinctrl_apalis_gpio8: apalis_gpio8 {
                        fsl,pins = <
                                MX6QDL_PAD_GPIO_6__GPIO1_IO06           0x1b0a8
                        >;
                };
        //};

};

&pwm1 {
        status = "okay";
};

&pwm2 {
        status = "okay";
};

&pwm3 {
        status = "okay";
};

&pwm4 {
        status = "okay";
};

The buzzer is connected to PWM_1 of the Apalis iMX6Q 2GB IT V1.1D
I expected the pwm-beeper to appear in /sys/kernel/debug/pwm but it is not listed:

root@apalis-imx6-10932060:~# sudo cat /sys/kernel/debug/pwm
platform/208c000.pwm, 1 PWM device
 pwm-0   (backlight           ): requested enabled period: 5000000 ns duty: 2490196 ns polarity: normal

platform/2088000.pwm, 1 PWM device
 pwm-0   ((null)              ): period: 992970 ns duty: 0 ns polarity: normal

platform/2084000.pwm, 1 PWM device
 pwm-0   ((null)              ): period: 992970 ns duty: 0 ns polarity: normal

platform/2080000.pwm, 1 PWM device
 pwm-0   ((null)              ): period: 992970 ns duty: 0 ns polarity: normal

If I do the same on BSP2.8b8 the pwm-beeper is listed as “beeper” for pwm1 (pwm@02080000):

~# sudo cat /sys/kernel/debug/pwm
platform/208c000.pwm, 1 PWM device
 pwm-0   (backlight           ): requested enabled period: 5000000 ns duty: 1882352 ns polarity: normal

platform/2088000.pwm, 1 PWM device
 pwm-0   ((null)              ): period: 0 ns duty: 0 ns polarity: normal

platform/2084000.pwm, 1 PWM device
 pwm-0   ((null)              ): period: 0 ns duty: 0 ns polarity: normal

platform/2080000.pwm, 1 PWM device
 pwm-0   (beeper              ): requested period: 5000000 ns duty: 0 ns polarity: normal

Any suggestions on what I am missing here?
Thanks in advance and best regards,

Hi @bgo ,

Initially I couldn’t find anything wrong with your overlay file. I tried creating an overlay that just adds the beeper node and updates pwm1’s status to be okay, but I got the same results as yours.

After doing some more research on Device Tree Overlays I found that in order to modify nodes which do not have a label such as / it is necessary to reference their absolute path in curly brackets. So the correct overlay should be something similar to this:

/dts-v1/;
/plugin/;

/ {
    compatible = "toradex,apalis_imx6q";
};

&{/} {
    beeper: beeper {
        compatible = "pwm-beeper";
        pwms = <&pwm1 0 5000000>;
    };
};

&pwm1 {
	status = "okay";
};

I applied the overlay above and beeper was successfully listed on an Apalis iMX6 Q 2GB IT V1.1B:

$ sudo cat /sys/kernel/debug/pwm
platform/208c000.pwm, 1 PWM device
 pwm-0   (backlight           ): requested enabled period: 5000000 ns duty: 2490196 ns polarity: normal

platform/2088000.pwm, 1 PWM device
 pwm-0   ((null)              ): period: 992970 ns duty: 0 ns polarity: normal

platform/2084000.pwm, 1 PWM device
 pwm-0   ((null)              ): period: 992970 ns duty: 0 ns polarity: normal

platform/2080000.pwm, 1 PWM device
 pwm-0   (beeper              ): requested period: 5000000 ns duty: 0 ns polarity: normal

For reference, I found the DTO absolute path syntax here: Using Device Tree Overlays, example on BeagleBone Cape add-on boards – BeagleBoard.org Blog.

It is also mentioned here: https://elinux.org/images/8/86/Overlay_frank.pdf

Try doing the above and see if it works.

Best regards,
Lucas Akira

1 Like

Hi @lucas_a.tx ,

thank you very much!

I did not realize this small but important detail! Thank you for the references, I will study them further.

Best regards,

Hi @bgo, how are you?

Did you progress on the topic? Do you still need further assistance with this?

Best regards,

Hi @gclaudino.tx , I am fine, thanks, I hope you are well too?

Sadly I did not have time to continue working on the driver and library to make our beeper work again. Currently I see the driver up and running but using the library does not produce any sound. I will share my solution here (or ask further questions) once I get to work on it again.

Best regards,

Hi @bgo,

Thanks for the update. Please return to us once you have your solution again or more questions. We’ll be glad to help.

Best regards,

Hi @lucas_a.tx , hi @gclaudino.tx ,
I hope you are all well!
Thanks again for your help! I tested the driver with another beep library that sends (writes) the “beep” event directly to /dev/input/event2 and it worked! So I cross-checked the Makefiles and found out I forgot to change CC=gcc to CC=arm-linux-gnueabihf-gcc. I recompiled the library and now everything is working! So now I am just looking for a way to deploy this library with torizoncore builder.
Best regards,

1 Like

Hi @bgo !

Please check this Building External Kernel Modules With Torizon | Toradex Developer Center article.

If you have any other questions, I would like to ask you to create a new post here about it (so we can separate the subjects :slight_smile: )

Best regards,