This issue has been resolved by manually installing icomps. However now I 
ran into another issue with a custom driver/protocol for my IO hardware 
(communicates via USB to RS485) Please see attached files and error 
messages. Any help would be greatly appreciated since I am merely just a 
power user. Thanks

starting mklauncher... done
starting configserver... done
starting ./python/pmcsfile_service.py... done
starting machinekit... MACHINEKIT - 0.1
Machine configuration directory is '/home/pmcs/Downloads/pmcs-rt'
Machine configuration file is 'v6.ini'
Starting Machinekit...
io started
halcmd loadusr io started
done
hal/v6.hal:14: insmod failed, returned -1:
do_load_cmd: dlopen: /usr/lib/linuxcnc/rt-preempt/hal_p260c.so: undefined 
symbol: hal_exit
rpath=/usr/lib/linuxcnc/rt-preempt
See /var/log/linuxcnc.log for more information.
Shutting down and cleaning up Machinekit...
Traceback (most recent call last):
  File "/home/pmcs/bin/estop.py", line 16, in <module>
Traceback (most recent call last):
  File "/home/pmcs/bin/mtc.py", line 15, in <module>
    time.sleep(2.00)
    KeyboardInterrupttime.sleep(2.00)

KeyboardInterrupt
Cleanup done
Machinekit terminated with an error.  You can find more information in the 
log:
    /home/pmcs/linuxcnc_debug.txt
and
    /home/pmcs/linuxcnc_print.txt
as well as in the output of the shell command 'dmesg' and in the terminal
stopping mklauncher... done
stopping configserver... done
stopping ./python/pmcsfile_service.py... done

On Wednesday, February 22, 2017 at 3:35:11 PM UTC-6, Daniel Skrlin wrote:
>
> Hello guys do not know if this pertains to this but just did a recent 
> upgrade/update and got this on my once working config
>
>   File "hal/init.py", line 14, in <module>
>     import motion
>   File "/home/pmcs/Downloads/pmcs-sim_OLD/hal/motion.py", line 14, in 
> <module>
>     convert = rt.newinst('float2u32', 'convert.active-origin-float')
>   File "machinekit/rtapi.pyx", line 264, in 
> machinekit.rtapi.RTAPIcommand.newinst (hal/cython/machinekit/rtapi.c:5506)
> RuntimeError: rtapi_newinst '('float2u32', 'convert.active-origin-float')' 
> failed: Operation not permitted
>
>
> On Tuesday, February 7, 2017 at 5:51:47 AM UTC-6, Schooner wrote:
>>
>> Hi
>>
>> This is to advise users, that a major merge has occurred in the 
>> Machinekit repo.
>>
>> The work christened 'multicore', has been finalised and tested for the 
>> last few months 
>> and is now part of Machinekit.
>>
>> What is multicore?
>> This talk from 2015 gives the full details. 
>> https://plus.google.com/events/cvhj9r8m2gh0v0kj7ccme36hlpo 
>>
>> What do you need to do?
>>
>> With 3 particular exceptions, *nothing at all*, the aim has been to make 
>> it backwardly compatible,
>> so all your configs should work as before.
>>
>> Please report any problems via the tracker at 
>> https://github.com/machinekit/machinekit/issues/1123
>>
>> Once any teething problems are sorted, the capabilities and enhancements 
>> available within the code,
>> will be rolled out, documented and advised for any users wishing to make 
>> use of them.
>>
>> *Exceptions *
>>
>>    - The primary exception is for anyone using the DE0-NANO-Soc or Zynq 
>>    as a Mesa 5i25 replacement 
>>
>> Improvements to the *hm2_soc_ol* driver now make use of a different 
>> string argument handling mechanism.
>>
>> In practice, this simply means editing your hal file driver instantiation 
>> line from
>> *newinst [HOSTMOT2](DRIVER) [HOSTMOT2]DEVNAME config=[HOSTMOT2](CONFIG)*
>> to
>> *newinst [HOSTMOT2](DRIVER) [HOSTMOT2]DEVNAME -- 
>> config=[HOSTMOT2](CONFIG)*
>>
>> The 2 dashes route the config string to the driver via a safer mechanism.
>> Any integer instanceparams such as 'debug=1' are passed as previously, so 
>> remain to the left side of the delimiter
>>
>> If interested, this gives more details
>> https://github.com/machinekit/machinekit-multicore/issues/20
>>
>>
>>    -  The multicore concept relies upon atomic operations in the C11++ 
>>    standard and newer 
>>
>> These are supported sufficiently in gcc 4.7.2 and above in x86, which 
>> means the code will build under Wheezy with backports installed
>>
>> There is however a problem on the ARM architecture running Wheezy which 
>> makes it unlikely it will build
>>
>> All builds fine on jessie-armhf and raspbian-armhf builds appear to be OK 
>> too.
>>
>> All of which means that packages for wheezy-armhf are likely to cease to 
>> be updated from this point.
>>
>> Users are encouraged to upgrade from Wheezy, which is almost 'end of 
>> life' and no longer receiving new backports from Debian in any case.
>>
>> Should you choose not to however, the current packages will continue to 
>> work as at present.
>>
>>    - Something that will only affect users who have written their own C 
>>    components which use ringbuffers.  (We have no idea if there are any out 
>>    there.)
>>    
>> An API change sees 
>> *hal_ring_detach(char *name, ringbuffer_t *rb)*
>> become
>> *hal_ring_detach(ringbuffer_t *rb)*
>>
>> regards
>>
>>
>>

