Preamble: Before this series of articles begins it should be noted that the techniques explored here are generally not needed. The speed gains for most processors are negligible. Only specially constrained system—such as needing fast responses on very slow microprocessor—will benefit from the these techniques. However, there may be some lessons that port to other applications and make this series of exploratory articles worthwhile. My interest in writing this article set was to explore such options irrespective of how useful their real-world application might be.
As an embedded programmer I’ve written a number of serial protocols over the years. Serial communication is often used for the device to talk to a host computer or connect several devices together. The protocols consists of several characters grouped together to form a packet. These packets are most often binary data and use an natural integer number, the command, to denote the purpose of the packet transaction. This is very typical.
In software there is some method for dispatching specific commands to sections of code that handle that specific command. The most basic are simply switch statements.
That becomes inefficient when there are a lot of commands because they are basically a series of if-statements. A rule of thumb one can assume that 50% of them are executed for each command, and if there are a 1000 commands that means 500 compares for every command. In addition this isn’t very modular. All the commands are handling code is in a single location. A better option is to use a lookup table that matches command numbers to a function that can handle the command.
Most of the protocols I design use a lookup table. This table is defined in a C file with nothing else in it. Then a general dispatch can use this table without knowing anything about the commands being executed. This allows the protocol to remain general and only the commands themselves be application specific.
In implementation the command handler function has more parameters and a return value.
Here is a more typical command handler function. It receives a pointer to either the entire packet, or the portion of the packet that has the command data. In addition, it receives a pointer to output data—data that is used in sending a response to the command. There is a location of where this data is to be stored, how much data can be stored there, and a pointer to set to denote how much data the handler function used. The handler itself is Boolean. I typically use a true on failure return result. This allows a Boolean flag to simply use a logical OR to run several function and at the end see if any of them failed.
Serial protocols differ depending on the application. The lookup table portion happens in the dispatcher. There can be a number of steps that take place before this such as packet integrity checking (such as verifying a CRC) as well as the maintenance of the transport layer. The dispatcher has to unpack enough of the packet to get the command number. It might also have to unpack an address to see if the packet is even directed to the current device. The command number also has to be verified.
In the example show, command number verification is as simple as checking that the number is less than the total number of commands. If so, there is a handler function in the lookup table. This isn’t always the case. Sometimes the command numbers are such there are gaps in command numbers.
In this command numbering system, there are 7 commands, but 13 command table entries. The command table can simply use NULL to denote areas that are not valid commands. The dispatcher must then check to see if the command handler is valid before running it.
I’ve worked on a number of applications needing a serial interface requiring a protocol like this and each application has unique protocol requirements. Some are single client/server configurations, some are multi-drop, some bidirectional, etc., etc. The lookup table command handler is part of all these system. What happens if the command is not a number, but instead a text string? That will be the topic of our next article.