Jump to content

Totally bizarre CAN API behavior


Recommended Posts

Within the context of a large test application, I recently wrote a set of utilities for defining CAN tags using the Channel API. In a nutshell, it allows for CAN channels and the associated messages to be defined from a configuration spreadsheet without the use of MAX. It handles scaling, limits, encoding, all the bits and bytes stuff, and is very easy and intuitive to use. It's all very cool, and most of it functioned perfectly right from the start without any hassles at all. I had successfully defined several little-endian, unsigned channels, of various widths, and everything worked great.

Then I tried to define a channel to read a single-precision floating point value using big-endian (Motorola) format. LabVIEW kept throwing cryptic "an input parameter is invalid (but I won't tell you which one)" errors that didn't seem to make any sense at all. I chatted about the situation with friends and colleagues at Bloomy Controls and VI Engineering, and no one seemed to have a clue why I has encountering difficulty. We were collectively beginning to think that the CAN Channel API somehow couldn't deal with a Float32. We needed to read a channel that started at bit 8 and was 32 bits in length, in big endian format, and format that into a float, and LabVIEW simply wouldn't accommodate us.

Since I knew that I could successfully read U16's, I formulated a fallback position that I would read the requisite 32 bits as two channels, and reconstruct the Float32 programmatically. Ugly, but workable. While I coded that, one of my co-workers at UTC Power hooked up a CANalyzer to watch the bus traffic. The CANalyzer showed the bytes coming through the way they were expected to, but my two U16's showed bytes shifted in strange ways, crossing word boundaries, and things didn't make sense. And then there was a flash of insight provided by the CANalyzer: when you changed the channel configuration from Intel to Motorola and back again, it automatically changed the location of the start bit. A 32-bit channel that starts at bit 8 for Intel (little endian) format becomes a 32-bit channel that starts at bit 32 for Motorola. I edited my channel configuration spreadsheet accordingly, and suddenly, magically, LabVIEW knew what to do. No channel configuration errors, and the data came through correctly.

WTF?

We scratched our heads for a minute, and the lights came on in our collective brains. The start of a CAN channel appeared to be specified by the least-significant bit of the least-significant byte. For a little-endian message beginning at bit 8 and spanning 32 bits, it's WYSIWYG. But a big-endian Float32 has its words, and the bytes within those words, swapped. So for a 32-bit message that resides from bit 8 to bit 40, the message "starts" at bit 32. It all makes perfect sense, in a totally frustrating and absolutely retarded way.

There are two really amazing things about this story. First, this bizarre idiosyncrasy was consistent across two completely separate and apparently unrelated software platforms: the LabVIEW CAN API, and a commercial CAN diagnostic tool. In other words, this isn't a bug, it's a feature, based upon a standard. Second, neither environment contained any hint of this requirement in its documentation.

The moral of the story: if you're using CAN and dealing with Floats and big-endians, watch out. Reality is not what it may seem to be.

You're welcome :frusty:

  • Like 1
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.