hal_bb_gpio: new hardware driver
Based on work in MachineKit by:
Alexander Rössler <mail.aroessler@gmail.com>
Charles Steinkuehler <charles@steinkuehler.net>
Ian McMahon <imcmahon@prototechnical.com>
Michael Haberler <git@mah.priv.at>
Signed-off-by: Jeff Epler <jepler@unpythonic.net>
This commit is contained in:
parent
5f0865a7ea
commit
1070a8ae44
3 changed files with 642 additions and 1 deletions
|
|
@ -831,7 +831,7 @@ hal_ppmc-objs := hal/drivers/hal_ppmc.o $(MATHSTUB)
|
||||||
|
|
||||||
obj-$(CONFIG_HOSTMOT2) += hostmot2.o hm2_test.o hm2_pci.o hm2_7i43.o hm2_7i90.o setsserial.o
|
obj-$(CONFIG_HOSTMOT2) += hostmot2.o hm2_test.o hm2_pci.o hm2_7i43.o hm2_7i90.o setsserial.o
|
||||||
ifeq ($(BUILD_SYS),uspace)
|
ifeq ($(BUILD_SYS),uspace)
|
||||||
obj-$(CONFIG_HOSTMOT2) += hm2_eth.o hm2_spi.o hm2_rpspi.o
|
obj-$(CONFIG_HOSTMOT2) += hm2_eth.o hm2_spi.o hm2_rpspi.o hal_bb_gpio.o
|
||||||
endif
|
endif
|
||||||
hostmot2-objs := \
|
hostmot2-objs := \
|
||||||
hal/drivers/mesa-hostmot2/hostmot2.o \
|
hal/drivers/mesa-hostmot2/hostmot2.o \
|
||||||
|
|
@ -875,6 +875,9 @@ hm2_spi-objs := \
|
||||||
hm2_rpspi-objs := \
|
hm2_rpspi-objs := \
|
||||||
hal/drivers/mesa-hostmot2/hm2_rpspi.o \
|
hal/drivers/mesa-hostmot2/hm2_rpspi.o \
|
||||||
$(MATHSTUB)
|
$(MATHSTUB)
|
||||||
|
hal_bb_gpio-objs := \
|
||||||
|
hal/drivers/hal_bb_gpio.o \
|
||||||
|
$(MATHSTUB)
|
||||||
hm2_test-objs := \
|
hm2_test-objs := \
|
||||||
hal/drivers/mesa-hostmot2/hm2_test.o \
|
hal/drivers/mesa-hostmot2/hm2_test.o \
|
||||||
hal/drivers/mesa-hostmot2/bitfile.o \
|
hal/drivers/mesa-hostmot2/bitfile.o \
|
||||||
|
|
@ -903,6 +906,7 @@ scope_rt-objs := hal/utils/scope_rt.o $(MATHSTUB)
|
||||||
obj-m += hal_lib.o
|
obj-m += hal_lib.o
|
||||||
hal_lib-objs := hal/hal_lib.o $(MATHSTUB)
|
hal_lib-objs := hal/hal_lib.o $(MATHSTUB)
|
||||||
|
|
||||||
|
ifeq ($(HALONLY),false)
|
||||||
obj-m += trivkins.o
|
obj-m += trivkins.o
|
||||||
trivkins-objs := emc/kinematics/trivkins.o
|
trivkins-objs := emc/kinematics/trivkins.o
|
||||||
|
|
||||||
|
|
@ -975,6 +979,8 @@ motmod-objs += emc/nml_intf/emcpose.o
|
||||||
motmod-objs += libnml/posemath/_posemath.o
|
motmod-objs += libnml/posemath/_posemath.o
|
||||||
motmod-objs += libnml/posemath/sincos.o $(MATHSTUB)
|
motmod-objs += libnml/posemath/sincos.o $(MATHSTUB)
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
TORTOBJS = $(foreach file,$($(patsubst %.o,%,$(1))-objs), objects/rt$(file))
|
TORTOBJS = $(foreach file,$($(patsubst %.o,%,$(1))-objs), objects/rt$(file))
|
||||||
ifeq ($(BUILD_SYS),uspace)
|
ifeq ($(BUILD_SYS),uspace)
|
||||||
EXTRA_CFLAGS += -fPIC -Os
|
EXTRA_CFLAGS += -fPIC -Os
|
||||||
|
|
@ -1086,6 +1092,7 @@ endif
|
||||||
../rtlib/hm2_eth$(MODULE_EXT): $(addprefix objects/rt,$(hm2_eth-objs))
|
../rtlib/hm2_eth$(MODULE_EXT): $(addprefix objects/rt,$(hm2_eth-objs))
|
||||||
../rtlib/hm2_spi$(MODULE_EXT): $(addprefix objects/rt,$(hm2_spi-objs))
|
../rtlib/hm2_spi$(MODULE_EXT): $(addprefix objects/rt,$(hm2_spi-objs))
|
||||||
../rtlib/hm2_rpspi$(MODULE_EXT): $(addprefix objects/rt,$(hm2_rpspi-objs))
|
../rtlib/hm2_rpspi$(MODULE_EXT): $(addprefix objects/rt,$(hm2_rpspi-objs))
|
||||||
|
../rtlib/hal_bb_gpio$(MODULE_EXT): $(addprefix objects/rt,$(hal_bb_gpio-objs))
|
||||||
|
|
||||||
ifeq ($(TRIVIAL_BUILD),no)
|
ifeq ($(TRIVIAL_BUILD),no)
|
||||||
READ_RTDEPS = $(wildcard $(RTDEPS))
|
READ_RTDEPS = $(wildcard $(RTDEPS))
|
||||||
|
|
|
||||||
177
src/hal/drivers/beaglebone_gpio.h
Normal file
177
src/hal/drivers/beaglebone_gpio.h
Normal file
|
|
@ -0,0 +1,177 @@
|
||||||
|
#ifndef _BEAGLEBONE_GPIO_H_
|
||||||
|
#define _BEAGLEBONE_GPIO_H_
|
||||||
|
|
||||||
|
#define CONTROL_MODULE_START_ADDR 0x44E10000
|
||||||
|
#define CONTROL_MODULE_END_ADDR 0x44E11FFF
|
||||||
|
#define CONTROL_MODULE_SIZE (CONTROL_MODULE_END_ADDR - CONTROL_MODULE_START_ADDR)
|
||||||
|
|
||||||
|
#define PIN_RX_DISABLED 0
|
||||||
|
#define PIN_RX_ENABLED (1<<5)
|
||||||
|
|
||||||
|
#define PIN_PULLUD_DISABLED 0
|
||||||
|
#define PIN_PULLUD_ENABLED (1<<3)
|
||||||
|
|
||||||
|
#define PIN_PULLUP (1<<4)
|
||||||
|
#define PIN_PULLDOWN 0
|
||||||
|
|
||||||
|
#define PIN_SLEW_FAST 0
|
||||||
|
#define PIN_SLEW_SLOW (1<<6)
|
||||||
|
|
||||||
|
|
||||||
|
#define PIN_MODE0 0
|
||||||
|
#define PIN_MODE1 1
|
||||||
|
#define PIN_MODE2 2
|
||||||
|
#define PIN_MODE3 3
|
||||||
|
#define PIN_MODE4 4
|
||||||
|
#define PIN_MODE5 5
|
||||||
|
#define PIN_MODE6 6
|
||||||
|
#define PIN_MODE7 7
|
||||||
|
|
||||||
|
|
||||||
|
#define CONF_GPIO1_28 0x878
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define GPIO_SIZE 0x2000
|
||||||
|
#define GPIO0_START_ADDR 0x44E07000
|
||||||
|
#define GPIO1_START_ADDR 0x4804C000
|
||||||
|
#define GPIO2_START_ADDR 0x481AC000
|
||||||
|
#define GPIO3_START_ADDR 0x481AE000
|
||||||
|
|
||||||
|
#define GPIO_OE 0x134
|
||||||
|
#define GPIO_SETDATAOUT 0x194
|
||||||
|
#define GPIO_CLEARDATAOUT 0x190
|
||||||
|
#define GPIO_DATAIN 0x138
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
volatile void *gpio_addr;
|
||||||
|
volatile unsigned int *oe_reg;
|
||||||
|
volatile unsigned int *setdataout_reg;
|
||||||
|
volatile unsigned int *clrdataout_reg;
|
||||||
|
volatile unsigned int *datain_reg;
|
||||||
|
} bb_gpio_port;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bb_gpio_port *port;
|
||||||
|
char port_num;
|
||||||
|
char pin_num;
|
||||||
|
unsigned short control_offset;
|
||||||
|
char claimed;
|
||||||
|
} bb_gpio_pin;
|
||||||
|
|
||||||
|
volatile void *control_module;
|
||||||
|
|
||||||
|
bb_gpio_port *gpio_ports[4];
|
||||||
|
|
||||||
|
bb_gpio_pin user_led_gpio_pins[4] = {
|
||||||
|
{ NULL, 1, 21, 0x854, 0 }, // led0, gpmc_a5
|
||||||
|
{ NULL, 1, 22, 0x858, 0 }, // led1, gpmc_a6
|
||||||
|
{ NULL, 1, 23, 0x85C, 0 }, // led2, gpmc_a7
|
||||||
|
{ NULL, 1, 24, 0x860, 0 } // led3, gpmc_a8
|
||||||
|
};
|
||||||
|
|
||||||
|
bb_gpio_pin p8_pins[47] = {
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 0 unused
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 1 GND
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 2 GND
|
||||||
|
{ NULL, 1, 6, 0x818, 0 }, // pin 3, gpmc_ad6
|
||||||
|
{ NULL, 1, 7, 0x81C, 0 }, // pin 4, gpmc_ad7
|
||||||
|
{ NULL, 1, 2, 0x808, 0 }, // pin 5, gpmc_ad2
|
||||||
|
{ NULL, 1, 3, 0x803, 0 }, // pin 6, gpmc_ad3
|
||||||
|
{ NULL, 2, 2, 0x890, 0 }, // pin 7, gpmc_advn_ale
|
||||||
|
{ NULL, 2, 3, 0x894, 0 }, // pin 8, gpmc_oen_ren
|
||||||
|
{ NULL, 2, 5, 0x89C, 0 }, // pin 9, gpmc_ben0_cle
|
||||||
|
{ NULL, 2, 4, 0x898, 0 }, // pin 10, gpmc_wen
|
||||||
|
{ NULL, 1, 13, 0x834, 0 }, // pin 11, gpmc_ad13
|
||||||
|
{ NULL, 1, 12, 0x830, 0 }, // pin 12, GPMC_AD12
|
||||||
|
{ NULL, 0, 23, 0x824, 0 }, // pin 13, gpmc_ad9
|
||||||
|
{ NULL, 0, 26, 0x828, 0 }, // pin 14, gpmc_ad10
|
||||||
|
{ NULL, 1, 15, 0x83C, 0 }, // pin 15, gpmc_ad15
|
||||||
|
{ NULL, 1, 14, 0x838, 0 }, // pin 16, gpmc_ad14
|
||||||
|
{ NULL, 0, 27, 0x82C, 0 }, // pin 17, gpmc_ad11
|
||||||
|
{ NULL, 2, 1, 0x88C, 0 }, // pin 18, gpmc_clk_mux0
|
||||||
|
{ NULL, 0, 22, 0x820, 0 }, // pin 19, gpmc_ad8
|
||||||
|
{ NULL, 1, 31, 0x884, 0 }, // pin 20, gpmc_csn2
|
||||||
|
{ NULL, 1, 30, 0x880, 0 }, // pin 21, gpmc_csn1
|
||||||
|
{ NULL, 1, 5, 0x814, 0 }, // pin 22, gpmc_ad5
|
||||||
|
{ NULL, 1, 4, 0x810, 0 }, // pin 23, gpmc_ad4
|
||||||
|
{ NULL, 1, 1, 0x804, 0 }, // pin 24, gpmc_ad1
|
||||||
|
{ NULL, 1, 0, 0x800, 0 }, // pin 25, gpmc_ad0
|
||||||
|
{ NULL, 1, 29, 0x87C, 0 }, // pin 26, gpmc_csn0
|
||||||
|
{ NULL, 2, 22, 0x8E0, 0 }, // pin 27, lcd_vsync
|
||||||
|
{ NULL, 2, 24, 0x8E8, 0 }, // pin 28, lcd_pclk
|
||||||
|
{ NULL, 2, 23, 0x8E4, 0 }, // pin 29, lcd_hsync
|
||||||
|
{ NULL, 2, 25, 0x8EC, 0 }, // pin 30, lcd_ac_bias_en
|
||||||
|
{ NULL, 0, 10, 0x8D8, 0 }, // pin 31, lcd_data14
|
||||||
|
{ NULL, 0, 11, 0x8DC, 0 }, // pin 32, lcd_data15
|
||||||
|
{ NULL, 0, 9, 0x8D4, 0 }, // pin 33, lcd_data13
|
||||||
|
{ NULL, 2, 17, 0x8CC, 0 }, // pin 34, lcd_data11
|
||||||
|
{ NULL, 0, 8, 0x8D0, 0 }, // pin 35, lcd_data12
|
||||||
|
{ NULL, 2, 16, 0x8C8, 0 }, // pin 36, lcd_data10
|
||||||
|
{ NULL, 2, 14, 0x8C0, 0 }, // pin 37, lcd_data8
|
||||||
|
{ NULL, 2, 15, 0x8C4, 0 }, // pin 38, lcd_data9
|
||||||
|
{ NULL, 2, 12, 0x8B8, 0 }, // pin 39, lcd_data6
|
||||||
|
{ NULL, 2, 13, 0x8BC, 0 }, // pin 40, lcd_data7
|
||||||
|
{ NULL, 2, 10, 0x8B0, 0 }, // pin 41, lcd_data4
|
||||||
|
{ NULL, 2, 11, 0x8B4, 0 }, // pin 42, lcd_data5
|
||||||
|
{ NULL, 2, 8, 0x8A8, 0 }, // pin 43, lcd_data2
|
||||||
|
{ NULL, 2, 9, 0x8AC, 0 }, // pin 44, lcd_data3
|
||||||
|
{ NULL, 2, 6, 0x8A0, 0 }, // pin 45, lcd_data0
|
||||||
|
{ NULL, 2, 7, 0x8A4, 0 } // pin 46, lcd_data1
|
||||||
|
};
|
||||||
|
|
||||||
|
bb_gpio_pin p9_pins[47] = {
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 0 unused
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 1 GND
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 2 GND
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 3 3.3v
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 4 3.v
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 5 Vdd 5v
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 6 Vdd 5v
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 7 Sys 5v
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 8 Sys 5v
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 9 power button
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 10 sys_reset
|
||||||
|
{ NULL, 0, 30, 0x870, 0 }, // pin 11, gpmc_wait0
|
||||||
|
{ NULL, 1, 28, 0x878, 0 }, // pin 12, gpmc_ben1
|
||||||
|
{ NULL, 0, 31, 0x874, 0 }, // pin 13, gpmc_wpn
|
||||||
|
{ NULL, 1, 18, 0x848, 0 }, // pin 14, gpmc_a2
|
||||||
|
{ NULL, 1, 16, 0x840, 0 }, // pin 15, gpmc_a0
|
||||||
|
{ NULL, 1, 19, 0x84C, 0 }, // pin 16, gpmc_a3
|
||||||
|
{ NULL, 0, 5, 0x95C, 0 }, // pin 17, spi0_cs0
|
||||||
|
{ NULL, 0, 4, 0x958, 0 }, // pin 18, spi0_d1
|
||||||
|
{ NULL, 0, 13, 0x97C, 0 }, // pin 19, uart1_rtsn
|
||||||
|
{ NULL, 0, 12, 0x978, 0 }, // pin 20, uart1_ctsn
|
||||||
|
{ NULL, 0, 3, 0x954, 0 }, // pin 21, spi0_d0
|
||||||
|
{ NULL, 0, 2, 0x950, 0 }, // pin 22, spi0_sclk
|
||||||
|
{ NULL, 1, 17, 0x844, 0 }, // pin 23, gpmc_a1
|
||||||
|
{ NULL, 0, 15, 0x984, 0 }, // pin 24, uart1_txd
|
||||||
|
{ NULL, 3, 21, 0x9AC, 0 }, // pin 25, mcasp0_ahclkx
|
||||||
|
{ NULL, 0, 14, 0x980, 0 }, // pin 26, uart1_rxd
|
||||||
|
{ NULL, 3, 19, 0x9A4, 0 }, // pin 27, mcasp0_fsr
|
||||||
|
{ NULL, 3, 17, 0x99C, 0 }, // pin 28, mcasp0_ahclkr
|
||||||
|
{ NULL, 3, 15, 0x994, 0 }, // pin 29, mcasp0_fsx
|
||||||
|
{ NULL, 3, 16, 0x998, 0 }, // pin 30, mcasp0_axr0
|
||||||
|
{ NULL, 3, 14, 0x990, 0 }, // pin 31, mcasp0_aclkx
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 32 VADC
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 33 AIN4
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 34 AGND
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 35 AIN6
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 36 AIN5
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 37 AIN2
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 38 AIN3
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 39 AIN0
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 40 AIN1
|
||||||
|
// { NULL, 3, 20, 0x9A8, 0 }, // pin 41, mcasp0_axr1 NOTE 41 and 42 each have two signals connected
|
||||||
|
{ NULL, 0, 20, 0x9B4, 0 }, // pin 41, xdma_event_intr1
|
||||||
|
{ NULL, 0, 7, 0x964, 0 }, // pin 42, ecap0_in_pwm0_out
|
||||||
|
// { NULL, 3, 18, 0x9A0, 0 }, // pin 42, mcasp0_aclkr
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 43 GND
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 44 GND
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 45 GND
|
||||||
|
{ NULL, -1, -1, -1, 1 }, // 46 GND
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
457
src/hal/drivers/hal_bb_gpio.c
Normal file
457
src/hal/drivers/hal_bb_gpio.c
Normal file
|
|
@ -0,0 +1,457 @@
|
||||||
|
/********************************************************************
|
||||||
|
* Description: hal_bb_gpio.c
|
||||||
|
* Driver for the BeagleBone GPIO pins
|
||||||
|
*
|
||||||
|
* Author: Ian McMahon <imcmahon@prototechnical.com>
|
||||||
|
* License: GPL Version 2
|
||||||
|
* Copyright (c) 2013.
|
||||||
|
*
|
||||||
|
********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "rtapi.h"
|
||||||
|
#include "rtapi_app.h"
|
||||||
|
|
||||||
|
#include "hal.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "beaglebone_gpio.h"
|
||||||
|
|
||||||
|
#define MODNAME "hal_bb_gpio"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Ian McMahon");
|
||||||
|
MODULE_DESCRIPTION("Driver for BeagleBone GPIO pins");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
#define HEADERS 2
|
||||||
|
#define PINS_PER_HEADER 46
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
hal_bit_t* led_pins[4];
|
||||||
|
hal_bit_t* input_pins[PINS_PER_HEADER * HEADERS]; // array of pointers to bivts
|
||||||
|
hal_bit_t* output_pins[PINS_PER_HEADER * HEADERS]; // array of pointers to bits
|
||||||
|
hal_bit_t *led_inv[4];
|
||||||
|
hal_bit_t *input_inv[PINS_PER_HEADER * HEADERS];
|
||||||
|
hal_bit_t *output_inv[PINS_PER_HEADER * HEADERS];
|
||||||
|
} port_data_t;
|
||||||
|
|
||||||
|
static port_data_t *port_data;
|
||||||
|
|
||||||
|
static const char *modname = MODNAME;
|
||||||
|
|
||||||
|
static void write_port(void *arg, long period);
|
||||||
|
static void read_port(void *arg, long period);
|
||||||
|
|
||||||
|
static off_t start_addr_for_port(int port);
|
||||||
|
static void configure_pin(bb_gpio_pin *pin, char mode);
|
||||||
|
|
||||||
|
static int comp_id;
|
||||||
|
static int num_ports;
|
||||||
|
|
||||||
|
static char *user_leds;
|
||||||
|
RTAPI_MP_STRING(user_leds, "user leds, comma separated. 0-3");
|
||||||
|
|
||||||
|
static char *input_pins;
|
||||||
|
RTAPI_MP_STRING(input_pins, "input pins, comma separated. P8 pins add 800, P9 pins add 900");
|
||||||
|
|
||||||
|
static char *output_pins;
|
||||||
|
RTAPI_MP_STRING(output_pins, "output pins, comma separated. P8 pins add 800, P9 pins add 900");
|
||||||
|
|
||||||
|
void configure_control_module() {
|
||||||
|
int fd = rtapi_open_as_root("/dev/mem", O_RDWR);
|
||||||
|
|
||||||
|
control_module = mmap(0, CONTROL_MODULE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, CONTROL_MODULE_START_ADDR);
|
||||||
|
|
||||||
|
if(control_module == MAP_FAILED) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: Unable to map Control Module: %s\n", modname, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void configure_gpio_port(int n) {
|
||||||
|
int fd = rtapi_open_as_root("/dev/mem", O_RDWR);
|
||||||
|
|
||||||
|
gpio_ports[n] = hal_malloc(sizeof(bb_gpio_port));
|
||||||
|
|
||||||
|
gpio_ports[n]->gpio_addr = mmap(0, GPIO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start_addr_for_port(n));
|
||||||
|
|
||||||
|
if(gpio_ports[n]->gpio_addr == MAP_FAILED) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: Unable to map GPIO: %s\n", modname, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_ports[n]->oe_reg = gpio_ports[n]->gpio_addr + GPIO_OE;
|
||||||
|
gpio_ports[n]->setdataout_reg = gpio_ports[n]->gpio_addr + GPIO_SETDATAOUT;
|
||||||
|
gpio_ports[n]->clrdataout_reg = gpio_ports[n]->gpio_addr + GPIO_CLEARDATAOUT;
|
||||||
|
gpio_ports[n]->datain_reg = gpio_ports[n]->gpio_addr + GPIO_DATAIN;
|
||||||
|
|
||||||
|
|
||||||
|
rtapi_print("memmapped gpio port %d to %p, oe: %p, set: %p, clr: %p\n", n, gpio_ports[n]->gpio_addr, gpio_ports[n]->oe_reg, gpio_ports[n]->setdataout_reg, gpio_ports[n]->clrdataout_reg);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rtapi_app_main(void) {
|
||||||
|
char name[HAL_NAME_LEN + 1];
|
||||||
|
int n, retval;
|
||||||
|
char *data, *token;
|
||||||
|
|
||||||
|
num_ports = 1;
|
||||||
|
n = 0; // port number... only one for now
|
||||||
|
|
||||||
|
// init driver
|
||||||
|
comp_id = hal_init(modname);
|
||||||
|
if(comp_id < 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: hal_init() failed\n", modname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate port memory
|
||||||
|
port_data = hal_malloc(num_ports * sizeof(port_data_t));
|
||||||
|
if(port_data == 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: hal_malloc() failed\n", modname);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// map control module memory
|
||||||
|
configure_control_module();
|
||||||
|
|
||||||
|
// configure userleds
|
||||||
|
if(user_leds != NULL) {
|
||||||
|
data = user_leds;
|
||||||
|
while((token = strtok(data, ",")) != NULL) {
|
||||||
|
int led = strtol(token, NULL, 10);
|
||||||
|
|
||||||
|
data = NULL;
|
||||||
|
|
||||||
|
if(user_led_gpio_pins[led].claimed != 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: userled%d is not available as a GPIO.\n", modname, led);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add HAL pin
|
||||||
|
retval = hal_pin_bit_newf(HAL_IN, &(port_data->led_pins[led]), comp_id, "bb_gpio.userled%d", led);
|
||||||
|
|
||||||
|
if(retval < 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: userled %d could not export pin, err: %d\n", modname, led, retval);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add HAL pin
|
||||||
|
retval = hal_pin_bit_newf(HAL_IN, &(port_data->led_inv[led]), comp_id, "bb_gpio.userled%d-invert", led);
|
||||||
|
|
||||||
|
if(retval < 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: userled %d could not export pin, err: %d\n", modname, led, retval);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize HAL pin
|
||||||
|
*(port_data->led_inv[led]) = 0;
|
||||||
|
|
||||||
|
int gpio_num = user_led_gpio_pins[led].port_num;
|
||||||
|
// configure gpio port if necessary
|
||||||
|
if(gpio_ports[gpio_num] == NULL) {
|
||||||
|
configure_gpio_port(gpio_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
user_led_gpio_pins[led].port = gpio_ports[gpio_num];
|
||||||
|
|
||||||
|
configure_pin(&user_led_gpio_pins[led], 'O');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure input pins
|
||||||
|
if(input_pins != NULL) {
|
||||||
|
data = input_pins;
|
||||||
|
while((token = strtok(data, ",")) != NULL) {
|
||||||
|
int pin = strtol(token, NULL, 10);
|
||||||
|
int header;
|
||||||
|
bb_gpio_pin *bbpin;
|
||||||
|
|
||||||
|
// Fixup old pin numbering scheme:
|
||||||
|
// P8/P9 was 1xx/2xx, now 8xx/9xx
|
||||||
|
if (pin < 300)
|
||||||
|
pin += 700;
|
||||||
|
|
||||||
|
if(pin < 801 || pin > 946 || (pin > 846 && pin < 901)) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: invalid pin number '%d'. Valid pins are 801-846 for P8 pins, 901-946 for P9 pins.\n", modname, pin);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pin < 900) {
|
||||||
|
pin -= 800;
|
||||||
|
bbpin = &p8_pins[pin];
|
||||||
|
header = 8;
|
||||||
|
} else {
|
||||||
|
pin -= 900;
|
||||||
|
bbpin = &p9_pins[pin];
|
||||||
|
header = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bbpin->claimed != 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin p%d.%02d is not available as a GPIO.\n", modname, header, pin);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = NULL; // after the first call, subsequent calls to strtok need to be on NULL
|
||||||
|
|
||||||
|
// Add HAL pin
|
||||||
|
retval = hal_pin_bit_newf(HAL_OUT, &(port_data->input_pins[pin + (header - 8)*PINS_PER_HEADER]), comp_id, "bb_gpio.p%d.in-%02d", header, pin);
|
||||||
|
|
||||||
|
if(retval < 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin p%d.%02d could not export pin, err: %d\n", modname, header, pin, retval);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add HAL pin
|
||||||
|
retval = hal_pin_bit_newf(HAL_IN, &(port_data->input_inv[pin + (header - 8)*PINS_PER_HEADER]), comp_id, "bb_gpio.p%d.in-%02d-invert", header, pin);
|
||||||
|
|
||||||
|
if(retval < 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin p%d.%02d could not export pin, err: %d\n", modname, header, pin, retval);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize HAL pin
|
||||||
|
*(port_data->input_inv[pin + (header - 8)*PINS_PER_HEADER]) = 0;
|
||||||
|
|
||||||
|
int gpio_num = bbpin->port_num;
|
||||||
|
|
||||||
|
// configure gpio port if necessary
|
||||||
|
if(gpio_ports[gpio_num] == NULL) {
|
||||||
|
configure_gpio_port(gpio_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
bbpin->port = gpio_ports[gpio_num];
|
||||||
|
|
||||||
|
configure_pin(bbpin, 'U');
|
||||||
|
rtapi_print("pin %d maps to pin %d-%d, mode %d\n", pin, bbpin->port_num, bbpin->pin_num, bbpin->claimed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure output pins
|
||||||
|
if(output_pins != NULL) {
|
||||||
|
data = output_pins;
|
||||||
|
while((token = strtok(data, ",")) != NULL) {
|
||||||
|
int pin = strtol(token, NULL, 10);
|
||||||
|
int header;
|
||||||
|
bb_gpio_pin *bbpin;
|
||||||
|
|
||||||
|
// Fixup old pin numbering scheme:
|
||||||
|
// P8/P9 was 1xx/2xx, now 8xx/9xx
|
||||||
|
if (pin < 300)
|
||||||
|
pin += 700;
|
||||||
|
|
||||||
|
if(pin < 801 || pin > 946 || (pin > 846 && pin < 901)) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: invalid pin number '%d'. Valid pins are 801-846 for P8 pins, 901-946 for P9 pins.\n", modname, pin);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pin < 900) {
|
||||||
|
pin -= 800;
|
||||||
|
bbpin = &p8_pins[pin];
|
||||||
|
header = 8;
|
||||||
|
} else {
|
||||||
|
pin -= 900;
|
||||||
|
bbpin = &p9_pins[pin];
|
||||||
|
header = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bbpin->claimed != 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin p%d.%02d is not available as a GPIO.\n", modname, header, pin);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = NULL; // after the first call, subsequent calls to strtok need to be on NULL
|
||||||
|
|
||||||
|
// Add HAL pin
|
||||||
|
retval = hal_pin_bit_newf(HAL_IN, &(port_data->output_pins[pin + (header - 8)*PINS_PER_HEADER]), comp_id, "bb_gpio.p%d.out-%02d", header, pin);
|
||||||
|
|
||||||
|
if(retval < 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin p%d.%02d could not export pin, err: %d\n", modname, header, pin, retval);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add HAL pin
|
||||||
|
retval = hal_pin_bit_newf(HAL_IN, &(port_data->output_inv[pin + (header - 8)*PINS_PER_HEADER]), comp_id, "bb_gpio.p%d.out-%02d-invert", header, pin);
|
||||||
|
|
||||||
|
if(retval < 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin p%d.%02d could not export pin, err: %d\n", modname, header, pin, retval);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize HAL pin
|
||||||
|
*(port_data->output_inv[pin + (header - 8)*PINS_PER_HEADER]) = 0;
|
||||||
|
|
||||||
|
int gpio_num = bbpin->port_num;
|
||||||
|
|
||||||
|
// configure gpio port if necessary
|
||||||
|
if(gpio_ports[gpio_num] == NULL) {
|
||||||
|
configure_gpio_port(gpio_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
bbpin->port = gpio_ports[gpio_num];
|
||||||
|
|
||||||
|
configure_pin(bbpin, 'O');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// export functions
|
||||||
|
rtapi_snprintf(name, sizeof(name), "bb_gpio.write");
|
||||||
|
retval = hal_export_funct(name, write_port, port_data, 0, 0, comp_id);
|
||||||
|
if(retval < 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: port %d write funct export failed\n", modname, n);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtapi_snprintf(name, sizeof(name), "bb_gpio.read");
|
||||||
|
retval = hal_export_funct(name, read_port, port_data, 0, 0, comp_id);
|
||||||
|
if(retval < 0) {
|
||||||
|
rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: port %d read funct export failed\n", modname, n);
|
||||||
|
hal_exit(comp_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtapi_print_msg(RTAPI_MSG_INFO, "%s: installed driver\n", modname);
|
||||||
|
|
||||||
|
hal_ready(comp_id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtapi_app_exit(void) {
|
||||||
|
|
||||||
|
hal_exit(comp_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_port(void *arg, long period) {
|
||||||
|
int i;
|
||||||
|
port_data_t *port = (port_data_t *)arg;
|
||||||
|
|
||||||
|
// set userled states
|
||||||
|
for(i=0; i<4; i++) {
|
||||||
|
if(port->led_pins[i] == NULL) continue; // short circuit if hal hasn't malloc'd a bit at this location
|
||||||
|
|
||||||
|
bb_gpio_pin pin = user_led_gpio_pins[i];
|
||||||
|
|
||||||
|
if(pin.claimed != 'O') continue; // if we somehow get here but the pin isn't claimed as output, short circuit
|
||||||
|
|
||||||
|
if((*port->led_pins[i] ^ *(port->led_inv[i])) == 0)
|
||||||
|
*(pin.port->clrdataout_reg) = (1 << pin.pin_num);
|
||||||
|
else
|
||||||
|
*(pin.port->setdataout_reg) = (1 << pin.pin_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set output states
|
||||||
|
for(i=1; i<=HEADERS*PINS_PER_HEADER; i++) {
|
||||||
|
if(port->output_pins[i] == NULL) continue; // short circuit if hal hasn't malloc'd a bit at this location
|
||||||
|
|
||||||
|
bb_gpio_pin pin;
|
||||||
|
|
||||||
|
if(i<PINS_PER_HEADER)
|
||||||
|
pin = p8_pins[i];
|
||||||
|
else
|
||||||
|
pin = p9_pins[i - PINS_PER_HEADER];
|
||||||
|
|
||||||
|
if(pin.claimed != 'O') continue; // if we somehow get here but the pin isn't claimed as output, short circuit
|
||||||
|
|
||||||
|
if((*port->output_pins[i] ^ *(port->output_inv[i])) == 0)
|
||||||
|
*(pin.port->clrdataout_reg) = (1 << pin.pin_num);
|
||||||
|
else
|
||||||
|
*(pin.port->setdataout_reg) = (1 << pin.pin_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void read_port(void *arg, long period) {
|
||||||
|
int i;
|
||||||
|
port_data_t *port = (port_data_t *)arg;
|
||||||
|
|
||||||
|
// read input states
|
||||||
|
for(i=1; i<=HEADERS*PINS_PER_HEADER; i++) {
|
||||||
|
if(port->input_pins[i] == NULL) continue; // short circuit if hal hasn't malloc'd a bit at this location
|
||||||
|
|
||||||
|
bb_gpio_pin pin;
|
||||||
|
|
||||||
|
if(i<PINS_PER_HEADER) {
|
||||||
|
pin = p8_pins[i];
|
||||||
|
} else {
|
||||||
|
pin = p9_pins[i - PINS_PER_HEADER];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(!(pin.claimed == 'I' || pin.claimed == 'U' || pin.claimed == 'D')) continue; // if we get here but the pin isn't claimed as input, short circuit
|
||||||
|
|
||||||
|
*port->input_pins[i] = ((*(pin.port->datain_reg) & (1 << pin.pin_num)) >> pin.pin_num) ^ *(port->input_inv[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
off_t start_addr_for_port(int port) {
|
||||||
|
switch(port) {
|
||||||
|
case 0:
|
||||||
|
return GPIO0_START_ADDR;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
return GPIO1_START_ADDR;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return GPIO2_START_ADDR;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
return GPIO3_START_ADDR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void configure_pin(bb_gpio_pin *pin, char mode) {
|
||||||
|
volatile unsigned int *control_reg = control_module + pin->control_offset;
|
||||||
|
pin->claimed = mode;
|
||||||
|
switch(mode) {
|
||||||
|
case 'O':
|
||||||
|
*(pin->port->oe_reg) &= ~(1 << pin->pin_num); // 0 in OE is output enable
|
||||||
|
*control_reg = PIN_MODE7 | PIN_PULLUD_DISABLED | PIN_RX_DISABLED;
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
*(pin->port->oe_reg) |= (1 << pin->pin_num); // 1 in OE is input
|
||||||
|
*control_reg = PIN_MODE7 | PIN_PULLUD_DISABLED | PIN_RX_ENABLED;
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
*(pin->port->oe_reg) |= (1 << pin->pin_num); // 1 in OE is input
|
||||||
|
*control_reg = PIN_MODE7 | PIN_PULLUD_ENABLED | PIN_PULLUP | PIN_RX_ENABLED;
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
*(pin->port->oe_reg) |= (1 << pin->pin_num); // 1 in OE is input
|
||||||
|
*control_reg = PIN_MODE7 | PIN_PULLUD_ENABLED | PIN_PULLDOWN | PIN_RX_ENABLED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue