Re: [Gumstix-users] PWM H-Bridge servo -- basix--breakout-gs

Hi Ben,
i am not sure, if you did understand some things wrong about writing a
kernel module. Perhaps you should take a look at this book for better
understanding http://lwn.net/Kernel/LDD3/. There is also a brief
tutorial at http://www.freesoftwaremagazine.com/articles/drivers_linux.
And you can find much more information about linux device drivers with
google.
A kernel module has to have a special structure and has to implement
methods, like init(), exit(), etc.
You can compile your kernel module as built-in module or as loadable
module. The easier way is to create loadable module, because you dont
have to change the bitbake recipes and makefiles of the kernel. During
compiling the module is linked against your kernel sources and is
therefore compatible to your kernel. Use the command insmod to install a
loadable kernel module and rmmod to remove it.
I used a bitbake recipe in combination with a makefile to compile my
kernel module. The ipkg packages can be transfered to the gumstix the
same way as you would do with a user applikation. After ipkg install
the kernel modules (.ko files) are located under
/lib/modules/2.6.2x./extra, but you can change this path of course in
your bitbake file, if you like to. Use the imod command to install your
module.
> As for kernel modules, I still have a few questions. Also, I still can
> not get your code to compile. Could you could send me your bitbake recipe?
> What is the procedure for adding a kernel module? Right now I have your
> code in com.gumstix.collection/packages/pwm/files/pwm.c I tried "bitbake
> pwm" to make sure I had the recipe correct, but I get the error "No such
> file or directory" on the included header files.
You need the information where the kernel can be found in your recipe.
> I also added
> "module_autoload_proc_gpio = 'pwm' " to gumstix-custom-basix.conf
>
This is not the way to get it work. There are a lot more files that
describe how the kernel is built. Use a loadable kernel module, it is a
lot easier.
> If I type "PWM_PWDUTY0 = 1000 & PWM_DCR_MASK", I get:
> -sh: PWM_PWDUTY0: not found
> -sh: PWM_DCR_MASK: not found
> [1] + Done(127) PWM_PWDUTY0 = 1000
>
Of course you cannot do this. "PWM_PWDUTY0 = 1000 & PWM_DCR_MASK" is c
code. You cannot use source code in combination with a shell.
Read the Linux Device Drivers book. There you will find different
methods to communicate with your device driver. You can for example use
the standard driver interface methods read(), write() or ioctl(), but
you can also use the proc or sys file system possibilities.
best reagrds
Sandra
recipe:
DESCRIPTION = "driver sample program"
PR = "r0"
RDEPENDS = "kernel (${KERNEL_VERSION})"
DEPENDS = "virtual/kernel"
SRC_URI = " \
file://foo.c \
file://Makefile \
"
S = "${WORKDIR}"
inherit module
EXTRA_OEMAKE = "-C ${KERNEL_SOURCE} SUBDIRS=${S}"
do_compile () {
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
oe_runmake
}
do_install () {
# kernel module installs with other modules
install -m 0755 -d ${D}${base_libdir}/modules/${KERNEL_VERSION}/extra/
# use cp instead of install so the driver doesn't get stripped
cp ${S}/foo.ko ${D}${base_libdir}/modules/${KERNEL_VERSION}/extra/
}
PACKAGES = "${PN}"
#FILES_${PN} = "${bindir}/foo"
FILES_${PN} = "${base_libdir}/modules/${KERNEL_VERSION}/extra/foo.ko"
Makefile:
ifneq ($(KERNELRELEASE),)
obj-m := foo.o
else
AKT := $(shell pwd)
default:
make -C $(KERNEL) SUBDIRS=$(AKT) modules
endif

