Hi,
I made up a simple applicationthat read serial data from a port using an arinc board… nothing strnge until now…
the apps runs without problems but the system is veeeeery slow…
I analyze my system and i found that this program is using a cpu time very high…i see that other apps have a growing CPU occupancy time but in my case it is growing too fast…
here the result of two calls to sin
procnto 1 0 0 0 0 52002
devc-con 2 60K 92K 4K 516K 229
slogger 4099 8K 60K 4K 516K 29
pipe 4100 16K 72K 20K 912K 16
mqueue 4101 12K 56K 4K 516K 19
pci-bios 8198 40K 56K 4K 516K 29
devc-bluestorm 8199 40K 112K 12K 780K 39
devc-eth_escc 8200 32K 76K 8K 648K 27
devc_arinc 8201 8K 60K 132K 644K 21
devc-par 8202 44K 76K 12K 648K 21
devc-pty 8203 44K 92K 4K 516K 40
io-net 24589 64K 484K 84K 1041K 712
qconn 28687 80K 140K 20K 912K 1950
inetd 28688 36K 88K 8K 516K 13
devb-eide 40974 52K 19M 72K 608K 165
nmea 98323 4K 56K 8K 516K 19
nmea 98324 4K 56K 8K 516K 23
arinc 98325 4K 516K 8K 516K 245268
sh 110604 144K 60K 4K 516K 25
sh 122897 144K 60K 4K 516K 17
telnetd 122898 108K 96K 12K 516K 18
sh 126998 144K 92K 8K 516K 16
sin 131095 80K 76K 8K 516K 0
procnto 1 0 0 0 0 52011
devc-con 2 60K 92K 4K 516K 229
slogger 4099 8K 60K 4K 516K 29
pipe 4100 16K 72K 20K 912K 16
mqueue 4101 12K 56K 4K 516K 19
pci-bios 8198 40K 56K 4K 516K 29
devc-bluestorm 8199 40K 112K 12K 780K 39
devc-eth_escc 8200 32K 76K 8K 648K 27
devc_arinc 8201 8K 60K 132K 644K 21
devc-par 8202 44K 76K 12K 648K 21
devc-pty 8203 44K 92K 4K 516K 40
io-net 24589 64K 484K 84K 1041K 716
qconn 28687 80K 140K 20K 912K 2034
inetd 28688 36K 88K 8K 516K 13
devb-eide 40974 52K 19M 72K 608K 165
nmea 98323 4K 56K 8K 516K 19
nmea 98324 4K 56K 8K 516K 23
arinc 98325 4K 516K 8K 516K 256024
sh 110604 144K 60K 4K 516K 25
sh 122897 144K 60K 4K 516K 17
telnetd 122898 108K 96K 12K 516K 18
sh 126998 144K 92K 8K 516K 16
sin 139287 80K 76K 8K 516K 0
between the first and the second call I wait just 1 second…
now my question is: how can I reduce this time growth?
with other apps the problem is solved when i do a fread() because the process enter a reply-blocked state. in this case (with arinc) I can’t do a fread call because i must use API calls supplied with the board (i’ve just a library and a programmer guide), so the process is always in ready state, so not blocked…
I hope I’ve been clear enough to make any of you understand…
Hello,
as I understand it, the read call of your API is not blocking when there is no data, so your program is effectivly always READY. Two possibilities:
- Browse your API for a blocking mechanism: Either a flag to tell open or read function to block when no data available or a dedicated wait function (like select()).
- Polling, and going to sleep for n milliseconds if no data available, effectively yielding the CPU to other processes.
Perhaps you can give some more infos on the API so we find out more.
Regards,
Albrecht
you perfectly understand!
so, reading the user’s manual of the board I can’t find out a way to block the process…
theorically (??) there is a way:
when you want to read from the device, you can’t use a read, but API gives a AR_GETNEXT() function which is described as:
[i]this utility attempts to get data from an input channel. If none is there, it continues trying for up 1/4 second before stopping. It calls AR_GETWORD repeatedly, returning when it receives a response or times out.
The system clock is used to time out this function. For the CEI-x20 in 32 bit Windows, the Sleep() function is used to avoid tying up the processor while waiting for label to arrive.[/i]
now:
CEI-x20 is my type of board.
AR_GETWORD is a function that read just once at calls (if you want to read more data, you might insert it inside a while, for exemple…or just use AR_GETNEXT
)
i try to use sleep, usleep, combine it with sched_yield, some other crazy things, but the process is always on ready state…
I’m trying to attach the read function to an interrupt but I don’t know how good is it (similar to 2) )
Hello,
-
sleep( n ) does block the calling thread for n seconds. No ifs, no buts. Try writing a simple program that calls sleep( 1 ) in an endless loop and watch the states in pidin. If that is not working your system is corrupt! Perhaps the API is silently creating some receiver thread on its own, and this thread is running mad. Try to identify the threads using pidin!
-
It looks that the API comes from Windows world. Have you got the source code? How did you get QNX on that board at all? Do you have a Board Support Package (BSP) from somewhere? There should be a serial driver included that maps /dev/ser1 in the path name space and you can use POSIX read() - blocking or NON-blocking - at your leisure. Or is it a special piece of hardware?
-
If the hardware asserts an interrupt when data is available then the ISR is definitely the spot where to put the AR_GETWORD() function. Or is this only a macro that expands to something crazy?
You see, it’s difficult to answer without any knowledge about the board. But we will find out.
Regards,
Albrecht
Don’t worry Alb, you are giving me a great hand!!
I know it is difficult (expecially for my chaotic english! - I’m sorry for that)
so…
-
API doesn’t starts any thread…
-
yes. i bought this board (that is a PC104 card, not an standard pc card). with the board they give me some packages precompiled for Windows, Dos and Linux Red Hat, and the source code of the api library… I must work on QNX (i’m doing it as work, they will pay me, but I’ve never seen a qnx system beforethat) so, I build this shared object which contain all the api calls for that board (not so difficult, except I spent a lot of time to find out the right memory mapping
)
i thought that probabily there is something wrong with the API, or with the way the were compiled, but i verify that everything works ok…I mean, if I try to read from the device, it receive all labels with no sigle error…the problem is, that if I read from arinc device, I can’t read from any other standard serial device…(effectively it doesn’t work
)
-
AR_GETWORD is a routine, not a macro…AR_GETNEXT is a routine too, based on AR_GETWORD(but is easy to use AR_GETNEXT instead of AR_GETWORD iside a while, with some if to verify if data are avaiable on channel, ecc…)
-
(uhm…there is not a 4th question…) interrupts are enebled/disabled via HW except my kind of board (grrr)…to do this I need a API call to AR_INT_CONTROL. there is another api call that is AR_INT_SET that rceive as parameter the number of the board(not so important now) and assigned number of interrupts choose between 3,5,6,7 and 9 using as default 5…
(in my system int5 is already assigned, so the only n/a is 9…
I hope there is some good informations…
thanks again…
Hi,
I don’t know what arinc device is or what labels are. Is arinc a hardware device? Are labels some kind of data packets? Remember, you have to be root and you have to have I/O privity (ThreadCtl(_NTO_TCL_IO, 0)) before you can make I/O to any hardware.
Regards,
Albrecht
ops, I’m sorry…
Arinc 429 is a serial protocol used for flight device comunications (airplanes, helicopters, etc…) I will not explain all characteristics and advantages (the most important is that arinc is better than rs422 because it can used to cover big distances with no signal dispersion)(I’m not sure it is good explaination - I’m sorry)
to interface my pc (in this case is a PC104, not a desk) i use this arinc board called CEI-420A by Condor Engineering…
labels are some kind of data packets (for more precion, the label is a part of the packet that identify the kind of the packet, and other bits are data, flags and stuff)…
I have both root and I/O privity…
For now I found some kind of solution:
In the main process I do all settings of the arinc board (such as bitrate, parity, internal wrap, etc…), so I start a thread with the looped read function and data conversion (I must attach time and data read from gps to the read message, but this is not a problem, everything work fine)…
if I do only this, situation is exactly the same…
so I enbled Interrupt on the board, and I’ve done:
while (1) {
InterruptWait(0, NULL);
. . .
// read, stuff and bla bla bla...
}
in this way the thread goes on INTR state but for now it is not able to receive any data (or probably i must set up in a better way the board to make it feel the interrupt)
however, thaks for your help until now…
Depending on how time critical your task is, you could create a signal event and use it with a timer to stop your READY whatever polling function. Then you go to sleep for a while, or use delay(), and then use the CPU-consuming routine again. This at least would give you some CPU time for other tasks, but of course also a maximum latency on receving the data equal to the time specified in the delay()… Very ugly, but if you don’t find another solution, this could help…
mmm very interesting thing…I will try it right now…
thanks…
Hi,
I refer to your code snippet with the InterruptWait() call. Remember that the thread that calls this function must be the one that calls InterruptAttachEvent(), otherwise it won’t work. After processing the interrupt, you must unmask it using InterruptUnmask() because the system masks the interrupt in the PIC prior to unblocking you.
I would try to avoid complicated polling schemes if at all possible.
Regards,
Albrecht
hi al,
I prefer choose the solution with interruptwait, so I’m working on it…
but reading the guide I learned that inside the ISR i can’t do kernel calls, so I wonder if I can do all the reading work (supplied by API)
…the fact is that I never worked with this… 