Serial Communication Take 2

Official FreeEMS vanilla firmware development, the heart and soul of the system!
davebmw
LQFP144 - On Top Of The Game
Posts: 331
Joined: Sun Jul 13, 2008 2:58 pm
Location: South Wales, UK

Re: Serial Communication Take 2

Post by davebmw »

DELTA...... He's gone all green! well done that man! :D

I think the routing of data packets to other nodes is a very cool idea. i can think of lots of applications where the FreeEMS can be used as a serial gateway not only into the EMS but any other CAN connected device.

That has some serious possibilities for CAN based cars.
93'BMW 325is M50B25TU, Rebuilt 06/06, JE10.5:1, polish&port. Scorpion BB, K&N CAI, TEJ21 WBO2, '07 M3 Evo 18" 225F, 255R, EBC Kevlar, Bilstien Sprint, Polyflex. Head rebuild Oct'08, OEM+FSE FPR, MS2v3.0_DJB Custom, Extra 2.0.1
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Serial Communication Take 2

Post by Fred »

For that you will definitely need a wrapped function otherwise the other nodes need the same protocol. I guess we can do both easily enough. Good thinking though.

I spent the train ride home working on the spec doc.

I've got some tax forms to fill out, server functionality to add to my router and other laptop (little one is number one now lol) and a tree to cut down. This weekend will be insane.

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Serial Communication Take 2

Post by Fred »

I worked on the spec doc again yesterday, and also the code for it a little as well as I thought about it and figured things out. I just wanted to say that I'm making good progress. I'll try to tidy up both today/tonight and do a release with serial docs and some code that works. This will allow Sean to make more flash progress, and perhaps start to fill out the serial functionality too? The woman is making me go for a walk now, but I'll work late if I have to. Damn this 20" is nice after the 10" during the week :-) Still, the little screen is enough, I'm just spoiled :-)

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Serial Communication Take 2

Post by Fred »

I got the part of the document where I was writing addressing information and thought I'd better look up CAN first. It turns out that CAN uses 8 byte packets and 4 byte addressing. This means that we will have to do one of two things (or possibly others I can't think of right now) :

1) Use the same sort of escaping and start stop setup as in serial and ignore the capabilities of can as much as possible
2) Utilise the addressing bytes to ensure that we know when a packet starts and stops

For 2, perhaps we could do something like :
  1. Source address
  2. Destination address
  3. Packet sequence number byte 1
  4. Packet sequence number byte 2
and just record the last seen sequence number and buffer stuff that is the same on top of what is already there, and reset if it changes. Because we know up front that the data is probably good (built in CRC), we can go ahead and use the length field from the header to know when to start processing the message as opposed to waiting for a stop byte as in serial.

If anyone has any thoughts on how this should be achieved, go right ahead.

One thing that I just realised is that if the CAN bus is really humming there is no way the serial bus could keep up with echoing messages out to the PC. Perhaps the best approach would be to ignore that.

Perhaps it is foolish to try to make it compatible with the j standard stuff. Maybe we should just ignore that and implement our own like MS have done with theirs?

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
EdG
TO220 - Visibile
Posts: 5
Joined: Wed Oct 15, 2008 7:57 pm

Re: Serial Communication Take 2

Post by EdG »

Hi folks

I've read through as much of these serial threads as I can & based on the 0.4 spec., I have some comments!

It looks pretty reasonable in general - you want as small an overhead as possible, but with enough tests there to ensure integrity.

Reading the earlier parts, I was going to suggest a 'payload length' *instead* of escaped characters in the payload. I see there is a payload length in the header, but still the esc. characters. Why use esc. characters at all? They are only of discriminatory use if they actually appear in the data, and they could potentially double payload sizes. The checksum & end byte appearing in the correct place should be enough, and that way you get predictable packet sizes - useful if these packets will be wrapped & sent over other comms. devices/channels in the future...

