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
[email protected]
https://lists.sourceforge.net/lists/listinfo/emc-developers