Is there a C api for the PWM function?

I've spent a day now searching the web for an answer but all I see is
the use of the shell. I need a programming API. Does that exist?

Thanks,
John

From: beagleboard@googlegroups.com
[mailto:beagleboard@googlegroups.com] On Behalf Of NeonJohn
Sent: Monday, February 25, 2013 2:28 AM
To: beagleboard@googlegroups.com
Subject: [beagleboard] Is there a C api for the PWM function?

I've spent a day now searching the web for an answer but all I see is
the use of the shell. I need a programming API. Does that exist?

Does this help - http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver's_Guide

Also, for PWM kernel api, you can refer to drivers/video/backlight/pwm_bl.c

Thanks,
Vaibhav

From: beagleboard@googlegroups.com
[mailto:beagleboard@googlegroups.com] On Behalf Of NeonJohn
Sent: Monday, February 25, 2013 2:28 AM
To: beagleboard@googlegroups.com
Subject: [beagleboard] Is there a C api for the PWM function?

I've spent a day now searching the web for an answer but all I see is
the use of the shell. I need a programming API. Does that exist?

Does this help - http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver's_Guide

Also, for PWM kernel api, you can refer to drivers/video/backlight/pwm_bl.c

[1] has a limited amount of information on the kernel api. I believe
the only interfaces for programming the PWM are currently at the
kernel level unless you apply hacks like the one in the BeagleBone
3.2.x kernels with TI patches or similar slightly more limited hacks
[2] used for kernel/hardware testing. I believe there is a strong need
in the embedded Linux community for someone to submit a generic
userspace PWM API via both syscalls and sysfs entries and I haven't
seen that anyone is taking on this task.

[1] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=Documentation/pwm.txt
[2] kernel/0003-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch at 3.8 · beagleboard/kernel · GitHub

Can anyone please explain the steps, or better yet, point to an example on how to expose a kernel module such as the omap_dm_timer from user space? Do I need to create a PWM device driver on top of the omap_dm_timer interface to expose the PWM hardware to user space? Something like the table below?



PWM C Application



User space application that uses PWM API to interface to the PWM hardware



PWM API Library



User Space API that provides a high-level abstraction interfaces to the PWM device driver



Custom PWM Device Driver



Kernel device driver that provides a higher-level interface to omap_dm_timer kernel module



omap_dm_timer



Kernel Module low-level interface to hardware



GPTIMER



Hardware OMAP general purpose dual-mode timer

I am working with the DM816x which like the BeagleBoard the timers seem to be only accessible from other kernel software. How do you expose this to user space applications?

ti-sdk-beagleboard-05.05.01.00/board-support/linux-3.3.7-r115/arch/arm/plat-omap/include/plat/dmtimer.h

I have spent several weeks as well understanding how to use the general purpose timers for PWM output. So far I have resigned my self to using a shell script that calls the devmem2 interface. Any tips or suggestions are appreciated.

Thanks in advance,

-Ed

I cannot get the devmem2 work-around working. Any ideas what can cause a “Bus Error”? It looks like CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y

GPTIMER4_BASE=0x48044000
TCLR=0x024

root@dm816x-evm:~# devmem2 0x48044024 w 0
/dev/mem opened.
Memory mapped at address 0x4026f000.
Bus error

Thanks,

-Ed

http://www.jumpnowtek.com/index.php?option=com_content&view=article&id=56&Itemid=63

There was patch submitted to get PWM functionality from DMTIMER, but
Still not got mainlined yet.

https://patchwork.kernel.org/patch/1864951/

And as far as User interface is concerned, you have to write
Kernel module to export it to User Space.
From PWM perspective, as mentioned by Jason, you can use sample
Application which will export PWM functionality to user space.

Thanks,
Vaibhav

This means interface clock to module is disabled and you
No longer have access module.

Thanks,
Vaibhav

There appears to be a pwm kernel module already written and in place. I
work with the Robert Nelson branch. I'm currently restoring my Angstrom
monstrosity to see if it's there too. In Robert's branch, the code is
in KERNEL/drivers/pwm. I've verified that it gets built and installed.

What I don't know is how to go from the kernel module to a user program.
I just don't know enough about the kernel yet?