-- 
website: http://www.machinekit.io blog: http://blog.machinekit.io github: 
https://github.com/machinekit
--- 
You received this message because you are subscribed to the Google Groups 
"Machinekit" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
Visit this group at https://groups.google.com/group/machinekit.
For more options, visit https://groups.google.com/d/optout.
diff --git a/src/Makefile b/src/Makefile
index 2e0101c..f9aa73b 100755
--- a/src/Makefile
+++ b/src/Makefile
@@ -1250,6 +1250,10 @@ 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)
 
+# CW - Add p260c HAL
+obj-$(CONFIG_HAL_P260C) += hal_p260c.o
+hal_p260c-objs := hal/drivers/hal_p260c.o $(MATHSTUB)
+
 ifdef TARGET_PLATFORM_RASPBERRY
 obj-$(CONFIG_HAL_GPIO) += hal_gpio.o
 hal_gpio-objs := hal/drivers/hal_gpio.o hal/drivers/cpuinfo.o
@@ -1707,6 +1711,7 @@ $(RTLIBDIR)/hal_motenc$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_motenc-objs))
 $(RTLIBDIR)/hal_ax5214h$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_ax5214h-objs))
 $(RTLIBDIR)/hal_ppmc$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_ppmc-objs))
 $(RTLIBDIR)/hal_skeleton$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_skeleton-objs))
+$(RTLIBDIR)/hal_p260c$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_p260c-objs))
 $(RTLIBDIR)/hal_speaker$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(hal_speaker-objs))
 $(RTLIBDIR)/opto_ac5$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(opto_ac5-objs))
 $(RTLIBDIR)/scope_rt$(MODULE_EXT): $(addprefix $(OBJDIR)/,$(scope_rt-objs))
diff --git a/src/Makefile.inc.in b/src/Makefile.inc.in
index 94f9627..a016c23 100644
--- a/src/Makefile.inc.in
+++ b/src/Makefile.inc.in
@@ -396,6 +396,7 @@ CONFIG_HAL_TIRO=m
 CONFIG_HAL_EVOREG=m
 CONFIG_HAL_MOTENC=m
 CONFIG_HAL_SKELETON=m
+CONFIG_HAL_P260C=m
 CONFIG_HAL_GPIO=m
 CONFIG_HM2_SOC=m
 CONFIG_HAL_SPI=m
/*
 HAL driver to talk to P260C I/O boards on an RS-485 chain.




*/

//#define NO_SERIAL 1
#define OPEN_ON_ERROR 1

#include "rtapi.h"		/* RTAPI realtime OS API */
#include "rtapi_app.h"		/* RTAPI realtime module decls */

#include "hal.h"		/* HAL public API decls */

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/serial.h>

#if !defined(BUILD_SYS_USER_DSO) 
#error "This driver is for usermode threads only"
#endif

#define MODNAME "hal_p260c"

/* module information */
MODULE_AUTHOR("Colin Whittaker");
MODULE_DESCRIPTION("Driver for P260C boards in a RS-485 string. Version 1.2");
MODULE_LICENSE("GPL");

#define MAX_BOARDS 16
#define INPUT_PINS 16
#define OUTPUT_PINS 16


//#define DEBUG_RX 1

typedef struct _board_s {
	// Board physical address setting
	u8   address;

	// HAL Pins
	hal_bit_t *input_pins[INPUT_PINS];
	hal_bit_t *output_pins[INPUT_PINS];
	// Status data
	int        invalid_timer;             // count since last error
	int        count_errors;              // count of errors per time if >X then comm_error
	hal_s32_t *invalidcnt;                // s32 total count of invalid reads
	hal_bit_t *comm_error;                // Currently in communication error
	hal_bit_t *permanent_error;           // Triggered permanet error ( must be reset )
	// Debug data
#ifdef DEBUG_RX
	hal_s32_t *writecnt;                  // s32 count of write calls
	hal_s32_t *readbytes;                 // s32 count of read bytes
	hal_s32_t *validcnt;                  // s32 count of valid read
	hal_s32_t *readbeforewritecount;
	hal_s32_t *readcount;
	hal_s32_t *read0;
	hal_s32_t *read1;
	hal_s32_t *read2;
	hal_s32_t *read3;
	hal_s32_t *maxreadtime;
#endif

	// Protocol data structures
	u16  output_bits;
	u8   output_data[4];

	u16  input_bits;
	u8   input_data[16];
	int  input_cnt;
	int  input_valid;

} board_t;

static const char *modname = MODNAME;

static char *addrs;
RTAPI_MP_STRING( addrs, "board addresses, comma separated.  0-F");

