Search code examples
embedded-linuxbeagleboneblackdevice-treepwm

How can I set the PWM period in a device tree overlay


I know that both PWM1A and PWM1B must have the same period, but using the default overlays prevents me from changing the period once loaded. I thought that loading both pins at once in a single overlay would maybe solve this problem, allowing me to set the period for both as they are muxed. I am trying to hook a servo up to both P9_16 and P9_14 (EHRPWM1A and EHRPWM1B), so they both need the same period, but not they 5000us in the default overlays.

Here is the overlay I have so far:

/dts-v1/;
/plugin/;

/ {
    compatible = "ti,beaglebone", "ti,beaglebone-black";

    /* identification */
    part-number = "car_pwm_controls";
    version = "00A0";

    /* state the resources this cape uses */
    exclusive-use =
      /* the pin header uses */
      "P9.14",    /* pwm: ehrpwm1A - STEERING */
      "P9.16",                /* pwm: ehrpwm1B - MOTOR */
      /* the hardware IP uses */
      "ehrpwm1A",
      "ehrpwm1B";

  fragment@0 {
    target = <&am33xx_pinmux>;
    __overlay__ {
      car_pwm_controls_pins: pinmux_pwm_controls_pins {
        pinctrl-single,pins = <
            0x048  0x6 /* P9_14 (ZCZ ball U14) | MODE 6 */
            0x04c  0x6 /* P9_16 (ZCZ ball T14) | MODE 6 */
        >;
      };
    };
  };

    fragment@1 {
        target = <&ocp>;
        __overlay__ {
            car_pwm_helper {
                 compatible  = "pwm_test";
                 pinctrl-names = "default";
                 pinctrl-0 = <&car_pwm_controls_pins>;

                 car_motor {
                   pwms    = <&ehrpwm1 0 20000000 1>;
                   pwm-names   = "PWM_P9_14";
                   enabled   = <1>;
                   duty    = <0>;
                   status    = "okay";
                 };

                 car_steering {
                   pwms    = <&ehrpwm1 1 20000000 1>;
                   pwm-names   = "PWM_P9_16";
                   enabled   = <1>;
                   duty    = <0>;
                   status    = "okay";
                 };
             };
        };
  };

};

I am really unsure about the second part (fragment1), and this is the first time I have written a non-trivial overlay that is more than just one pin or simple gpio.

I have seen both the answer here and here but I am curious how to make this work with an overlay, and if that is a better solution? The main problem is that although this overlay compiles it will not load and does not set the PWM pins up.


Solution

  • I inspected the overlay used for the 3D printer cape and made some changes. The new overlay works, and even creates the pwm folders with custom names instead of just P9_16_PWM lie the default.

    /dts-v1/;
    /plugin/;
    
    / {
        compatible = "ti,beaglebone", "ti,beaglebone-black";
    
        /* identification */
        part-number = "CAR_CONTROLS";
        version = "00A0";
    
        /* state the resources this cape uses */
        exclusive-use =
            /* the pin header uses */
            "P9.14",        /* pwm: ehrpwm1A - STEERING */
                    "P9.16",                /* pwm: ehrpwm1B - MOTOR */
            /* the hardware IP uses */
            "ehrpwm1A",
                    "ehrpwm1B";
    
        // Each PWM pin is it's own node, even though they are on the same module
        fragment@0 {
            target = <&am33xx_pinmux>;
            __overlay__ {
                car_steering_pins: pinmux_car_steering_pins {  // STEERING PIN
                    pinctrl-single,pins = <0x048  0x6>;    /* P9_14 (ZCZ ball U14) | MODE 6 */
                };
                            car_motor_pins: pinmux_car_motor_pins {      // MOTOR CONTROL PIN
                                    pinctrl-single,pins = <0x04c  0x6>;  /* P9_16 (ZCZ ball T14) | MODE 6 */
                };
            };
        };
    
        fragment@1 {
            target = <&ocp>;
            __overlay__ {
                car_pwm_helper {
                    car_steering {      // Directory Will Be Called this
                        compatible  = "pwm_test";   // unknown ???
                        pinctrl-names   = "default";    // unknown ???
                        pinctrl-0   = <&car_steering_pins>;
                        pwms        = <&ehrpwm1 0 20000000 1>;  // Module 0 at 20MHz ... unsure what last 1 is?
                        pwm-names   = "STEER_P9_14";
                        enabled     = <1>;      // enable plz
                        polarity        = <0>;      // 0=normal, 1=inverse
                        duty        = <0>;      // initial duty
                        status      = "okay";   // be ok plz?
                    };
                    car_motor {     // Directory will be called this
                        compatible  = "pwm_test";
                        pinctrl-names   = "default";
                        pinctrl-0   = <&car_motor_pins>;
                        pwms        = <&ehrpwm1 1 20000000 1>;  // Module 1 at 20MHz ... unsure what last 1 is?
                        pwm-names   = "MOTOR_P9_16";
                        enabled     = <1>;      // enable plz
                        polarity        = <0>;      // 0=normal, 1=inverse
                        duty        = <0>;      // initial duty
                        status      = "okay";   // be ok plz?
                    };
                };
            };
        };
    };
    

    Still unsure about what a few lines do but it works so our project can move forward. Answering my own question so that maybe this will help someone else out there.