06-20-2022 03:10 PM
I have a polling application running at 100 Hz. When it receives various messages from a Windows application it starts performing some tasks. I run it through LabWindows/CVI on a real-time target. When I try to stop the program it crashes the PXI. What is the best method to stop the program where the PXI will be in a state where I can restart the program through CVI?
This is how I'm currently trying to end it:
while (!RTIsShuttingDown() && !flagRestart)
{
ProcessSystemEvents();
SleepUS (10000);
}
setNextRunNumber(); // Save the current run number
/* Thread cleanup code. */
Done:
DiscardAsyncTimer(-1);
if (ai0TaskHandle) DAQmxClearTask(ai0TaskHandle); // Stop DAQ AI thread
if (ai1TaskHandle) DAQmxClearTask(ai1TaskHandle); // Stop DAQ AI thread
if (ai2TaskHandle) DAQmxClearTask(ai2TaskHandle); // Stop DAQ AI thread
if (threadPool) CmtDiscardThreadPool (threadPool); // CmtDiscardThreadPool waits for the thread function to exit.
if (ThreadWriteDataToFile.tsqHandle) CmtDiscardTSQ (ThreadWriteDataToFile.tsqHandle);
//if (DataFile) fclose(DataFile); // when you want data add these lines back in!
if (g_SessionRef) nxClear(g_SessionRef); // Clear XNET session
if (registered) UnregisterTCPServer (23); // Stop TCP server thread
if (VaisalaTCPConnected) DisconnectFromTCPServer (VaisalaTCPConnectionHandle);
if (ao0TaskHandle) DAQmxClearTask(ao0TaskHandle); // Stop DAQ AO thread
if (ao1TaskHandle) DAQmxClearTask(ao1TaskHandle); // Stop DAQ AO thread
if (ao2TaskHandle) DAQmxClearTask(ao2TaskHandle); // Stop DAQ AO thread
if (doTaskHandle)
{
DAQDOChannels[0]->Value = 1; // RT shutting down so kill the engine
for (int count = 1; count < numDOChannels; count++)
DAQDOChannels[count]->Value = 0; // Turn off all other digital channels
DAQOutputDigital();
DAQmxClearTask(doTaskHandle); // Stop DAQ DO thread
}
if (numTimers > 0)
{
for (indexChannel = 0; indexChannel < numTimers; indexChannel++)
Timer_Port_Close(indexChannel);
}
FreeMemory();
flagRestart = 0;
flagStart = 1;
if (RTIsShuttingDown() || flagClose)
CloseCVIRTE ();
}
}
static int FreeMemory(void)
{
int count = 0;
while (DAQAIChannels[count] != NULL)
{
free(DAQAIChannels[count]);
DAQAIChannels[count++] = NULL;
}
count = 0;
while (DAQAOChannels[count] != NULL)
{
free(DAQAOChannels[count]);
DAQAOChannels[count++] = NULL;
}
count = 0;
while (DAQDOChannels[count] != NULL)
{
free(DAQDOChannels[count]);
DAQDOChannels[count++] = NULL;
}
count = 0;
while(CLControls[count] != NULL)
{
free(CLControls[count]);
CLControls[count++] = NULL;
}
count = 0;
while (Safeties[count] != NULL)
{
free(Safeties[count]);
Safeties[count++] = NULL;
}
count = 0;
numModes = 0;
while (Mode[count] != NULL)
{
free(Mode[count]);
Mode[count++] = NULL;
}
free(DAQDevices);
free(aiRawData);
free(aiTask0RawData);
free(aiTask1RawData);
free(aiTask2RawData);
numaiTask0Channels = 0;
numaiTask1Channels = 0;
numaiTask2Channels = 0;
return 1;
}
06-21-2022 04:14 PM
I figured it out. I thought CloseCVIRTE(); would close it, but it didn't. I needed to get out of the infinite while loop and call return;
Here is a short snippet as a starting point for a polling application. There may be better ways, and if so, I welcome the feedback.
I pulled this out of my program so it may or may not run, but it should be close.
#define Hz_LOOP_RATE 100
static short flagClose = 0; // allows you to bounce out of primary while loop to end program
static short flagClosed = 0; // confirmation that program can end
static short flagRestart = 0; // flushes memory and restarts from the beginning
static short loopCounter = 0; // counts from 0 to 99 inside of the 100 Hz loop
void CVIFUNC_C RTmain (void)
{
if (InitCVIRTE (0, 0, 0) == 0)
return; /* out of memory */
while (1 && !flagClosed)
{
// Start a 100 Hz timer Hz_LOOP_RATE = 100
NewAsyncTimer (1.0 / Hz_LOOP_RATE, -1, 1, MainLoop, 0);
while (!RTIsShuttingDown() && !flagRestart && !flagClose)
{
ProcessSystemEvents();
SleepUS (10000);
}
if (RTIsShuttingDown() || flagClose)
{
CloseCVIRTE ();
flagClosed = 1;
}
}
return;
}
int CVICALLBACK MainLoop (int reserved, int timerId, int event, void *callbackData, int eventData1, int eventData2)
{
if (event == EVENT_TIMER_TICK)
{
_100HzCode();
if (loopCounter % 10 == 0) // 10 Hz functions
_10HzCode();
if (loopCounter % 50 == 0) // 2 Hz functions
_2HzCode();
if (loopCounter == 0) // 1 Hz functions
_1HzCode();
loopCounter++;
}
return 0;
}