#ifndef NO_SERIAL
static char *tty;
RTAPI_MP_STRING( tty, "Serial port name, /dev/ttyUSB0");
static char *tty_debug;
RTAPI_MP_STRING( tty_debug, "Serial port name, /dev/ttyUSB1");
#endif

static int comp_id; 

unsigned long runtime;
unsigned long threadtime;

typedef struct _mod_status {
	hal_s32_t *maxruntime;
	hal_s32_t *minruntime;
	hal_s32_t *maxreadtime;
	hal_s32_t *maxwritetime;

	hal_s32_t *writecnt;                  // s32 count of write calls
	
	hal_bit_t *comm_error;               // Currently some board has a communication error
	hal_bit_t *permanent_error;          // Permanent error triggered by comm_error ( Must be reset )
	hal_bit_t *reset_permanent;          // Input bit to reset permanent error

	// Parameters
	hal_s32_t clear_comm_count;
	hal_s32_t set_perm_count;
	hal_s32_t min_tx_boards;
	hal_s32_t max_rx_wait;

	hal_bit_t debug_on_error;
} mod_status_t;

//#define ERROR_CLEAR_TIME     10  // 10 cycles without an error to clear the comm_error
//#define MAX_ERRORS_PER_TIME  5   // 5 errors without 10 clean, count as a comm_error

mod_status_t *mstat;

static int num_boards = 0;
board_t *boards;

static int sfd;
static int debug_fd;

static void serial_port_task( void *arg, long period );

#ifndef NO_SERIAL
static char *serialdev = "/dev/ttyUSB0";
static void closeserial( int fd );
static int openserial(char *devicename, int baud );
static struct termios oldterminfo;
#endif
//static int gpio48, gpio49;
//static int openGPIO( int number );

#ifdef DEBUG_BB_GPIO
#include "util_bb_gpio.c"
#else
void util_bb_init() {}
void write_gpio( int gpio, int on ) {}
void configure_output( int gpio ) {}
#endif

int rtapi_app_main(void) 
{
	int   i, j, retval;
	char *data, *token;
	char  name[HAL_NAME_LEN + 1];


	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 board structures.
	boards = hal_malloc( MAX_BOARDS * sizeof( board_t ) );
	if ( boards == NULL )
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: hal_malloc() failed\n", modname);
		hal_exit(comp_id);
		return -1;
	}
	memset( boards, 0, MAX_BOARDS * sizeof( board_t ) );
	// Allocate status structures.
	mstat = hal_malloc( sizeof( mod_status_t ) );
	if ( mstat == NULL )
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: hal_malloc() failed\n", modname);
		hal_exit(comp_id);
		return -1;
	}
	memset( mstat, 0, sizeof( mod_status_t ) );

	// Parse parameters
	if ( addrs != NULL )
	{
		data = addrs;
		while((token = strtok(data, ",")) != NULL) 
		{
			int add = strtol(token, NULL, 16);

			if ( add < 0 || add > 15 )
			{
				rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: address %s = %x is not valid. Only 0-F\n", modname, token, add );
				hal_exit(comp_id);
				return -1;
			}
			boards[num_boards++].address = add;

			data = NULL;
		}
	}
	else
	{
		// No parameteres default to 1 boards address 0
		boards[0].address = 0;
		num_boards = 1;
	}

#ifndef NO_SERIAL
	if ( tty != NULL )
	{
		serialdev = tty;
	}
#endif


	// Open and configure the serial port
#ifdef NO_SERIAL
	sfd = 0;
#else
    sfd = openserial(serialdev,B3000000);
	if ( tty_debug != NULL )
	{
		debug_fd = openserial(tty_debug,B576000);
	}
	else
	{
		debug_fd = 0;
	}