Chris Dollar wrote:
>
> I used this snippit in the past to set lcd contrast with pwm1 on a connex.
>
> PXAREGS=/usr/sbin/pxaregs
> start() {
> echo "Setting LCD contrast on PWM1"
> # set GPIO to AF2
> $PXAREGS GAFR0U_17 2
> ...
>
Chris,
Thanks for the response! I ran this code from the command line, with a
o-scope on the pwm1 line. It worked great for a few seconds (nice square
wave), then the wave turned into garbage. I can't reproduce the square
wave, even if I restart the gumstix. Any ideas on why this is happening?
Also, does anyone have any c or c++ code that can set the pwm lines?
Thanks,
-Ben
--
View this message in context: http://www.nabble.com/PWM-H-Bridge-servo----basix--breakout-gs-tp23491954p23606621.html
Sent from the Gumstix mailing list archive at Nabble.com.

Hi Ben,
i used this c code in a kernel module on a verdex:
#include <asm/arch/pxa-regs.h> //contains defines for GPIO and PWM
register access
#include <asm/hardware.h> //contains comfortable Methods
seting GPIO alternate functions
#define PWM_CR_MASK 0x3F //0x3F is the largest value
allowed for the PWM_CTR register
#define PWM_DCR_MASK 0x3FF //0x3FF is the largest value allowed
for the PWM_PWDUTY register
#define PWM_PCR_MASK 0x3FF //0x3FF is the largest value allowed
for the PWM_PERVAL register
//setze GPIO16 und GPIO17 als PWM pin
pxa_gpio_mode(GPIO16_PWM0_MD);
//setze PWM register
PWM_CTRL0 = PWM_CR_MASK; //Set
Scaled Counter Clock
PWM_PWDUTY0 = PWM_DCR_MASK; // Set Duty Cycle
PWM_PERVAL0 = PWM_PCR_MASK; // Set Period
pxa_set_cken(CKEN_PWM0, 1);
//enable PWM Clock
After enabling the PWM clock, i can see the square wave with a o-scope
on pwm0 line. It runs on and on, until i reset the gumstix, or switch
the PWM clock of. ( pxa_set_cken(CKEN_PWM0, 0))
best regards,
Sandra
> Chris Dollar wrote:
>
>> I used this snippit in the past to set lcd contrast with pwm1 on a connex.
>>
>> PXAREGS=/usr/sbin/pxaregs
>> start() {
>> echo "Setting LCD contrast on PWM1"
>> # set GPIO to AF2
>> $PXAREGS GAFR0U_17 2
>> ...
>>
>>
>
> Chris,
> Thanks for the response! I ran this code from the command line, with a
> o-scope on the pwm1 line. It worked great for a few seconds (nice square
> wave), then the wave turned into garbage. I can't reproduce the square
> wave, even if I restart the gumstix. Any ideas on why this is happening?
>
> Also, does anyone have any c or c++ code that can set the pwm lines?
>
> Thanks,
> -Ben
>

Sandra Jobst wrote:
>
> i used this c code in a kernel module on a verdex:
>
> #include <asm/arch/pxa-regs.h> //contains defines for GPIO and PWM
> register access
> #include <asm/hardware.h> //contains comfortable Methods
> seting GPIO alternate functions
> ...
>
Thanks for the code Sandra, sorry, I forgot to mention I am using OE.
I'm not completely sure, but I don't think this works for OE (it can't find
any of the required files). I have no experience with kernel modules, so
this might be a stupid question: would I be able to constantly change the
duty cycle from my program if this were a kernel module?
I was able to get your code to work by using the "system" function in my
c++ program. This of course was way to slow (28ms), I need no more than
100us.
Maybe it is not possible, but I was expecting the pwm lines to be as
simple (and as fast) as setting and clearing the GPIO lines (void
gpio_set(u32 gpio)). Does anyone know if this can be done or have any code
that can do it?
thanks,
-Ben
--
View this message in context: http://www.nabble.com/PWM-H-Bridge-servo----basix--breakout-gs-tp23491954p23644747.html
Sent from the Gumstix mailing list archive at Nabble.com.

Hi Ben,
under "gumstix-oe\com.gumstix.collection\packages\linux" you can find
the bitbake and config files for your kernel. The sources are loaded,
when you are compiling your kernel. You can find them in the working
directory for example in
"gumstix-oe\tmp\work\gumstix-custom-verdex-angstrom-linux-gnueabi\gumstix-kernel-2.6.2x"
or in
"gumstix-oe\tmp\staging\gumstix-custom-verdex-angstrom-linux-gnueabi\kernel".
There are different possibilities to handle a gpio access.
1. you can map the addresses into userspace as shown here:
http://docwiki.gumstix.com/index.php/Sample_Code/C/LED, but i think this
is a rather risky way, because you could easily overwright important
things in kernelspace, without noticing.
2. you can wright a userspace driver: http://lwn.net/Articles/232575/,
it seems to be a good possibility for not time critical issues
3. you can write a kernel module, as for example
"gumstix-oe\com.gumstix.collection\packages\gpio-event". It is the
safest possibility, and when you need such high resolution timings, the
only way i think.....
The PWM is nearly as fast, as setting a gpio line; of course the new
value is not updated until the next period. Perhaps take a look at the
PXA27x_Processor_Family_Developers_Manual. There is a really detailed
section about the PWM controller unit.
Of course you can change the duty cycle: for example with
int x;
PWM_PWDUTY0 = x & PWM_DCR_MASK; // Set Duty Cycle
Do you want to control a motor with your code and do you really need to
change the value every 100us?
If you use standard kernel 2.6.21, timer resolution (jiffy) is 10ms, so
10ms is the smallest time unit.
best regards
Sandra
> Sandra Jobst wrote:
>
>> i used this c code in a kernel module on a verdex:
>>
>> #include <asm/arch/pxa-regs.h> //contains defines for GPIO and PWM
>> register access
>> #include <asm/hardware.h> //contains comfortable Methods
>> seting GPIO alternate functions
>> ...
>>
>>
>
> Thanks for the code Sandra, sorry, I forgot to mention I am using OE.
> I'm not completely sure, but I don't think this works for OE (it can't find
> any of the required files). I have no experience with kernel modules, so
> this might be a stupid question: would I be able to constantly change the
> duty cycle from my program if this were a kernel module?
> I was able to get your code to work by using the "system" function in my
> c++ program. This of course was way to slow (28ms), I need no more than
> 100us.
>
> Maybe it is not possible, but I was expecting the pwm lines to be as
> simple (and as fast) as setting and clearing the GPIO lines (void
> gpio_set(u32 gpio)). Does anyone know if this can be done or have any code
> that can do it?
>
> thanks,
> -Ben
>

Sandra Jobst wrote:
>
> There are different possibilities to handle a gpio access.
> 1. you can map the addresses into userspace as shown here:
> http://docwiki.gumstix.com/index.php/Sample_Code/C/LED, but i think this
> is a rather risky way, because you could easily overwright important
> things in kernelspace, without noticing.
> 2. you can wright a userspace driver: http://lwn.net/Articles/232575/,
> it seems to be a good possibility for not time critical issues
> 3. you can write a kernel module, as for example
> "gumstix-oe\com.gumstix.collection\packages\gpio-event". It is the
> safest possibility, and when you need such high resolution timings, the
> only way i think.....
>
Sandra,
Thanks for the detailed response. I believe that the code I am using
for GPIO maps the addresses into userspace. I understand that this is
risky, but if someone that knew what they were doing wrote the code, it
could be perfectly safe, correct? I obviously would not write it, but
perhaps someone already has some code with pwm mapped where you can easily
set the duty cycle. That would be the easiest for me, because then I don't
have to rebuild the kernel.
As for kernel modules, I still have a few questions. Also, I still can
not get your code to compile. Could you could send me your bitbake recipe?
What is the procedure for adding a kernel module? Right now I have your
code in com.gumstix.collection/packages/pwm/files/pwm.c I tried "bitbake
pwm" to make sure I had the recipe correct, but I get the error "No such
file or directory" on the included header files. I also added
"module_autoload_proc_gpio = 'pwm' " to gumstix-custom-basix.conf
From what I gather, I believe I need to issue the following commands:
bitbake -c rebuild gumstix-kernel
bitbake -c rebuild gumstix-basic-image
then install the image on the gumstix, as decribed in
http://www.gumstix.net/Software/view/Getting-started/Replacing-the-file-system-image/111.html.
Is that it? Well, I did all of this, and I don't think it worked. How
exactly do I know if it did? I checked /sbin and /usr/sbin, but "pwm" does
not exist. If I type "PWM_PWDUTY0 = 1000 & PWM_DCR_MASK", I get:
-sh: PWM_PWDUTY0: not found
-sh: PWM_DCR_MASK: not found
[1] + Done(127) PWM_PWDUTY0 = 1000
But there is no square wave on the scope. Do you know what I did wrong?
thanks,
-Ben
--
View this message in context: http://www.nabble.com/PWM-H-Bridge-servo----basix--breakout-gs-tp23491954p23788237.html
Sent from the Gumstix mailing list archive at Nabble.com.

Hi Ben,
i am not sure, if you did understand some things wrong about writing a
kernel module. Perhaps you should take a look at this book for better
understanding http://lwn.net/Kernel/LDD3/. There is also a brief
tutorial at http://www.freesoftwaremagazine.com/articles/drivers_linux.
And you can find much more information about linux device drivers with
google.
A kernel module has to have a special structure and has to implement
methods, like init(), exit(), etc.
You can compile your kernel module as built-in module or as loadable
module. The easier way is to create loadable module, because you dont
have to change the bitbake recipes and makefiles of the kernel. During
compiling the module is linked against your kernel sources and is
therefore compatible to your kernel. Use the command insmod to install a
loadable kernel module and rmmod to remove it.
I used a bitbake recipe in combination with a makefile to compile my
kernel module. The ipkg packages can be transfered to the gumstix the
same way as you would do with a user applikation. After ipkg install
the kernel modules (.ko files) are located under
/lib/modules/2.6.2x./extra, but you can change this path of course in
your bitbake file, if you like to. Use the imod command to install your
module.
> As for kernel modules, I still have a few questions. Also, I still can
> not get your code to compile. Could you could send me your bitbake recipe?
> What is the procedure for adding a kernel module? Right now I have your
> code in com.gumstix.collection/packages/pwm/files/pwm.c I tried "bitbake
> pwm" to make sure I had the recipe correct, but I get the error "No such
> file or directory" on the included header files.
You need the information where the kernel can be found in your recipe.
> I also added
> "module_autoload_proc_gpio = 'pwm' " to gumstix-custom-basix.conf
>
This is not the way to get it work. There are a lot more files that
describe how the kernel is built. Use a loadable kernel module, it is a
lot easier.
> If I type "PWM_PWDUTY0 = 1000 & PWM_DCR_MASK", I get:
> -sh: PWM_PWDUTY0: not found
> -sh: PWM_DCR_MASK: not found
> [1] + Done(127) PWM_PWDUTY0 = 1000
>
Of course you cannot do this. "PWM_PWDUTY0 = 1000 & PWM_DCR_MASK" is c
code. You cannot use source code in combination with a shell.
Read the Linux Device Drivers book. There you will find different
methods to communicate with your device driver. You can for example use
the standard driver interface methods read(), write() or ioctl(), but
you can also use the proc or sys file system possibilities.
best reagrds
Sandra
recipe:
DESCRIPTION = "driver sample program"
PR = "r0"
RDEPENDS = "kernel (${KERNEL_VERSION})"
DEPENDS = "virtual/kernel"
SRC_URI = " \
file://foo.c \
file://Makefile \
"
S = "${WORKDIR}"
inherit module
EXTRA_OEMAKE = "-C ${KERNEL_SOURCE} SUBDIRS=${S}"
do_compile () {
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
oe_runmake
}
do_install () {
# kernel module installs with other modules
install -m 0755 -d ${D}${base_libdir}/modules/${KERNEL_VERSION}/extra/
# use cp instead of install so the driver doesn't get stripped
cp ${S}/foo.ko ${D}${base_libdir}/modules/${KERNEL_VERSION}/extra/
}
PACKAGES = "${PN}"
#FILES_${PN} = "${bindir}/foo"
FILES_${PN} = "${base_libdir}/modules/${KERNEL_VERSION}/extra/foo.ko"
Makefile:
ifneq ($(KERNELRELEASE),)
obj-m := foo.o
else
AKT := $(shell pwd)
default:
make -C $(KERNEL) SUBDIRS=$(AKT) modules
endif

Hi Ben,
i am not sure, if you did understand some things wrong about writing a
kernel module. Perhaps you should take a look at this book for better
understanding http://lwn.net/Kernel/LDD3/. There is also a brief
tutorial at http://www.freesoftwaremagazine.com/articles/drivers_linux.
And you can find much more information about linux device drivers with
google.
A kernel module has to have a special structure and has to implement
methods, like init(), exit(), etc.
You can compile your kernel module as built-in module or as loadable
module. The easier way is to create loadable module, because you dont
have to change the bitbake recipes and makefiles of the kernel. During
compiling the module is linked against your kernel sources and is
therefore compatible to your kernel. Use the command insmod to install a
loadable kernel module and rmmod to remove it.
I used a bitbake recipe in combination with a makefile to compile my
kernel module. The ipkg packages can be transfered to the gumstix the
same way as you would do with a user applikation. After ipkg install
the kernel modules (.ko files) are located under
/lib/modules/2.6.2x./extra, but you can change this path of course in
your bitbake file, if you like to. Use the imod command to install your
module.
> As for kernel modules, I still have a few questions. Also, I still can
> not get your code to compile. Could you could send me your bitbake recipe?
> What is the procedure for adding a kernel module? Right now I have your
> code in com.gumstix.collection/packages/pwm/files/pwm.c I tried "bitbake
> pwm" to make sure I had the recipe correct, but I get the error "No such
> file or directory" on the included header files.
You need the information where the kernel can be found in your recipe.
> I also added
> "module_autoload_proc_gpio = 'pwm' " to gumstix-custom-basix.conf
>
This is not the way to get it work. There are a lot more files that
describe how the kernel is built. Use a loadable kernel module, it is a
lot easier.
> If I type "PWM_PWDUTY0 = 1000 & PWM_DCR_MASK", I get:
> -sh: PWM_PWDUTY0: not found
> -sh: PWM_DCR_MASK: not found
> [1] + Done(127) PWM_PWDUTY0 = 1000
>
Of course you cannot do this. "PWM_PWDUTY0 = 1000 & PWM_DCR_MASK" is c
code. You cannot use source code in combination with a shell.
Read the Linux Device Drivers book. There you will find different
methods to communicate with your device driver. You can for example use
the standard driver interface methods read(), write() or ioctl(), but
you can also use the proc or sys file system possibilities.
best reagrds
Sandra
recipe:
DESCRIPTION = "driver sample program"
PR = "r0"
RDEPENDS = "kernel (${KERNEL_VERSION})"
DEPENDS = "virtual/kernel"
SRC_URI = " \
file://foo.c \
file://Makefile \
"
S = "${WORKDIR}"
inherit module
EXTRA_OEMAKE = "-C ${KERNEL_SOURCE} SUBDIRS=${S}"
do_compile () {
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
oe_runmake
}
do_install () {
# kernel module installs with other modules
install -m 0755 -d ${D}${base_libdir}/modules/${KERNEL_VERSION}/extra/
# use cp instead of install so the driver doesn't get stripped
cp ${S}/foo.ko ${D}${base_libdir}/modules/${KERNEL_VERSION}/extra/
}
PACKAGES = "${PN}"
#FILES_${PN} = "${bindir}/foo"
FILES_${PN} = "${base_libdir}/modules/${KERNEL_VERSION}/extra/foo.ko"
Makefile:
ifneq ($(KERNELRELEASE),)
obj-m := foo.o
else
AKT := $(shell pwd)
default:
make -C $(KERNEL) SUBDIRS=$(AKT) modules
endif
------------------------------------------------------------------------------
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT
is a gathering of tech-side developers & brand creativity professionals.
Meet
the minds behind Google Creative Lab, Visual Complexity, Processing, &
iPhoneDevCamp as they present alongside digital heavyweights like Barbarian
Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com
_______________________________________________
gumstix-users mailing list
gumstix-users@...
https://lists.sourceforge.net/lists/listinfo/gumstix-users