GPIO pins and Device Trees with 3.14 kernel

Hello,

I’m attempting to get GPIO pins to configure / work under:

Debian 7.7 console
Linux beaglebone 3.14.19-ti-r30 #1 SMP PREEMPT Mon Oct 13 20:34:06 UTC 2014 armv7l GNU/Linux

I have added an include to am335x-boneblack-4dcape-43t.dts (I have a 4DCape-43t) to configure my GPIO pins.

It compiles without issues.

I replaced the /boot/am335x-boneblack-4dcape-43t.dtb file with my own and it boots without complaint.

There is no cape manager yet for 3.14.

I’m not sure how to list the current pin mix configuration to validate my changes have taken effect.

Where are the output / input pins mapped in the file system? Should they show up under /sys/class/gpio/gpiochip(0, 32, 64, 96)?

I should have file system entries for PWM pins I have enabled in the device tree, but I see nothing under the /sys/class/pwm/ directory.

Is this where the entries should show up?

Obviously, I could use a good tutorial on how to configure the device tree and access the GPIO functions under kernel 3.14

Thanks for any help.

So, is the answer to wait for Config-pin and BBB-IO to come out for kernel 3.14?
Do I need to roll back to 3.8 kernel so I can use cape manager?

The whole point of config-pin and the universal cape was to be able to
play with GPIO pins w/o needing to mess with device tree overlays.

You can already use config-pin with the 3.14 kernel, most of the
universal overlay is part of the default 3.14 device-tree by default
(and you can add more of it in if necessary).

I'm not sure how to list the current pin mix configuration to validate my
changes have taken effect.

Dig around in /sys/kernel/debug/pinctrl/

Where are the output / input pins mapped in the file system? Should they
show up under /sys/class/gpio/gpiochip(0, 32, 64, 96)?

The gpiochip* files are the four banks of GPIO pins. The individual
pins will show up as a directory if exported by the kernel, something like:

$ ls -1 /sys/class/gpio/
export
gpio110
gpio111
gpio112
gpio113
gpio114
gpio115
gpio116
gpio117
gpio14
gpio15
gpio2
gpio20
...

I should have file system entries for PWM pins I have enabled in the device
tree, but I see nothing under the /sys/class/pwm/ directory.

Is this where the entries should show up?

IIRC how PWM is handled changed in the 3.14 kernel, but I haven't worked
with it yet. Try searching through the list, I think there have been a
few threads on PWM and the 3.14 kernel.

Thanks for the info Charles.

I must have something wrong in my rebuild of the dtb file.
I have no pin entries under /sys/class/gpio.
I'll look around in /sys/kernel/debug/pinctl to see what the current config settings are.

All my searches on this forum and the web turn up examples for the 3.8 kernel and cape manager.
I've found references to configuring the GPIO pins under 3.14, but no examples or explainations of where changes can be verified.
Cape Manager under 3.8 is documented very well.

I found the repository for config-pin, but apt-cache search turned up nothing for installing it.
Do I need to compile the source from the repo on the BBB to get config-pin?

Thanks for the info.

So, I can get config-pin to install by getting the universal-io from git

#apt-get install gcc g++ make device-tree-compiler
#git clone https://github.com/cdsteinkuehler/beaglebone-universal-io
#cd beaglebone-universal-io/
#make
#sudo make install

after that, I can change the mode of my pin

PIN 8 - P8-19 gpio0[22] 22 0x820 EHRPWM2A

to PWM with:

#config-pin p8.19 pwm

it changes the configuration, I can verify it by checking with

#config-pin -q p8.19

however, I can't export the pin using:

sudo cat 2 > /sys/class/pwm/export

it always comes back with permission denied

also, the /sys/class/pwm directory is empty, there should be something in there, right?

Any ideas what I need to do to get pwm working?

Is PWM supported in kernel 3.14?
Is there some trick that will populate the /sys/class/PWM directory with export and other entries needed to configure PWM?
I see lots of examples for generic GPIO under 3.14 and they work fine.
However, all the PWM examples I see use 3.8 and cape manager and device overlays.

So, I can get config-pin to install by getting the universal-io from git