#endif
	if ( sfd < 0 )
	{
		hal_exit(comp_id);
		return -1;
	}

	// Add pins
	for (i=0;i<num_boards;i++)
	{
		int add = boards[i].address;
		for (j=0;j<INPUT_PINS;j++)
		{
			retval = hal_pin_bit_newf(HAL_OUT, &(boards[i].input_pins[j]), comp_id, "%s.%d.pin-%02d-in", modname, add, j+1);
			if(retval < 0) 
			{
				rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin %d.%02d could not export pin, err: %d\n", modname, add, j+1, retval);
				hal_exit(comp_id);
				return -1;
			}

		}
		for (j=0;j<OUTPUT_PINS;j++)
		{
			retval = hal_pin_bit_newf(HAL_IN, &(boards[i].output_pins[j]), comp_id, "%s.%d.pin-%02d-out", modname, add, j+1);
			if(retval < 0) 
			{
				rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin %d.%02d could not export pin, err: %d\n", modname, add, j+1, retval);
				hal_exit(comp_id);
				return -1;
			}

		}

		retval = hal_pin_s32_newf(HAL_IN, &(boards[i].invalidcnt), comp_id, "%s.%d.rx_cnt_error", modname, add );
		if(retval < 0) 
		{
			rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin %d.serial_invalidcnt could not export pin, err: %d\n", modname, add, retval);
			hal_exit(comp_id);
			return -1;
		}
		retval = hal_pin_bit_newf(HAL_OUT, &(boards[i].comm_error), comp_id, "%s.%d.rx_comm_error", modname, add );
		if(retval < 0) 
		{
			rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin %d.comm_error could not export pin, err: %d\n", modname, add, retval);
			hal_exit(comp_id);
			return -1;
		}
		retval = hal_pin_bit_newf(HAL_OUT, &(boards[i].permanent_error), comp_id, "%s.%d.rx_perm_error", modname, add );
		if(retval < 0) 
		{
			rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin %d.permanent_error could not export pin, err: %d\n", modname, add, retval);
			hal_exit(comp_id);
			return -1;
		}

		// Debug
#ifdef DEBUG_RX
		hal_pin_s32_newf(HAL_IN, &(boards[i].writecnt), comp_id, "%s.%d.serial_writecnt", modname, add );
		hal_pin_s32_newf(HAL_IN, &(boards[i].readbytes), comp_id, "%s.%d.serial_readbytes", modname, add );
		hal_pin_s32_newf(HAL_IN, &(boards[i].validcnt), comp_id, "%s.%d.serial_validcnt", modname, add );
		hal_pin_s32_newf(HAL_IN, &(boards[i].readbeforewritecount), comp_id, "%s.%d.serial_readbeforewrcnt", modname, add );
		hal_pin_s32_newf(HAL_IN, &(boards[i].readcount), comp_id, "%s.%d.serial_readcnt", modname, add );
		hal_pin_s32_newf(HAL_IN, &(boards[i].read0), comp_id, "%s.%d.serial_read0", modname, add );
		hal_pin_s32_newf(HAL_IN, &(boards[i].read1), comp_id, "%s.%d.serial_read1", modname, add );
		hal_pin_s32_newf(HAL_IN, &(boards[i].read2), comp_id, "%s.%d.serial_read2", modname, add );
		hal_pin_s32_newf(HAL_IN, &(boards[i].read3), comp_id, "%s.%d.serial_read3", modname, add );
		hal_pin_s32_newf(HAL_IN, &(boards[i].maxreadtime), comp_id, "%s.%d.serial_maxreadtime", modname, add );
#endif                                       
	}
	retval = hal_pin_s32_newf(HAL_IN, &(mstat->maxreadtime), comp_id, "%s.sys_max_read", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin maxreadtime could not export pin, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}
	retval = hal_pin_s32_newf(HAL_IN, &(mstat->maxwritetime), comp_id, "%s.sys_max_write", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin maxwritetime could not export pin, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}
	retval = hal_pin_s32_newf(HAL_IN, &(mstat->writecnt), comp_id, "%s.sys_writecnt", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin writecnt could not export pin, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}
	retval = hal_pin_bit_newf(HAL_OUT, &(mstat->comm_error), comp_id, "%s.rx_comm_error", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin comm_error could not export pin, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}
	retval = hal_pin_bit_newf(HAL_OUT, &(mstat->permanent_error), comp_id, "%s.rx_perm_error", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin permanent_error could not export pin, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}
	retval = hal_pin_bit_newf(HAL_IN, &(mstat->reset_permanent), comp_id, "%s.rx_reset_error", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: pin reset_permanent could not export pin, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}

	// Parameters
	retval = hal_param_s32_newf(HAL_RW, &(mstat->clear_comm_count), comp_id, "%s.clear_comm_count", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: param clear_comm_count could not create, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}
	retval = hal_param_s32_newf(HAL_RW, &(mstat->set_perm_count), comp_id, "%s.set_perm_count", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: param set_perm_count could not create, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}
	retval = hal_param_s32_newf(HAL_RW, &(mstat->min_tx_boards), comp_id, "%s.minimum_tx", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: param minimum_tx could not create, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}
	retval = hal_param_s32_newf(HAL_RW, &(mstat->max_rx_wait), comp_id, "%s.max_rx_wait", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: param minimum_tx could not create, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}
	retval = hal_param_bit_newf(HAL_RW, &(mstat->debug_on_error), comp_id, "%s.debug_on_error", modname );
	if(retval < 0) 
	{
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: param debug_on_error could not create, err: %d\n", modname, retval);
		hal_exit(comp_id);
		return -1;
	}

	mstat->set_perm_count = 5;
	mstat->clear_comm_count = 10;
	mstat->min_tx_boards = 6;
	mstat->max_rx_wait = 5000000;
	mstat->debug_on_error = 0;

	// Debug
	util_bb_init();
	configure_output( 915 );
	configure_output( 923 );
//	gpio48 = openGPIO( 48 );
//	gpio49 = openGPIO( 49 );

	// Export the run thread function
	rtapi_snprintf( name, sizeof(name), "%s.refresh", modname );
	retval = hal_export_funct( name, serial_port_task, 0, 0, 0, comp_id);
	if(retval < 0) {
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: refresh funct export failed\n", modname);
		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)
{
#ifndef NO_SERIAL
	closeserial( sfd );
#endif

	hal_exit(comp_id);
}