Hints would be appreciated.

Thanks
John

There appears to be a pwm kernel module already written and in place. I
work with the Robert Nelson branch. I'm currently restoring my Angstrom
monstrosity to see if it's there too. In Robert's branch, the code is
in KERNEL/drivers/pwm. I've verified that it gets built and installed.

What I don't know is how to go from the kernel module to a user program.
I just don't know enough about the kernel yet?

Hints would be appreciated.

Thanks
John

I've spent a day now searching the web for an answer but all I see is
the use of the shell. I need a programming API. Does that exist?

Does this help - http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver's_Guide

I had found that in my searching. It just shows using the shell to send
commands directly into kernel memory.

Also, for PWM kernel api, you can refer to drivers/video/backlight/pwm_bl.c

That's the wrong controller for general purpose use. We want to use the
ehrpwm hardware.

I haven't found a solution yet but I'm making progress. I'm hoping this
progress report will persuade someone who knows to speak up.

In the Kernel there are two places where the PWM is addressed (referring
to the Robert Nelson version).

KERNEL/arch/arm/mach-omap2

I think this is the one that generates the /sys interface that the shell
programming uses.

and

KERNEL/drivers/pwm

I think that this establishes a user interface to the timers, though I
don't understand the Linux user space/kernel interface for kernel
modules well enough yet to be sure.

In both these directories the relevant code is compiled and linked, in
hte case of mach-omap2 to a kernel module (.ko).

I spent a lot of time trying to get the memory interface to work but
have failed so far. This involves using offsets into kernel memory to
hit the proper memory-mapped registers of the PWM hardware.

A few years ago there was a Google Summer of Code (GSOC) project to
write a mmem() interface to the PWM on the Bone. It worked until a
kernel update turned off the PWM clock by default.

According to several references on the web, undefining
CONFIG_OMAP_RESET_CLOCKS remedies this situation. Not in 3.2.0-38.
That define is only used in one place,
KERNEL/arch/arm/mach-omap2/clock.c, about line 425 and wraps around a
function called

omap2_clk_disable_unused()

The thing is, this function is not called from anywhere in this version
of the kernel that I can find. I grepped the entire kernel tree looking
for that function call. Not used. I put a kprint() call in the
function to to make sure. Besides, the PWM clock would almost have to
be working for the shell commands to work.

Next, I found this thread.

https://groups.google.com/forum/?fromgroups=#!topic/beagleboard/7kLlxZ7fg80

It's a very long thread and contains a lot of background on the PWM
function. About half way down (search for

//////////INCLUSION OF ADDITIONAL FUNCTION CALLS

Mohit hada modifies the GSOC code by adding code to start the clocks.
It worked in 2011 but it does not work now. The code, cleaned up so
it'll cross-compile under Ubuntu is available here:

https://dl.dropbox.com/u/81715047/DM3530-pwm.tar.bz2

The very first part of the program does this

  mem_fd = open("/dev/mem", O_RDWR | O_SYNC);

fprintf(stderr,"dm3730-pwm-demo.c:calling mmap() \n");
  pinconf = (unsigned long*)mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
MAP_SHARED, mem_fd, 0x48000000);

Execution on the bone shows the fprintf statement executing and then a
bus error occurs. The mmap call never returns. Since this code was
written for the BeagleBoard, I suspect the magic number 0x48000000 is
wrong but I haven't figured out the correct number. In other words, the
program generates a kernel error with a dmesg of

Unhandled fault: external abort on non-linefetch (0x1018) at 0x40352d40

long before the code gets to the part where it starts the clocks.

That's about where I stand right now. I'm trying to figure out the
device drivers with the help of this book

http://lwn.net/Kernel/LDD3/

I put all the PDF pieces together into one big PDF (using pdftk). It's
available here:

https://dl.dropbox.com/u/81715047/Linux%20Device%20Drivers%203rd%20Edition.pdf

Another good resource is

http://www.tldp.org/LDP/lkmpg/2.4/html/index.html

Both of these books address Version 2 of the kernel but so I've read
elsewhere, there is still enough similarity between 2 and 3's driver
interface for these to be useful. So far I'm finding that to be the case.

So now I have several questions.