I'd be tempted to consider a 16 bit checksum if the packets are going to be long. Maybe for larger packets, and potentially more critical data, additional checksumming could be included inside the payload?
Also, checksum header & payload. For example, what if just 'payload type' were corrupted. Can't think of any reason not to do this.
Pre/post ESCed payload? Doesn't really matter I suppose, though I'd probably tend to C'sum all the actual bytes which are transferred over the comms link - that's the purpose of the c'sum.

Stretchable integer - this looks like an unnecessary complication to me. Again, it might be useful in reducing the larger & far less frequent tranmissions, but I'd be tempted to keep it simpler for the more frequent, shorter simple. (Also, why have you written the bytes in right-left bit order? took me 3 attempts to realise it! :? ) Additional types could always be added for larger data (such as firmware uploads) with compression within the payload, handled at a level above as it were.

In the Acknowledgement Receipt section, I don't understand the comments in red at all. Sorry! I'd assume positive ACK equals <message received ok> & negative ACK equals <message not received ok> & an error type in the payload?
Does the 'ACK byte present' bit in the Header Flags indicate that an ACK is required in response to this message? Or is an ACK always required (hence the fixed ACK number byte).

Hardware control I would say isn't really necessary, and not commonly used. Use of Acks should be sufficient. If something goes wrong, both systems could lock up equally well. :) For this eventuality, it might be worth defining maximum response times to requests so sensible timeouts can be used. Just something to add to the docs once it's coded, not something to define now.

Max Packet size - interesting... I'd probably go for a simple fixed maximum, though that could still be a problem with ESCs ;) . Is the system going to expand to such an extent that larger packets will be required? If the system is going to change that much (from a 'simple' EMS) then wouldn't that be a different entity anyway, with different requirements, and a whole new serial protocol?
Having said that, the other option - a reported maximum - isn't really any overhead (though possibly unnecessary) so I'd vote for that. It's there if needed, or can be ignored.

Other than that, it looks expandable enough. Maybe it could be trimmed a little for simple messages if the ACK system isn't quite right.


As for the CAN bus discussions, I agree - disregard it for now. Serial is point to point & should be treated as such for now to keep it simple & sensible. CAN isn't designed to be point to point at all - all packets are effectively broadcast - but point-to-point comms can exist over it. If you were going to design some protocol usable on both then you'd have to seriously think about the overall design of the CAN messaging first.
In the instance of sending these serial type messages over CAN to the EMS, I'd envisage the messages being wrapped into CAN messages. In the other instance of sending serial messages to the EMS to be forwarded onto a CAN bus to other devices, cross that bridge when required. ;) It doesn't affect this protocol for now.

Think that was a little more than 2p worth :roll: .
Ed
EdG
TO220 - Visibile
Posts: 5
Joined: Wed Oct 15, 2008 7:57 pm

Re: Serial Communication Take 2

Post by EdG »

Just as a slight aside, regarding the CAN, what are people wanting or expecting from it?

I'd say it's a huge overhead at this point, and a distraction to the goal of something functioning.

I'm not an expert on vehicle CAN systems - if someone is really in the know here, is it worth pursuing at this point?

Ed
User avatar
jharvey
1N4001 - Signed up
Posts: 1607
Joined: Tue Jun 10, 2008 5:17 pm

Re: Serial Communication Take 2

Post by jharvey »

I thought non extended CAN had an 11 bit identifier?

http://en.wikipedia.org/wiki/Canbus

I also agree, we should ignore CAN for now, however the serial spec is being written as a multi point spec, and has many similarities to the CAN spec. I'm not sure if that's good or bad at this point. Straight serial comm should have a good idea who is at the other end. I also agree flow control isn't required.

I kind of think the serial spec shouldn't have addresses, ect. It should cover the data being transfered not where it's going or how to get there. I see serial comms useful for getting data in during firmware upgrade/updates, debug data out during testing, and sensor data out (to dash gauges, ect). So I might encourage packets to be framed in those three categories.

