Automotive and Embedded Networks

cancel
Showing results for 
Search instead for 
Did you mean: 

XNet Flush Return Number Flushed

So I am using a Frame Out Queued session where I am putting several things on the queue to be written, and I monitor the size of this queue.  If the queue gets too low I add more frames to it, making sure there are always some frames ready to go out.  Frames should be read by a device on the bus regularly but that isn't guaranteed.  I have a case where I want to write some new data to the bus, but there will likely be many frames already in the queue waiting to be written.  At the moment this causes a delay in calling the function to write the new data, and then the new data actually going on the bus.

 

So for instance I have a frame that goes out ever 10ms, and my queue size is 40.  That means if I have a new value I want to write, I can put it on the queue but I need to wait 400ms before that message will actually go out.

 

A solution to this might be to flush the queue where it is, and then just put the new frame on the bus and it will go out on the next scheduled write.  My problem with this is the reason I'm using the queue in the first place is because there is a counter that I need to increment with every frame.  So those 40 frames waiting to be written have a counter that goes up with each frame.  So if I flush my queue, then write my new frame with my new value, I won't know what my new counter value should be, unless I know how many frames were flushed when I called it.

 

I could possibly call the number of frames pending, see that for instance there are 20 frames in the queue, then call the flush and write my new frame moving my counter value back 20.  The problem I see with this is between the call of number of items waiting to be sent, and the flush, there is the potential that another frame has gone out, and now my counter would think 20 frames had been waiting in the queue, but it was actually 19.

 

So is there a way to know how many frames were flushed from the queue when calling a flush function?  Or is there a way to know the actual values of the frames in the queue that are waiting to be sent?  I could make the time shorter by making my queue size smaller, but I then run the risk of having all my frames in the queue already sent, and having frames not go out at the correct rate.  

 

Another option I just thought of that I don't really like is I could have echo turned on, and then all frames I write can be read back, and using another Signal In Single-Point session I could read what the counter value last was.

0 Kudos
Message 1 of 7
(4,086 Views)

I can the mentioned functionality to our list of feature requests. I agree that having additional control/information over the queues would be very useful.

 

In the mean time, you might be able to implement this functionality yourself by wrapping up a stream session with your own queue implementation. Granted there would be some challenges with cyclic frames and some trade offs will have to be made.

Jeff L
National Instruments
0 Kudos
Message 2 of 7
(4,043 Views)

@JefeL wrote:

 

In the mean time, you might be able to implement this functionality yourself by wrapping up a stream session with your own queue implementation. Granted there would be some challenges with cyclic frames and some trade offs will have to be made.


This is exactly what I'm trying to avoid.  I want this to be hardware timed.  As I mentioned the cyclic frames go out at 10ms.  I don't want to be in a loop pulling from that queue, and writing a single frame every 10ms, keeping track of the message counter value.  The amount of jitter would probably be on the order of a few ms, which would be 10's of percent error.  I realize even with hardware timed CAN transmission I likely won't see frames at 10.000ms, but having the hardware do it (when the hardware supports it) is my favorite option.  Especially since this might be deployed to low power RT hardware and offloading work that the CPU could be doing, to hardware more dedicated would help free up resources for other processes.

 

The technique currently being used is the one I mentioned, where a separate single point signal in session is opened, with the frames being echo'ed back.  This isn't great on jitter, when I need to perform a flush, then a read on the signal, then calculate the new frame with new counter and CRC, but this jitter only happens when a value in the frame changes other than the counter.  The device under test seems happy with it.  Still all of this extra session work (or separate queue with single frame writing) could be avoided if the flush returned more information.  Or all of this could be avoided if CRC and message counters could be implemented by XNet natively.

0 Kudos
Message 3 of 7
(4,032 Views)

Hi Hooovahh,

 

Were you ever able to come up with a more elegant solution to this problem? I want to achieve the exact same thing as this. Did NI ever implement XNET driver functionality to achieve this?

 

Thanks

0 Kudos
Message 4 of 7
(2,475 Views)

Well sorta, but not really.  So on all CAN hardware that isn't XNet I just have it be software timed in a loop sending each frame one at a time when enough time has passed.  A pain, lots of overhead, lots of jitter, and gets worst with more frames. 

 

With XNet we have this Queue mode and so I came up with the bucket filling technique to keep the queue from being empty.  I was doing this for the CRC and Counter functions needed to make my ECU happy.  I made blog post about it here.  There really wasn't a good solution at the time for changing payload data.  There were a couple of ways of accomplishing this that all suck for one or more reasons.

 

1) You could only have a value change when the queue was being reset, so like check when the counter was 0x00 and then change the payloads then.  But this would mean you'd have to wait around for a value change to actually go out.  If a value change came in when the counter was 0x01 your new value won't go out for a while since the queue is already full of the older payload value.  In practice this might mean a couple of seconds from a value change request, to the request going out.

 

2) You could work your way backwards, and flush the queue, then figure out what the last value was, put new frames into the queue starting at the next counter value.  But this would add a decent amount of jitter as mentioned before.  This jitter only happens on a value change, and might not be all that bad.

 

3) You could create a single point read on your echo'ed data, and now you can know what the last counter value was that actually went out.  But this does make more sessions to keep track of.

 

BUT!  The best solution for me was to use an undocumented feature of the XNet hardware which allowed putting code on the CAN device, which modifies the frame before sending it out.  This is talked about in Part 10 of my CAN blog.  Here you just write your frame as a single point once.  It continues to go out as hardware timed with counter and CRC being updated.  Then you write a new single frame once on value change, and the CRC and Counter keep going out.  Like magic!  But a reminder this is undocumented, and unsupported.  It likely won't break anything, but when it doesn't work you might not be able to call NI to try to figure it out.

0 Kudos
Message 5 of 7
(2,466 Views)

Hi Hooovahh,

 

Thanks for your quick response! I had read your blog prior, very helpful btw! Unfortunately I have the same issue as you where there hardware implemented CRC is not going to work because we are doing custom CRC calculations based on several CAN frames and passing that CRC out on a separate frame. So I ended up taking the bucket filling approached, however, it is not perfect since we have a delay after a value change in the payload now. I am surprised NI has not come up with a way to push custom binary's to the XNET device for these scenarios. Its been a while since you flagged the issue/need for this.

0 Kudos
Message 6 of 7
(2,449 Views)

Well that is a new technique to me.  The custom code running on XNet hardware likely won't be possible for you because of the way you need to calculate the CRC.  Bucket filling, or software timed operations is all you'll be able to do.  It sounds a bit painful for sure. 

 

I'd do some experimenting with trying to have that value change happen faster, by flushing the write buffer on a value change, and then try to figure out what the last write was, with something like the echo'd write, or creating some read sessions.  This gets complicated and more difficult to manage with the more frames you need to keep track of.  Something scalable might be able to be made but it would take some time to get it right.  Sorry I don't have anything else to suggest.

0 Kudos
Message 7 of 7
(2,435 Views)