/***********************************************************************
Implementation
*/
#if 0 // Can't use GPIO for TX-enable (too slow)
static int openGPIO( int number )
{
	int  fd;
	char buf[128];

	sprintf( buf, "/sys/class/gpio/gpio%d/value", number );

	fd = open( buf, O_RDWR | O_NONBLOCK );
	if ( fd < 0 )
		printf( "gpio open failed %s", buf );

	return fd;
}
static void setGPIO( int fd, int level )
{
	int err;
	if (level)
	{
		err = write( fd, "1\n", 2 );
		if ( err < 0 )
			printf("error %d, errno %d %s\n", err, errno, strerror(errno) );
	}
	else
	{
		err = write( fd, "0\n", 2 );
		if ( err < 0 )
			printf("error %d, errno %d %s\n", err, errno, strerror(errno) );
	}
	
}
#endif
#ifndef NO_SERIAL
static int openserial(char *devicename, int baud)
{
	int            fd = 0;
    struct termios options;

    if ((fd = open(devicename, O_RDWR | O_NONBLOCK | O_NOCTTY)) <0) {
		rtapi_print_msg(RTAPI_MSG_ERR, "%s: ERROR: Failed to open %s\n", modname, devicename);
    }

    if (tcgetattr(fd, &oldterminfo) == -1) {
       	rtapi_print_msg(RTAPI_MSG_ERR,"openserial(): tcgetattr()");
        return -1;
    }
    options = oldterminfo;
	rtapi_print_msg(RTAPI_MSG_INFO, "termios\niflag = %08X\noflag = %08X\ncflag = %08X\nlflag = %08X\n",
		options.c_iflag, options.c_oflag, options.c_cflag, options.c_lflag );
	
	// Ignore input break
	// Check parity
	options.c_iflag = IGNBRK;
//	options.c_iflag |= INPCK;
	options.c_iflag |= IGNPAR;
//	options.c_iflag |= PARMRK;

	options.c_oflag = 0;
//	options.c_oflag = OPOST;

	// CLOCAL means don't allow
	// control of the port to be changed
	// CREAD says to enable the receiver
	// CS8 means 8-bits per work
	// PARENB is enable parity bit
	// so this disables the parity bit
	// CSTOPB means 2 stop bits
	// otherwise (in this case)
	// only one stop bit
	options.c_cflag = 0;
	options.c_cflag |= (CLOCAL | CREAD);
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS8;
//	options.c_cflag &= ~PARENB;
	options.c_cflag |= PARENB;
	options.c_cflag &= ~CSTOPB;

	options.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH|TOSTOP|ECHOCTL|ECHOKE|FLUSHO);

	// set the read and write speed to
	// All speeds can be prefixed with B
	// as a settings.
//	cfsetispeed(&options, B115200);
//	cfsetospeed(&options, B115200);

//	cfsetispeed(&options, B3000000);
//	cfsetospeed(&options, B3000000);
	cfsetispeed(&options, baud );
	cfsetospeed(&options, baud );



	// Set the timeouts
	options.c_cc[VMIN] = 1;

	// The amount of time to wait
	// for the amount of data
	// specified by VMIN in tenths
	// of a second.
	options.c_cc[VTIME] = 0;

    if (tcflush(fd, TCIOFLUSH) == -1) {
       	rtapi_print_msg(RTAPI_MSG_ERR,"openserial(): tcflush()");
        return -1;
    }
    if (tcsetattr(fd, TCSANOW, &options) == -1) {
       	rtapi_print_msg(RTAPI_MSG_ERR,"initserial(): tcsetattr()");
        return -1;
    }

#if 0    // RS485 settings.
	{
	struct serial_rs485 rs485conf;
	if (ioctl (fd, TIOCGRS485, &rs485conf) < 0) {
		/* Error handling. See errno. */
		rtapi_print_msg(RTAPI_MSG_ERR, "Error getting RS485 %d %s\n", errno, strerror(errno) );
	}
	rtapi_print_msg(RTAPI_MSG_INFO, "rs485conf = %u\n",rs485conf.flags );

	/* Enable RS485 mode: */
	rs485conf.flags |= SER_RS485_ENABLED;

	/* Set logical level for RTS pin equal to 1 when sending: */
//	rs485conf.flags |= SER_RS485_RTS_ON_SEND;
	/* or, set logical level for RTS pin equal to 0 when sending: */
//	rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);

	/* Set logical level for RTS pin equal to 1 after sending: */
//	rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
	/* or, set logical level for RTS pin equal to 0 after sending: */
//	rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);

	/* Set rts delay before send, if needed: */
	//rs485conf.delay_rts_before_send = ...;

	/* Set rts delay after send, if needed: */
	//rs485conf.delay_rts_after_send = ...;

	/* Set this flag if you want to receive data even whilst sending data */
	rs485conf.flags |= SER_RS485_RX_DURING_TX;

	if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
		/* Error handling. See errno. */
		rtapi_print_msg(RTAPI_MSG_ERR, "Error ioctl %08X, flags %08X errno %d %s\n", TIOCSRS485, rs485conf.flags, errno, strerror(errno) );
	}
	}
