Hello everyone, I am the Mixed Content Guy.
More and more hardware products are not just integrated on a single board, but consist of multiple control boards working together.
At this point, communication between multiple boards (wired/wireless communication) comes into play, which involves communication protocols. Often, we define some custom protocols.
Previously, we shared a commonly used custom protocol format:
Sharing a highly flexible protocol format (with code examples)

In multi-board systems, the following application scenarios may arise:
- Each board has a requirement for OTA upgrades.
- One of the boards may be a public board that is also used by other projects, and the software on this public board needs to be compatible with multiple projects simultaneously.
During the software iteration process, we may need to upgrade the data for inter-board interactions, such as adding new data.
A new data attribute belongs to a certain data collection, for example, it is of the same type as a certain structure. Theoretically, to make the program design more reasonable, this data should be added to the existing structure.
However, this may involve compatibility issues.
If we directly add data to the structure, during the upgrade, some boards may upgrade successfully while others may not. This could lead to data anomalies causing functional issues.
After the public board upgrades with the new protocol, it may not be fully compatible with the boards communicating with it.
For example, there is a piece of data called device information that needs to be communicated between boards, which includes: device IP and device MAC.
#define MSG_ID_DEV_INFO 0x0001
typedef struct _dev_info
{
char dev_ip[IP_MAX_LEN];
char dev_mac[MAC_MAX_LEN];
}dev_info_t;
At this point, if there is a new requirement to add a device’s serial number (sn), how should we add this data?
If it is during the mid-stage of the project, while still in the development phase, we can modify it freely. Since the device sn is also part of the device information, it would be reasonable to add it directly to the device information data:
#define MSG_ID_DEV_INFO 0x0001
typedef struct _dev_info
{
char dev_ip[IP_MAX_LEN];
char dev_mac[MAC_MAX_LEN];
char dev_sn[SN_MAX_LEN];
}dev_info_t;
If it is later in the project or already in circulation, then we need to consider compatibility issues.
For this compatibility issue, the following solutions are available:
Solution 1: New data follows a separate data protocol
For example, based on the above example, we can expand it like this:
#define MSG_ID_DEV_INFO 0x0001
#define MSG_ID_DEV_SN 0x0002
typedef struct _dev_info
{
char dev_ip[IP_MAX_LEN];
char dev_mac[MAC_MAX_LEN];
}dev_info_t;
typedef struct _dev_sn
{
char dev_sn[SN_MAX_LEN];
}dev_sn_t;
This solution, while solving the problem, can lead to increasingly disorganized code as more data is scattered, making it difficult to maintain.
Moreover, it is impossible to plan all data perfectly from the beginning. Is there a method to reasonably expand data while also addressing compatibility issues?
Let’s look at Solution 2.
Solution 2: Introduce some data serialization libraries in the early design phase of the project.
For example, protobuf.
Protocol Buffers is a data description language developed by Google, similar to XML, that can serialize structured data and is used for data storage, communication protocols, etc. It is language and platform-independent and highly extensible.
Compared to XML, Protocol Buffers have many advantages in serializing structured data:
Good message format upgrades and compatibility- Supports cross-platform and multi-language
- Serialization and deserialization speed is very fast
- Serialized size is smaller than JSON and XML, suitable for network transmission
Related articles:
Protobuf: A smaller, faster, and more efficient protocol
Essentials | Is your project struggling? nanopb can help you!
Essentials | Using protobuf-c on embedded platforms
How to use Google’s protobuf to implement your own RPC framework
For the above example, using protobuf.
The original data:
syntax = "proto2";
message dev_info
{
required string dev_ip = 1;
required string dev_mac = 2;
}
New data dev_sn can be added directly:
syntax = "proto2";
message dev_info
{
required string dev_ip = 1;
required string dev_mac = 2;
required string dev_sn = 3;
}
That concludes this sharing session. Feel free to bookmark and share!

END
Source: Embedded Mixed Content
Copyright belongs to the original author. If there is any infringement, please contact for deletion.
▍Recommended Reading
Zhi Hui Jun is quietly doing big things again!
The principle of automatic baud rate recognition for STM32 serial ports
After 7 years of coding, I encountered such a ridiculous bug for the first time!
→ Follow to avoid getting lost ←