*) Is drivers/pwm what I'm interested in as an API and if so, how do I
access the function calls within? probably ioctl() calls but I don't
have any idea of the structure of the call nor what device to apply it to.

*) or does the code in KERNEL/arch/arm/mach-omap2 what I'm interested
in? I think that the drivers/pwm is the general user interface and the
mach-omap2 is the hardware interface code.

*) What is the magic number to make the GSOC code work and more
importantly, where can that be found.

I'm hoping that some of the kernel gurus that I know monitor this list
will come out and help.

John

From: beagleboard@googlegroups.com
[mailto:beagleboard@googlegroups.com] On Behalf Of NeonJohn
Sent: Wednesday, February 27, 2013 10:44 PM
To: beagleboard@googlegroups.com
Subject: Re: [beagleboard] Is there a C api for the PWM function?
Progress report

>> I've spent a day now searching the web for an answer but all I see
is
>> the use of the shell. I need a programming API. Does that exist?
>>
> Does this help -
http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver's_Guide

I had found that in my searching. It just shows using the shell to
send
commands directly into kernel memory.

> Also, for PWM kernel api, you can refer to
drivers/video/backlight/pwm_bl.c

That's the wrong controller for general purpose use. We want to use
the
ehrpwm hardware.

[Hiremath, Vaibhav] First off all that's not the controller, it's a client driver which
Uses PWM api's, as backlight HW works over PWM.

I haven't found a solution yet but I'm making progress. I'm hoping
this
progress report will persuade someone who knows to speak up.

In the Kernel there are two places where the PWM is addressed
(referring
to the Robert Nelson version).

KERNEL/arch/arm/mach-omap2

I think this is the one that generates the /sys interface that the
shell
programming uses.

and

KERNEL/drivers/pwm

I think that this establishes a user interface to the timers, though I
don't understand the Linux user space/kernel interface for kernel
modules well enough yet to be sure.

In both these directories the relevant code is compiled and linked, in
hte case of mach-omap2 to a kernel module (.ko).

I spent a lot of time trying to get the memory interface to work but
have failed so far. This involves using offsets into kernel memory to
hit the proper memory-mapped registers of the PWM hardware.

A few years ago there was a Google Summer of Code (GSOC) project to
write a mmem() interface to the PWM on the Bone. It worked until a
kernel update turned off the PWM clock by default.

According to several references on the web, undefining
CONFIG_OMAP_RESET_CLOCKS remedies this situation. Not in 3.2.0-38.
That define is only used in one place,
KERNEL/arch/arm/mach-omap2/clock.c, about line 425 and wraps around a
function called

omap2_clk_disable_unused()

The thing is, this function is not called from anywhere in this version
of the kernel that I can find. I grepped the entire kernel tree
looking
for that function call. Not used. I put a kprint() call in the
function to to make sure. Besides, the PWM clock would almost have to
be working for the shell commands to work.

Next, I found this thread.

https://groups.google.com/forum/?fromgroups=#!topic/beagleboard/7kLlxZ7
fg80

It's a very long thread and contains a lot of background on the PWM
function. About half way down (search for

//////////INCLUSION OF ADDITIONAL FUNCTION CALLS

Mohit hada modifies the GSOC code by adding code to start the clocks.
It worked in 2011 but it does not work now. The code, cleaned up so
it'll cross-compile under Ubuntu is available here:

https://dl.dropbox.com/u/81715047/DM3530-pwm.tar.bz2

The very first part of the program does this

  mem_fd = open("/dev/mem", O_RDWR | O_SYNC);

fprintf(stderr,"dm3730-pwm-demo.c:calling mmap() \n");
  pinconf = (unsigned long*)mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
MAP_SHARED, mem_fd, 0x48000000);

Execution on the bone shows the fprintf statement executing and then a
bus error occurs. The mmap call never returns. Since this code was
written for the BeagleBoard, I suspect the magic number 0x48000000 is
wrong but I haven't figured out the correct number. In other words,
the
program generates a kernel error with a dmesg of

Unhandled fault: external abort on non-linefetch (0x1018) at 0x40352d40

long before the code gets to the part where it starts the clocks.

That's about where I stand right now. I'm trying to figure out the
device drivers with the help of this book

