I have a source that sends UDP packets at 819.2 Hz (~ 1.2 ms) to my QNX Neutrino machine. I want to receive and process these messages with minimal delay and jitter.
My first code was basically:
SetupUDPSocket(); while (true) { recv(socket, buffer, BufferSize, MSG_WAITALL); // blocks until whole packet is received processPacket(buffer); }
The problem is that recv () only checks for every tick of the system timer if there is a new package. The timer is usually 1 ms. So, if I use this, I get a huge jitter because I process the packet every 1 ms or every 2 ms. I could reset the size of the timer ticks, but that would affect the whole system (and other timers of other processes, etc.). And I will still tremble, because I will definitely never exactly correspond to 819.2 Hz.
So, I tried to use the network card interrupt line (5). But it looks like there are other things that make interruption grow. I used the following code:
ThreadCtl(_NTO_TCTL_IO, 0); SIGEV_INTR_INIT(&event); iID = InterruptAttachEvent(IRQ5, &event, _NTO_INTR_FLAGS_TRK_MSK); while(true) { if (InterruptWait(0, NULL) == -1) { std::cerr << "errno: " << errno << std::endl; } length = recv(socket, buffer, bufferSize, 0); // non-blocking this time LogTimeAndLength(); InterruptUnmask(IRQ5, iID; }
This results in the only successful read at the beginning, followed by a read with a length of 0 bytes after passing 0 time. It seems that after InterruptUnmask (), InterruptWait () does not wait at all, so there should already be a new interrupt (or the same ?!).
Is it possible to do something similar with a network card interrupt line? Are there any other options for receiving packets at 819.2 Hz?
Some network card information: pci -vvv outputs:
Class = Network (Ethernet) Vendor ID = 8086h, Intel Corporation Device ID = 107ch, 82541PI Gigabit Ethernet Controller PCI index = 0h Class Codes = 020000h Revision ID = 5h Bus number = 4 Device number = 15 Function num = 0 Status Reg = 230h Command Reg = 17h I/O space access enabled Memory space access enabled Bus Master enabled Special Cycle operations ignored Memory Write and Invalidate enabled Palette Snooping disabled Parity Error Response disabled Data/Address stepping disabled SERR# driver disabled Fast back-to-back transactions to different agents disabled Header type = 0h Single-function BIST = 0h Build-in-self-test not supported Latency Timer = 40h Cache Line Size= 8h un-cacheable PCI Mem Address = febc0000h 32bit length 131072 enabled PCI Mem Address = feba0000h 32bit length 131072 enabled PCI IO Address = ec00h length 64 enabled Subsystem Vendor ID = 8086h Subsystem ID = 1376h PCI Expansion ROM = feb80000h length 131072 disabled Max Lat = 0ns Min Gnt = 255ns PCI Int Pin = INT A Interrupt line = 5 CPU Interrupt = 5h Capabilities Pointer = dch Capability ID = 1h - Power Management Capabilities = c822h - 28002000h Capability ID = 7h - PCI-X Capabilities = 2h - 400000h Device Dependent Registers: 0x040: 0000 0000 0000 0000 0000 0000 0000 0000 ... 0x0d0: 0000 0000 0000 0000 0000 0000 01e4 22c8 0x0e0: 0020 0028 0700 0200 0000 4000 0000 0000 0x0f0: 0500 8000 0000 0000 0000 0000 0000 0000
and 'nicinfo':
wm1: INTEL 82544 Gigabit (Copper) Ethernet Controller Physical Node ID ........................... 000E0C C5F6DD Current Physical Node ID ................... 000E0C C5F6DD Current Operation Rate ..................... 100.00 Mb/s full-duplex Active Interface Type ...................... MII Active PHY address ....................... 0 Maximum Transmittable data Unit ............ 1500 Maximum Receivable data Unit ............... 0 Hardware Interrupt ......................... 0x5 Memory Aperture ............................ 0xfebc0000 - 0xfebdffff Promiscuous Mode ........................... Off Multicast Support .......................... Enabled
Thanks for reading!