Packing It In There

Comments [0]

One of the projects I worked on was an embedded turbine controller that had an incredible amount of inherent complexity designed into the product. The controller used two processors, Motorola 68360 and MPC505, as well as dual-port memory for the inter-process communications (IPC). The developers spent a substantial amount of time installing the development software and trying to get the processors to communicate. This was the era where the software would be licensed to a NIC and so you could only compile the code on the machine with the licensed NIC. They even hired a consultant to help figure out how to make the processors talk.

I caught the tail-end of this project and it was not a pleasant beginning. My responsibility was to finish the PC configuration software for the controller after the high-priced consultant left. I had just moved over from another project so I had no exposure to this project. I found an incredibly complicated database schema and object-oriented software (C++/MFC-based) to go with the overly complicated controller! The consultant apparently had never heard of the KISS principle (where possible) and had created a behomoth. I had to dig through many, many classes and debug all of the classes to find why the database wouldn't save correctly. I found most of the time the consultant forgot to call the parent class constructor from the derived class constructor, although there were plenty of other bugs to fix.

One of the developers created an emulation program for the embedded controller that ran on a PC. The configuration software worked great with the emulation program, but would not talk to the actual embedded controller. It turned out it was a combination of structure packing and Endian problems. When the developers were trying to make the embedded processors talk, they chose a packing scheme that could not be natively duplicated by Windows or Visual Studio. The actual statement was:

#pragma pack(4,8)

Unfortunately I don't have the documentation handy, but as I recall it meant to align on 4-byte boundaries and align sub-structures on 8-byte boundaries. The key was the sub-structures and I couldn't get Visual Studio to duplicate the packing schema with the sub-structures without affecting the host structure as well.

"It seemed like a good idea at the time..." Here are the elaborate steps I took to solve the problem:

  1. I ended up using some macros to extract the structures from the header files (there were lots and lots of structures) and put them into Excel.
  2. I created the Excel spreadsheet and scripts to automatically calculate the size of the structure on the embedded platform and to look for "Endian" data types (mainly doubles and longs).
  3. I created another Excel script to generate a C file that contained a string that contained the information to encode and decode the message. The script accounted for padding and endian conversion.
  4. The conversion function was used in the emulator and the configuration software and worked successfully.

In hind sight, this solution was reasonable (since we didn't want to modify the embedded controller) but there is a very good reason you occassionally see:

WORD Reserved1;
WORD Reserved2;

throughout system header files. It is a very good idea to add manual packing variables rather than relying on the compiler to do it for you, especially if the software will be used cross-platform.

Comment Section

Comments are closed.