Troubleshooting HDLC SNRM Handshake Timeout and 4-Byte Address Extension Bit
-
Problem Description
When connecting to 3-phase smart meters over RS-485 using DLMS/COSEM HDLC profile (IEC 62056-46), the client sends an SNRM (Set Normal Response Mode) frame, but the meter fails to return an unnumbered acknowledgment (UA) frame, resulting in communication timeout.
Raw Hex Frame Trace
7E A0 0A 00 02 00 23 03 93 D4 71 7EHDLC Frame Breakdown
- Opening/Closing Flag:
7E - Frame Format:
A0 0A(Type 3, length 10 bytes) - Server Address:
00 02 00 23(4-byte logical + physical address) - Client Address:
03(Management client 0x01 shifted:0x01 << 1 | 1=0x03) - Control Field:
93(SNRM command, P/F bit set) - Header Check Sequence (HCS):
D4 71(CRC-16 CCITT)
Observed Behavior
Looking closely at the 4-byte server address field
00 02 00 23:- Byte 1:
00(Logical address upper bits, bit 0 is 0 - extension bit) - Byte 2:
02(Logical address lower bits, bit 0 is 0 - extension bit) - Byte 3:
00(Physical address upper bits, bit 0 is 0 - extension bit) - Byte 4:
23(Physical address lower bits, hex 0x23 = 00100011b)
In our custom gateway driver, the address generation logic forgot to mask the least significant bit (LSB) as the final address delimiter (bit 0 = 1) across the upper bytes, causing the meter's HDLC state machine to wait endlessly for additional address octets.
- Opening/Closing Flag:
-
Great catch @david_miller! According to ISO/IEC 13239 / IEC 62056-46 Clause 6.2.2, the HDLC address field is extended using the low-order bit (bit 0):
- In all octets except the last, bit 0 MUST be
0. - In the last octet of the address, bit 0 MUST be
1.
Here is a clean C implementation for serializing multi-byte HDLC server addresses properly:
void encode_hdlc_address(uint16_t logical, uint16_t physical, uint8_t *buf, int *len) { // Logical Device Address (2 bytes) buf[0] = (uint8_t)((logical >> 7) & 0xFE); // bit 0 = 0 buf[1] = (uint8_t)((logical << 1) & 0xFE); // bit 0 = 0 // Physical Device Address (2 bytes) buf[2] = (uint8_t)((physical >> 7) & 0xFE); // bit 0 = 0 buf[3] = (uint8_t)(((physical << 1) & 0xFE) | 0x01); // bit 0 = 1 (TERMINATOR) *len = 4; }Once bit 0 is set only on the terminal octet, the meter instantly processes the SNRM frame and replies with UA (
7E A0 ... 73 ... 7E). - In all octets except the last, bit 0 MUST be
-
We ran into this exact issue when integrating with Landis+Gyr and Itron meters in our Head-End System. Some meter models strictly validate the HDLC address length and will discard frames immediately if the CRC passes but the address field delimiter doesn't match the configured addressing mode.
Also remember to ensure your client address uses the shifted format (
client_id << 1 | 0x01), so Client 16 (0x10) becomes0x21. -
Field testing confirms this resolution on 120+ meters in the regional substation gateway deployment. After patching the gateway firmware with Elena's bit-extension mask, all optical probe and RS-485 connection timeouts dropped to zero.
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login