For upgrades, I'd say time isn't critical, and data needs to be accurate. So a structure that allows redundancy and larger block sizes. Redundancy in terms of things like ack/nack, resubmit requests and CRC(s). I don't know if I'd say binary or ASCII. I think binary would take say 1 second to upload, where ASCII would take 8 seconds. Still seconds either way, and not a critical amount of time. However conversion to ASCII for transfer, can introduce error, so I'd likely go for binary. It's not like ASCII will make this type of transfer more human readable any how. I'd say packet size should be fixed at a larger block size. Not sure what a good size would be, what ever size it is should work well for table transfers.

For debug data, (assuming we don't all have BDM capabilities) I see data being snap shots of counters, PC reg(s), perhaps a table, ect. Accurate data is required, as well as speed. Data can range from small packets to large packets. I can see a need for both binary as well as ASCII. Binary to decrease sources of error, and ASCII for human readable data scrolling by a prompt. I can see a need for a variety of packet lengths.

For sensor data, I see packets that are very small, accuracy can be assumed and isn't' that critical. Small blips in a gauge caused by neutrinos, or what have you, are of course not liked, but also not a huge deal. So I'd say ASCII only, NO CRC, fixed at 2 bytes, one as a sensor designator, another as a the data.

This in mind I think a CAN spec can be written later on, that allows for serial comms to addressable nodes.

So perhaps I should propose, a structure where the first byte is control information about the following data, and the bytes to follow can vary based on this first byte. The control byte can also work as the first byte of an ASCII transfer w/o CRC, by making the first to bits 01. Binary "A" is "01000001"

1st byte structure
bit 0, CRC?, not included = 0, included = 1
bit 1, min packet size?, longer length = 0, min length = 1
bit 2, ACK?, not requested = 0, requested = 1
bit 3-7, packet length is 1 byte to 32

Any how enough pot stiring for now. Anyone have some thoughts about it?
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Serial Communication Take 2

Post by Fred »

Welcome along Ed :-)

Perhaps I should have marked 0.4 as out of date too :-)
EdG wrote:Reading the earlier parts, I was going to suggest a 'payload length' *instead* of escaped characters in the payload. I see there is a payload length in the header, but still the esc. characters. Why use esc. characters at all? They are only of discriminatory use if they actually appear in the data, and they could potentially double payload sizes. The checksum & end byte appearing in the correct place should be enough, and that way you get predictable packet sizes - useful if these packets will be wrapped & sent over other comms. devices/channels in the future...
The idea is to simplify the reception process and allow it to be layered. The size increase *could* be double, but more likely it will be about (256 + 3) / 256 in practice. The escapes never make it inside to the buffer or out to another protocol, they only exist on the physical line and though the first layer. It also adds another mode of error checking in that if you have an escape appear and you flag the next byte as being escaped, and it isn't one of the three escaped bytes possible, then you can drop reception and start looking for a start byte again. Also, how would you plan to know when you were starting reception and not? timestamps and time outs? This is irrespective of timing. You simply look for start, when you find it you start receiving. If you find an escape you set a flag, when the next char comes you convert it and store it, if it doesn't match you reset. The length can be checked once the packet has been fully received. Ditto the checksum. I think there would be too much stuff being done in the ISR to base it on header contents up front. As it stands its quite minimal and will get a complete packet into the buffer with minimal ISR overhead. Once it is there a flag can be set and the main loop processing code can deal with it.

