From 2b9f76dd887430623d6510d99fe8d72965c3ffda Mon Sep 17 00:00:00 2001 From: Richard Hirst Date: Thu, 30 Aug 2012 21:58:53 +0100 Subject: [PATCH] Updates to allow tweaking timing via module parameters --- ServoBlaster/Makefile | 8 +++++--- ServoBlaster/README.txt | 36 +++++++++++++++++++++++++++++++++++ ServoBlaster/servoblaster.c | 22 ++++++++++++++------- ServoBlaster/servoblaster.ko | Bin 8909 -> 9167 bytes 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/ServoBlaster/Makefile b/ServoBlaster/Makefile index 623dea7..54f8d54 100644 --- a/ServoBlaster/Makefile +++ b/ServoBlaster/Makefile @@ -1,9 +1,11 @@ -KERNEL_TREE := /home/richard/Pi/git/linux +KERNEL_TREE := /home/richard/github/linux -all: servoblaster.ko servodemo +all: servoblaster.ko servoblaster.ko: servoblaster.c servoblaster.h - make -C ${KERNEL_TREE} ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabi- M=$(PWD) modules + @[ -d ${KERNEL_TREE} ] || { echo "Edit Makefile to set KERNEL_TREE to point at your kernel"; exit 1; } + @[ -e ${KERNEL_TREE}/Module.symvers ] || { echo "KERNEL_TREE/Module.symvers does not exist, you need to configure and compile your kernel"; exit 1; } + make -C ${KERNEL_TREE} ARCH=arm M=$(PWD) modules servodemo: servodemo.c servoblaster.h gcc -Wall -g -O2 -o servodemo servodemo.c -Wl,--export-dynamic `pkg-config --cflags gtk+-3.0 gmodule-export-2.0` `pkg-config --libs gtk+-3.0 gmodule-export-2.0` diff --git a/ServoBlaster/README.txt b/ServoBlaster/README.txt index aaa5080..a7e0319 100644 --- a/ServoBlaster/README.txt +++ b/ServoBlaster/README.txt @@ -77,6 +77,42 @@ take the 5 volts for it from the header pins on the Pi, but I find that doing anything non-trivial with four servos connected pulls the 5 volts down far enough to crash the Pi! +If you wish to compile the module yourself, the approach I took was to run +rpi-update to get the latest kernel from github, then follow the instructions +on the wiki (http://elinux.org/RPi_Kernel_Compilation) to compile the kernel, +then edit the servoblaster Makefile to point at your kernel tree, then build +servoblaster. + +NOTE: There is some doubt over how to configure the PWM clock at present. For +me the clock is 600KHz, which leads to a tick lenght of 10us. However at least +one person has reported that the pulses are out by about a factor of about 8, +and so are repeated every 2.5ms rather than every 20ms. To work round this I +have added two module parameters: + +tick_scale defaults to 6, which should be a divisor of 600KHz, which should +give a tick of 10us. You set the pulse width in ticks (echo 2=27 > +/dev/panalyzer to set 27 ticks). + +cycle_ticks is the cycle time in ticks, and defaults to 2000 to give 20ms if +one tick is 10us. cycle_ticks should be a multiple of 8. The max pulse width +you can specify by writing to /dev/servoblaster is (cycle_ticks/8 - 1), so for +the default parameters it is 249, or 2.49ms. + +For example: + +sudo insmod ./servoblaster.ko tick_scale=48 + +should slow it down by a factor of 8 (6*8=48). + +If you can't get quite what you want with tick_scale, you can also tweak +cycle_ticks. + +Eventually I might get round to letting you specify how many servo control +outputs you want, and which outputs to use, via module parameters. + +As of August 30th 2012 the servoblaster.ko module is built against a 2.6.27+ +kernel source from github. + Richard Hirst August 2012 diff --git a/ServoBlaster/servoblaster.c b/ServoBlaster/servoblaster.c index a6b1c80..4d59df5 100644 --- a/ServoBlaster/servoblaster.c +++ b/ServoBlaster/servoblaster.c @@ -50,7 +50,7 @@ #include #include #include -#include "servoblaster.h" +//#include "servoblaster.h" #define GPIO_LEN 0xb4 #define DMA_LEN 0x24 @@ -139,6 +139,8 @@ static volatile uint32_t *pwm_reg; static dev_t devno; static struct cdev my_cdev; static int my_major; +static int cycle_ticks = 2000; +static int tick_scale = 6; // Wait until we're not processing the given servo (actually wait until // we are not processing the low period of the previous servo, or the @@ -187,7 +189,7 @@ int init_module(void) } ctldatabase = __get_free_pages(GFP_KERNEL, 0); - printk(KERN_INFO "ServoBlaster: Control page is at 0x%lx\n", ctldatabase); + printk(KERN_INFO "ServoBlaster: Control page is at 0x%lx, cycle_ticks %d, tick_scale %d\n", ctldatabase, cycle_ticks, tick_scale); if (ctldatabase == 0) { printk(KERN_WARNING "ServoBlaster: alloc_pages failed\n"); cdev_del(&my_cdev); @@ -234,7 +236,7 @@ int init_module(void) ctl->cb[i].info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5); ctl->cb[i].src = (uint32_t)(&ctl->pwmdata) & 0x7fffffff; ctl->cb[i].dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | 0x7e000000; - ctl->cb[i].length = sizeof(uint32_t) * 100; // default 1000us high + ctl->cb[i].length = sizeof(uint32_t) * 1; // default 1 tick high ctl->cb[i].stride = 0; ctl->cb[i].next = (uint32_t)(ctl->cb + i + 1) & 0x7fffffff; // Set gpio lo @@ -250,7 +252,7 @@ int init_module(void) ctl->cb[i].info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(5); ctl->cb[i].src = (uint32_t)(&ctl->pwmdata) & 0x7fffffff; ctl->cb[i].dst = ((PWM_BASE + PWM_FIFO*4) & 0x00ffffff) | 0x7e000000; - ctl->cb[i].length = sizeof(uint32_t) * 150; // default 1500us, to give 2.5ms per servo + ctl->cb[i].length = sizeof(uint32_t) * (cycle_ticks / 8 - 1); ctl->cb[i].stride = 0; ctl->cb[i].next = (uint32_t)(ctl->cb + i + 1) & 0x7fffffff; } @@ -262,7 +264,7 @@ int init_module(void) udelay(10); clk_reg[PWMCLK_DIV] = 0x5A000000 | (32<<12); // set pwm div to 32 (19.2MHz/32 = 600KHz) clk_reg[PWMCLK_CNTL] = 0x5A000011; // Source=osc and enable - pwm_reg[PWM_RNG1] = 6; // 600KHz/6 = 10us per FIFO write + pwm_reg[PWM_RNG1] = tick_scale; // 600KHz/6 = 10us per FIFO write udelay(10); ctl->pwmdata = 1; // Give a pulse of one clock width for each fifo write pwm_reg[PWM_DMAC] = PWMDMAC_ENAB | PWMDMAC_THRSHLD; @@ -346,7 +348,7 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * printk(KERN_WARNING "ServoBlaster: Bad servo number %d\n", servo); return -EINVAL; } - if (cnt < 0 || cnt > 249) { + if (cnt < 0 || cnt > cycle_ticks / 8 - 1) { printk(KERN_WARNING "ServoBlaster: Bad value %d\n", cnt); return -EINVAL; } @@ -357,7 +359,7 @@ static ssize_t dev_write(struct file *filp,const char *buf,size_t count,loff_t * } else { ctl->cb[servo*4+0].dst = ((GPIO_BASE + GPSET0*4) & 0x00ffffff) | 0x7e000000; ctl->cb[servo*4+1].length = cnt * sizeof(uint32_t); - ctl->cb[servo*4+3].length = (250 - cnt) * sizeof(uint32_t); + ctl->cb[servo*4+3].length = (cycle_ticks / 8 - cnt) * sizeof(uint32_t); } local_irq_enable(); @@ -378,3 +380,9 @@ MODULE_DESCRIPTION("ServoBlaster, Multiple Servo Driver for the RaspberryPi"); MODULE_AUTHOR("Richard Hirst "); MODULE_LICENSE("GPL v2"); +module_param(cycle_ticks, int, 0); +MODULE_PARM_DESC(cycle_ticks, "number of ticks per cycle, max pulse is cycle_ticks/8"); + +module_param(tick_scale, int, 0); +MODULE_PARM_DESC(tick_scale, "scale the tick length, 6 should be 10us"); + diff --git a/ServoBlaster/servoblaster.ko b/ServoBlaster/servoblaster.ko index afd9fcba6b48ffbb5960dfb5697fd50a15cf59ca..4e8cd673d8d014681ba7bec079d3bc750e2a76e9 100644 GIT binary patch literal 9167 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