LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Best method to gracefully terminate real time program.

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;
}
Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 1 of 2
(815 Views)

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;
}

 

Programming Data Acquisition and Control in Measurement Studio and Labwindows/CVI
0 Kudos
Message 2 of 2
(784 Views)