-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bluetooth: Mesh: Add separate macro define for opcode #67662
Conversation
0d03906
to
6d8f402
Compare
547fc3f
to
3759abb
Compare
include/zephyr/bluetooth/mesh/msg.h
Outdated
/** 1-octet opcode. */ | ||
#define BT_MESH_MODEL_OP_LEN_1 1 | ||
/** 2-octets opcode. */ | ||
#define BT_MESH_MODEL_OP_LEN_2 2 | ||
/** 3-octets opcode. */ | ||
#define BT_MESH_MODEL_OP_LEN_3 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recommend to remove these macros.
@LingaoM the latest iteration of the PR is closer to what I'd consider acceptable, thanks! However, it's really a pity that we'd have to effectively double the opcode definition lists with two declarations for each opcode, when in principle all the information we need is already in the original declarations. Did you explore the possibility of having the #define BT_MESH_MODEL_OP_1(b0) ((uint8_t[]){ (b0) })
#define BT_MESH_MODEL_OP_2(b0, b1) ((uint8_t[]){ (b0), (b1) })
#define BT_MESH_MODEL_OP_3(b0, cid) ((uint8_t[]){ (b0), ((cid) >> 8), ((cid) & 0xff) }) |
I think this modification is more complicated, have you considered that the opcode is also referenced elsewhere in the code. |
What we need is in the preprocessing-time rather than build-time. |
Yes, you're right. I overlooked that part. There are a couple of subsystems in Zephyr where advanced preprocessor macro tricks (aka macrobatics) are heavily used, e.g. the logging subsystem as well as device tree. It would be nice if we could get some of the developers in those areas to take a look at this case, since I still haven't given up the hope that there exists a way to keep both the definition and usage of the opcodes as simple as they are now :) |
Actually, are you sure about that? I thought the main idea of this PR was to convert runtime message init to build time init? It's true that you can't use |
Hi @jhedberg if use it as part of C code if-branches, something like this: if (BT_MESH_MODEL_OP_LEN(_op) == 2) {
NET_BUF_SIMPLE_DEFINE(msg, ....);
} else {
NET_BUF_SIMPLE_DEFINE(msg, ....);
}
key_idx_pack_pair(&msg, net_idx, app_idx); Obvious, The compiler will report build error:
|
50824dc
to
53477d5
Compare
53477d5
to
f547dfc
Compare
One thought that came to mind is to have just a single |
This method still does not work, because the opcode is split into a byte list, and it is an unexpected symbol( |
That's because of the way that you've extended the (uint8_t net_buf_data_##_name[_size] = { __VA_ARGS__ }); you'd have something like this: (uint8_t net_buf_data_##_name[_size] = (uint8_t[])(__VA_ARGS__)); E.g. the following is valid C code (I don't get any warnings): const uint32_t op = 0x0000ffff;
struct {
uint8_t *buf;
} b = {
.buf = op > 0xff ? ((uint8_t[]){ (op >> 8), (op & 0xff) }) : ((uint8_t[]){ (op & 0xff) }),
}; |
COND_CODE_1(IS_EMPTY(__VA_ARGS__), \ | ||
(uint8_t net_buf_data_##_name[_size];), \ | ||
(uint8_t net_buf_data_##_name[_size] = { __VA_ARGS__ });) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if it came up as part of earlier reviews, but couldn't you remove the COND_CODE_1()
and instead always just do:
uint8_t net_buf_data_##_name[_size] = { __VA_ARGS__ };
Even if __VA_ARGS__
is empty that should still be valid code. The difference in behaviour to the previous version is that now we'd always explicitly initialize the content of the data array, whereas previously this would have been uninitialised memory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to do this because it will significantly increase the flash size. And will cause the default behavior to change. initialize the content of the 0, whereas previously this would have been uninitialised memory.
@LingaoM I just realised this won't work, because of the way you're using two levels of |
@LingaoM I suspect your current proposal with #define Z_OP_1(...) (GET_ARG_N(1, __VA_ARGS__))
#define Z_OP_2(...) ((Z_OP_1(__VA_ARGS__) << 8) | (GET_ARG_N(2, __VA_ARGS__)))
#define Z_OP_3(...) (0xc00000 | (Z_OP_2(__VA_ARGS__) << 8) | (GET_ARG_N(3, __VA_ARGS__)))
#define BT_MESH_MODEL_OPCODE(...) COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
Z_OP_1(__VA_ARGS__), \
COND_CODE_1(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
Z_OP_2(__VA_ARGS__, dummy), \
Z_OP_3(__VA_ARGS__, dummy, dummy)))
#define BT_MESH_MODEL_OP_STD(b0, ...) COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
(b0), ((b0), (GET_ARG_N(1, __VA_ARGS__, _))))
#define BT_MESH_MODEL_OP_VND(b0, cid) ((b0), (cid), ((cid) >> 8)) If we'd want to keep just a single definition per opcode, we might also want to create a helper for the opcode handler lists creation, something like: #define BT_MESH_MODEL_OP(_op_bytes, _len, _func) \
{ \
.opcode = BT_MESH_MODEL_OPCODE(_op_bytes), \
.len = _len, \
.func = _func, \
} The other alternative, which has the same overhead as your current solution of having two definitions per opcode, would be to have the "raw" array format as well as the the traditional integer format, i.e. something like: #define OP_HEARTBEAT_PUB_STATUS_RAW BT_MESH_MODEL_OP_STD(0x06)
#define OP_HEARTBEAT_PUB_STATUS BT_MESH_MODEL_OPCODE(OP_HEARTBEAT_PUB_STATUS_RAW)
#define OP_APP_KEY_DEL_RAW BT_MESH_MODEL_OP_STD(0x80, 0x00)
#define OP_APP_KEY_DEL BT_MESH_MODEL_OPCODE(OP_APP_KEY_DEL_RAW) Anyway, I just wanted to put the above out there so that it can be considered. Ultimately, this PR is about an optimisation, however since it comes with API changes I want us to acknowledge all possible options before locking us into one (the feature freeze for Zephyr 3.6 is end of next week, so if this gets merged before that then we'll be stuck with it for some time). |
That great, cool, thanks! |
f547dfc
to
9c27aa8
Compare
9c27aa8
to
cf1932b
Compare
include/zephyr/bluetooth/mesh/msg.h
Outdated
NET_BUF_SIMPLE_DEFINE(_buf, BT_MESH_MODEL_BUF_LEN(_op, _payload_len), \ | ||
_op ## _RAW, ##__VA_ARGS__) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I'd make the BT_MESH_MODEL_BUF_INIT()
API require the existence of a define whose name must follow the pattern OP_*_RAW
. We had to have this kind of required naming scheme with the earlier _LEN
solution, but I don't think there's any strong reason to require it now. Someone could be perfectly happy to define their opcodes using only the new _SIG() or _VND() macros, and then use the BT_MESH_MODEL_OPCODE()
conversion explicitly in the places where it's needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, how todo ?
Change to directly use OP_*_RAW
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the BT_MESH_MODEL_BUF_INIT()
would take as input a value created using the new OP_STD() or OP_VND() macros, which in your current proposal is the *_RAW defines.
@LingaoM looks pretty good, thanks for adopting my suggestion! :) I left one more inline comment regarding the requirement of always having *_RAW defines. I think it would also be good to get some more thoughts (especially from @PavelVPV) regarding the "two defines per opcode" solution. Previously, with your *_LEN solution, there was no way to avoid two separate defines per opcode, however now we have the option of just one, if we want to. The downside is that you'd need to wrap this single define through |
Use a single macro for all opcode length and add more args to initinalize. Signed-off-by: Lingao Meng <[email protected]>
cf1932b
to
c1f60b7
Compare
Initially I though it is good that we can get rid of |
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
Use separate macro define for mesh message buf define. And remove duplicate init.