#apt-get install gcc g++ make device-tree-compiler
#git clone https://github.com/cdsteinkuehler/beaglebone-universal-io
#cd beaglebone-universal-io/
#make
#sudo make install

after that, I can change the mode of my pin

PIN 8 - P8-19 gpio0[22] 22 0x820 EHRPWM2A

to PWM with:

#config-pin p8.19 pwm

it changes the configuration, I can verify it by checking with

#config-pin -q p8.19

however, I can't export the pin using:

sudo cat 2 > /sys/class/pwm/export

???
sudo echo 2 > /sys/class/pwm/export
maybe?
"cat 2” would try to concatenate (or print) a file named “2” to stdout and then redirect it to a file named /sys/class/pwm/export

Yes, that,was a typo.

#sudo echo 2 > /sys/class/pwm/export

I thought that would export EHRPWM2 so I could configure it.

I have a LCD cape 4DSCape-43T
I'm loading am335x-boneblack-4dcape-43t.dtb

Do I need to load a different dtb to enable pwm?

Yes, that,was a typo.

#sudo echo 2 > /sys/class/pwm/export

I thought that would export EHRPWM2 so I could configure it.

I have a LCD cape 4DSCape-43T
I’m loading am335x-boneblack-4dcape-43t.dtb

Do I need to load a different dtb to enable pwm?

No… Someone actually had to figure out how to enable the pwm via the DTS in v3.14.x…

Hint I haven’t much time on it nor figured it out… Hence its not enabled by default.

It appears to not be a trivial thing.
The modules for pwm are enabled by default in the kernel. It should be a matter of getting the DTC to build a device tree for pwm.
The DTC dtsi files contain pwm definitions, but changing the status to okay fails to create the pwm entries in the file system.
The answer to this issue is beyond what I can find using Google and other resources.

If it helps, here is the device tree overlay that works for 3.8 kernel.
This will enable three PWM pins.

/dts-v1/;
/plugin/;

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

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

  /* state the resources this cape uses */
  exclusive-use =
    /* the pin header uses */
    "P9.14",
    /* the hardware IP uses */
    "ehrpwm1A",
    /* the pin header uses */
    "P8.13",
    /* the hardware IP uses */
    "ehrpwm2B",
    /* the pin header uses */
    "P8.19",
    /* the hardware IP uses */
    "ehrpwm2A";

  fragment@0 {
    target = <&epwmss0>;
    __overlay__ {
      status = "okay";
    };
  };

  fragment@1 {
    target = <&ehrpwm0>;
    __overlay__ {
      status = "okay";
    };
  };

  fragment@2 {
    target = <&ecap0>;
    __overlay__ {
      status = "okay";
    };
  };

  fragment@3 {
    target = <&epwmss1>;
    __overlay__ {
      status = "okay";
    };
  };

  fragment@4 {
    target = <&ehrpwm1>;
    __overlay__ {
      status = "okay";
    };
  };

  fragment@5 {
    target = <&epwmss2>;
    __overlay__ {
      status = "okay";
    };
  };

  fragment@6 {
    target = <&ehrpwm2>;
    __overlay__ {
      status = "okay";
    };
  };

  fragment@7 {
    target = <&ecap2>;
    __overlay__ {
      status = "okay";
    };
  };

    fragment@8 {
  target = <&am33xx_pinmux>;
  __overlay__ {
      bs_pwm_P9_14_0xe: pinmux_bs_pwm_P9_14_0xe {
          pinctrl-single,pins = <0x048 0xe>;
      };
      bs_pwm_P8_13_0xc: pinmux_bs_pwm_P8_13_0xc {
          pinctrl-single,pins = <0x024 0xc>;
      };
      bs_pwm_P8_19_0xc: pinmux_bs_pwm_P8_19_0xc {
          pinctrl-single,pins = <0x020 0xc>;
      };
        };
    };

    fragment@9 {
        target = <&ocp>;
  __overlay__ {
      bs_pwm_test_P9_14 {
    compatible = "pwm_test";
    pwms = <&ehrpwm1 0 500000 0>;
    pwm-names = "PWM_P9_14";

    pinctrl-names = "default";
    pinctrl-0 = <&bs_pwm_P9_14_0xe>;

    enabled = <1>;
    duty = <0>;
    status = "okay";
      };
      bs_pwm_test_P8_13 {
        compatible = "pwm_test";
        pwms = <&ehrpwm2 1 500000 0>;
        pwm-names = "PWM_P8_13";

        pinctrl-names = "default";
        pinctrl-0 = <&bs_pwm_P8_13_0xc>;
    
        enabled = <1>;
        duty = <0>;
        status = "okay";
          };
      bs_pwm_test_P8_19 {
    compatible = "pwm_test";
    pwms = <&ehrpwm2 0 500000 0>;
    pwm-names = "PWM_P8_19";

    pinctrl-names = "default";
    pinctrl-0 = <&bs_pwm_P8_19_0xc>;

    enabled = <1>;
    duty = <0>;
    status = "okay";
      };
        };
    };

};

  • config-pin [pin] [state] will mux the pins to the PWM Subsystems

  • Modifying am33xx.dtsi under the dtb-rebuilder project such that: epwmss0, epwmss1, and epwmss2 status = “okay”, and their children, ehrpwm0, ehrpwm1, and erhpwm2 status = “okay”, will enable the system clocks for each subsystem. This equivalent to setting the following registers to the given values in their respective order:
    reg[0x44E00000] = 0x0 # CM_PER_L4L3_CLKSTCTRL.CLKTRCTRL = NO_SLEEP
    reg[0x44E000D4] = 0x2 # CM_PER_EPWMSS0_CLKCTRL.MODULEMODE = ENABLE
    reg[0x44E000CC] = 0x2 # CM_PER_EPWMSS1_CLKCTRL.MODULEMODE = ENABLE
    reg[0x44E000D8] = 0x2 # CM_PER_EPWMSS2_CLKCTRL.MODULEMODE = ENABLE

  • However, after all this, the PWM subsystems will still not work because the Time Based Clocks are not enabled. To enable them, one would need kernel elevated privileges: such as modifying the register through a simple kernel module.

