Re: [Xenomai] rtdm and rasberry-pi GPIO
On Thursday 18 April 2013, Gilles Chanteperdrix wrote: On 04/18/2013 06:38 PM, Ross Williamson wrote: Is this a bad idea from a RTlinux point of view or a style point of view? It is a bad idea from a very general point of view. gpiolib does two things: - it ensures that no two drivers try and request the same gpio - if toggling a gpio state implies a read-modify-write operation, it protects it with a spinlock, so that no two drivers can interrupt each other and cause issues in the operation. - Code portability. As the underlying hardware evolves or you switch to a different board, your code requires little, if any modification. By accessing the registers directly, you do not get these protections. ___ Xenomai mailing list Xenomai@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai
Re: [Xenomai] rtdm and rasberry-pi GPIO
On 04/19/2013 11:44 AM, Paul wrote: On Thursday 18 April 2013, Gilles Chanteperdrix wrote: On 04/18/2013 06:38 PM, Ross Williamson wrote: Is this a bad idea from a RTlinux point of view or a style point of view? It is a bad idea from a very general point of view. gpiolib does two things: - it ensures that no two drivers try and request the same gpio - if toggling a gpio state implies a read-modify-write operation, it protects it with a spinlock, so that no two drivers can interrupt each other and cause issues in the operation. - Code portability. As the underlying hardware evolves or you switch to a different board, your code requires little, if any modification. Yes, and that too. And that my even be the most important reason if the code being developed has to be maintained. -- Gilles. ___ Xenomai mailing list Xenomai@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai
Re: [Xenomai] rtdm and rasberry-pi GPIO
On 04/18/2013 01:12 AM, Ross Williamson wrote: So I managed to get it working in kernel space - I'm not entirely sure what I did to fix it - I did a full read/modify/write on the GPIO registers That is not a good idea either. You should use the gpiolib interface. -- Gilles. ___ Xenomai mailing list Xenomai@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai
Re: [Xenomai] rtdm and rasberry-pi GPIO
Ross, any reason not to use just userland memory mapped port I/O like with this library: http://www.airspayce.com/mikem/bcm2835 ? that worked fine for me with a userland RT thread, no drivers needed - Michael Am 17.04.2013 um 22:12 schrieb Ross Williamson rwilliam...@astro.caltech.edu: I'm trying to get a simple rtdm module to toggle the GPIO pins on a raspberry pi on and off. I've currently reverted back to writing a none-realtime module but with the Xenemoai kernel booted. The problem is that I have kernel hangs intermittently It usually does but sometimes is fine and only on write operation not read (and the read value seems ok). I'm pretty new to this so suspect it's something dumb. Code is below: #include linux/module.h #include linux/ioport.h #include asm/io.h MODULE_LICENSE(GPL); #define BCM2708_PERI_BASE_VIRT 0x2000 #define GPIO_BASE_VIRT (BCM2708_PERI_BASE_VIRT + 0x20) /* GPIO controller */ //Offsets of registers #define GPFSEL0 (0x00) /*GPIO Function Select 0*/ #define GPFSEL1 (0x04) /*GPIO Function Select 1*/ #define GPFSEL2 (0x08) /*GPIO Function Select 2*/ #define GPFSEL3 (0x0C) /*GPIO Function Select 3*/ #define GPFSEL4 (0x10) /*GPIO Function Select 4*/ #define GPFSEL5 (0x14) /*GPIO Function Select 5*/ #define GPSET0 (0x1C) /*GPIO pin Output Set 0*/ #define GPSET1 (0x20) /*GPIO pin Output Set 1*/ #define GPCLR0 (0x28) /*GPIO pin Output Clear 0*/ #define GPCLR1 (0x2C) /*GPIO pin Output Clear 1*/ /*There are any more but these should be enough*/ #define HEARTBEAT_PERIOD 100 /* 100 ms */ static __iomem *gpio = NULL; int __init init_heartbeat(void) { unsigned int data; struct resource *mem = NULL; int err = 0; mem = request_mem_region(GPIO_BASE_VIRT,4096,gpio); if (mem == NULL) { printk(Could not request mem region\n); err = -ENOMEM; goto err; } else { printk(Have access to mem region\n); } gpio = ioremap_nocache(GPIO_BASE_VIRT, 4096); if (gpio == NULL) { printk(Could not request gpio region\n); err = -ENOMEM; goto err; } else { printk(Have access to gpio region\n); } //Setup GPIO 7 as output //Need to set bit 21 to 1 on GPFSEL0 //Need write - the set for some reason and this is //obvously screwing up the other settings // iowrite32((u32)0, gpio+GPFSEL0); //Hangs most of the time but not all data = ioread32(gpio+GPFSEL0); //iowrite32(0x20,gpio+GPFSEL0); printk(finished with GPIO setup\n); //And set high as a test - Just bit 7 on GPSET0 //iowrite32(data,gpio+GPSET0); data = ioread32(gpio + GPFSEL0); printk(Should now be high %x\n, data); return 0; err: return 1; // return rtdm_task_init(heartbeat_task, heartbeat, heartbeat, NULL, // 99, HEARTBEAT_PERIOD); } void __exit cleanup_heartbeat(void) { // end = 1; // rtdm_task_join_nrt(heartbeat_task, 100); iounmap(gpio); printk(Unliading modklskdksdf\n); release_mem_region(GPIO_BASE_VIRT, 4096); } module_init(init_heartbeat); module_exit(cleanup_heartbeat); -- Ross Williamson Research Scientist - Sub-mm Group California Institute of Technology 626-395-2647 (office) 312-504-3051 (Cell) ___ Xenomai mailing list Xenomai@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai ___ Xenomai mailing list Xenomai@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai
Re: [Xenomai] rtdm and rasberry-pi GPIO
Hi Michael, I did manage to get the userland working great but I was hoping to get a bit better latency hence the kernel module. I'll probably be ok with the userland but it would be nice to get the kernel version working... Cheers, Ross On Wed, Apr 17, 2013 at 1:59 PM, Michael Haberler mai...@mah.priv.atwrote: Ross, any reason not to use just userland memory mapped port I/O like with this library: http://www.airspayce.com/mikem/bcm2835 ? that worked fine for me with a userland RT thread, no drivers needed - Michael Am 17.04.2013 um 22:12 schrieb Ross Williamson rwilliam...@astro.caltech.edu: I'm trying to get a simple rtdm module to toggle the GPIO pins on a raspberry pi on and off. I've currently reverted back to writing a none-realtime module but with the Xenemoai kernel booted. The problem is that I have kernel hangs intermittently It usually does but sometimes is fine and only on write operation not read (and the read value seems ok). I'm pretty new to this so suspect it's something dumb. Code is below: #include linux/module.h #include linux/ioport.h #include asm/io.h MODULE_LICENSE(GPL); #define BCM2708_PERI_BASE_VIRT 0x2000 #define GPIO_BASE_VIRT (BCM2708_PERI_BASE_VIRT + 0x20) /* GPIO controller */ //Offsets of registers #define GPFSEL0 (0x00) /*GPIO Function Select 0*/ #define GPFSEL1 (0x04) /*GPIO Function Select 1*/ #define GPFSEL2 (0x08) /*GPIO Function Select 2*/ #define GPFSEL3 (0x0C) /*GPIO Function Select 3*/ #define GPFSEL4 (0x10) /*GPIO Function Select 4*/ #define GPFSEL5 (0x14) /*GPIO Function Select 5*/ #define GPSET0 (0x1C) /*GPIO pin Output Set 0*/ #define GPSET1 (0x20) /*GPIO pin Output Set 1*/ #define GPCLR0 (0x28) /*GPIO pin Output Clear 0*/ #define GPCLR1 (0x2C) /*GPIO pin Output Clear 1*/ /*There are any more but these should be enough*/ #define HEARTBEAT_PERIOD 100 /* 100 ms */ static __iomem *gpio = NULL; int __init init_heartbeat(void) { unsigned int data; struct resource *mem = NULL; int err = 0; mem = request_mem_region(GPIO_BASE_VIRT,4096,gpio); if (mem == NULL) { printk(Could not request mem region\n); err = -ENOMEM; goto err; } else { printk(Have access to mem region\n); } gpio = ioremap_nocache(GPIO_BASE_VIRT, 4096); if (gpio == NULL) { printk(Could not request gpio region\n); err = -ENOMEM; goto err; } else { printk(Have access to gpio region\n); } //Setup GPIO 7 as output //Need to set bit 21 to 1 on GPFSEL0 //Need write - the set for some reason and this is //obvously screwing up the other settings // iowrite32((u32)0, gpio+GPFSEL0); //Hangs most of the time but not all data = ioread32(gpio+GPFSEL0); //iowrite32(0x20,gpio+GPFSEL0); printk(finished with GPIO setup\n); //And set high as a test - Just bit 7 on GPSET0 //iowrite32(data,gpio+GPSET0); data = ioread32(gpio + GPFSEL0); printk(Should now be high %x\n, data); return 0; err: return 1; // return rtdm_task_init(heartbeat_task, heartbeat, heartbeat, NULL, // 99, HEARTBEAT_PERIOD); } void __exit cleanup_heartbeat(void) { // end = 1; // rtdm_task_join_nrt(heartbeat_task, 100); iounmap(gpio); printk(Unliading modklskdksdf\n); release_mem_region(GPIO_BASE_VIRT, 4096); } module_init(init_heartbeat); module_exit(cleanup_heartbeat); -- Ross Williamson Research Scientist - Sub-mm Group California Institute of Technology 626-395-2647 (office) 312-504-3051 (Cell) ___ Xenomai mailing list Xenomai@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai -- Ross Williamson Research Scientist - Sub-mm Group California Institute of Technology 626-395-2647 (office) 312-504-3051 (Cell) ___ Xenomai mailing list Xenomai@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai
Re: [Xenomai] rtdm and rasberry-pi GPIO
On 04/17/2013 10:59 PM, Michael Haberler wrote: Ross, any reason not to use just userland memory mapped port I/O like with this library: http://www.airspayce.com/mikem/bcm2835 ? that worked fine for me with a userland RT thread, no drivers needed It is a bad idea to access GPIO registers in user-space via memory mapped I/O: you will not get the mutual exclusion the kernel driver gives you. -- Gilles. ___ Xenomai mailing list Xenomai@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai
Re: [Xenomai] rtdm and rasberry-pi GPIO
So I managed to get it working in kernel space - I'm not entirely sure what I did to fix it - I did a full read/modify/write on the GPIO registers and changed the gpio pointer to u8 but that's about it. Works ok at outputting a 10khz square wave with about a few us latency but doesn't look that much better than the user-space however I haven't done any load tests yet so I'm guessing that doesn't say much. Anyhow code is below - feel free to rip it apart or tell me better ways of doing things. #include linux/module.h #include linux/ioport.h #include asm/io.h #include rtdm/rtdm_driver.h MODULE_LICENSE(GPL); #define BCM2708_PERI_BASE_VIRT 0x2000 #define GPIO_BASE_VIRT (BCM2708_PERI_BASE_VIRT + 0x20) /* GPIO controller */ //Offsets of registers #define GPFSEL0 (0x00) /*GPIO Function Select 0*/ #define GPFSEL1 (0x04) /*GPIO Function Select 1*/ #define GPFSEL2 (0x08) /*GPIO Function Select 2*/ #define GPFSEL3 (0x0C) /*GPIO Function Select 3*/ #define GPFSEL4 (0x10) /*GPIO Function Select 4*/ #define GPFSEL5 (0x14) /*GPIO Function Select 5*/ #define GPSET0 (0x1C) /*GPIO pin Output Set 0*/ #define GPSET1 (0x20) /*GPIO pin Output Set 1*/ #define GPCLR0 (0x28) /*GPIO pin Output Clear 0*/ #define GPCLR1 (0x2C) /*GPIO pin Output Clear 1*/ /*There are any more but these should be enough*/ #define HEARTBEAT_PERIOD 5 /* 10khz */ static u8 *gpio = NULL; static rtdm_task_t heartbeat_task; static int end = 0; /* NOTE this is all a hack to work on GPIO7 */ void heartbeat(void *cookie) { int state = 0; while (!end) { rtdm_task_wait_period(); if (state) iowrite32((17),(gpio+GPSET0)); else iowrite32((17),(gpio+GPCLR0)); state ^= 1; } } int __init init_heartbeat(void) { unsigned int data; struct resource *mem = NULL; int err = 0; mem = request_mem_region(GPIO_BASE_VIRT,0xfff,gpio); if (mem == NULL) { printk(Could not request mem region\n); err = -ENOMEM; goto err; } else { printk(Have access to mem region\n); } gpio = ioremap_nocache(GPIO_BASE_VIRT, 0xfff); if (gpio == NULL) { printk(Could not request gpio region\n); err = -ENOMEM; goto err; } else { printk(Have access to gpio region\n); } data = ioread32(gpio+GPFSEL0); data = ~(721); iowrite32(data,(gpio+GPFSEL0)); data = ioread32(gpio+GPFSEL0); data |= (121); iowrite32(data,(gpio+GPFSEL0)); data = ioread32(gpio + GPFSEL0); printk(Should now be high %x\n, data); //return 0; return rtdm_task_init(heartbeat_task, heartbeat, heartbeat, NULL, 99, HEARTBEAT_PERIOD); err: return err; } void __exit cleanup_heartbeat(void) { end = 1; rtdm_task_join_nrt(heartbeat_task, 100); iounmap(gpio); printk(Unliading modklskdksdf\n); release_mem_region(GPIO_BASE_VIRT, 0xfff); } module_init(init_heartbeat); module_exit(cleanup_heartbeat); On Wed, Apr 17, 2013 at 2:33 PM, Gilles Chanteperdrix gilles.chanteperd...@xenomai.org wrote: On 04/17/2013 10:59 PM, Michael Haberler wrote: Ross, any reason not to use just userland memory mapped port I/O like with this library: http://www.airspayce.com/mikem/bcm2835 ? that worked fine for me with a userland RT thread, no drivers needed It is a bad idea to access GPIO registers in user-space via memory mapped I/O: you will not get the mutual exclusion the kernel driver gives you. -- Gilles. -- Ross Williamson Research Scientist - Sub-mm Group California Institute of Technology 626-395-2647 (office) 312-504-3051 (Cell) ___ Xenomai mailing list Xenomai@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai
Re: [Xenomai] rtdm and rasberry-pi GPIO
Hi Ross, I'm guessing that doesn't say much. Anyhow code is below - feel free to rip it apart or tell me better ways of doing things. You might be interested to take a look at the following article: http://veter-project.blogspot.com/2012/04/precise-pwms-with-gpio-using-xenomai.html Corresponding sources are available here: https://github.com/andreynech/rtdm-pwm As suggested in this list, we were able to get better results with timer-based approach instead of using tasks. Regards, Andrey. web: http://veterobot.org blog: http://veter-project.blogspot.com ___ Xenomai mailing list Xenomai@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai