Digital I/O

cancel
Showing results for 
Search instead for 
Did you mean: 

NiFpga_ReadFifo high cpu usage

Solved!
Go to solution

Hi everyone

 

I'm doing some tests with the board PCI-7811R installed in a PC with OpenSUSE 13.1 and NI-RIO 14. Using the NI FPGA C API I found some issues related to the CPU usage when my program waits values to be inserted into a Target to Host DMA FIFO of 64 bits elements.

labview.png

This is the FPGA VI that I'm using for the test. It waits a signal generated in another VI (the signal is generated at a user-defined rate), reads the inputs values and insert them into FIFO. My C++ program waits the FIFO to have the requested amount of samples (using the NiFpga_ReadFifoU64 function with infinite timeout) and do a simple change detection. The program runs as expected but it consumes 100% CPU time regardless the sample rate (tested with values between 10 and 15360 samples per second). I tried to let only the code that reads the FIFO but the problem persists.

 

Another thing that happens is the processes watchdog and kworker consumes a lot of CPU when the sample rate and the requested amount of samples is the same (this causes the NiFpga_ReadFifoU64 function to be executed one time per second).

labview2.png

 

This only happens with this program and both processes CPU consuption are not constant. They return to normal when the program is stopped.

 

I tried to use the NiFpga_AcquireFifoWriteElementsU64 function instead of NiFpga_ReadFifoU64 but it keeps returning the value -63193 (feature not supported).

 

Anyone knows how to solve it?

 

My program code:

NiFpga_Status status = NiFpga_Initialize();
if (!NiFpga_IsNotError(status))
{
	cout << "error: " << status << endl;
	return 1;
}

NiFpga_Session session;

status = NiFpga_Open(NiFpga_DAQ_Bitfile, NiFpga_DAQ_Signature,
	"RIO0", NiFpga_OpenAttribute_NoRun, &session);
if (!NiFpga_IsNotError(status))
{
	cout << "error: " << status << endl;
}

NiFpga_Reset(session);

// sample rate
status = NiFpga_WriteU32(session, NiFpga_DAQ_ControlU32_SamplesPerSecond, 2048);
if (!NiFpga_IsNotError(status))
{
	cout << "error: " << status << endl;
}

NiFpga_StartFifo(session, NiFpga_DAQ_TargetToHostFifoU64_SamplesFIFO);

status = NiFpga_Run(session, 0);
if (!NiFpga_IsNotError(status))
{
	cout << "error: " << status << endl;
}

uint64_t buffer[2048];

uint64_t old;

while (true)
{
	size_t nSamples = 2048;

	status = NiFpga_ReadFifoU64(session, NiFpga_DAQ_TargetToHostFifoU64_SamplesFIFO,
		buffer, nSamples, -1, &nSamples);
	if (!NiFpga_IsNotError(status))
	{
		cout << "error: " << status << endl;
	}
	else
	{
		for (int i = 0; i < nSamples; i++)
		{
			// change detection
			if (buffer[i] != old)
				printf("Samples %llx\n", buffer[i]);
			old = buffer[i];
		}
	}

}

NiFpga_MergeStatus(&status, NiFpga_Close(session, 0));

/* must be called after all other calls */
NiFpga_MergeStatus(&status, NiFpga_Finalize());
return 0;

 

 

Thanks for the help

 

Luiz Carlos

0 Kudos
Message 1 of 3
(4,989 Views)
Solution
Accepted by topic author luizcvm

Hey luizcvm

 

Long story short, this is mostly expected behavior with the PCI-7811R you are using.

 

100% CPU Utilization occurs because the NiFpga_ReadFifo is implemented with a busy wait for your target. http://digital.ni.com/public.nsf/allkb/583DDFF1829F51C1862575AA007AC792 has some additional information and some guidelines for architecting an application to avoid pegging the CPU.

 

NiFpga_AcquireFifoWriteElements is not supported on the PCI-7811R. 

 

I don't really have an explanation for the processes watchdog and kworker result. If I understand correctly, this only happens when data is being read at the exact same rate as it is being generated. Is that correct?

 

0 Kudos
Message 2 of 3
(4,979 Views)

Yes, but it seems to happen when the sample rate is low. It stopped after I used some thread blocking function to wait the samples to be available (usleep). This also reduced the program CPU time to 3%.

 

Thanks for the help

 

Luiz Carlos

0 Kudos
Message 3 of 3
(4,957 Views)