TS-7500: Accessing DIO from C and Python via server

The TS-7500 single board computer from Technologic Systems is one of a family of boards based on the Cavium ARM processor. The board runs a standard Debian Linux system from an SD card, useful for development, and alternatively a uClibc/Busybox system from flash for the production phase (boots in less than 3 sec). This computer board can be plugged onto a TS-252 IO-board for external connections.

The IO-pins can be accessed via the two port dioctl server running on the main board (or directly). One server port serves manual access by Telnet, the other one accesses from programs – any programming language with a socket library, remote or local.


Here is a Python program to read internal pin number 26 to 40 which map to pin number 1-8 on the lower connection block. To read a pin you first have to send a message consisting of a opcode and pin number byte, see the outdated documentation dioctl.rtf within the boards dioctl tarball. There are of course opcodes for configuration and output pin setting too. I timed the loop (without the print), took about 5 msec for each read, 3.5 msec when run from my PC via direct Ethernet cable connection.

import socket
import sys
import time
HOST= 'localhost'
PORT= 4500
try:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
    sys.stderr.write("[ERROR] %s\n" % msg[1])
    sys.exit(1)
try:
    sock.connect((HOST, PORT))
except socket.error, msg:
    sys.stderr.write("[ERROR] %s\n" % msg[1])
    sys.exit(2)
for i in (26,28,30,32,34,36,38,40):
    s= chr(4)+chr(i) # s[0]= op code, s[1] pin number
    sock.send(s)
    data = sock.recv(1)
    print "%d %x"%(i, ord(data))

And here is a C program doing the same task. I programmed this on my PC, cross compiled and copied over to the TS-7500. I timed the main function loop to take about 3 msec.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int readInputPin(int sd, int pin);
int dioportOpen(int port, char * hostName);

int main(void)
{
	int sd, portno, i, r;
	char hostname[50];
	portno= 4500;
	strcpy(hostname,"localhost");
	printf("I'm diotest - crosscompiled for uClibc\n");
	sd= dioportOpen(portno, hostname);
	switch(sd) {
	case -1: printf("Unknown host\n"); break;
	case -2: printf("No such host\n"); break;
	case -3: printf("problem connecting\n"); break;
	default:                beg= time(NULL);
             for(i=26; i<=40; i += 2) {
                        r= readInputPin(sd, 30);
                        printf("%d %d\n", i, r);
                }
                close(sd);
                return 0;
        }
        return -1;
}
 
int readInputPin(int sd, int pin)
{
	char buffer[2];
	int n;
	buffer[0]= 4;
	buffer[1]= pin;
	n = write(sd,buffer,2);
	if (n < 0) return -1; // error writing to socket
	n = read(sd,buffer,1);
	if (n < 0) return -2; //error reading from socket
	if(buffer[0]&0x40) return 1;
	return 0;
}
int dioportOpen(int port, char * hostName)
{
    int sd;
    struct sockaddr_in sin;
    struct hostent *host= gethostbyname(hostName);
    if (host == NULL) return -1;
    sd = socket(AF_INET, SOCK_STREAM, 0);
    if (sd < 0) return -2;
    memcpy((char *) &sin.sin_addr.s_addr, host->h_addr, host->h_length);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);
    if (connect(sd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
        return -3;
    return sd;
}

And the accompanying Makefile, see my post
Cross compile for ARM, TS-7500 board about how to install the cross compiler.

CC=/usr/local/ts7500/arm-uclibc-3.4.6/bin/arm-linux-uclibc-gcc
CFLAGS=-c -Wall -march=armv4 -Os
LDFLAGS= --rpath=/slib 

all: diotest_uc

diotest_uc: diotest.o
	$(CC)  $(LDFLAGS) diotest.o -o diotest_uc
diotest.o:diotest.c
	$(CC) $(CFLAGS) diotest.c -o diotest.o

 

 

Now, it is also possible to bypass the server complexity and access the hardware directly using C functions. The getdiopin function below is taken from the TS-7500 manual. The speed is now about 30 micro sec for each loop.

#include <stdio.h>
#include <unistd.h>
#include "sbus.h"
int getdiopin(int pin)
{
    int pinOffSet;
    int pinValue = 99999;

    sbuslock();
    if (pin <= 40 && pin >= 37) {
        pinOffSet = pin - 25;
        pinValue = (sbus_peek16(0x66) >> pinOffSet) & 0x0001;
    }
    else if (pin <= 36 && pin >= 21) {
        pinOffSet = pin - 21;
        pinValue = (sbus_peek16(0x68) >> pinOffSet) & 0x0001;
    }
    else if (pin <= 20 && pin >= 5) {
        pinOffSet = pin - 5;
        pinValue = (sbus_peek16(0x6e) >> pinOffSet) & 0x0001;
    }
    sbusunlock();
    return pinValue;
}

int main(void)
{
    int r, i;
    for(i=28; i<=40; i += 2) {
        r= getdiopin(i);
        printf("Read value: %d  %d\n", i, r);
    }
    return 0;
}

The buslock and unlock functions are in sbus.c and sbus.h. Copy them to the present directory and run this Makefile to produce the diotestdir executeable (which must be run as root):

CC=/usr/local/ts7500/arm-uclibc-3.4.6/bin/arm-linux-uclibc-gcc
CFLAGS=-c -Wall -march=armv4 -Os
LDFLAGS= --rpath=/slib

all: diotestdir

diotestdir: diotestdir.o sbus.o
$(CC) $(LDFLAGS) diotestdir.o sbus.o -o diotestdir

diotestdir.o:diotestdir.c
$(CC) $(CFLAGS) diotestdir.c -o diotestdir.o

sbus.o:sbus.c
$(CC) $(CFLAGS) sbus.c -o sbus.o

 

0 Responses to “TS-7500: Accessing DIO from C and Python via server”


  • No Comments

Leave a Reply