LUFA CDC problem in Linux

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

Hello,

I'm developing my own USB board with an ATmega16U4 and I'm coming along great thanks to the use of LUFA (thanks Dean!) and the VirtualSerial demo using CDC.

I have one problem However, I implemented a set of possible commands for the device, among which a Ping command. This works great under windows, not a single glitch in any of the commands, whether complicated or a simple ping (0x50)(which directly puts "pong" (0x51) on the output buffer of the AVR).

But in Linux the device is recognized as a ttyACM0 (is that right? I don't know!) and when I try to write to it from console (sending keystroke P) or send 0x50 from C code nothing happens. Nor do any of the "LED_ON" command sequences actually turn on the LEDs, where Windows has no problem flashing them in any pattern I desire.

Is there something that needs to be configured in Linux first? I'm very much a newbie in Linux, but I do want this board to function with it so my friends can choose their own OS.

Best regards,

Robert!

Embedded design is as much a life choice as any other and I demand the right to legally marry my work.
-------
If it helps, I can PM you my answer in a number of different languages. Ask if you have trouble reading my high-speed-babble in English.

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

Tiny update:
The LED on / off commands do work, there was a tiny problem in there, both through "echo" in console and from C code, I had made a error in calculating the right byte to send.

However, I still receive no answer from the USB device, while Windows does receive the PONG and ACK responses.

Any ideas why I can't receive either in "cat" in console or in the C file buffer?

Embedded design is as much a life choice as any other and I demand the right to legally marry my work.
-------
If it helps, I can PM you my answer in a number of different languages. Ask if you have trouble reading my high-speed-babble in English.

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

Have you checked your permissions? Try opening your terminal with "sudo" or similar - on Ubuntu at least, users by default do not have the needed permissions to directly access ACM devices. A permanent fix for this would be to add the LUFA VID/PID to your "udev" scripts, but personally I've just always opened my terminal app with root privileges.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Sorry for the late reaction, I thought I had it configured so I would get an e-mail when there was a reply :-S

It seems root login doesn't help really, weird thing is that at one point CAT in root seemed to spew a whole lot of nonsense, including two pong responses (letter Q). Whether the two Q's among the @'s #'s and %'s, etc were actual responses or pure coincidence I cannot say, as the device does only send back the pong byte. But that was the first and last time that happened.
Also running the program, using open() close() etc as root does not seem to help, it keeps hanging on the receive part of the program.
If I add a LED-toggle to the ping handler in the chip the LED toggles exactly as expected, but the difference between Linux and windows stays that windows does receive the responses and Linux does not.

Is there an essential difference between things like open() and fopen() in this case? I know the basics, but maybe I overlooked something to do with the whole tty-aspect.

Basically the code for the port test is ("all silly remarks and commented code removed"):

int fd;
char reply[100];
int bytesWritten; 
int bytesRead;


fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NONBLOCK);

if( fd == -1 ) {
	perror("open_port: Unable to open /dev/ttyACM0 - ");
}
else {
	fcntl(fd, F_SETOWN, getpid() );
			// Use blocking behaviour
	fcntl(fd, F_SETFL, 0);
}

bytesWritten = write(fd, "P", 1 );

if( bytesWritten < 0 ) {
	 fputs("Sending of PING failed\n", stdout);    
	if( fd != -1 ) close(fd);
		return 1;	
}	
else     
	fputs("Sending of PING succeeded!\n", stdout);

bytesRead = read(fd, reply, 1);

if( bytesRead < 0 )
	fputs("Receiving of PONG failed\n", stdout);    
else     
	fputs("Receiving of PONG succeeded!\n", stdout);

printf("% s\n", reply); // <-- added a space between % and s, 
//because phpBB choked on it, 
//in the code this bit is without spaces :-).
if( fd != -1 ) close(fd);

The console shows upon compile/make and run:

Tests have been started
Sending of PING succeeded!

And after that: Nothing.
At the moment it is run the test LED also toggles, so it did indeed send the ping byte.

Embedded design is as much a life choice as any other and I demand the right to legally marry my work.
-------
If it helps, I can PM you my answer in a number of different languages. Ask if you have trouble reading my high-speed-babble in English.

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

If you use gdb to step that Linux code presumably it is simply never returning from the read() then?

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

going to attempt figuring out how gdb works (remember, I'm not a native Linuxian - Linuxer - Linuxist.. ?!?!), but from the way it hangs combined with CAT's behavior I'm almost sure it's safe to say that is indeed not returning from read().
I'm also very sure that somewhere in my head this triggers a tiny little bell... But it isn't loud enough. Probably because I have a volatile-chemicals-hang-over right now.

Embedded design is as much a life choice as any other and I demand the right to legally marry my work.
-------
If it helps, I can PM you my answer in a number of different languages. Ask if you have trouble reading my high-speed-babble in English.

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

For an easy life apt-get (or yum or whatever) a copy of ddd to accompany the gdb and wrap a nice, easy to follow/use GUI around the command line hell that is gdb. You can then (assuming it's built with -g) just "ddd myprog" and then "run " after placing a breakpoint at the entry to main(), from there step on/over through it.

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

Yay! I just used gdb!
It does indeed hang on the read(), which isn't a real miracle if there's no new data, but I'm pretty sure there should be a nice Q for it to receive.

*frown*
---
edit:
Will look into ddd later, sounds like a good plan, as I just threw away 30 minutes of the boss' time to get how to use three functions of gdb.
Thanks for that, seeing as my program will have to become more complex later to test all functions such as a set of LM92 I2C temperature sensors and interval checking and possibly even a separate thread for receiving unpredictable data.

Embedded design is as much a life choice as any other and I demand the right to legally marry my work.
-------
If it helps, I can PM you my answer in a number of different languages. Ask if you have trouble reading my high-speed-babble in English.

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

It seems it's all in Linux, I have put the OS aside until all the embedded code is complete and will then resume this discussion on a Linux forum.

I would like to thank you all for your help and attention and if there is anything you happen to think of don't hesitate to send me a message.

Special thanks once again to Dean for a marvellous toolset that goes by the name of LUFA - Good stuff!

*hugs*

Robert!

Embedded design is as much a life choice as any other and I demand the right to legally marry my work.
-------
If it helps, I can PM you my answer in a number of different languages. Ask if you have trouble reading my high-speed-babble in English.

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

You neglected to turn off line buffering. The Serial Programming Guide for POSIX Operating Systems by Michael R Sweet is worth a read.