Something other than polling?

Lord Banshee

Golden Member
Sep 8, 2004
1,495
0
0
OK well i have a USB controller i designed in FPGA that is connected to a windows machine. The basic interface is the windows program sends a command out to the USB and it returns some data, always.

So in my program i have button, when click it sends a command to do something, receives data (accepted command basically), then it sends another command asking if it is done yet, receives such data. If it is done, the button click function ends. But if not i keep sending a command out to the USB device till it is finished.

So what this does it freezes the application until the button event is done. It works for now but soon i would like some more function out of the program such as status updates as while the device is doing what ever i told it to do.

I know using a MCU i am able to use timers and interrupts to check at certain time allowing for other things to happen in between. So how would one go about doing such a C++.Net?

I guess you probably can tell i don't have a lot of programming experience as i am an EE student and unfortunately our EE program there is hardly any programming classes required or even offered, which is shame, that counts toward our degrees other than EE classes involving Assembly/C programing for MCU and HDL for digital circuits.

any help for links to sites with help would be great.

thanks,
chris
 

bsobel

Moderator Emeritus<br>Elite Member
Dec 9, 2001
13,346
0
0
Basic solution: Create a thread to manage the port.
Advanced solution: IO completion ports and callbacks.

From what you've said it sounds like a basic solution should work fine. Just have your UI queue work and a worker thread which accepts the work and does the USB IO...
 

Lord Banshee

Golden Member
Sep 8, 2004
1,495
0
0
Thanks bsoble, but no knowledge on thread usage here. I will start searching on Google, but if you know some good sites that explain it well or tutorials that would be great.

Thanks
 

esun

Platinum Member
Nov 12, 2001
2,214
0
0
If you're in .NET, look up the Thread class. You can literally just declare a thread, assign it some code that will poll the port periodically, queue the data when ready, and then alert the main thread that the data is ready.
 

Lord Banshee

Golden Member
Sep 8, 2004
1,495
0
0
yes i found this using the thread class:

http://www.codeproject.com/managedcpp/mcppthreads01.asp

looks simple enough, but i wonder if my code will work with it as i have not created my function in a separate class like the example, have some very badly written code that just works lol. All my functions are apart of the WinForms class that VS makes.

I wish i had more time to learn how to correctly do all this stuff but for the time being i am getting away with what works and does not crash works good enough.

Thanks again guys

 

Lord Banshee

Golden Member
Sep 8, 2004
1,495
0
0
ok i have a problem:

I am trying to use the code example given from:
http://msdn2.microsoft.com/en-...ading.threadstart.aspx

with my current project but i get some errors

my class:
---------------------------------------------------
ref class MyThreads
{
public:
static void ThreadProc(int ms)
{
Thread::Sleep(ms);
MessageBox::Show("Sleep Thread Done");
}
};

my function:
------------------------------------------------------
private: System::Void Debug3_btnVertMove_Click(System::eek:bject^ sender, System::EventArgs^ e) {

MyThreads^ myThread = gcnew MyThreads;

ThreadStart^ threadDelegate = gcnew ThreadStart( myThread, &MyThreads::ThreadProc(5000) ); //**ERROR HERE
Thread^ newThread = gcnew Thread( threadDelegate );
newThread->Start();

MessageBox::Show("Thread Sent");

}

i get the following errors:
---------------------------------------------------------------
error C2102: '&' requires l-value
error C3350: 'System::Threading::ThreadStart' : a delegate constructor expects 2 argument(s)

so i am guess either i missed something completely or i can not use this type of code in my project? I am using the WinForms project and i've tried the class inside and outside of the namespace just to see what it will do.

Any ideas what i am doing wrong? i am using VS 2005 Pro if that helps
 

Lord Banshee

Golden Member
Sep 8, 2004
1,495
0
0
got it work work by changing this:
ThreadStart^ threadDelegate = gcnew ThreadStart( myThread, &MyThreads::ThreadProc(5000) );
to
ThreadStart^ threadDelegate = gcnew ThreadStart( myThread, &MyThreads::ThreadProc);