#endif

	return fd;
}
static void closeserial( int fd )
{
    tcsetattr(fd, TCSANOW, &oldterminfo);
	close(fd);
}

int setRTS(int fd, int level)
{
    int status;

    if (ioctl(fd, TIOCMGET, &status) == -1) {
        return 0;
    }
    if (level)
        status |= TIOCM_RTS;
    else
        status &= ~TIOCM_RTS;

    if (ioctl(fd, TIOCMSET, &status) == -1) {
        return 0;
    }
    return 1;
}
int setDTR(int fd, int level)
{
    int status;

    if (ioctl(fd, TIOCMGET, &status) == -1) {
        return 0;
    }
    if (level)
        status |= TIOCM_DTR;
    else
        status &= ~TIOCM_DTR;

    if (ioctl(fd, TIOCMSET, &status) == -1) {
        return 0;
    }
    return 1;
}

#endif

static void set_debug( int pin, int val )
{
	if ( pin == 0 )
	{
		write_gpio( 915, val );
		if ( debug_fd != 0 )
		{
			setDTR( debug_fd, val );
		}
	}
	else
	{
		write_gpio( 923, val );
		if ( debug_fd != 0 )
		{
			setRTS( debug_fd, val );
		}
	}
}
/***********************************************************************

 Protocol task functions

***/


static void flush_input( int board )
{
	unsigned char inp;
	int cnt = 0;

	// Flush the input data first
	while ( read( sfd, &inp, 1 ) > 0 && cnt++ < 1000 )
	{
		if ( debug_fd )
		{
			write( debug_fd, &inp, 1 );
		}
	}

#ifdef DEBUG_RX
	if ( boards[board].readbeforewritecount != NULL )
	{
		*(boards[board].readbeforewritecount) = cnt;
	}
#endif
	if ( cnt )
	{
		set_debug( 0, 0 );
		set_debug( 0, 1 );
	}
}

static void wait_tx_empty()
{
	// Wait for write to be complete.
	tcdrain(sfd);
}

static void send_data( int board )
{
#ifdef DEBUG_RX
//	flush_input( board );
#endif

	// Write protocol data
#ifndef NO_SERIAL
	write( sfd, boards[board].output_data, 4 );
#endif

#ifdef DEBUG_RX
	if ( boards[board].writecnt != NULL )
	{
		*(boards[board].writecnt) = *(boards[board].writecnt) + 1;
	}
#endif

}

static unsigned char nibble_xsum( unsigned char *data )
{
	unsigned char xsum;
	int i;

	xsum = 0;
	for ( i=0; i<4; i++ )
	{
		xsum = xsum ^ (data[i]>>4);
		xsum = xsum ^ (data[i] & 0xf );
	}

	return xsum;
}

