-
Loop problem: CPU usage
Hi all,
I'm running a thread that's polling a list to see if any action is necessary and this thread loops using a while(true).
Obviously this is using all of my CPU time which I'd like to use for other worker threads and I'd like to poll non-continuously but I need to poll at a period of not less more than 0.1 milliseconds, so windows timers are out. Also there's no way of using an event to release the thread.
The code I'm using actually works really well, but I'm using pretty much a whole processor.
Any help appreciated.
Thanks.
Ben.
Code:
long WINAPI Thread_ObjectPoll(LPVOID lpParam)
{
while (true)
{
QueryPerformanceCounter(&lpPerformanceCount);
date = lpPerformanceCount.QuadPart;
nb_objects = p_list->size();
for (i=nb_objects-1;i>=0;i--)
{
object = get_an_object(i);
if (date >= object->action_date)
{
//SetEvent for processing thread
}
if (object->finished_processing == true)
{
//delete the object
erase_an_object(i);
}
}
}
return 0;
}
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by shoppinit
but I need to poll at a period of not less more than 0.1 milliseconds
Not sure what this really means. However, I doubt you are going to be able to get that kind of accuracy in Windows. Your best bet is either timers, or sleep for 1 ms.
You could try to "Sleep(0);" as soon as you're done polling. But, I'm not sure how much that'll buy you. Sleeping for 0ms effectively gives up the rest of your timeslice.
Viggy
-
Re: Loop problem: CPU usage
Thanks for that. I meant that I must poll more frequently than once every 1ms. Probably about 10 times every 1ms.
I'll try the Sleep(0) - didn't occur to me before.
-
Re: Loop problem: CPU usage
The Sleep(0) doesn't reduce CPU usage, but this isn't surprising since I guess unless it's got some other thread to run it'll stay in this thread.
Interestingly my other threads seem to run better (more predictably), so thanks for the tip, Viggy!
I'd still be interested in finding a way to reduce the frequency of the polling, though. Right now it's entering the loop once every 0.15 µs approx.
I just don't like while(true) loops, but maybe this is necessary in this case.
Ben.
-
Re: Loop problem: CPU usage
Well, unless you can poll > 1ms, you can't reduce the CPU usage. Windows is not a RTOS.
Viggy
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by shoppinit
...but I need to poll at a period of not less more than 0.1 milliseconds, so windows timers are out.
Windows in standard user mode can not do it. The fastest available stuff is a multi-media event buth they only go down to order 1ms. If you really have real-time constraints on the order of 100µs, then you need to write a kernel driver or use an external device.
Could you please briefly explain why you need these kinds of timing constraints. Sometimes there can be a design simplification allowing for the use of standard timers and events.
Sincerely, Chris.
-
Re: Loop problem: CPU usage
Here's about all I can come up with.......
While your resolution is very small (smaller than Windows is designed to handle), perhaps the frequency of release isn't so demanding?
Here's what I mean. Imagine your schedule of the next 1 second were laid out in a linear calendar. Do you have something to be fired off every 0.1ms?
Probably not, but then I don't know. Let's say you don't, at least on occasion.
The resolution I get from waiting on events with release times stated at 1ms is as high as 16ms on my hardware, and perhaps even 20ms on some occasions, meaning the highest resolution I can afford to predict I can release a thread after some kind of hold is about 20ms or so.
If I sorted the schedule (using a tree if the insertion activity is high), then I could tell if the next time for a release is within this 20ms target zone.
If the next release is inside 20ms, then the loop must run full steam.
On the other hand, if there's, say, 40ms before the next release is due, I could schedule a wait (or Sleep or whatever) for 20ms.
I used this approach in an animation scheduling mechanism some time ago. We were simulating a walk through in an artist's installation presentation. We wanted to show how the 'system' - a series of sensors, lights, videos, music - etc.. would work with several people walking through.
I recorded the motion of the 'people' using the mouse drag, noting the time of each motion sample.
The resolution wasn't near your demand, but essentially I could look into the 'next position' of the various 'people' in the simulation, and just Sleep until a short time before that next position was due.
As I recall, every time I came out of a sleep, I checked the remaining time, and slept again (for a shorter duration) if there was enough time. I never 'slept' the full delay to target, always about 60% or so - never missing a schedule release of the next position. It demanded nothing from the CPU.
Obviously if you've got releases constantly inside the margin of your timed release, this can't help - but only you know your data.
-
Re: Loop problem: CPU usage
Hi JVene,
You're quite right, the frequency of arriving objects is less than the polling frequency and my thread that detects a new object arriving uses Events so I can know fairly precisely the time window that I'd need to scan in. That's an interesting idea and I'm going to implement it to see what the results are like.
Something else also occured to me. My I/O card has an external rate generator that can generate interrupts at a programmable frequency. I've never tried to use this and the SDK is a nightmare, but it might be worth investigating. What do you think?
Thanks!
Ben.
-
Re: Loop problem: CPU usage
Hi Chris,
Thanks for your reply, I missed it first time round. The app detects objects on a conveyor belt that arrive unpredictably - I use a proximity switch for this. 500 ms after their detection, some action must be taken on them. The window for taking this action is about 2ms.
As soon as the object is detected, the app writes it's detection date into a list as well as the date that action must be taken and this is what's being polled.
I can't see myself writing a Kernel driver - I think that's well outside of my abilities. I have seen that 3rd party realtime plug-ins exist for Windows but I have absolutely no experience of them. I think Venturcom RTX was one I heard of.
Do you know anything about these realtime plug-ins? Are they difficult to implement?
Thanks.
Ben.
-
Re: Loop problem: CPU usage
Quote:
I use a proximity switch for this. 500 ms after their detection, some action must be taken on them. The window for taking this action is about 2ms.
I have been developing realtime systems professionally for nearly 30 years. Would not even consider using windows to directly attempt this. A simple microcontroller (e.g. PIC) would be much more appropriate.
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by TheCPUWizard
I have been developing realtime systems professionally for nearly 30 years. Would not even consider using windows to directly attempt this. A simple microcontroller (e.g. PIC) would be much more appropriate.
I just wanted to write back and indicate that I do all of this kind of stuff with an intermediate microcontroller device. But TheCPUWizard beat me to it. Years ago I wrote some kernel mode device drivers. However, for the past 10 years or so I have done all of these kinds of things with simple microcontroller boards. The intermediate board is much simpler to deal with than a kernel level driver. I use 8051, Infineon C167, Motorola HC08 as well as NEC V850.
You can get a simple starter kit with a modern flash microcontroller for around 100 dollars or maybe a few hundred dollars. There will be samples and demo compiler versions.
But just for further information, I wrote a simple sample using a Windows Multi-Media Timer. This is about as close as you can get to 1ms resolution in the Windows User Mode. See the sample below.
But heed the words of TheCPUWizard. Windows will never guarantee real-time response times in user mode.
Sincerely, Chris.
Code:
#include <windows.h>
#include <mmsystem.h>
#include <iostream>
// link with multimedia library
#pragma comment(lib, "winmm.lib")
inline DWORD TickSet(const DWORD t) { return ::GetTickCount() + t; }
inline bool TickTimeout(const DWORD tID) { return ::GetTickCount() - tID < static_cast<DWORD>(0x7FFFFFFFu); }
int main(void)
{
// Create event and periodic 1ms multi-media timer.
const HANDLE mm_event = ::CreateEvent(0, FALSE, FALSE, 0);
const MMRESULT result = ::timeSetEvent(1u,
1u,
static_cast<LPTIMECALLBACK>(mm_event),
static_cast<DWORD_PTR>(0),
TIME_PERIODIC | TIME_CALLBACK_EVENT_PULSE);
// Something just happenend and I want to check something every millisecond.
const DWORD tID = ::TickSet(500u);
int count = 0;
while(!TickTimeout(tID))
{
::WaitForSingleObject(mm_event, 500);
++count;
}
std::cout << "The millisecond count is: " << count << std::endl;
}
-
Re: Loop problem: CPU usage
Thanks for the support dude :wave: :wave:
One other opportunity (if all the work, MUST be done on "PC Hardware"....) is to check out the QNX operating system. It is a "Unix like" system that is specifically designed for real time operations.
[I was lead architect on one of the first all digital professional audio consoles about a decade ago (when 200Mhz was the fastest Intel processor that money could buy). Some of the timning requirements were on the order of 50uS (0.05 mS) and it was no problem (but did require care). With processor speeds now more than 10 times faster........]
-
Re: Loop problem: CPU usage
Thanks for all the useful info, guys. I'll definitely consider the microcontroller route. Can you recommend one for a first-time user ? I've never had any experience with them and I'd like to avoid assembler as far as possible.
With a microcontroller would I be able to this:
1. Microcontroller detects object presence (date)
2. It initiates action N°1 at a later date and informs the PC (date + x ms)
3. Upon being informed, the PC carries out analysis on the object and makes a decision whether the action N°2 should be A or B
4. PC informs the microcontroller of the action to carry out (A or B)
5. Microcontroller initiates action N°2 (date + x + y ms)
Is this kind of communication between the PC and microcontoller possible? Since the object arrive asynchronously, this kind of interaction would require object tracking, I guess.
I'm sorry if these sound like silly questions. Like I said, I have no experience of using microcontrollers.
Thanks.
Ben.
-
Re: Loop problem: CPU usage
You have the basics down 100% :)
It has been a few [3+] years since I have dealt with uControillers. They change even faster than PC's :eek: So I can not really recommend a specific one.
Almost every uC comes with "C" and the majority of them come with "C++". The library functions are sometimes limited (e.g. no-STL) because the intent is to write the highest performance code.
Communication with the PC can be done with the serial port for almost every uC, and some have USB communication.
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by shoppinit
Thanks for all the useful info, guys. I'll definitely consider the microcontroller route. Can you recommend one for a first-time user ?
For a high-power 32-bit machine with a really good on-chip dubugger, I recomment the NEC V850 line. The first link is a list of microcontroller starter kits. The second link is my recommendation for NEC V850.
http://www.am.necel.com/esales/
http://www.am.necel.com/esales/order...-MINI2-V850/J2
For a low-end controller you can use any 8051 for example the Infineon XC800 series with a demo compiler from Keil (an ARM company). Zilog recently put out a new line of flash micros with a good starter kit. It's called the Z8 Encore. My brother had good results with the starter kit, but I can't find the link right now.
Quote:
Originally Posted by shoppinit
I've never had any experience with them and I'd like to avoid assembler as far as possible.
The NEC starter kits come with demo C/C++ compilers from IAR. The Zilog stuff comes with optimizing C compiler.
Quote:
Originally Posted by shoppinit
With a microcontroller would I be able to this:
1. Microcontroller detects object presence (date)
2. It initiates action N°1 at a later date and informs the PC (date + x ms)
3. Upon being informed, the PC carries out analysis on the object and makes a decision whether the action N°2 should be A or B
4. PC informs the microcontroller of the action to carry out (A or B)
5. Microcontroller initiates action N°2 (date + x + y ms)
Any one you can find. You need to take a bit of time to get accustomed to µC design. The flash tools, build environment, etc. Please note that microcontrollers do not have anything like a CMOS clock. They do not 'know' the date and time, only relative times from the startup.
Quote:
Originally Posted by shoppinit
Is this kind of communication between the PC and microcontoller possible? Since the object arrive asynchronously, this kind of interaction would require object tracking, I guess.
Yes. RS232 can be a very good and simple way to go, as mentioned earlier. I also use some high-end controller boards with USB as well as TCP/IP.
Sincerely, Chris.
-
Re: Loop problem: CPU usage
Thanks for the brilliant info. I'll definitely check out those microcontrollers and have a go at programming one, if only for my own amusement.
I wonder if RS-232 fast enough for my purposes. I guess so since I'll have quite a large window (300-400 ms) to receive the result from the PC before the action has to be carried out.
The TCP-IP option sounds attractive, but I guess it's on a much more expense microcontroller.
Guys, thanks again for all the useful info.
Ben.
-
Re: Loop problem: CPU usage
I, too, support the proposal of a microcontroller.
You can never be completely certain Windows won't 'pause' while it does something 'else' - destroying your timing.
That said, we see games responding to 'real time' on PC's, albeit where a brief pause doesn't mean something destined for bound Chicago doesn't end up in the bin for Milwaukee, but....
If you can get an interrupt, or perhaps respond to an interrupt from the serial port (see the serial port examples in MSDN for NT), you could fire your routines based on that with very high response time.
I still don't think I'd devote a Windows machine to industrial control, but since you're already almost there with what you have, you could try it to see if it's workable for you, while you wait for a microcontroller to arrive.
The idea would be, instead of polling, you'd wait on an interrupt from serial data.
As long as you have complete control over the Windows machine (so you know someone doesn't launch a browser to check email :) ), and assuming you don't have multiple streams of data firing off several threads all pegging the CPU, it might even work.
It's that might part that gives me pause....
-
Re: Loop problem: CPU usage
Hey guys,
You've all definitely given me food for thought, and I'm seriously looking at the microcontoller route - I hope I can get it up and running quickly. It's a little intimidating since I've never used one before.
From looking around, I like the look of the Philipps LPC2138 - it may be a little over the top for what I need, but I'm fairly sure it can do what I need it to. I'm about to get this development board to experiment with (or even integrate):
http://www.olimex.com/dev/lpc-mt-2138.html
What do you think?
Chris, I looked at the controllers you recommended, but I think I'll be able to get started easier on the LPC2138.
Sorry if this is going off topic a bit.
Thanks.
Ben.
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by shoppinit
It's a little intimidating since I've never used one before.
I understand this. Indeed, the first time you get a micro up and running can be a difficult step. I see that your selected board comes with samples. These should be of great assistance.
Also take a good look at the term JTAG, a synonym for OCDS (On Chip Debug Service). OCDS (JTAG) is a realtively new (within the last 5-10 years) form of hardware support for debug systems. OCDS allows host source-level debugging within moderate costs. If you go the microcontroller route, then you need a monitor program or, better yet, OCDS interface. The only problem with OCDS is finding good windows software for source-level dubug.
You might really want to take a look at some of the products offerd by Keil (an ARM company). I am certain that Keil manufactures an ARM7 starter kit. And Keil offers truly state of the art debug support for micros, and the evaluation stuf is just the same tool chain, just with code-size limitations. The GNU stuff for microcontroller applications sucks!. Using this GNU stuff for µC's is like taking a walk in the past about 25 years ago (groovy man)...
Quote:
Originally Posted by shoppinit
From looking around, I like the look of the Philipps LPC2138 - it may be a little over the top for what I need, but I'm fairly sure it can do what I need it to. I'm about to get this development board to experiment with (or even integrate):
What do you think?
Looks fine. It made me want to buy it...
Quote:
Originally Posted by shoppinit
Sorry if this is going off topic a bit.
Not off topic at all as far as I'm concerned. This is actually the right way to go for real time interfaces.
Good luck with your developments.
Sincerely, Chris.
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by JVene
As long as you have complete control over the Windows machine (so you know someone doesn't launch a browser to check email :) ), and assuming you don't have multiple streams of data firing off several threads all pegging the CPU, it might even work.
It does for our company. We track items on conveyors using Windows XP Embedded. As long as you can tolerate an indeterminacy of plus or minus a millisecond or two then you can get away with it. The only caveats are that you must run your app at realtime priority class, perform no disc activity and specify unique priority levels to each thread. ie Highest -> System timer, Processing, GUI <- Lowest.
The downside is that if your app locks up then you can usually do nothing except pull the power cord!
-
Re: Loop problem: CPU usage
Getting back to your attempt at a Windows-based solution, please think about this:
Quote:
Originally Posted by shoppinit
... The app detects objects on a conveyor belt that arrive unpredictably - I use a proximity switch for this. 500 ms after their detection, some action must be taken on them. The window for taking this action is about 2ms.
As soon as the object is detected, the app writes it's detection date into a list as well as the date that action must be taken and this is what's being polled. ...
Instead of polling, re-write so that your thread waits on an event that's set to the signalled state by the app that updates the detection date/action. In other words, after your app updates the the detection date and the action-to-be-taken, it should also set an event to the signalled state. Then replace your "polling" thread with a thread that simply sits at a WaitForSingleObject, waiting for the event to be set. No polling is necessary, and you automatically get the fast response time that you need (within, of course, the thread-slice time of around 15 ms which you can never get around).
If there are only a few different proximity switches (i.e., less than 64), then each one can set its own event. Then use WaitForMultipleObjects instead, which will automatically tell you which of the switches need action, without the need to through the entire p_list each time. Otherwise, each switch can set the same event, and you will need to go through your entire p_list like you do now.
Just a thought. I think you might be overly focussed on the imagined requirement for a 1 ms polling rate, and how to get that, when in fact your real requirement might be more simply phrased as "I need to do something quickly after the proximity switch is hit".
Mike
-
Re: Loop problem: CPU usage
Another idea to try: Connect your proximity detector to ping one of the state pins on a COM port. (CTS or RI perhaps?) Then make a Com port object with a thread that waits for that signal to go high. Then you can start the thread to process that object and wait for the next one to show up. If you set that thread to a higher than normal priority, you should have no problem keeping up with object flow.
-
Re: Loop problem: CPU usage
Hi Guys,
Thanks for those suggestions. I think I'm going to try *all* of the above solutions and see what happens :)
The problem with the serial port idea is that I have no problem detecting the object - I'm using a DIO board that generates an interrupt so I can know pretty precisely when the object passes the sensor. The problem is getting the PC to take action exactly X ms later.
In fact, my tests so far have shown me, as you say John@Wessex, that I can accurately take the action at the right time, but I use up a whole processor doing it. I'm considering going the quad processor route, too.
My concern is that one day Windows is going to decide to do something I've got no control over that throws my timing off no matter how much processor power I've got. I've got no virtual memory, 2 gig of RAM and the bare minimum installed on the HDD and yet I'm still seeing anomalies. I put in a loop to simulate processor load in another thread:
Code:
finish_date = start_date.QuadPart + max_analysis_time_ticks;
QueryPerformanceCounter(&date_now);
while (date_now.QuadPart < finish_date)
{
int i;
double bob = 0;
bob = rand();
for( i = 0; i < 4000;i++ )
{
toto = (1 / (sqrt(bob+i)));
}
QueryPerformanceCounter(&date_now);
}
QueryPerformanceCounter(&stop_date);
This should keep the processor busy for 50ms and 999 times out of 1000 it does to within a few nanoseconds. But occasionally, I see that it's taken 57ms. My only idea is that there's been a thread context change somewhere in there that's taken 7ms.
My gut tells me that the microcontroller is the way forward and my evaluation board is already on its way from Bulgaria. My only worry with this is the communication between the micro and the PC - I don't know much about serial comms.
All of your help is much appreciated, really. It's good that there are people like you out there.
Ben.
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by shoppinit
.... The problem is getting the PC to take action exactly X ms later. ...
Well, that puts an entirely different complexion on things, and incidentally seems fundamentally different from what you said earlier:
Quote:
The window for taking this action is about 2ms.
IT seems to me that there's a big difference between the two.
If you need some mechanical action to take place exactly X ms after some other mechanical event, then Windows will almost always be the wrong answer since it's not a RTOS.
Your needs would probably be best served with a RTOS.
Mike
-
Re: Loop problem: CPU usage
Sorry, the 'exactly' was more for illustration purposes. There is a window of 1-2ms for the action to be taken.
Ben.
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by shoppinit
Sorry, the 'exactly' was more for illustration purposes. There is a window of 1-2ms for the action to be taken.
Ben.
I guess you mean
Code:
X msec +/- 1 or 2 msec
Ben, the Windows multi-media timer, as I had described it in a previous post, is as close as you can get to the 1-2ms resolution in the response time running in Windows User Mode. I did post the relevant code for setting a multimedia-based timer event for setting a precise timer event in the future of the program.
However, only the following will guarantee the response time resolution:
1) RTOS running on the PC
2) running in Windows Kernel Mode (Ring)
3) a microcontroller solution
Sincerely, Chris.
-
Re: Loop problem: CPU usage
I have sorta the same problem. I need to send serial commands every 400 Microsec. Reading here Windows will not be able to do it. Too bad since that requirement just got added and its only a small part of the whole program writing in C#.
I have never used a micro controller, so let me see if i got this straight.
PC ------------->Micro Controller >---------Hardware Device
The Board sits in betwee the PC and the Hardware? or its just straight controller card to hardware?
-
Re: Loop problem: CPU usage
Your "picture" is correct. Most controllers communicate with the PC over either Serial or USB. In your case (and based on the "other" thread), you would be able to send higher level commands to the controller which could very accurately (usually as sub microsecond resolution) send the information to your hardware device.
The programming of the board should be fairly trivial, even with a learning curve I would expect it to be accomplished in a few days [myself or some of the other posters on this thread, could probably do it in just a few hours].
Take a serious look at it. Since this appears to be a work related project, the investment of a few hundred dollars to at least evaluate a solid robust solution should not be a problem....
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by TheCPUWizard
Your "picture" is correct. Most controllers communicate with the PC over either Serial or USB. In your case (and based on the "other" thread), you would be able to send higher level commands to the controller which could very accurately (usually as sub microsecond resolution) send the information to your hardware device.
The programming of the board should be fairly trivial, even with a learning curve I would expect it to be accomplished in a few days [myself or some of the other posters on this thread, could probably do it in just a few hours].
Take a serious look at it. Since this appears to be a work related project, the investment of a few hundred dollars to at least evaluate a solid robust solution should not be a problem....
Well we have decided to go that route. However, i saw the list of boards in this thread, and i have a question.
Does these boards come with a serial driver / package already. My point is that, and i dont know if this makes sense in the micro controller world, can i just get board, and after setting it up, start writing the actual logic on it ( the functions, etc etc ). or i have to write the serial driver myself first in order for it to communicate with the PC?
THis is the idea .
PC ( GUI, user types in commands ) -------*Low speed serial / usb * -----> Board.( Takes the command passed by the PC, and send that command at the given microsend interval) ----------------*HIGH SPEED SERIAL*----->Hardware board.
So then again, do i ineed to write the package for it to communicate or it has something already built in ( something like the SerialPort class in .NET? )
-
Re: Loop problem: CPU usage
Every board that I have wotrked with comes with the Compiler/Tools and a program for downloading to the board. Many of them come with a debugger also.
Once the controller is up and running, YOU will determine what the protocol for your program communicating with the board will be. There are typicaly sendchar/getchar routines in the boards runtime, and your PC program just opens up the serial port as normal.
Let me know how it goes...
-
Re: Loop problem: CPU usage
Hey thanks for the fast reply. Things getting clearer now, its kinda confusing when everyone that i talked to at work they mention that i have to write a serial driver and such.
So lets say i decide all communication is going to be serial. You did mention sendchar and getchar routines. Lets say i send 10 bytes thru the port, from my PC. Where those bytes are stored in the board? in memory? in registers that i can then reference too? ( maybe im thinking too OO but all my coding have been with OO languages ).
Lets say im trying to do this:
Code:
int echo(serialRead) // where serialRead is the data received in the port.
{
return(serialRead) // echos it back
}
In the microcontroller board, how i get serialRead? are those values store where and how can i get to them?
-
Re: Loop problem: CPU usage
It is specific to the board. You will have to read the documentation (there are almost always samples also). :eek:
-
Re: Loop problem: CPU usage
Hi all.
I got my evaluation board and have been making some pretty good progress. After a few initial problems I got the IDE (Rowley) and JTAG debugger working nicely.
I've been playing with the I/O and serial comms and so far everything looks pretty good.
Right now I'm playing with freeRTOS (www.freertos.org) which is pretty impressive. Early days yet, but this looks like a pretty useful OS for delaing with time critical tasks and slower operations like running the LCD display at the same time. Does anyone have any experience of freeRTOS? So far my only issue is the default max tick (interrupt) frequency of 1000Hz but I'm still digging.
I'd definitely recommend my evaluation board and IDE for any first timers. I think I was pretty lucky in my choice of components.
All the best.
Ben.
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by shoppinit
I got my evaluation board and have been making some pretty good progress. After a few initial problems I got the IDE (Rowley) and JTAG debugger working nicely.
Right now I'm playing with freeRTOS (
www.freertos.org) which is pretty impressive. Early days yet, but this looks like a pretty useful OS for delaing with time critical tasks and slower operations like running the LCD display at the same time. Does anyone have any experience of freeRTOS?
No, I write my own operating systems. However, some other developers whom I know use the MicroC-OS. It is a very light weight kernel. I do not know if there is support for your microcontroller. If you are interested in this kind of thing, then take a look at this: http://www.amazon.com/MicroC-OS-II-K.../dp/1578201039
Back to your UART / RS232 design: A good design tip for you would be to write an interrupt handler for your UART receive. You should not rely on the multitasking tick of 1kHz for your response time. Write an interrupt handler for the UART receive and set an operating system event for processing the data.
Quote:
Originally Posted by dvazriel
So lets say i decide all communication is going to be serial. You did mention sendchar and getchar routines. Lets say i send 10 bytes thru the port, from my PC. Where those bytes are stored in the board? in memory? in registers that i can then reference too? ( maybe im thinking too OO but all my coding have been with OO languages ).
You need to write a serial driver or possibly find one in some kind of a sample for your board. Many microcontrollers have one single serial receive buffer with a depth of one byte. Others have multi-byte queues. I did mention above that a sensible design is an interrupt controlled serial driver responsible for sending and receiving bytes. You need to use the microcontroller hardware for send / recv and combine this with enough software for your communications buffers. Please try to investigate this kind of thing.
Look at the books in the Amazon URL: The book with 'building blocks' from La Brosse describes this kind of stuff in great detail: http://www.amazon.com/Embedded-Syste...361063-0877445
Sorry, I should have mentioned these links earlier. Your company should buy these two books for your microcontroller development processes.
Good luck. Chris.
-
Re: Loop problem: CPU usage
Thanks for the info, Chris.
I'm liking freeRTOS. It means I can program events / interrupts like in Windows. Since my application is simple though, I may just have a polling loop checking to see if action is required on an object and use a couple of interrupts to deal with IO and UART.
My UART Rx is interrupt driven and seems to work well for single character transmissions which is all I've tested so far. I'm taking on board your comments about writing the necessary buffers for dealing with chains. I need this to be reliable though and the whole communication with the PC worries me a little. I'm thinking that I'll have a thread waiting for comms from the micro, but I don't know if I should do any handshaking... it's a bit of a new area for me. Any ideas?
Thanks again for all the good info.
Ben.
-
Re: Loop problem: CPU usage
While a "custom OS" is often chosen by hard-core embedded developers to meet specific requiremets. The available ones offer significant advantages, as they really help bootstrap the development process...
-
1 Attachment(s)
Re: Loop problem: CPU usage
Hi Ben, it's good to see that you are making progress.
Quote:
Originally Posted by shoppinit
I'm liking freeRTOS.
If you like it, then use it. If you *really* want to write your own polling OS, then you can do this. However for a first project like yours, I agree with TheCPUWizard in so far as it might simply be better to use the existing OS from the free ware community.
Quote:
Originally Posted by shoppinit
My UART Rx is interrupt driven and seems to work well for single character transmissions which is all I've tested so far. I'm taking on board your comments about writing the necessary buffers for dealing with chains.
I have attatched a low-level driver from another CPU architecture which I wrote years ago in C. It shows very clearly how to implement a ring buffer and interrupt-driven send/recv. Because this is a hardware-driver, it is platform dependent and you will need to modify it for your architecture. However, I tried to separate at least some of the hardware dependencies using inline functions. The macro ISR_CAT2(...) generates the interrupt handler. Of course, you need to replace this with hand-coded interrupt idioms for your tool chain. You must also use the UART registers for your architecture. Please note that the Rx and Tx interrupts are disabled before all buffer operations (shared critical data). This is essential for an interrupt driven communications driver. Also note that the Tx send operation is carried out using an interrupt chain until the buffer is empty.
Quote:
Originally Posted by shoppinit
I need this to be reliable though and the whole communication with the PC worries me a little. I'm thinking that I'll have a thread waiting for comms from the micro, but I don't know if I should do any handshaking.it's a bit of a new area for me. Any ideas?
Develop a simple protocol with the following rudimentary information:
- Frame wake-up, followed by
- service ID, followed by
- the number of data bytes in the transmission, followed by
- these data bytes, followed by
- a checksum such as CRC8 or modulo2.
This kind of single-frame protocol can be simple and bi-directional.
Sincerely, Chris.
-
Re: Loop problem: CPU usage
Quote:
Develop a simple protocol with the following rudimentary information:
- Frame wake-up, followed by
- service ID, followed by
- the number of data bytes in the transmission, followed by
- these data bytes, followed by
- a checksum such as CRC8 or modulo2.
This kind of single-frame protocol can be simple and bi-directional.
Most common: (items in <brackets> are well defined ASCII characters.
Code:
<SOH>FixedSizeHeadeerInfo<STX>VariableLengthMessage(LengthInHeader)<ETX>[CheckSum]
-
Re: Loop problem: CPU usage
Hi again.
Thanks for all the great info. It's helped me to program the µC nicely, though now my problems are all on the PC side. I expected the opposite!
The µC seems to be able to send and receive faster than I need it to, but the PC can't seem to keep up.
I'm using the CSerial class for driving serial comms and the Rx works really well. I've got the Rx code in a thread on its own waiting for a serial event and that part works ok.
I've got another thread that transmits independantly of what the Rx thread is doing - still using the same instance of CSerial - but if I ask that thread to transmit too often then the whole thing comes crashing down with an ERROR_INVALID_PARAMETER (87) error.
I've been turning this around for hours without finding a clue to the solution.
I believe the µC UART Rx and Tx functions are independant so I don't have any sharing issues but I'm not sure about the PC side. Maybe I can't write and read date to the com port at the same time?
I'm Rxing and Txing chains of 3 or 4 bytes at a time.
Any ideas? I really appreciate your help.
Ben.
P.S. At least this is coming slightly back on topic!
Code:
bool fContinue = true;
do
{
// Wait for an event
lLastError = the_analyser->serial.WaitEvent();
if (eEvent & CSerial::EEventRecv)
{
QueryPerformanceCounter(&date);
the_analyser->lastRxTime = date.QuadPart;
// Read data, until there is nothing left
DWORD dwBytesRead = 0;
char szBuffer[101];
do
{
// Read data from the COM-port
lLastError = the_analyser->serial.Read(szBuffer,sizeof(szBuffer)-1,&dwBytesRead);
if (lLastError != ERROR_SUCCESS)
return the_analyser->ShowError(the_analyser->serial.GetLastError(), _T("Unable to read from COM-port."));
if (dwBytesRead > 0)
{
// Finalize the data, so it is a valid string
szBuffer[dwBytesRead] = '\0';
// Display the data
printf("Message '%s' received at: %I64d\n", szBuffer, date.QuadPart);
//printf("%s\n", szBuffer);
}
}
Code:
lLastError = serial.Write(Tx, 3);
if (lLastError != ERROR_SUCCESS)
ShowError(serial.GetLastError(), _T("Unable to send data"));
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by shoppinit
I'm Rxing and Txing chains of 3 or 4 bytes at a time.
Ben,
We need to look at the design constraints for the PC-side more closely, in particular the baud-rate as well as the desired transmission and reception frequencies for data packages.
What underlying baud rate are you using (57600 bps)? With what frequencies do you want to send and receive Rx and Tx packages of 3-4 bytes? Are you using (or do you want to use) any kinds of windows messages for receive, for send or for both?
The PC will be able to keep up. You just need to make sure that you use events sparingly and make sensible use of software buffers. You see, the problem with the PC is where we started this thread in the first place: It can not respond in a healthy fashion to ms-based real-time requirements.
Explain your design a bit more.
Sincerely, Chris.
-
Re: Loop problem: CPU usage
Additionally are you using:
1) "Three Wire" [Tx,Tx,Gnd]
2) "Three Wire With Software Handshake" (typically XON/XOFF)
3) "Hardware Handshaking" [RTC/CTS, etc..]
-
Re: Loop problem: CPU usage
Hi Chris,
1. µC detects objects, stores information in a structure then sends a 3 byte message to the PC (115200 baud), including a unique number for the object.
2. The PC receives the message - there's a thread with WaitForSingleObject that unblocks when an Rx event occurs. This works really well, and quickly.
3. The PC carries out the analysis required and when done sends back the result (good or bad) with the object number. It has quite a large window (~200ms) to do this.
4. The µC interrupts on Rx and inserts the result of that unique object number into the structure.
5. At the appropriate time, the µC carries out action based on the result of the analysis received from the PC. If the result isn't received in time it carries out the default action.
The frequency of the Rx and Tx could be anything up to 60 times per second. I'm not using windows messages - my test program is console based for the time being (and will probably stay that way).
I'm not using any kind of handshaking (I don't think the LPC2138 supports it) so there's no flow control of any kind.
I think the problem is my poor understanding of overlapped I/O. I've made progress since my last post. I tried using non-overlapped at first, but that created all sorts of problems including the (87) error. Now I'm using non-overlapped things seem to be more reliable, but my confidence level is low!
Ben.
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by TheCPUWizard
Additionally are you using:
1) "Three Wire" [Tx,Tx,Gnd]
2) "Three Wire With Software Handshake" (typically XON/XOFF)
3) "Hardware Handshaking" [RTC/CTS, etc..]
The LPC2138 doesn't seem to have any UART functions other than Rx / Tx. No CTS, etc...
There's definitely no XON/XOFF going on.
Table 72: UART0 pin description
Pin Type Description
RXD0 Input Serial Input. Serial receive data.
TXD0 Output Serial Output. Serial transmit data.
I've just looked at the manual again, and UART1 has a full modem interface - CTS, RTS, DTR, etc. Unfortunatly I can't use this one because the serial port on my evaluation board is wired to UART0. I could solve this by getting a different board...
-
Re: Loop problem: CPU usage
[QUOTE=shoppinit]I think the problem is my poor understanding of overlapped I/O. I've made progress since my last post. I tried using non-overlapped at first, but that created all sorts of problems including the (87) error. Now I'm using non-overlapped things seem to be more reliable, but my confidence level is low!
QUOTE]
Ben,
Based on your last two posts, you should probably be fine without any handshaking. The Rx side (froma PC point of view) is working, and that is where it is most likely needed. On the Tx side, I was wondering if the uC could be expecting handshake from the PC, but not getting it (since it does not support it, this is eliminated.
However your least paragraph of the post I quoted has be confused. You say you tried non-overlapped first, then switched to non-overlapped. :confused: :confused: :confused:
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by TheCPUWizard
[However your least paragraph of the post I quoted has be confused. You say you tried non-overlapped first, then switched to non-overlapped. :confused: :confused: :confused:
I mean, when I started developping the comms I wanted to use non-overlapping I/O so I could keep control over what was happening. The problem was that using non-overlapping my Tx thread would block until an Rx event occured. I couldn't get to the bottom of this so I switched to overlapped which works now... but the additional complexity worries me.
I've just tested the Rx and Tx at 60 per second and both the µC and the PC seem to be able to keep up so that's quite encouraging.
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by shoppinit
I mean, when I started developping the comms I wanted to use non-overlapping I/O so I could keep control over what was happening. The problem was that using non-overlapping my Tx thread would block until an Rx event occured. I couldn't get to the bottom of this so I switched to overlapped which works now... but the additional complexity worries me.
I've just tested the Rx and Tx at 60 per second and both the µC and the PC seem to be able to keep up so that's quite encouraging.
Wait a minute Ben. The PC side is extremely powerful. There should not be a problem here no matter what baud rate you are using.
You just need to design the right kind of driver using the Win32 API for your particular requirements. For your simple communication needs, I don't think that you need any kind of overlapped design. Nor do I think that you need send events or receive events on the PC side. You predominantly use interrupt supported polling on the microcontroller side. And you can probably very well get away with a simple polling thread on the PC side combined with a sensible use of the Sleep(...) function. Maybe you can handle send as well as receive within a single worker thread.
Can you try to re-think your design and get it as simple as possible? Also do make sure that you have full command of the RS232 in the Win32-API so that you are not struggling with two issues at once.
I have been really busy lately so I can't get all over this---maybe next week if you still need assistance at that time.
Sincerely, Chris.
-
Re: Loop problem: CPU usage
Thanks for that.
The RS-232 comms seem to be working OK. I need my PC Rx to be event driven but not the Tx. It seems that with non overlapping I can't Tx while the Rx is waiting for an event. It doesn't matter, the overlapped IO seems to be working for me.
I have 2 serial ports on the PC and micro, so if things get out of control I'll use one for Rx and the other for Tx.
It's a real pleasure knowing that if you ask the micro to do something at x ms it'll do it :-)
Thanks for all your help so far.
Ben.
-
Re: Loop problem: CPU usage
Hi Ben,
Quote:
Originally Posted by shoppinit
I have 2 serial ports on the PC and micro, so if things get out of control I'll use one for Rx and the other for Tx.
You should really try to develop your microcontroller serial driver with both Rx and Tx using one port. You can even write the majority of the code (except for the register stuff) using the same code for both channels. Did you have a chance to study the sample driver which I had attatched a few weeks ago?
Quote:
Originally Posted by shoppinit
It's a real pleasure knowing that if you ask the micro to do something at x ms it'll do it :-)
Yes, it is almost strange in this day and age when a computer actually does something that it was programmed to do. :)
Mixing microcontrollers, which offer reaction times in hard real-time, with the comfort of a PC interface can be a very powerful technique.
It sounds like you are coming along pretty well with your project.
Keep going! :thumb:
Sincerely, Chris.
-
Re: Loop problem: CPU usage
Hi Chris,
I looked at your halser.c and it helped with developping the micro side of things. Thanks. That part works really well, I'm quite happy with my serial driver for the micro.
My only concern was the PC side which seems to be working OK now (fingers crossed). I'll keep testing and let you know :-)
Off hand, do you know if the following is feasible:
Create a thread (possibly with higher than normal priority) which waits for an event generated by the micro every 1 ms. The aim being to generate a "realtime" tick in the PC. Not sure what I'd use if for yet, but it's been in the back of my mind.
Have a good weekend!
Ben.
-
Re: Loop problem: CPU usage
Quote:
Originally Posted by shoppinit
Off hand, do you know if the following is feasible:
Create a thread (possibly with higher than normal priority) which waits for an event generated by the micro every 1 ms. The aim being to generate a "realtime" tick in the PC. Not sure what I'd use if for yet, but it's been in the back of my mind.
Ben,
Unfortunately this is not possible with the PC running any kind of Windows. As you may recall at the beginning of this thread, we had a lot of discussion pertaining to the feasibility of generating an internal semi-realtime tick within the Windows environment. And we argued that it was not possible. Sadly the semi-realtime response to an external tick is also not possible within the Windows environment.
A high priority or critical priority thread will not provide for semi-realtime performance. Other processes will simply interrupt this thread.
You can, however, access a real-time tick within the PC. Assuming you have some generation of Pentium, there is support for the pentium time stamp counter, accessed with the rdtsc assembler operation (google and search here for rdtsc). Also Windows supports QueryPerformanceFrequency(...) as well as QueryPerformanceCounter(...). There is a lot of information at CodeGuru about all of these fast counters. All of these fast counters will give you the exact tick (with some sort of tick units) at the time of the call. However, the timing resolution of the call is governed by the limitations of Windows.
Sincerely, Chris.