I wrote some EMC2 HAL driver to use the generic linux GPIO
API for driving the device.
The thing works like the parport HAL, but is more flexible,
as any GPIO-port or GPIO-expansion-card supported by linux
can be used for bitbanging the stepper signals and so on.

There's a "cfg" module parameter, which configures which GPIO ports
are used. The default string probably is not very useful, but you get
the idea of what it does.

Some comments?



Index: emc2/src/hal/drivers/hal_linux_gpio.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ emc2/src/hal/drivers/hal_linux_gpio.c       2008-07-05 17:49:55.000000000 
+0200
@@ -0,0 +1,341 @@
+/*
+ * Linux GPIO HAL driver
+ *
+ * Copyright 2008 Michael Buesch <[EMAIL PROTECTED]>
+ *
+ * Derived from the HAL skeleton:
+ * Copyright John Kasunich and Martin Kuhnle.
+ *
+ * Licensed under the GNU/GPL version 2.
+ */
+
+#ifndef RTAPI
+# error hal_linux_gpio needs RTAPI, check makefile and flags
+#endif
+
+#include "rtapi.h"
+#include "rtapi_app.h"
+#include "hal.h"
+
+#include <linux/gpio.h>
+
+
+#define PFX    "hal-linux-gpio: "
+
+#define MAX_NR_IN_PINS         256
+#define MAX_NR_OUT_PINS                256
+
+enum pin_type {
+       PIN_UNUSED = 0,
+       PIN_OUT,
+       PIN_IN,
+};
+
+struct gpio_pin {
+       /* The HAL state of the pin */
+       hal_bit_t *pin;
+       /* Inverted */
+       hal_bit_t *inv_pin;
+       /* The hardware state of the pin. This is only valid
+        * for OUT pins. */
+       bool hw_state;
+       /* Type of the pin */
+       enum pin_type type;
+       /* The GPIO number of the pin */
+       unsigned int gpio;
+};
+
+struct port_state {
+       struct gpio_pin out[MAX_NR_OUT_PINS];
+       struct gpio_pin in[MAX_NR_IN_PINS];
+};
+
+static struct port_state *pstate; /* The GPIO ports state */
+static int comp_id; /* component ID */
+
+/* Configuration string */
+static char *cfg = "1=out,2=out,3=out,4=out,5=in,6=in,7=in,8=in";
+RTAPI_MP_STRING(cfg, "config string");
+
+
+/* Port write callback */
+static void write_port(void *d, long period)
+{
+       struct port_state *port = d;
+       struct gpio_pin *pin;
+       unsigned int i;
+       bool state;
+
+       for (i = 0; i < MAX_NR_OUT_PINS; i++) {
+               pin = &(port->out[i]);
+
+               if (pin->type == PIN_UNUSED)
+                       break;
+               state = !!(*(pin->pin));
+               if (*(pin->inv_pin))
+                       state = !state;
+               if (state == pin->hw_state)
+                       continue; /* Nothing to do */
+
+               gpio_set_value(pin->gpio, state);
+               pin->hw_state = state;
+       }
+}
+
+/* Port read callback */
+static void read_port(void *d, long period)
+{
+       struct port_state *port = d;
+       struct gpio_pin *pin;
+       unsigned int i;
+       bool state;
+
+       for (i = 0; i < MAX_NR_IN_PINS; i++) {
+               pin = &(port->in[i]);
+
+               if (pin->type == PIN_UNUSED)
+                       break;
+               state = !!gpio_get_value(pin->gpio);
+               *(pin->pin) = state;
+               *(pin->inv_pin) = !state;
+       }
+}
+
+static void free_gpio_pins(struct port_state *port)
+{
+       struct gpio_pin *pin;
+       unsigned int i;
+
+       for (i = 0; i < MAX_NR_IN_PINS; i++) {
+               pin = &(port->in[i]);
+               if (pin->type == PIN_UNUSED)
+                       break;
+               gpio_free(pin->gpio);
+       }
+       for (i = 0; i < MAX_NR_OUT_PINS; i++) {
+               pin = &(port->out[i]);
+               if (pin->type == PIN_UNUSED)
+                       break;
+               gpio_free(pin->gpio);
+       }
+}
+
+static int export_functions(struct port_state *port)
+{
+       char name[HAL_NAME_LEN];
+       int err;
+
+       snprintf(name, HAL_NAME_LEN, "linux-gpio.%d.read", 0);
+       err = hal_export_funct(name, read_port, port, 0, 0, comp_id);
+       if (err) {
+               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                               "Failed to register READ function\n");
+               err = -ENOMEM;
+               goto out;
+       }
+
+       snprintf(name, HAL_NAME_LEN, "linux-gpio.%d.write", 0);
+       err = hal_export_funct(name, write_port, port, 0, 0, comp_id);
+       if (err) {
+               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                               "Failed to register WRITE function\n");
+               err = -ENOMEM;
+               goto out;
+       }
+
+       err = 0;
+out:
+       return err;
+}
+
+static int build_port(struct port_state *port, const char *config)
+{
+       const char *end;
+       char one_cfg[24]; /* temporary config for one pin */
+       char direction[sizeof(one_cfg)];
+       unsigned int gpio;
+       int res, err;
+       unsigned int in_idx = 0;
+       unsigned int out_idx = 0;
+       struct gpio_pin *pin;
+
+       /* First parse the pin config and register the pins. */
+       while (1) {
+               if (strlen(config) == 0)
+                       break;
+               memset(one_cfg, 0, sizeof(one_cfg));
+               end = strchr(config, ',');
+               if (!end) { /* is last param */
+                       strlcpy(one_cfg, config, sizeof(one_cfg) - 1);
+                       config = "";
+               } else {
+                       size_t nr = (size_t)(end - config);
+                       memcpy(one_cfg, config, min(nr, sizeof(one_cfg) - 1));
+                       config = end + 1; /* config = next param */
+               }
+               if (strlen(one_cfg) == 0)
+                       continue;
+
+               res = sscanf(one_cfg, "%u=%s", &gpio, direction);
+               if (res != 2) {
+                       rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                                       "Invalid pin configuration: %s\n",
+                                       one_cfg);
+                       err = -EINVAL;
+                       goto err_unroll_gpio;
+               }
+
+               if (strcmp(direction, "in") == 0) {
+                       /* New input pin */
+                       if (in_idx >= MAX_NR_IN_PINS) {
+                               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                                               "Too many IN ports configured 
(>%d)\n",
+                                               MAX_NR_IN_PINS);
+                               err = -EINVAL;
+                               goto err_unroll_gpio;
+                       }
+                       pin = &(port->in[in_idx]);
+
+                       err = gpio_request(gpio, "emc-hal");
+                       if (err) {
+                               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                                               "GPIO-%u request failed: %d\n",
+                                               gpio, err);
+                               goto err_unroll_gpio;
+                       }
+                       gpio_direction_input(gpio);
+                       pin->gpio = gpio;
+                       err = hal_pin_bit_newf(HAL_OUT, &pin->pin, comp_id,
+                                              "linux-gpio.%d.pin-%u-in", 0, 
gpio);
+                       if (err) {
+                               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                                               "Failed to allocate HAL bit\n");
+                               err = -ENOMEM;
+                               gpio_free(gpio);
+                               goto err_unroll_gpio;
+                       }
+                       err = hal_pin_bit_newf(HAL_OUT, &pin->inv_pin, comp_id,
+                                              "linux-gpio.%d.pin-%u-in-not", 
0, gpio);
+                       if (err) {
+                               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                                               "Failed to allocate HAL bit\n");
+                               err = -ENOMEM;
+                               gpio_free(gpio);
+                               goto err_unroll_gpio;
+                       }
+
+                       pin->type = PIN_IN;
+                       in_idx++;
+                       continue;
+               }
+
+               if (strcmp(direction, "out") == 0) {
+                       /* New output pin */
+                       if (out_idx >= MAX_NR_OUT_PINS) {
+                               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                                               "Too many OUT ports configured 
(>%d)\n",
+                                               MAX_NR_OUT_PINS);
+                               err = -EINVAL;
+                               goto err_unroll_gpio;
+                       }
+                       pin = &(port->out[out_idx]);
+
+                       err = gpio_request(gpio, "emc-hal");
+                       if (err) {
+                               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                                               "GPIO-%u request failed: %d\n",
+                                               gpio, err);
+                               goto err_unroll_gpio;
+                       }
+                       pin->hw_state = 0;
+                       gpio_direction_output(gpio, pin->hw_state);
+                       pin->gpio = gpio;
+                       err = hal_pin_bit_newf(HAL_IN, &pin->pin, comp_id,
+                                              "linux-gpio.%d.pin-%u-out", 0, 
gpio);
+                       if (err) {
+                               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                                               "Failed to allocate HAL bit\n");
+                               err = -ENOMEM;
+                               gpio_free(gpio);
+                               goto err_unroll_gpio;
+                       }
+                       err = hal_pin_bit_newf(HAL_IN, &pin->inv_pin, comp_id,
+                                              
"linux-gpio.%d.pin-%u-out-invert", 0, gpio);
+                       if (err) {
+                               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                                               "Failed to allocate HAL bit\n");
+                               err = -ENOMEM;
+                               gpio_free(gpio);
+                               goto err_unroll_gpio;
+                       }
+
+                       pin->type = PIN_OUT;
+                       out_idx++;
+                       continue;
+               }
+
+               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                               "Invalid pin direction: %s\n",
+                               one_cfg);
+               err = -EINVAL;
+               goto err_unroll_gpio;
+       }
+
+       /* Export the HAL functions */
+       err = export_functions(port);
+       if (err)
+               goto err_unroll_gpio;
+
+       return 0;
+
+err_unroll_gpio:
+       free_gpio_pins(port);
+
+       return err;
+}
+
+int rtapi_app_main(void)
+{
+       int err;
+
+       err = -ENODEV;
+       comp_id = hal_init("hal_linux_gpio");
+       if (comp_id < 0) {
+               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                               "hal_init failed\n");
+               goto err_out;
+       }
+
+       err = -ENOMEM;
+       pstate = hal_malloc(sizeof(*pstate));
+       if (!pstate) {
+               rtapi_print_msg(RTAPI_MSG_ERR, PFX
+                               "Failed to allocate SHM\n");
+               goto err_hal_exit;
+       }
+
+       err = build_port(pstate, cfg);
+       if (err)
+               goto err_hal_exit;
+
+       rtapi_print_msg(RTAPI_MSG_INFO, PFX
+                       "linux-GPIO HAL driver ready\n");
+       hal_ready(comp_id);
+
+       return 0;
+
+err_hal_exit:
+       hal_exit(comp_id);
+err_out:
+       return err;
+}
+
+void rtapi_app_exit(void)
+{
+       free_gpio_pins(pstate);
+       hal_exit(comp_id);
+}
+
+MODULE_AUTHOR("Michael Buesch");
+MODULE_DESCRIPTION("Linux GPIO driver for EMC HAL");
+MODULE_LICENSE("GPL");
Index: emc2/src/Makefile
===================================================================
--- emc2.orig/src/Makefile      2008-07-03 23:47:53.000000000 +0200
+++ emc2/src/Makefile   2008-07-03 23:49:20.000000000 +0200
@@ -638,6 +638,8 @@
 hal_speaker-objs := hal/drivers/hal_speaker.o $(MATHSTUB)
 obj-$(CONFIG_HAL_SKELETON) += hal_skeleton.o
 hal_skeleton-objs := hal/drivers/hal_skeleton.o $(MATHSTUB)
+obj-$(CONFIG_HAL_LINUX_GPIO) += hal_linux_gpio.o
+hal_linux_gpio-objs := hal/drivers/hal_linux_gpio.o $(MATHSTUB)
 
 obj-$(CONFIG_HOSTMOT2) += hostmot2.o hm2_7i43.o hm2_5i20.o
 hostmot2-objs :=                          \
Index: emc2/src/Makefile.inc.in
===================================================================
--- emc2.orig/src/Makefile.inc.in       2008-07-03 23:49:25.000000000 +0200
+++ emc2/src/Makefile.inc.in    2008-07-03 23:49:56.000000000 +0200
@@ -194,6 +194,7 @@
 CONFIG_HAL_PPMC=m
 CONFIG_PCI_8255=m
 CONFIG_HOSTMOT2=m
+CONFIG_HAL_LINUX_GPIO=m
 
 [EMAIL PROTECTED]@
 [EMAIL PROTECTED]@

-- 
Greetings Michael.

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
Emc-developers mailing list
Emc-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/emc-developers

Reply via email to