static u8 validate_input_buffer( u8 *input_data, u16 *bits )
{
	u8 input_address = input_data[0] >> 3;

	if ( nibble_xsum( input_data ) == 0 )
	{
		if ( (input_data[0] & 0x7) == 2 )
		{
			if ( (input_data[3] & 0xF) == 3 )
			{
				*bits = (input_data[1]<<8) & 0xFF00;
				*bits |= (input_data[2] & 0xFF);

				return input_address;
			}
		}
	}
	return -1;
}
#if 0
static int validate_input( int board )
{
	u8 *input_data = &boards[board].input_data[boards[board].input_cnt - 4];
	u8 input_address;
	u16 bits;

	if ( (input_address=validate_input_buffer( input_data, &bits )) >= 0 )

	if ( input_address == boards[board].address )
	{
		boards[board].input_bits  = bits;
		boards[board].input_valid = 1;
		return 1;
	}
	return 0;
}
#endif
//
// Count RX valids.
//   gets called once per cycle for each board.
// 
static int read_counts( int board )
{
	int ret = 0;

	if ( mstat->debug_on_error )
	{
		if ( tty_debug != NULL && debug_fd != 0 )
		{
			closeserial(debug_fd);
			debug_fd = 0;
		}
	}


	if ( boards[board].input_valid )
	{
		// Good data
		if ( boards[board].invalid_timer >= mstat->clear_comm_count )
		{
			// Max out
			boards[board].invalid_timer = mstat->clear_comm_count;
			// Clear error counter
			boards[board].count_errors = 0;
			// Clear comm error
			if ( boards[board].comm_error != NULL )
			{
				*(boards[board].comm_error) = 0;
			}
		}
#ifdef DEBUG_RX
		if ( boards[board].validcnt != NULL )
		{
			*(boards[board].validcnt) = *(boards[board].validcnt) + 1;
		}
#endif
	}
	else
	{
		ret=1;
		if ( mstat->debug_on_error )
		{
			if ( tty_debug != NULL && debug_fd == 0 )
			{
				debug_fd = openserial(tty_debug,B576000);
				mstat->debug_on_error = 0;
			}
		}
		set_debug( 1, 1 );

		// new error
		boards[board].count_errors++;
		// reset timer
		boards[board].invalid_timer = 0;
		// Total Count
		if ( boards[board].invalidcnt != NULL )
		{
			*(boards[board].invalidcnt) = *(boards[board].invalidcnt) + 1;
		}
	}
	if ( boards[board].count_errors >= mstat->set_perm_count )
	{
		// Max out.
		boards[board].count_errors = mstat->set_perm_count;
		// Set comm error
		if ( boards[board].comm_error != NULL )
		{
			*(boards[board].comm_error) = 1;
		}
		// Go into permenant error
		if ( boards[board].permanent_error != NULL )
		{
			*(boards[board].permanent_error) = 1;
		}
	}

	boards[board].invalid_timer++;

	return ret;
}
//
// Read for a maximum of 8 bytes time and timeout
// 8 bytes at 3,000,000 baud is about 30 usec
// wait for 1/2 msec since the usb turn around is long.
//
#if 0
static void read_data( int board )
{
	unsigned long t0, t1;
	unsigned char inp=0;
	int           cnt=0;
	int           valid = 0;

	t1 = t0 = rtapi_get_time();

	boards[board].input_cnt = 0;
//	boards[board].input_valid = 0;


//	while ( t1-t0 < 2000000 && boards[board].input_cnt < 15 )
	while ( t1-t0 < 200000 && boards[board].input_cnt < 15 )
	{
#ifndef NO_SERIAL
		cnt = read( sfd, &inp, 1 );
//		if ( read( sfd, &inp, 1 ) > 0 )
#endif
		if ( cnt > 0 )
		{
			set_debug( 1, 0 );

			boards[board].input_data[boards[board].input_cnt++] = inp;
#ifdef DEBUG_RX
			if ( boards[board].readbytes != NULL )
			{
				*(boards[board].readbytes) = *(boards[board].readbytes) + 1;
			}
#endif
			if ( boards[board].input_cnt >= 4 )
			{
//				boards[board].input_valid = validate_input( board );
				valid = validate_input( board );
			}

			// reset timeout
//			t0 = rtapi_get_time();

		}
		// Debug
#ifdef DEBUG_RX
		{
			int idx = (boards[board].input_cnt >= 4)?(boards[board].input_cnt - 4):0;
			if ( boards[board].readcount != NULL )
			{
				*(boards[board].readcount) = boards[board].input_cnt;
			}
			if ( boards[board].read0 != NULL )
			{
				*(boards[board].read0) = boards[board].input_data[idx++];
			}
			if ( boards[board].read1 != NULL )
			{
				*(boards[board].read1) = boards[board].input_data[idx++];
			}
			if ( boards[board].read2 != NULL )
			{
				*(boards[board].read2) = boards[board].input_data[idx++];
			}
			if ( boards[board].read3 != NULL )
			{
				*(boards[board].read3) = boards[board].input_data[idx++];
			}
		}
#endif
		if ( valid )
		{
			set_debug( 1, 0 );
			break;
		}

		t1 = rtapi_get_time();
	}

#ifdef DEBUG_RX
	if ( boards[board].maxreadtime != NULL )
	{
		if ( *(boards[board].maxreadtime) < (t1-t0) )
		{
			*(boards[board].maxreadtime) = t1-t0;
		}
	}
#endif
	
	read_counts( board );

}
#endif

unsigned long last_readtime;

static void read_all_data()
{
	unsigned long t0, t1;
	unsigned char inp=0;
	int           i, cnt=0;
	int           valid = 0;
	int           input_cnt = 0;
	int           input_idx = 0;
	u8            input_data[256];
	u8            input_address;
	u16           bits;

	t1 = t0 = rtapi_get_time();

#ifdef DEBUG_RX
	if ( boards[0].readcount != NULL )
	{
		*(boards[0].readcount) = 0;
	}
#endif

	while ( t1-t0 < mstat->max_rx_wait && input_idx < 255 )
	{
#ifndef NO_SERIAL
		cnt = read( sfd, &inp, 1 );
#endif
		if ( cnt > 0 )
		{
			set_debug( 0, 1 );
			input_data[input_idx++] = inp;
			input_cnt++;
			// Count all bytes in the first board
#ifdef DEBUG_RX
			if ( boards[0].readbytes != NULL )
			{
				*(boards[0].readbytes) = *(boards[0].readbytes) + 1;
			}
			if ( boards[0].readcount != NULL )
			{
				*(boards[0].readcount) = *(boards[0].readcount) + 1;
			}
#endif
			if ( input_cnt >= 4 )
			{
				if ( (input_address=validate_input_buffer( &input_data[input_idx - 4], &bits )) >= 0 )
				{
					// Find the board for this data
					for ( i=0;i<num_boards;i++)
					{
						if ( boards[i].address == input_address )
						{
							boards[i].input_bits  = bits;
							boards[i].input_valid = 1;
							boards[i].input_cnt = input_cnt;
							valid++;
							break;
						}
					}
					// Check for no boards...
					if ( i == num_boards)
					{
						// error, valid data for a board we don't have.
					}
					input_cnt = 0;
				}
			}

			// reset timeout
			t0 = rtapi_get_time();
			
			// Check max time between reads
			if ( last_readtime && *(mstat->maxreadtime) < (t0-last_readtime) )
			{
				*(mstat->maxreadtime) = (t0-last_readtime);
			}
			last_readtime = t0;
		}
		else // cnt > 0
		{
			// Are we done....
			if ( valid >= num_boards)
			{
				break;
			}
		}

		t1 = rtapi_get_time();
	}

	set_debug( 0, 0 );

	valid = 0;
	for ( i=0;i<num_boards;i++)
	{
		valid += read_counts( i );
	}
//	if ( valid )

	// Send data to debug
//	if (0)
	{
		if ( debug_fd != 0 )
		{
			write( debug_fd, input_data, input_idx );
		}
	}
}

