[LinuxPPS] Some help with linuxpps

Jeff Angielski jeff at theptrgroup.com
Mon Mar 29 22:35:59 CEST 2010


Marc Leclerc wrote:

> 
> I plan to use a gpio to connect the PPS pulse to my device PORT G pin 0
> which can be configured as interrupt if that is required?. It also can
> be map to /dev/gpio/83, also if required?. Here I cannot solve how to
> have the device present (do I need an entry in /etc/makedevs.d?) and how
> to configure the pin (interrupt or input) and the driver to use that
> gpio. Is there a need for me to do some coding to get the precess going
> or does the driver take care of this?

I am struggling trying to make all of this work but I can at least 
answer this question.

As a quick hack, just scan /proc/devices and look for the pps device. 
This will give you your character device major number.  Just manually 
create the nodes using mknod.  It's a hack but it will get you started. 
  Later you can get udev to add it automagically.

You will need to configure it is as interrupt.  Nobody is "polling" the 
GPIO line.

Here is a simple IRQ client that I am currently playing with that you 
may find useful as a starting point.  The driver works but still can use 
some cleanup.



*
  * pps-hwirq.c
  *
  *
  * Based on the ktimer from:
  * Copyright (C) 2005-2006   Rodolfo Giometti <giometti at linux.it>
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
  *   the Free Software Foundation; either version 2 of the License, or
  *   (at your option) any later version.
  *
  *   This program is distributed in the hope that it will be useful,
  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *   GNU General Public License for more details.
  *
  *   You should have received a copy of the GNU General Public License
  *   along with this program; if not, write to the Free Software
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/pps_kernel.h>
#include <linux/irq.h>
#include <linux/interrupt.h>

/*
  * Global variables
  */

/* TODO: Make a module parameter and leave this as default */
#define PPS_HWIRQ_DEFAULT	6
static unsigned int pps_hwirq = PPS_HWIRQ_DEFAULT;

/* TODO: Make a structure to share all of this */
static unsigned int pps_virq;
static int source;

/*
  *
  */
static irqreturn_t pps_hwirq_handler(int irq, void *parm)
{
	struct timespec __ts;
	struct pps_ktime ts;

	/* First of all we get the time stamp... */
	getnstimeofday(&__ts);

	/* ... and translate it to PPS time data struct */
	ts.sec = __ts.tv_sec;
	ts.nsec = __ts.tv_nsec;

	pps_event(source, &ts, PPS_CAPTUREASSERT, NULL);

	pr_debug("PPS event at %lu\n", jiffies);

	return IRQ_HANDLED;
}

/*
  * The echo function
  */

static void pps_hwirq_echo(int source, int event, void *data)
{
	pr_info("echo %s %s for source %d\n",
		event & PPS_CAPTUREASSERT ? "assert" : "",
		event & PPS_CAPTURECLEAR ? "clear" : "",
		source);
}

/*
  * The PPS info struct
  */

/* TODO: Decipher the needed flags */
static struct pps_source_info pps_hwirq_info = {
	.name		= "pps_hwirq",
	.path		= "",
	.mode		= PPS_CAPTUREASSERT | PPS_OFFSETASSERT | \
			  PPS_ECHOASSERT | \
			  PPS_CANWAIT | PPS_TSFMT_TSPEC,
	.echo		= pps_hwirq_echo,
	.owner		= THIS_MODULE,
};

/*
  * Module staff
  */

static void __exit pps_hwirq_exit(void)
{
	free_irq(pps_virq, NULL);

	pps_unregister_source(source);

	pr_info("hwirq PPS source unregistered\n");
}

static int __init pps_hwirq_init(void)
{
	int ret;

	pps_virq = irq_create_mapping(NULL, pps_hwirq);
	if (pps_virq == NO_IRQ) {
		printk(KERN_ERR "cannot create irq mapping for hw irq: %d\n", pps_hwirq);
		return -EINVAL;
	}

	/* TOOD: Do we need to pass anything into the handler? */
	ret = request_irq( pps_virq, pps_hwirq_handler, IRQF_TRIGGER_RISING, 
"pps hwirq", NULL);
	if (ret) {
		printk(KERN_ERR "failed to register handler for virq: %d\n", pps_virq);
		return ret;
	}

	ret = pps_register_source(&pps_hwirq_info,
				PPS_CAPTUREASSERT | PPS_OFFSETASSERT);

	if (ret < 0) {
		printk(KERN_ERR "cannot register hwirq source\n");
		return ret;
	}
	source = ret;

	pr_info("hwirq PPS source registered at %d\n", source);

	return  0;
}

module_init(pps_hwirq_init);
module_exit(pps_hwirq_exit);

MODULE_AUTHOR("Jeff Angielski <jeff at theptrgroup.com>");
MODULE_DESCRIPTION("Hardware interrupt PPS source");
MODULE_LICENSE("GPL");



-- 
Jeff Angielski
The PTR Group
www.theptrgroup.com



More information about the LinuxPPS mailing list