reg[0x44E10664] = 0x7 # CONTROL_MODULE.pwmss_ctrl = pwmss0_tbclken | (pwmss1_tbclken << 1) | (pwmss2_tbclken << 2)

Using a simple kernel module I built for hardware debugging, I was able to confirmed this. (Look at ioremap & iounmap under kernel module development)

after doing so how do you control duty cycle, period…?

I see someone has recently asked a question on this old post.

Controlling pwm using linux is nicely documented in kernel docs:
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-pwm

controlling simple servo takes period 20 ms and duty_cycle 1 - 2 ms, start with these values
echo 20000000 > /sys/class/pwm/pwmchip[num]/pwm[num]/period
… rest is up to you

As for the ‘howto’ described by Tekuconcept in previous reply, I wouldn’t bother about modifying dtb files anymore:
-Upgrade kernel to 4.1 (since this post is originally about the 3.14 kernel)
— add ‘deb [arch=armhf] http://repos.rcn-ee.com/ubuntu trusty main’ to apt sources (modify to own needs), install new linux-image.
— modify /boot/uEnv.txt or /boot/uboot/uEnv.txt so the new kernel is loaded, I mixed up my original uEnv and the suggestions from:
https://eewiki.net/display/linuxonarm/BeagleBone+Black#BeagleBoneBlack-DealingwitholdBootloaderineMMC
— dont screw up uEnv… (manual loading of kernel image in memory using uboot console is possible with serial debugger but painfull…)
-clone ‘bb-overlays’ github repo and install
-clone ‘universal-io’ github repo and install
-reboot (took me an hour to figure this one out…)
Now you can ‘config-pin overlay cape-universaln’, ‘config-pin P[num] pwm’. (all in user space)

That’s about it, works flawless. (took me a couple of days to figure everything out though, as hobbyist it’s fishing for the correct info on the web…)

kind regards,
Dieter

Thanks for the update dieter! I didn’t know kernel version 4.1 was recently released… well, I now know what I’m going to be doing over the next month with our team’s Repository.

Dear TekuConcept,

Could you please share your kernel module that enable Time Based Clocks of PWMSS?
Thanks.

在 2015年4月16日星期四 UTC+8下午9:29:59,TekuConcept写道:

https://github.com/USU-Robosub/Poseidon/tree/remote-control/kernel/drivers/PWM