⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 5i2x_gpio.c

📁 CNC 的开放码,EMC2 V2.2.8版
💻 C
字号:
/*************************************************************************Copyright (C) 2007 John Kasunich <jmkasunich AT sourceforge DOT net>$RCSfile: 5i2x_gpio.c,v $$Author: jmkasunich $$Locker:  $$Revision: 1.2 $$State: Exp $$Date: 2007/07/18 02:57:39 $This is the driver the General Purpose I/O pins on the Mesa Electronics5i2x boards.  It configures the I/O as defined by data stored in theFPGA RAM, and exports the corresponding HAL pins.*************************************************************************//*************************************************************************Each physical pin has a number of options that are selected as part ofthe FPGA configuration.  Pins can be input, output, tristate, or opencollector.  Additionally, they can be active high or active low.  Whenused for inputs, data from a physical pin appears on an optional HAL pinas well as at the inputs to any FPGA modules (such as encoder counters)that are connected to the pin.  When used as an output, the pin data canbe driven from only one source, either general purpose I/O, or an FPGAmodule (such as a step generator or PWM generator).Items are exported to the HAL based on the capabilities thatthe config supplies.  <boardId> is the PCI board number andis formated as "%d". <channel> goes from "A00" (first pin onfirst connector) to "C23" (last pin on last connector).Digital In:  Pins:	bit	m5i20.<boardId>.pin-<channel>-in	bit	m5i20.<boardId>.pin-<channel>-in-not  Functions:	void    m5i20.<boardId>.digital-in-readDigital Out:  Parameters:	bit	m5i20.<boardId>.pin-<channel>-out-invert  Pins:	bit	m5i20.<boardId>.pin-<channel>-out	bit	m5i20.<boardId>.pin-<channel>-out-en  Functions:	void    m5i20.<boardId>.digital-out-write**************************************************************************This program is free software; you can redistribute it and/ormodify it under the terms of version 2 of the GNU GeneralPublic License as published by the Free Software Foundation.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111 USATHE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FORANY HARM OR LOSS RESULTING FROM ITS USE.  IT IS _EXTREMELY_ UNWISETO RELY ON SOFTWARE ALONE FOR SAFETY.  Any machinery capable ofharming persons must have provisions for completely removing powerfrom all motors, etc, before persons enter any danger area.  Allmachinery must be designed to comply with local and national safetycodes, and the authors of this software can not, and do not, takeany responsibility for such compliance.This code was written as part of the EMC HAL project.  For moreinformation, go to www.linuxcnc.org.*************************************************************************/#ifndef RTAPI#error This is a realtime component only!#endif#include <linux/pci.h>#include "rtapi.h"			// RTAPI realtime OS API.#include "rtapi_app.h"			// RTAPI realtime module decls.#include "hal.h"			// HAL public API decls.#include "hal_5i2x.h"			// Hardware dependent defines./***************************************************************************                          config ROM defines***************************************************************************/#define POLARITY_MASK		0x01#define HAL_INPUT_PIN_MASK	0x02#define MODE_MASK		0x0C#define MODE1_MASK		0x08#define MODE0_MASK		0x04#define MODE_INPUT_ONLY		(0 << 2)#define MODE_OUTPUT_ONLY	(1 << 2)#define MODE_TRI_STATE		(2 << 2)#define MODE_OPEN_COLLECTOR	(3 << 2)#define SOURCE_MASK		0x70#define SOURCE2_MASK		0x40#define SOURCE1_MASK		0x20#define SOURCE0_MASK		0x10/*************************************************************************                          typedefs and defines*************************************************************************//* register addresses (relative to base addr) */#define GPIO_IN		0#define GPIO_OUT	0#define GPIO_OUT_ENA	1#define GPIO_MODE0	2#define GPIO_MODE1	3#define GPIO_SOURCE0	4#define GPIO_SOURCE1	5#define GPIO_SOURCE2	6#define GPIO_POLARITY	7/***************************************************************************                         Data Structures***************************************************************************//* one 24-pin physical port */typedef struct gpio_t {    struct gpio_t *next;    hal_bit_t *in[PINS_PER_PORT];    hal_bit_t *in_not[PINS_PER_PORT];    hal_bit_t *out[PINS_PER_PORT];    hal_bit_t out_invert[PINS_PER_PORT];    hal_bit_t *out_ena[PINS_PER_PORT];    void __iomem *addr;} gpio_t;/*************************************************************************                                   Globals*************************************************************************/static hal_bit_t dummy_in;static hal_bit_t dummy_out = 0;static hal_bit_t dummy_oe = 1;/*************************************************************************                                 Realtime Code ************************************************************************/static void read_gpio(void *arg, long period){    gpio_t *g;    int n;    __u32 data;    g = arg;    data = ioread32(g->addr+GPIO_IN);    for ( n = 0 ; n < PINS_PER_PORT; n++ ) {	*(g->in[n]) = (data & 1);	*(g->in_not[n]) = ~(data & 1);    }}static void read_gpios(void *arg, long period){    gpio_t *s;    s = arg;    while ( s != NULL ) {	read_gpio(s, period);	s = s->next;    }}static void write_gpio(void *arg, long period){    gpio_t *g;    int n;    __u32 data, enable, mask;    g = arg;    data = 0;    enable = 0;    mask = 1;    for ( n = 0 ; n < PINS_PER_PORT; n++ ) {	if ( *(g->out_ena[n]) ) {	    enable |= mask;	}	if (( *(g->out[n]) && ~g->out_invert[n] ) ||	    ( ~*(g->out[n]) && g->out_invert[n] )) {	    data |= mask;	}	mask <<= 1;    }    iowrite32(data, g->addr+GPIO_OUT);    iowrite32(enable, g->addr+GPIO_OUT_ENA);}static void write_gpios(void *arg, long period){    gpio_t *s;    s = arg;    while ( s != NULL ) {	write_gpio(s, period);	s = s->next;    }}/******************************************************************************                                HAL export code ******************************************************************************//* the data for a "gpio" consists of a code byte, a two byte base address,   and 24 pin config bytes - formatted as follows:   XSSSMMPI   I = export input HAL pin   P = polarity   MM = mode (input, output, tristate, open-collector)   SSS = source (one of up to eight, 000 = GPIO)   X = no care   output and output-enable HAL pins are exported based on the values   of the source and mode bits.  If the source is non-zero, the pin is   not usable as a GP output, and the pins are not exported.  If it is   zero, the output pin is exported unless the mode is "input only",   and the output-enable pin is exported only if the mode is "tristate"*/int export_gpio(__u8 **ppcfg, board_data_t *board){    __u8 *data;    int retval, export_out, export_oe;    int portnum, boardnum, pin;    char portchar;    gpio_t *gpio, **p;    int code, addr;    __u8 *cfg_bytes;    char name[HAL_NAME_LEN + 2];    __u32 mode0, mode1, source0, source1, source2, polarity, mask;    /* read and validate config data */    data = *ppcfg;    code = data[0];    addr = (data[1] << 8) + data[2];    cfg_bytes = &(data[3]);    /* return ptr to next block */    *ppcfg = &(cfg_bytes[24]);    /* Allocate HAL memory */    gpio = (gpio_t *)(hal_malloc(sizeof(gpio_t)));    if ( gpio == NULL ) {	rtapi_print_msg(RTAPI_MSG_ERR, "5i2x: ERROR: hal_malloc() failed\n");	return -1;    }    /* find end of linked list */    boardnum = board->num;    portnum = 0;    p = &(board->gpio);    while ( *p != NULL ) {	p = &((*p)->next);	portnum++;    }    portchar = 'A' + portnum;    /* add to end of list */    *p = gpio;    gpio->next = NULL;    /* save base address */    gpio->addr = board->base + addr;    mode0 = 0;    mode1 = 0;    source0 = 0;    source1 = 0;    source2 = 0;    polarity = 0;    mask = 1;    for ( pin = 0 ; pin < PINS_PER_PORT ; pin++ ) {	if ( cfg_bytes[pin] & HAL_INPUT_PIN_MASK ) {	    /* export output HAL pins for the input bit */	    retval = hal_pin_bit_newf(HAL_OUT, &(gpio->in[pin]),		comp_id, "5i20.%d.pin-%c%02d-in", boardnum, portchar, pin);	    if (retval != 0) return retval;	    retval = hal_pin_bit_newf(HAL_OUT, &(gpio->in_not[pin]),		comp_id, "5i20.%d.pin-%c%02d-in-not", boardnum, portchar, pin);	    if (retval != 0) return retval;	    /* initial values for pins */	    *(gpio->in[pin]) = 0;	    *(gpio->in_not[pin]) = 1;	} else {	    /* input pins not used, point them at a dummy */	    gpio->in[pin] = &dummy_in;	    gpio->in_not[pin] = &dummy_in;	}	export_out = 0;	export_oe = 0;	if ( (cfg_bytes[pin] & SOURCE_MASK) == 0 ) {	    switch ( cfg_bytes[pin] & MODE_MASK ) {	    case MODE_TRI_STATE:		export_oe = 1;	    case MODE_OUTPUT_ONLY:	    case MODE_OPEN_COLLECTOR:		export_out = 1;	    case MODE_INPUT_ONLY:	    default:		break;	    }	}	if ( export_out ) {	    /* export input HAL pin for the output bit */	    retval = hal_pin_bit_newf(HAL_IN, &(gpio->out[pin]),		comp_id, "5i20.%d.pin-%c%02d-out", boardnum, portchar, pin);	    if (retval != 0) return retval;	    /* export HAL param for inversion */	    retval = hal_param_bit_newf(HAL_RW, &(gpio->out_invert[pin]),		comp_id, "5i20.%d.pin-%c%02d-invert", boardnum, portchar, pin);	    if (retval != 0) return retval;	    /* set initial value for pin and param */	    *(gpio->out[pin]) = 0;	    gpio->out_invert[pin] = 0;	} else {	    /* output pin not used, point at a dummy */	    gpio->out[pin] = &dummy_out;	}	if ( export_oe ) {	    /* export input HAL pin for the output enable bit */	    retval = hal_pin_bit_newf(HAL_IN, &(gpio->out_ena[pin]),		comp_id, "5i20.%d.pin-%c%02d-out-en", boardnum, portchar, pin);	    if (retval != 0) return retval;	    /* set initial value for pin */	    *(gpio->out_ena[pin]) = 0;	} else {	    /* output enable pin not used, point at a dummy */	    gpio->out_ena[pin] = &dummy_oe;	}	/* set appropriate bits in config register words */	if ( cfg_bytes[pin] & SOURCE2_MASK ) source2 |= mask;	if ( cfg_bytes[pin] & SOURCE1_MASK ) source1 |= mask;	if ( cfg_bytes[pin] & SOURCE0_MASK ) source0 |= mask;	if ( cfg_bytes[pin] & MODE1_MASK ) mode1 |= mask;	if ( cfg_bytes[pin] & MODE0_MASK ) mode0 |= mask;	if ( cfg_bytes[pin] & POLARITY_MASK ) polarity |= mask;	mask <<= 1;    }    /* write config to registers */    iowrite32(source2, gpio->addr+GPIO_SOURCE1);    iowrite32(source1, gpio->addr+GPIO_SOURCE1);    iowrite32(source0, gpio->addr+GPIO_SOURCE0);    iowrite32(mode1, gpio->addr+GPIO_MODE1);    iowrite32(mode0, gpio->addr+GPIO_MODE0);    iowrite32(polarity, gpio->addr+GPIO_POLARITY);    /* export functions - one funct serves all ports */    if ( portnum > 0 ) {	/* already exported */	return 0;    }    rtapi_snprintf(name, HAL_NAME_LEN, "5i20.%d.gpio.read", boardnum);    retval = hal_export_funct(name, read_gpios, gpio, 0, 0, comp_id);    if (retval != 0) {	rtapi_print_msg(RTAPI_MSG_ERR,	    "5i20: ERROR: board %d GPIO read funct export failed\n",	    boardnum);	return -1;    }    rtapi_snprintf(name, HAL_NAME_LEN, "5i20.%d.gpio.write", boardnum);    retval = hal_export_funct(name, write_gpios, gpio, 0, 0, comp_id);    if (retval != 0) {	rtapi_print_msg(RTAPI_MSG_ERR,	    "5i20: ERROR: board %d GPIO write funct export failed\n",	    boardnum);	return -1;    }    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -