Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place! |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
02-10-2010, 11:01 AM
|
#1
|
LQ Newbie
Registered: Jun 2006
Distribution: openSUSE, Ubuntu
Posts: 23
Rep:
|
RS232c and OpenGL in same program
I am trying to write a program that accepts user input from the keyboard and a joystick and then sends out the data using the rs232 port of my system to other hardware. I need to send out about 10 bytes every 20 milliseconds. The thing is I need to also keep on reading data from the same port and display it on an opengl screen. This visualizes the hardware data coming in.
So the way I did it was by spinning everything around opengl..I setup GLUT - as follows :
/* register call back functions */
glutDisplayFunc(redraw);
glutReshapeFunc(resize);
glutIdleFunc(visualize);
glutKeyboardFunc(getkey);
glutSpecialFunc(getspecialkey);
and in the idle function visualize() ...I currently do the joystick reading and rs232 packet sending and recv stuff.
I also call redraw after I am done so if I have received new data above, then it gets drawn on the screen.
Everything works fine except that calling redraw() from visualize() is logical in a PC simulation where the simulation state needs to be rendered on screen after a simulation step. But in my case it takes up too much time ...much greater than 20 ms.....so I can no longer guarantee i can send out packets through the rs232 port every 20 ms.
What are my options here if I want to send out packets and visualize data at a reasonable frame rate - packets within 20 ms is more imp of course.
|
|
|
02-10-2010, 11:24 AM
|
#2
|
Senior Member
Registered: Jul 2005
Distribution: Slackware
Posts: 2,012
Rep:
|
I'd suggest you use SDL for your opengl context. It's far easier to control how the mainloop operates and the event API is superior.
For the main issue, create a worker thread to do the sim and shove the data into the rs232 device. The visualization should take a snapshot of the sim state and display it however it likes (I'm assuming that the keyboard and joystick input has zero impact on the sim results).
|
|
|
02-10-2010, 11:36 AM
|
#3
|
Member
Registered: Jan 2010
Location: the universe
Distribution: Slackware (modified), Slackware64 (modified), openSuSE (modified)
Posts: 342
Rep:
|
Perhaps you should put the time critical data i/o over the RS232 into a separate thread so that you do not have to wait until the screen was rendered. Maybe you should have a look on the pthreads manual page.
What I would suggest is a solution closer to the unix philosophy:
Write a program that does all the hardware i/o and receives it commands and data and sends its results over some of the IPC mechanisms (unix sockets or shared memory) to your visualizing application.
This ensures that the time critical i/o works reliable and you could even replace the visualizing software on the fly or allow multiple applications to use the data at the same time.
On further benefit will be that the daemon can be run as a different user than the visualizing software and so this also increases security. Furthermore this kind of architecture is easier to debug. As a side effect only minor changes will be required to run the visualizing software on a more powerful system (higher frame rate) while the i/o daemon is running on a slower system. But use your own imagination in this case.
|
|
1 members found this post helpful.
|
02-10-2010, 12:18 PM
|
#4
|
LQ Newbie
Registered: Jun 2006
Distribution: openSUSE, Ubuntu
Posts: 23
Original Poster
Rep:
|
yes right....I think I will split up the 2 things into 2 threads.
ok 2 things : first the visualizing part -
I think I will drop opengl & glut for the visualizing part as I just need to show some basic 2D gauges and SDL should suffice as well as handle the keyboard event management stuff. I think SDL should be more lightweight than opengl and the thread should run fast enough.
If it doesnt run fast enough then the problem is it may miss keyboard input as SDL does not use callbacks like glut, it uses an event loop.
As for the joystick I am directly using the joystick C api whose code is something like this......
Code:
if ((fd_joystick = open("/dev/js0", O_RDONLY)) < 0) {
perror("jstest");
exit(1);
}
ioctl(fd_joystick, JSIOCGAXES, &axes);
ioctl(fd_joystick, JSIOCGBUTTONS, &buttons);
if (read(fd_joystick, &js, sizeof(struct js_event)) != sizeof(struct js_event)) {
perror("\njstest: error reading");
return 0;
}
switch(js.type & ~JS_EVENT_INIT) {
case JS_EVENT_BUTTON:
button[js.number] = js.value;
break;
case JS_EVENT_AXIS:
axis[js.number] = js.value;
break;
}
I could use SDL for the joystick input as well though I am not sure if it will be faster than the direct method above. So I will put this code in the same event loop just after the switch-case to check keyboard events.
I just hope SDL is fast enough to not actually drop any inputs from the keyboard.
Now for the worker thread :
Here I can simply keep sending packets at 20 ms and then receive whatever is coming back.The receiving call is of course non blocking so it doesnt jam the thread. I can have this thread at a higher priority.
So pthreads is the standard for threading in Linux ? I just need something with minimum overhead for context switches
|
|
|
02-10-2010, 12:22 PM
|
#5
|
LQ Newbie
Registered: Jun 2006
Distribution: openSUSE, Ubuntu
Posts: 23
Original Poster
Rep:
|
I had though of IPC and sockets but since the application is very basic there didnt seem to be a need for adding an extra layer of communication....since threads stay in the same address space they can access common variables faster.
|
|
|
02-10-2010, 12:37 PM
|
#6
|
Member
Registered: Jan 2010
Location: the universe
Distribution: Slackware (modified), Slackware64 (modified), openSuSE (modified)
Posts: 342
Rep:
|
pthreads stands for "posix threads" and is the standard under linux. All programs and libraries I know use pthreads, either directly or over some higher level library.
Why are you afraid of loosing keyboard input? There are buffers in the kernel and in the X server and xlib (if using under x11). I do not think that you will press keys so quickly that these buffers will overflow unless using a very old system.
|
|
|
02-10-2010, 02:31 PM
|
#7
|
Senior Member
Registered: Jul 2005
Distribution: Slackware
Posts: 2,012
Rep:
|
Quote:
I could use SDL for the joystick input as well though I am not sure if it will be faster than the direct method above. So I will put this code in the same event loop just after the switch-case to check keyboard events.
|
"Premature optimization is the root of all evil"
Before you do funny stuff like directly access the joystick device and lose cross-platform compatibility, make sure that it's actually the bottleneck with profiling. It's actually also quite dangerous because SDL assumes you aren't doing such things and will do things like take locks.
SDL's input subsystems are quite fast enough. After all, games have extremely strict real-time requirements. SDL also has a threading subsystem as well, so you can use them and still keep cross-platform compatibility.
Quote:
I had though of IPC and sockets but since the application is very basic there didnt seem to be a need for adding an extra layer of communication....since threads stay in the same address space they can access common variables faster.
|
Shared memory being faster is a myth. More often than not, locking requirements completely destroy any possible benefits. In fact, you should try to avoid sharing as much data as possible between threads because of the costs of locking, in the overhead of the lock itself, that the lock turns your multi-threaded program into a single-threaded program, and the headache involved with making sure you don't end up with race conditions.
Last edited by tuxdev; 02-10-2010 at 02:46 PM.
|
|
1 members found this post helpful.
|
02-10-2010, 06:45 PM
|
#8
|
LQ Newbie
Registered: Jun 2006
Distribution: openSUSE, Ubuntu
Posts: 23
Original Poster
Rep:
|
Yeah..i think I ll go ahead with SDL. About the threads...I am planning to store the user inputs in a set of global variables by the thread containing the SDL event loop and having it picked up from there to be sent by the rs232 thread. After sending, the same thread checks if anything is there in the local UART buffer and if so, it stores it in a different set of receive variables. The receive variables are only read by the SDL event thread and never written to.
So in either case, 1 thread is writing and the other reading....so I am hoping this wont cause any locking issues as these are the minimum variables which have to be shared.
|
|
|
02-10-2010, 07:05 PM
|
#9
|
Member
Registered: Jan 2010
Location: the universe
Distribution: Slackware (modified), Slackware64 (modified), openSuSE (modified)
Posts: 342
Rep:
|
But there is still a need for locking, because the SDL event thread can try to read data while the rs232 thread is writing it. The same goes for the input handling. Perhaps you will never observe any errors but locking will be required anyway.
|
|
|
02-10-2010, 07:14 PM
|
#10
|
LQ Newbie
Registered: Jun 2006
Distribution: openSUSE, Ubuntu
Posts: 23
Original Poster
Rep:
|
hmmm...maybe I can have a semaphore variable in there to lock the data while the rs232 thread writes it....as somehow I need to get the data from the port to the rendering thread. Does Pthread support priorities so I can run the rs232 thread at a higher one. It may cause the rendering thread to often not have access to the shared variables if the rs232 is constantly locking it....but I guess there is no other way around it.
|
|
|
02-10-2010, 07:22 PM
|
#11
|
Member
Registered: Jan 2010
Location: the universe
Distribution: Slackware (modified), Slackware64 (modified), openSuSE (modified)
Posts: 342
Rep:
|
You can find a tutorial to pthreads here:
https://computing.llnl.gov/tutorials/pthreads
pthread_attr_setschedparam can be used to set the priority of the thread.
You can also use condition variables: The render thread will sleep until there is new data to render and this won't waste cpu time. (see the link above)
|
|
1 members found this post helpful.
|
All times are GMT -5. The time now is 02:44 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|