and making the passing data a data variable of a class instead of the parameter of a function.
 

exdeath

Lifer
Jan 29, 2004
13,679
10
81
IOCPs and async IO would be the best way. Let the OS handle things in the most efficient way possible in hardware (automatically service and buffer hardware events as they occur) and call your callback function/thread on demand.

I'd have to reference the API myself as it's been a while, but basically you read/write to the IO handle with a flag to set asynchronous operation for the read/write with a callback for the OS to call when the event completes.

But if your program can't continue or only has that single task, it won't be of much use, and will just sleep until the IO completes. But thats a lot better than sitting in a polling loop consuming CPU time.

http://www.microsoft.com/techn...IoCompletionPorts.mspx

http://msdn2.microsoft.com/en-us/library/aa365683.aspx

I don't recall the semantics, but I believe you can even do something stupidly simply like read/write to a handle with OVERLAPPED and then WaitForSingleObject(handle) to kick your program out of the scheduler (sleep) until the I/O completes? I'm not entirely sure on that one though.

If you program absolutely cannot continue it's best to perform a blocked read/write with a API function or do one of the above to put the thread to sleep. Manually looping and performing non blocked polls will result in 100% CPU usage, etc. A blocking read in the Win32 API will usually automatically put your thread into a WAIT state to be checked before it's scheduled, thus eliminating the need to poll or use IOCP if you are only single tasking.

Update:

Does this thing have a driver layer or are you just poking at a raw USB address? In order to perform async I/O the device driver would have to start an interrupt event on the USB bus and have a driver that performs completion tasks, etc, otherwise you are just moving the location of the polling from the user program to the driver. If the only means you have is to send commands to a USB address, I'm not sure there is much else you can do but poll if the device itself isn't somewhat autonomous (ie: able to interrupt and signal status to a driver, etc). If the device can't notify the OS automatically, the OS can't notify your app automatically. If you are serious about eliminating polling, your MCU will have to be capable of USB interrupt events and have a basic miniport driver that can service the events for that USB id in order to complete the back end of the IOCP chain.

Otherwise, if the completion times are predictable, you might bet better off just using Sleep(ms) before trying to poll to burn some time without burning CPU cycles.

Any decent EE program should have at least one 'systems programming' or 'operating systems principles' class for this kind of thing, but typically in the real world, the person writing the driver and interfacing with the OS is different from the person designing the hardware and firmware. Operating systems is a whole world by itself, much less cramming it into a 4 year engineering program. :(
 

Lord Banshee

Golden Member
Sep 8, 2004
1,495
0
0
Well my school is like the 31st top EE schools and nope the only required 1 programming class, C or C++. I took C++ but it only covered basics. There is one other programming elective called C++, but found out last semester it is C or C++ but scripting with perl, lol i hope they change the name haha.

There is more computer programming classes if you do the Computer Engineering side of the EE but did not elect to do so, i think i should have done both.

Anyway this project has no MCU... yet. Everything is created in a FPGA. The USB chip does have a driver but as far as i can tell i do not know how to do a event trigger like you were talking about. But trying to figure it out it might me more work figuring it out what i have designed the USB device to do now. But i do agree about using a timing type of pooling instead of of the normal one.

My idea was to make a thread class that has a USB send and USB read. Then have another thread class which accompany all my events such as SendData, IsDone, StatusReport, blah blah... I have not programmed it yet but my understanding is. I will call a new thread to SendData inside a button, then call a another new thread IsDone. Inside IsDone it will send/read data from the USB every 50ms to check if it is done, when done depending on what i am doing, will send the data to the correct place... So this is the idea at least :)

thanks
 

exdeath

Lifer
Jan 29, 2004
13,679
10
81
Problem with threads with your device is they are still awake and actively polling and your process will still show 100%. It doesn't solve the problem, it just moves it out of sight. Unless the hardware is interrupt driven, you really have no choice but to poll, but you can do so more 'responsibly'. The idea is to go to sleep on a blocking I/O operation, or do something else that is useful, instead of sitting around in a endless loop consuming CPU cycles waiting and incurring system call overhead and consuming bus and device I/O bandwidth unnecessarily.