I see a lot of pluses for Stu's way, and the 1.5% hit in speed seems negligible to me. I'm open to being convinced, but packet sizes will be consistent in the buffer and for forwarding, and the speed hit is minimal. Thoughts?
I'd be tempted to consider a 16 bit checksum if the packets are going to be long. Maybe for larger packets, and potentially more critical data, additional checksumming could be included inside the payload?
With the parity bit on each byte, the escape scheme, the length, the length to ID relationship, and the 8 bit checksum, the chances of getting bad data have to be pretty slim don't they? As for inside the payload, sure, that is a possibility, but the point of checksumming at all is to have transparent reliable comms for the application layer. (I've been converted to this layer terminology since starting to actually code it)
Also, checksum header & payload. For example, what if just 'payload type' were corrupted. Can't think of any reason not to do this.
I can't think of one not to do it either, but then again, I can't think of one to do it, and it will cost an extra byte (not that that matters). The worst case for the above is that you listen to one message for too long before realising it's bad. Even that is slim to none type stuff as the next message will have a start byte at the beginning and cause a reset as soon as it starts anyway. I understand the limitation of the 8 bit checksum, but I'm not convinced we need any more. I had a hard enough time convincing some people that we needed a checksum and packetising etc at all. I see it as important, but I don't want 100% certainty that the data IS correct, just a 99.9% is ok by me. The speed and complexity hits for more complex and more checksums seem to outweigh any benefits for the small % cases that will get through the other checks.
Pre/post ESCed payload? Doesn't really matter I suppose, though I'd probably tend to C'sum all the actual bytes which are transferred over the comms link - that's the purpose of the c'sum.
I wasn't sure either, but thinking about it now the escapes will check themselves anyway and doing it preescaping means you can run the checksum and store it before transmission (I'm not doing it that way, but you could.)
Stretchable integer - this looks like an unnecessary complication to me.
It's gone already.

A few places you mentioned larger packet sizes. As it stands there is no requirement to deliver more than about 1k of data at a time. There isn't the buffer to do it, and for local stuff the flash block granularity is 1k. So sizes aren't an issue for us, 16 bits is heaps, and I think 60k of data should be enough per packet for anything really (famous last words). I base that on the fact that bigger stuff could be broken up into chunks quite easily if required.

Does the 'ACK byte present' bit in the Header Flags indicate that an ACK is required in response to this message? Or is an ACK always required (hence the fixed ACK number byte).
Acks were a work in progress. It's open for debate as is everything else :-)

Currently what I have is the following :
When a device wishes to receive confirmation that what it asked for was actioned appropriately and indeed whether the outcome was successful or not it should set the header bit for acknowledgement valid/required, and populate the acknowledgement field with the next value in the sequence being used. After processing the request the receiving device will respond with the correct payload type/id, the matching acknowledgement number, and the flag set to either success of failure. In the case of failure the body, if present, will be interpretted as an error code. In the case of success the body will either be empty or contain the requested data.
That uses two 1 bit flags in the header and the 8 bit ack. I decided to leave all fields always present to simplify things a little more. That could be subject to change yet, we'll see how it looks when I start to code up the packet handling stuff.

The thing is that it is 1 byte from 8 (with addresses) and it is the only one that is optional. I tend to think it should stay just to keep the locations of the other aspects consistent. IE, payload always starts at buffer start + 8 etc.
Hardware control I would say isn't really necessary, and not commonly used.
It's gone. To keep it atomic and simple the ecu will just turn off the receive isr while handling a packet and turn it back on after it's done. This avoids funky stuff happening on the ECU side which is the main concern.

I tend to feel that the tuning authors shouldn't be *able* to screw up the insides of the ecu. Hence the push towards a defined interface for most stuff. In this case, if they were to flood the line with messages, you would get the first one and start dealing with it and be blissfully ignorant of the rest. The tuning tool would realise it didn't get what it wanted and try again at some point.
For this eventuality, it might be worth defining maximum response times to requests so sensible timeouts can be used. Just something to add to the docs once it's coded, not something to define now.
Good point, I'll add in an empty section now as a reminder. Thanks!
Having said that, the other option - a reported maximum - isn't really any overhead (though possibly unnecessary) so I'd vote for that. It's there if needed, or can be ignored.
Exactly, that is the current state of the play for that. A given firmware will define its individual message types as certain sizes and it then only matters for forwarding stuff to CAN etc. So the facility exists to ask for it, but it won't be used for normal stuff at all.
As for the CAN bus discussions, I agree - disregard it for now.
I'm happy to do that with the single exception that we need to be able to pass data through to it. Perhaps that should be part of the firmware part of the document rather than an integral protocol function. I just don't want to limit ourselves for that by making a bad decision now.

