Problem with NGW100 + ttyS1 + select()

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have some test code that I am unable to get working.

I was hoping someone else could try it or tell me where I'm going wrong.

I have an NGW100 and am running the latest buildroot distro from www.atmel.no (release 2.1.0, updated 20071213).

I am trying to use the select() function on port /dev/ttyS1, using the following code ...

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//#include "../nfbase/StdAfx.h"
#define TRUE 1
#define FALSE 0

#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1					//POSIX compliant source

FILE *input;
FILE *output;

main(void) {
	int fd, res, i;
	char buf[255];							//buffer for where data is put
	
	fd_set rfds;
	struct timeval tv;
	
	input = fopen("/dev/tty", "r");			//open the terminal keyboard
	output = fopen("/dev/tty", "w");		//open the terminal screen
	
	// open the device(com port) to be non-blocking (read will return immediately)
	fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
	if (fd < 0) {
		perror(MODEMDEVICE);
		exit(-1);
	}
	
	// make fd asynchronous
	fcntl(fd, F_SETFL, FASYNC);
	
	// init timeout
	FD_ZERO(&rfds);
	FD_SET(fd, &rfds);
	
	// loop forever ...
	while (1) {
		// reset timeout value (because select() invalidates the timeout values)
		tv.tv_sec = 1;
		tv.tv_usec = 0;
		// wait for request (or a timeout)
		if ((select(fd + 1, &rfds, NULL, NULL, &tv)) > 0) {
			fputc('S', output);
			// read heartbeat char
			res = read(fd, buf, 1);
			fputc('H', output);
			fflush(output);
		} else {
			// display timeout message
			fprintf(output, "Timeout waiting for heartbeat, err = %d\n", errno);
			// reset fd bit
			FD_SET(fd, &rfds);
		}
	}
	
	close(fd);		//close the com port
}

I set up the comms port using the command ...

stty -F /dev/ttyS1 raw

If nothing is connected to the comms port, when I run my code, I get the output ...

Timeout waiting for heartbeat, err = 0
Timeout waiting for heartbeat, err = 0
...

But when I connect my test kit (which is outputting the letter 'H' every 500ms), I get ...

I/O possible

If I do an strace, I get the output ...

...
open("/dev/ttyS1", O_RDWR|O_NOCTTY|O_NONBLOCK) = 5
fcntl(5, F_SETFL, O_RDONLY|O_ASYNC)     = 0
select(6, [5], NULL, NULL, {1, 0})      = 1 (in [5], left {0, 596000})
--- SIGIO (I/O possible) @ 0 (0) ---
+++ killed by SIGIO +++
Process 224 detached

If I change a single flag via stty ...

stty -F /dev/ttyS1 icanon

I get the output as if nothing was connected ... i.e. ...

Timeout waiting for heartbeat, err = 0
Timeout waiting for heartbeat, err = 0
...

Can anyone help me diagnose what's going on ?

BTW, this code was taken from an Atmel AT91 dev kit where it all works fine.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As an additional piece of info, if I just "cat" from the comms port, it all seems to work ???

# cat < /dev/ttyS1
HHHHHHHH
#
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

FIXED !! :D

I removed the fcntl() call. Reading the fcntl() man page shows that this *does* send a SIGIO to the task, which is exactly what was happening (doh!!).

Now why this worked on the AT91 dev kit, I don't know, but who cares !!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mpfjackson wrote:
Now why this worked on the AT91 dev kit, I don't know, but who cares !!

Async I/O is broken on ARM? ;-)

Good to see that you figured it out!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, I've got the following code running on the NWG100:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
static float Counter = 0,SinOfCounter;
static void SetPin(int Set);


static void sigio_handler(int sig, siginfo_t *info, void *context)
{
    unsigned long new_state;
    static int Toggle;
	 /* Even if use_nonblock is set, this should never fail as we
	 * shouldn't be here if no new data is available.
	 */
	if (read(Fd1, &new_state, sizeof(new_state)) < 0)
		perror("read error in sigio_handler");
// I want to do stuff here
        SetPin(Toggle);
        Toggle = !Toggle;  
        Counter+=1.0/400.0;
}

int InitTestPins(void)
{
	const char *dev_name = "/dev/gpio0";
	const char *dev_name1 = "/dev/gpio1";
	Fd = open(dev_name, O_RDWR);
	if (Fd < 0) {
		fprintf(stderr, "failed to open %s: %s\n\r",
			dev_name, strerror(errno));
		return 1;
	}
	Fd1 = open(dev_name1, O_RDONLY);
	if (Fd1 < 0) {
		fprintf(stderr, "failed to open %s: %s\n\r",
			dev_name, strerror(errno));
		return 1;
	}
	return 0;
}

void InstallSigIoHandler(void)
{
		struct sigaction sigio_action = {
			.sa_sigaction = sigio_handler,
			.sa_flags = SA_SIGINFO,
		};
		int flags;

		/*
		 * Don't mask any signals when handling SIGIO (except
		 * SIGIO itself, which is masked by default.)
		 */
		sigemptyset(&sigio_action.sa_mask);
		if (sigaction(SIGIO, &sigio_action, NULL)) {
			perror("failed to install SIGIO handler");
			return ;
		}

		/* Tell the kernel that our process will take care of SIGIO */
		if (fcntl(Fd1, F_SETOWN, getpid())) {
			perror("failed to set fd owner");
			return ;
		}

		/* Enable asynchronous I/O */
		flags = fcntl(Fd1, F_GETFL);
		if (fcntl(Fd1, F_SETFL, /*flags |*/ O_ASYNC) < 0) {
			perror("failed to set O_ASYNC");
			return ;
		}

}

static void SetPin(int Set)
{
    unsigned long new_state;
    if (Fd > 0)
    {
      if (Set)
      {
	new_state = 0x80000;
	if (write(Fd, &new_state, sizeof(new_state)) < 0) {
		perror("failed to write new pin state");
	}
      }
      else
      {  
	new_state = 0;
	if (write(Fd, &new_state, sizeof(new_state)) < 0) {
		perror("failed to write new pin state");
	}
      }  
    }     
}

int main(void)
{
  InitTestPins();
  InstallSigIoHandler();
  printf("\n");
  while (1)
  {
    float tmp;	
        tmp = Counter;
        while (tmp > M_PI) tmp -= 2*M_PI;  
        SinOfCounter = sin(tmp);
    printf("\rCounter = %+12.3f (sin(%+7.4f) = %+7.4f)",Counter,tmp,SinOfCounter); 
    if (fabs(SinOfCounter) > 1.0) printf("\n\r");
  }
  return 0;
}

If I inject a signal to get the SIGIO to trigger the printing in the main function stops after a while. The higher the frequency, the sooner the console freezes. The interrupt routine continues to run (measuring with a scope). Any ideas?