// get HAL pins and set data
static void set_output( int board )
{
	int i, bit;

	// Get bits from HAL pins
	bit = 1;
	for (i=0;i<OUTPUT_PINS;i++)
	{
		if ( *(boards[board].output_pins[i]) )
		{
			boards[board].output_bits |= bit;
		}
		else
		{
			boards[board].output_bits &= ~bit;
		}

		bit = bit<<1;
	}

	// If error, reset outputs
	if ( *mstat->permanent_error )
	{
		boards[board].output_bits = 0;
	}

	// Build protocol bytes
	boards[board].output_data[ 0 ] = (boards[board].address << 3);
	boards[board].output_data[ 0 ] |= 0x3;

	boards[board].output_data[ 1 ] = (boards[board].output_bits >> 8) & 0xFF;
	boards[board].output_data[ 2 ] = boards[board].output_bits & 0xFF;
	boards[board].output_data[ 3 ] = 0x3;
	boards[board].output_data[ 3 ] |= ( nibble_xsum( boards[board].output_data ) << 4 );
}

static void set_input( int board )
{
	int i, bit;

	// If error, clear inputs
	if ( *mstat->permanent_error )
	{
		boards[board].input_bits = 0;
	}

	bit = 1;
	for(i=0;i<INPUT_PINS;i++)
	{
		if ( boards[board].input_bits & bit )
		{
			*(boards[board].input_pins[i]) = 1;
		}
		else
		{
			*(boards[board].input_pins[i]) = 0;
		}

		bit = bit<<1;
	}
}

static void handle_errors( void )
{
	int i, err;
	// Handle error reset
	if ( *mstat->reset_permanent )
	{
		*mstat->reset_permanent = 0;

		if ( ! *mstat->comm_error )
		{
			*mstat->permanent_error = 0;
			for ( i=0;i<num_boards;i++)
			{
				*(boards[i].permanent_error) = 0;
			}
		}
	}
	// Check for errors
	err = 0;
	for ( i=0;i<num_boards;i++)
	{
		if ( *(boards[i].comm_error) )
		{
			err = 1;
		}
	}
	*mstat->comm_error = err;
	if ( err )
	{
		*mstat->permanent_error = 1;
		set_debug( 1, 1 );
	}
}

static void serial_port_task( void *arg, long period )
{
	unsigned long        t0, t1;
	int                  i;
	char dat[4];

	memset( dat,0, 4);

	t0 = rtapi_get_time();

	// Update max time between thread calls.
	if ( threadtime && *(mstat->maxwritetime) < (t0-threadtime) )
	{
		*(mstat->maxwritetime) = (t0-threadtime);
	}

	// Check to be sure we are at the 10msec time < 9.5msec wait for the next tick.
	if ( (t0-threadtime) < 9500000 )
	{
		return;
	}
	threadtime = t0;

	*mstat->writecnt += 1;

	// Start the transmit to the first board.
	set_debug( 1, 0 );
//	set_debug( 0, 1 );
//  flush_input( 0 );
	set_debug( 0, 0 );

	// Send data to all boards
	for ( i=0;i<num_boards;i++)
	{
		// get pins from user
		set_output( i );

		set_debug( 0, 0 );
		send_data( i );
		set_debug( 0, 1 );

		// Make sure it goes before queuing the next one
		wait_tx_empty();
		set_debug( 0, 0 );

		// Reset receive data flags
		boards[i].input_valid = 0;
		boards[i].input_cnt = 0;
	}
	// Fill in minimum tx data with 0's
	for ( i=num_boards; i<mstat->min_tx_boards; i++)
	{
		set_debug( 0, 0 );
		write( sfd, dat, 4 );
		set_debug( 0, 1 );
		wait_tx_empty();
		set_debug( 0, 0 );
	}

	// Read data from all boards
	read_all_data();

	handle_errors();

	// Set pins to user
	for ( i=0;i<num_boards;i++)
	{
		set_input( i );
	}
	t1 = rtapi_get_time();
	runtime = t1 - t0;

}

Attachment: hal_p260c.so
Description: Binary data

Reply via email to