Skip to content

Commit d29f76e

Browse files
committed
Emit the MAVLink message table once instead of per translation unit
protocol.h compiles the MAVLink helpers with MAVLINK_HELPER = static, and mavlink_helpers.h holds the message table as a function-local static inside mavlink_get_msg_entry(). Every translation unit calling it therefore gets its own private copy of the table, and the linker cannot merge them, because each is a distinct static object. There are two call sites - mavlink_routing.c and mavlink_runtime.c - so the firmware carries the table twice. arm-none-eabi-nm on a 1 MB target: 08093870 00000fcc t mavlink_message_crcs.0 08092814 00000fcc t mavlink_message_crcs.1 8088 bytes for 4044 bytes of data. Nothing warns about it: it is const data rather than code, so no unused-symbol diagnostic fires and no diff shows it. mavlink_helpers.h anticipates this with a MAVLINK_GET_MSG_ENTRY hook that suppresses its own definition. Defining it and supplying one out-of-line definition in mavlink_msg_entry.c leaves a single copy. Only this function moves out of line - every other helper keeps its inlining, so frame parsing is unchanged. Worth about 4 KB on every target that carries MAVLink. Verified with nm that one copy remains, and unit tests, SITL (warnings-as-errors) and hardware targets all build clean.
1 parent 6236a85 commit d29f76e

6 files changed

Lines changed: 104 additions & 1 deletion

File tree

src/main/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,8 @@ main_sources(COMMON_SRC
415415
mavlink/mavlink_mission.c
416416
mavlink/mavlink_mission.h
417417
mavlink/mavlink_modes.c
418+
mavlink/mavlink_msg_entry.c
419+
mavlink/mavlink_msg_entry.h
418420
mavlink/mavlink_modes.h
419421
mavlink/mavlink_types.h
420422
mavlink/mavlink_ports.c
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* This file is part of INAV.
3+
*
4+
* INAV is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* INAV is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with INAV. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "mavlink/mavlink_types.h"
19+
20+
#if defined(USE_TELEMETRY_MAVLINK) || defined(USE_SERIALRX_MAVLINK)
21+
22+
/*
23+
* The single definition of mavlink_get_msg_entry(), replacing the per
24+
* translation unit copies the header would otherwise emit. See
25+
* mavlink_msg_entry.h for why.
26+
*
27+
* The body is the generated one from mavlink_helpers.h: a bisection search,
28+
* which requires the table to stay sorted by msgid.
29+
*/
30+
const mavlink_msg_entry_t *mavlink_get_msg_entry(uint32_t msgid)
31+
{
32+
static const mavlink_msg_entry_t mavlink_message_crcs[] = MAVLINK_MESSAGE_CRCS;
33+
34+
uint32_t low = 0;
35+
uint32_t high = sizeof(mavlink_message_crcs) / sizeof(mavlink_message_crcs[0]) - 1;
36+
37+
while (low < high) {
38+
uint32_t mid = (low + 1 + high) / 2;
39+
if (msgid < mavlink_message_crcs[mid].msgid) {
40+
high = mid - 1;
41+
continue;
42+
}
43+
if (msgid > mavlink_message_crcs[mid].msgid) {
44+
low = mid;
45+
continue;
46+
}
47+
low = mid;
48+
break;
49+
}
50+
51+
if (mavlink_message_crcs[low].msgid != msgid) {
52+
return NULL;
53+
}
54+
55+
return &mavlink_message_crcs[low];
56+
}
57+
58+
#endif
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* This file is part of INAV.
3+
*
4+
* INAV is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* INAV is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with INAV. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#pragma once
19+
20+
#include <stdint.h>
21+
22+
/*
23+
* mavlink_helpers.h defines mavlink_get_msg_entry() with the message table as a
24+
* function-local static, and protocol.h compiles the helpers as MAVLINK_HELPER
25+
* = static. Every translation unit that calls it therefore gets a private copy
26+
* of that table, and the linker cannot merge them. With two callers - routing
27+
* and runtime - the firmware carried the table twice: 8088 bytes on a full
28+
* build, of which 4044 was pure duplicate.
29+
*
30+
* Defining MAVLINK_GET_MSG_ENTRY suppresses the header's definition, and
31+
* mavlink_msg_entry.c supplies a single out-of-line one instead. Only this
32+
* function moves out of line; the rest of the helpers keep their inlining, so
33+
* the frame parsing hot path is unchanged.
34+
*
35+
* This must be included before storm32/mavlink.h, because mavlink_helpers.h
36+
* calls mavlink_get_msg_entry() internally and needs the declaration first.
37+
*/
38+
#define MAVLINK_GET_MSG_ENTRY
39+
40+
struct __mavlink_msg_entry;
41+
const struct __mavlink_msg_entry *mavlink_get_msg_entry(uint32_t msgid);

src/main/mavlink/mavlink_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#ifndef MAVLINK_COMM_NUM_BUFFERS
2929
#define MAVLINK_COMM_NUM_BUFFERS MAX_MAVLINK_PORTS
3030
#endif
31+
#include "mavlink/mavlink_msg_entry.h"
3132
#include "storm32/mavlink.h"
3233
#pragma GCC diagnostic pop
3334

src/main/rx/mavlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#pragma GCC diagnostic push
2323
#pragma GCC diagnostic ignored "-Wunused-function"
2424
#define MAVLINK_COMM_NUM_BUFFERS MAX_MAVLINK_PORTS
25+
#include "mavlink/mavlink_msg_entry.h"
2526
#include "storm32/mavlink.h"
2627
#pragma GCC diagnostic pop
2728

src/test/unit/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ set_property(SOURCE gimbal_serial_unittest.cc PROPERTY definitions USE_SERIAL_GI
8080

8181
set_property(SOURCE mavlink_unittest.cc PROPERTY depends
8282
"fc/fc_mavlink.c" "mavlink/mavlink_command.c" "mavlink/mavlink_guided.c" "mavlink/mavlink_mission.c" "mavlink/mavlink_modes.c" "mavlink/mavlink_ports.c"
83-
"mavlink/mavlink_routing.c" "mavlink/mavlink_runtime.c" "mavlink/mavlink_streams.c" "telemetry/mavlink.c"
83+
"mavlink/mavlink_msg_entry.c" "mavlink/mavlink_routing.c" "mavlink/mavlink_runtime.c" "mavlink/mavlink_streams.c" "telemetry/mavlink.c"
8484
"common/crc.c" "common/maths.c" "common/streambuf.c" "common/string_light.c" "msp/msp_serial.c")
8585
set_property(SOURCE mavlink_unittest.cc PROPERTY definitions USE_TELEMETRY USE_TELEMETRY_MAVLINK)
8686
set_property(SOURCE mavlink_unittest.cc PROPERTY extra_includes

0 commit comments

Comments
 (0)