http://lwn.net/Kernel/LDD3/

I put all the PDF pieces together into one big PDF (using pdftk). It's
available here:

https://dl.dropbox.com/u/81715047/Linux%20Device%20Drivers%203rd%20Edit
ion.pdf

Another good resource is

http://www.tldp.org/LDP/lkmpg/2.4/html/index.html

Both of these books address Version 2 of the kernel but so I've read
elsewhere, there is still enough similarity between 2 and 3's driver
interface for these to be useful. So far I'm finding that to be the
case.

So now I have several questions.

*) Is drivers/pwm what I'm interested in as an API and if so, how do I
access the function calls within? probably ioctl() calls but I don't
have any idea of the structure of the call nor what device to apply it
to.

[Hiremath, Vaibhav] You may get some basic information on user interface on
PWM driver her - http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver's_Guide

*) or does the code in KERNEL/arch/arm/mach-omap2 what I'm interested
in? I think that the drivers/pwm is the general user interface and the
mach-omap2 is the hardware interface code.

[Hiremath, Vaibhav] What I feel here is, you are totally confused and don't what exactly
You need. Let me help you with some details which I know -

arch/arm/mach-oma2/:

[Hiremath, Vaibhav] You may get some basic information on user interface on
PWM driver her - http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver's_Guide

Yes, I found that in my searching.

*) or does the code in KERNEL/arch/arm/mach-omap2 what I'm interested
in? I think that the drivers/pwm is the general user interface and the
mach-omap2 is the hardware interface code.

[Hiremath, Vaibhav] What I feel here is, you are totally confused and don't what exactly
You need. Let me help you with some details which I know -

Yes I am indeed confused. I wouldn't be trying to pry help out of
people on this list otherwise.

arch/arm/mach-oma2/:
-------------------
I believe you are referring to timer code here right? This is actually PWM over DMTimer.
Please note that not all timers can provide you PWM functionality, so You may want to
check TRM for your device (assuming you mentioned TI816x).

I don't think so. In that directory is timer.c and board-am335xevm.c
among a lot of other stuff. Timer.c looks like it does indeed work with
timers but the am335xevm.c deals with the PWM controllers.

in order to get PWM functionality to user space you have to write kernel module
which uses DMTimer, I pointed you to one patch in my last response.

I didn't see that patch.

Driver/pwm:
----------
If you are referring to ti_pwm drivers, then it is actually using PWM Hardware available
In AM335x.

I hope this would give you fair idea on how things are and where you stand.

Not really. I still don't have a good overall view of how the PWM
hardware works. I guess I need to spend some more time in TRM.

My goal is very simple: I need a 40kHz square wave that I can vary the
duty cycle from 0 to 100%. I need it done in hardware so that my
software isn't constantly having to attend to it like it would with
timers.

Also, I would like to know why the GSOC program won't work. That little
hunk of code does exactly what I need done - when it works.

John

From: beagleboard@googlegroups.com
[mailto:beagleboard@googlegroups.com] On Behalf Of NeonJohn
Sent: Thursday, February 28, 2013 5:12 AM
To: beagleboard@googlegroups.com
Subject: Re: [beagleboard] Is there a C api for the PWM function?
Progress report

> [Hiremath, Vaibhav] You may get some basic information on user
interface on
> PWM driver her -
http://processors.wiki.ti.com/index.php/AM335x_PWM_Driver's_Guide

Yes, I found that in my searching.

>> *) or does the code in KERNEL/arch/arm/mach-omap2 what I'm
interested
>> in? I think that the drivers/pwm is the general user interface and
the
>> mach-omap2 is the hardware interface code.
>>
> [Hiremath, Vaibhav] What I feel here is, you are totally confused and
don't what exactly
> You need. Let me help you with some details which I know -

Yes I am indeed confused. I wouldn't be trying to pry help out of
people on this list otherwise.

>
>
> arch/arm/mach-oma2/:
> -------------------
> I believe you are referring to timer code here right? This is
actually PWM over DMTimer.
> Please note that not all timers can provide you PWM functionality, so
You may want to
> check TRM for your device (assuming you mentioned TI816x).