The 50ms delay is a good idea. You could write a built in profiler in the code at the start of the polling process and at the end, and make adjustments to the target delay time on the fly.

Good thing you are using USB! The importance of not wasting time/bandwidth resources would be more evident if you were trying to send 2k status packets over RS232 every 1ms :) But at least it wouldn't be shared and starving other devices heh.
 

Lord Banshee

Golden Member
Sep 8, 2004
1,495
0
0
yes good thing it is USB :) ... and i was actually going to use RS232 if i couldn't get the USB to work.

About CPU cycles on my machine with 100ms sleep delay there is 0-1% CPU usage in task manager. So unless such a demand is not able to be viewed in the task manager, USB bus, then i think i am ok for now. This is also without using threads just simple polling. What ever computer that is hooked up to this device it will be the only USB device so it should be ok... later testing will find these problems out.


Thanks for all the help guys





 

exdeath

Lifer
Jan 29, 2004
13,679
10
81
Sounds good. Re-read the thread. For the purpose of improving UI response time threading would absolutely be the answer. You'd still have an endless loop polling the hardware with whatever delays or thread sleeping you implement to keep the CPU from pegging on your second thread, but the thread handling the application window main loop wouldn't get blocked from handling mouse overs, dragging, repainting, etc, in the mean time pending return from the poll function (and you could return progress, attempt 1, attempt 2, etc)

100ms sounds more than reasonable for an external device, esp if the device controls mechanical stuff that is much much slower than that or it's a one time wait for something that is expected to perform a lot of work in one go (amortization).
 

Lord Banshee

Golden Member
Sep 8, 2004
1,495
0
0
yeps these functions talked about here are controlling DC motors with encoders... I wish it was the programming that was making me mad though :), damn Motors and Gears are off by about one degree when i tell it to move 45. It might not sound bad but it is very bad for this project :( oh well for now i will just have some kind of alignment factor.
 

exdeath

Lifer
Jan 29, 2004
13,679
10
81
Originally posted by: Lord Banshee
yeps these functions talked about here are controlling DC motors with encoders... I wish it was the programming that was making me mad though :), damn Motors and Gears are off by about one degree when i tell it to move 45. It might not sound bad but it is very bad for this project :( oh well for now i will just have some kind of alignment factor.

1 degree trim on a missile flying mach 4 is the difference between a direct hit and civilian casualties ;)
 

Lord Banshee

Golden Member
Sep 8, 2004
1,495
0
0
Originally posted by: exdeath
Originally posted by: Lord Banshee
yeps these functions talked about here are controlling DC motors with encoders... I wish it was the programming that was making me mad though :), damn Motors and Gears are off by about one degree when i tell it to move 45. It might not sound bad but it is very bad for this project :( oh well for now i will just have some kind of alignment factor.

1 degree trim on a missile flying mach 4 is the difference between a direct hit and civilian casualties ;)

lol exactly ;)
 

smack Down

Diamond Member
Sep 10, 2005
4,507
0
0
Originally posted by: Lord Banshee
Originally posted by: exdeath
Originally posted by: Lord Banshee
yeps these functions talked about here are controlling DC motors with encoders... I wish it was the programming that was making me mad though :), damn Motors and Gears are off by about one degree when i tell it to move 45. It might not sound bad but it is very bad for this project :( oh well for now i will just have some kind of alignment factor.

1 degree trim on a missile flying mach 4 is the difference between a direct hit and civilian casualties ;)

lol exactly ;)

Sounds like it is time for negitive feedback.
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
You may wish to create the Button send thread outside of the Send Button logic.
Either create the thread suspended or have the thread suspend itself when initialization has been completed.


Then when the send button is clicked; setup the data needed for the thread and release the thread.

The thread processes what needs to be done, loops back and suspends itself.
This is more efficient than creating a new thread each time.

When the program is terminating, make sure that you delete all created threads that still are in use.