With regards addresses in the serial spec, I realise it should be point to point, and I was urring on the no addresses side too, but the way delta put it, it's very straight forward to do it right, and it allows misuse of the serial lines by paralleling other devices up. I tend to think they should stay. Again, I'm open to discussion, but we really need to nail this down a bit more firmly very soon. I'll try to get the document released later today, but no promises on that. I've already made too many as it stands!

What do I expect from CAN :
Share runtime data with other nodes
Configure other nodes through one serial connection
Perhaps command other nodes to perform actions, but this shouldn't be required, just program it to perform the action based on some data and then just send the data right?

Jared,
and ASCII for human readable data scrolling by a prompt.
That just isn't going to happen as it's not at all practical for a simple AND reliable setup. MS is a mixed bag, but has no checksums no packetising, you just cross your fingers and hope for the best. Once you ditch that paradigm you are going to lose the ASCII fairly quickly. The overhead isn't just for conversions, it's for bandwidth as well because to represent 65000 you need 5 bytes, but really it was only 2 ditto 255 is 3 instead of 1 and 4294967296 is 10 instead of 4.

As for your sensor data 2 byte thing, the data itself is 2 bytes, and there are more than 255 different RT variables or will be soon anyway.

It should be trivial to dump this packetised data out to the console through a processor, if you wanna see it go by, why not see it go by and be sure it is good. What is it that you have against a simple console tool like that?

Fred.
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
User avatar
Fred
Moderator
Posts: 15431
Joined: Tue Jan 15, 2008 2:31 pm
Location: Home sweet home!
Contact:

Re: Serial Communication Take 2

Post by Fred »

Just in case I don't get a chance to release 0.0.17 tonight, here are some updated pdfs of the comms specs for review and criticism. The formatting may have been dodgy in the past, but this should look ok.

Criticism and suggestions/discussion of course welcome as always. That doesn't mean I won't argue about stuff though :-)

Fred.
Attachments
FreeEMS_Serial_Protocol_FreeEMS_Vanilla_Specific.pdf
0.5 vanilla doc
(28.56 KiB) Downloaded 606 times
FreeEMS_Serial_Protocol_Core_Specification.pdf
0.5 core doc
(57.87 KiB) Downloaded 629 times
DIYEFI.org - where Open Source means Open Source, and Free means Freedom
FreeEMS.org - the open source engine management system
FreeEMS dev diary and its comments thread and my turbo truck!
n00bs, do NOT PM or email tech questions! Use the forum!
The ever growing list of FreeEMS success stories!
EdG
TO220 - Visibile
Posts: 5
Joined: Wed Oct 15, 2008 7:57 pm

Re: Serial Communication Take 2

Post by EdG »

Jared does have some valid points there - in the case of just having runtime information out of the ECU, you're going to want it with as little overhead as possible (small 'packets')

For now, it appears we want the serial comms to:
Download flash block data for programming.
Code debugging of variables.
Runtime system information (for display/datalog/tuning)

I'd say keep that in mind & engineer the serial comms to do just that, and as efficiently as possible.
Making the serial link part of a higher level network, where the ECU is one of many addressed devices, to my mind, isn't necessary. Certainly not at this point.
If that becomes obviously necessary at some later time, when other 'nodes' are present, then extend or rewrite the serial protocol then, though I suspect it may never be necessary. If you had, say 5 different devices in the car, networked via CAN & wanted to plug your serial cable into any one of them to tweak your ECU tune, then fair enough. For now, KIS :)

If I was doing this myself, I'd have
[simple header] containing start/status/payload type/payload length
[payload]
[checksum]
plus maybe the ACK functionality too, but only where the payload type requires it.

As you say, having parity on gives a good amount of error detection (single bit loss is the most common)- I don't often use it myself & have few problems in 'quiet' environments. Parity & checksum combined should give you high confidence.
I agree with the point about the ESC start assuring you of a start condition, but there will only ever be a transmitter & receiver on the serial and I think it's an unnecessary overhead.

That's just my take on it. In short, I'd go for less overhead at this point, rather than more.

As for CAN, is there some standard you intend to be compatible with? I found references to J1939. Is anyone looking at that right now? ('CAN' isn't the easiest thing to search the forum for!)
Post Reply