I don't think so. In that directory is timer.c and board-am335xevm.c
among a lot of other stuff. Timer.c looks like it does indeed work
with
timers but the am335xevm.c deals with the PWM controllers.

[Hiremath, Vaibhav] This is board file and __was__ responsible for creating
Platform_device.

Please note that now we do not have this board concept and everything
Will be done by DT.

>
> in order to get PWM functionality to user space you have to write
kernel module
> which uses DMTimer, I pointed you to one patch in my last response.

I didn't see that patch.

[Hiremath, Vaibhav] I did share this patch before on the list -

https://patchwork.kernel.org/patch/1864951/

Note: It is still not accepted in the mainline.

>
> Driver/pwm:
> ----------
> If you are referring to ti_pwm drivers, then it is actually using PWM
Hardware available
> In AM335x.
>
>
> I hope this would give you fair idea on how things are and where you
stand.

Not really. I still don't have a good overall view of how the PWM
hardware works. I guess I need to spend some more time in TRM.

[Hiremath, Vaibhav] I agree.

My goal is very simple: I need a 40kHz square wave that I can vary the
duty cycle from 0 to 100%. I need it done in hardware so that my
software isn't constantly having to attend to it like it would with
timers.

[Hiremath, Vaibhav] If you have BeagleBone with you, then you can follow
The steps in Userguide and see whether it helps you.

As Jason mentioned you have to use dummy sample driver to get PWM
Functionality to user space.

https://github.com/beagleboard/kernel/blob/3.8/patches/pwm/0003-pwm-pwm_test-Driver-support-for-PWM-module-testing.patch

Thanks,
Vaibhav

Also, I would like to know why the GSOC program won't work. That
little
hunk of code does exactly what I need done - when it works.

[Hiremath, Vaibhav] I am not the right person for GSOC stuff.

Thanks,
Vaibhav

First thing, Vaibhav, thank you so much for your attempt to help. Your
advice lead me astray but that's mostly on my head for being such a
kernel novice.

Now to the important stuff. I have the PWM output working. Right now
in the form of a shell script but soon as a C library.

One of the things that has greatly confused me has been so much
information out there that is obsolete. I'm learning that if the advice
is more than about 6 months old, it's probably obsolete.

That said, the key ingredient to making things work was found here:

http://www.gigamegablog.com/2012/03/16/beaglebone-coding-101-buttons-and-pwm/

I had been real close for a couple of days. What I missed was setting
the pin mux.

On his page he presents a javascript (link broken but findable by
google) to set the clock. As of the kernel I'm running,

3.2.33-psp26.1 #16 Mon Feb 25 00:32:03 EST 2013

which is Robert Nelson's version, the PWM clock is back on by default.
The script is NOT necessary.

Without further ado, here are the scripts.

To set the PWM frequency and turn it on, a script I call pwmon

#!/bin/sh

From: beagleboard@googlegroups.com
[mailto:beagleboard@googlegroups.com] On Behalf Of NeonJohn
Sent: Friday, March 01, 2013 3:40 AM
To: beagleboard@googlegroups.com
Subject: Re: [beagleboard] PWM function? Now working

First thing, Vaibhav, thank you so much for your attempt to help. Your
advice lead me astray but that's mostly on my head for being such a
kernel novice.

Now to the important stuff. I have the PWM output working. Right now
in the form of a shell script but soon as a C library.

One of the things that has greatly confused me has been so much
information out there that is obsolete. I'm learning that if the
advice
is more than about 6 months old, it's probably obsolete.

[Hiremath, Vaibhav] That's very true if you don't have driver accepted in
Mainline.
So you always end up doing something which may change in the future.

So the key is to get code in to mainline ASAP.

That said, the key ingredient to making things work was found here:

http://www.gigamegablog.com/2012/03/16/beaglebone-coding-101-buttons-
and-pwm/

I had been real close for a couple of days. What I missed was setting
the pin mux.

[Hiremath, Vaibhav] I don't like and wouldn't recommend to have user control
The pin mux using devmem/debugfs. It should be handled as part of kernel/driver.
In your kernel version, it should have been set by board file.

Anyway, that's different issue all together. Good thing is you could able to
Get PWM working at your end.

Thanks,
Vaibhav