can-api-generator 2.1.0__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- can_api_generator-2.3.0/Advantics_Bootloader.kcd +384 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/PKG-INFO +76 -6
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/README.md +74 -4
- can_api_generator-2.3.0/manual_api_test.c +93 -0
- can_api_generator-2.3.0/manual_api_test.h +60 -0
- can_api_generator-2.3.0/manual_api_test.o +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/__about__.py +1 -1
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/code_generator.py +16 -1
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/main.py +44 -5
- can_api_generator-2.3.0/src/can_api_generator/templates/callback_macros.jinja +13 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/templates/encoding_macros.jinja +12 -12
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/templates/header_template.jinja +13 -12
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/templates/rx_macros.jinja +8 -25
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/templates/source_template.jinja +6 -6
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/templates/tx_macros.jinja +87 -54
- can_api_generator-2.3.0/test_1_rx_over_can +0 -0
- can_api_generator-2.3.0/test_api.c +78 -0
- can_api_generator-2.3.0/test_api.h +68 -0
- can_api_generator-2.3.0/test_kcd_api_test_mux_with_same_signal_names_labeled_mux_variants.c +686 -0
- can_api_generator-2.3.0/test_mux_with_same_signal_names_labeled_mux_variants.c +237 -0
- can_api_generator-2.3.0/test_mux_with_same_signal_names_labeled_mux_variants.h +265 -0
- can_api_generator-2.3.0/test_test_1_rx_over_can.c +65 -0
- can_api_generator-2.3.0/test_test_basic_multiplex_rx_over_can.c +67 -0
- can_api_generator-2.3.0/test_test_mux_with_partially_labled_index_rx_over_can.c +67 -0
- can_api_generator-2.3.0/test_test_mux_with_same_signal_names_labeled_mux_variants_rx_over_can.c +67 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_cli.py +37 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_cross_interface_compat.py +2 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_message_parser.py +2 -0
- can_api_generator-2.3.0/tests/test_tx_function.py +118 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/todo.md +9 -3
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/.gitignore +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/LICENSE.txt +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/manual_cag_test.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/pyproject.toml +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/__init__.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/cbdb_generator.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/msg_processor.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/templates/canframe.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/templates/declaration_macros.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/templates/dyndec_header.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/templates/dyndec_source.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/types.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/src/can_api_generator/utils.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/__init__.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/cantool_test_utils.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/compat_shim.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/dyndec_test_harness.c +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/multiple_busses_test.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_1.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_basic_multiplex.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_big_endian.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_can_db_model_dep.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_cbdb_generator.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_cross_interface_compat.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_dyndec_round_trip.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_float_wrong_length.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_missing_consumer.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_missing_producer.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_mux_group_count_out_of_order.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_mux_with_labeled_index.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_mux_with_partially_labled_index.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_mux_with_same_signal_names.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_mux_with_same_signal_names_labeled_mux_variants.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_mux_with_scale_and_offset.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_non_encodable_0.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_overlapping_signals.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_periodic_tx_over_can.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_procedures.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_prog_source_template.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_rx_over_can.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_direction.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/double_plain.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/double_scaled.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/double_scaled_offset.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/float_plain.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/float_scaled.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/float_scaled_offset.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/sint_matching_fractional_scaled.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/sint_matching_fractional_scaled_offset.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/sint_matching_plain.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/sint_matching_scaled.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/sint_matching_scaled_offset.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/sint_nonmatching_fractional_scaled.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/sint_nonmatching_plain.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/sint_nonmatching_scaled.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/sint_nonmatching_scaled_offset.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/test_decoding_numerical_value.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/test_encoding_numerical_value.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/test_signal_encoding_wrong_float_size.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/uint_matching_fractional_scaled.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/uint_matching_plain.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/uint_matching_scaled.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/uint_matching_scaled_offset.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/uint_nonmatching_fractional_scaled.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/uint_nonmatching_plain.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/uint_nonmatching_scaled.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_encoding/uint_nonmatching_scaled_offset.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_signal_info.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_too_large_message.kcd +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_tx_over_can.jinja +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_utils.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_vcan_round_trip.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_yaml_cbdb.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_yaml_input.py +0 -0
- {can_api_generator-2.1.0 → can_api_generator-2.3.0}/tests/test_yaml_kcd_equivalence.py +0 -0
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
<?xml version="1.0" ?>
|
|
2
|
+
<NetworkDefinition xmlns="http://kayak.2codeornot2code.org/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="KCD_Definition.xsd">
|
|
3
|
+
<Document name="Advantics_Bootloader" version="1" author="[...]" company="Advantics" date="2019-11-19"/>
|
|
4
|
+
<Node id="0" name="User"/>
|
|
5
|
+
<Node id="5" name="Bootloader"/>
|
|
6
|
+
<Bus name="Bootloader" baudrate="500000">
|
|
7
|
+
<Message id="0x8000" length="8" name="Bootloader_Identification" interval="1000" format="extended">
|
|
8
|
+
<Notes>Identification of the device</Notes>
|
|
9
|
+
<Producer> <NodeRef id="5"/> </Producer>
|
|
10
|
+
<Signal name="Device_type" offset="0" length="8">
|
|
11
|
+
<Notes> The device identification field, uniquely identifies the sender in the network </Notes>
|
|
12
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
13
|
+
</Signal>
|
|
14
|
+
<Signal name="HW_revision" offset="8" length="8">
|
|
15
|
+
<Notes>The hardware revision number</Notes>
|
|
16
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
17
|
+
</Signal>
|
|
18
|
+
<Signal name="HW_variant" offset="16" length="8">
|
|
19
|
+
<Notes>The DSP firmware revision number</Notes>
|
|
20
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
21
|
+
</Signal>
|
|
22
|
+
<Signal name="Stack_position" offset="24" length="8">
|
|
23
|
+
<Notes>Position of the module within the stack</Notes>
|
|
24
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
25
|
+
</Signal>
|
|
26
|
+
<Signal name="SN_number" offset="32" length="32">
|
|
27
|
+
<Notes>Unique module serial number</Notes>
|
|
28
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
29
|
+
</Signal>
|
|
30
|
+
</Message>
|
|
31
|
+
|
|
32
|
+
<Message id="0x8001" length="8" name="Bootloader_Fwinfo" interval="1000" format="extended">
|
|
33
|
+
<Notes>Git revision of the DSP firmware</Notes>
|
|
34
|
+
<Producer> <NodeRef id="5"/> </Producer>
|
|
35
|
+
<Multiplex name="FW_info_mux" offset="56" length="8">
|
|
36
|
+
<MuxGroup count="0">
|
|
37
|
+
<Signal name="FW_revision_0" offset="0" length="8">
|
|
38
|
+
<Notes>Character 0</Notes>
|
|
39
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
40
|
+
</Signal>
|
|
41
|
+
<Signal name="FW_revision_1" offset="8" length="8">
|
|
42
|
+
<Notes>Character 1</Notes>
|
|
43
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
44
|
+
</Signal>
|
|
45
|
+
<Signal name="FW_revision_2" offset="16" length="8">
|
|
46
|
+
<Notes>Character 2</Notes>
|
|
47
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
48
|
+
</Signal>
|
|
49
|
+
<Signal name="FW_revision_3" offset="24" length="8">
|
|
50
|
+
<Notes>Character 3</Notes>
|
|
51
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
52
|
+
</Signal>
|
|
53
|
+
<Signal name="FW_revision_4" offset="32" length="8">
|
|
54
|
+
<Notes>Character 3</Notes>
|
|
55
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
56
|
+
</Signal>
|
|
57
|
+
<Signal name="FW_revision_5" offset="40" length="8">
|
|
58
|
+
<Notes>Character 3</Notes>
|
|
59
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
60
|
+
</Signal>
|
|
61
|
+
<Signal name="FW_revision_6" offset="48" length="8">
|
|
62
|
+
<Notes>Character 3</Notes>
|
|
63
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
64
|
+
</Signal>
|
|
65
|
+
</MuxGroup>
|
|
66
|
+
<MuxGroup count="1">
|
|
67
|
+
<Signal name="FW_revision_7" offset="0" length="8">
|
|
68
|
+
<Notes>Character 7</Notes>
|
|
69
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
70
|
+
</Signal>
|
|
71
|
+
<Signal name="FW_revision_8" offset="8" length="8">
|
|
72
|
+
<Notes>Character 8</Notes>
|
|
73
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
74
|
+
</Signal>
|
|
75
|
+
<Signal name="FW_revision_9" offset="16" length="8">
|
|
76
|
+
<Notes>Character 9</Notes>
|
|
77
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
78
|
+
</Signal>
|
|
79
|
+
<Signal name="FW_revision_10" offset="24" length="8">
|
|
80
|
+
<Notes>Character 10</Notes>
|
|
81
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
82
|
+
</Signal>
|
|
83
|
+
<Signal name="FW_revision_11" offset="32" length="8">
|
|
84
|
+
<Notes>Character 11</Notes>
|
|
85
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
86
|
+
</Signal>
|
|
87
|
+
<Signal name="FW_revision_12" offset="40" length="8">
|
|
88
|
+
<Notes>Character 12</Notes>
|
|
89
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
90
|
+
</Signal>
|
|
91
|
+
<Signal name="FW_revision_13" offset="48" length="8">
|
|
92
|
+
<Notes>Character 13</Notes>
|
|
93
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
94
|
+
</Signal>
|
|
95
|
+
</MuxGroup>
|
|
96
|
+
<MuxGroup count="2">
|
|
97
|
+
<Signal name="FW_datecode_0" offset="0" length="8">
|
|
98
|
+
<Notes>Character 0</Notes>
|
|
99
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
100
|
+
</Signal>
|
|
101
|
+
<Signal name="FW_datecode_1" offset="8" length="8">
|
|
102
|
+
<Notes>Character 1</Notes>
|
|
103
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
104
|
+
</Signal>
|
|
105
|
+
<Signal name="FW_datecode_2" offset="16" length="8">
|
|
106
|
+
<Notes>Character 2</Notes>
|
|
107
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
108
|
+
</Signal>
|
|
109
|
+
<Signal name="FW_datecode_3" offset="24" length="8">
|
|
110
|
+
<Notes>Character 3</Notes>
|
|
111
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
112
|
+
</Signal>
|
|
113
|
+
<Signal name="FW_datecode_4" offset="32" length="8">
|
|
114
|
+
<Notes>Character 3</Notes>
|
|
115
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
116
|
+
</Signal>
|
|
117
|
+
<Signal name="FW_datecode_5" offset="40" length="8">
|
|
118
|
+
<Notes>Character 3</Notes>
|
|
119
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
120
|
+
</Signal>
|
|
121
|
+
<Signal name="FW_datecode_6" offset="48" length="8">
|
|
122
|
+
<Notes>Character 3</Notes>
|
|
123
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
124
|
+
</Signal>
|
|
125
|
+
</MuxGroup>
|
|
126
|
+
<MuxGroup count="3">
|
|
127
|
+
<Signal name="FW_datecode_7" offset="0" length="8">
|
|
128
|
+
<Notes>Character 7</Notes>
|
|
129
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
130
|
+
</Signal>
|
|
131
|
+
<Signal name="FW_datecode_8" offset="8" length="8">
|
|
132
|
+
<Notes>Character 8</Notes>
|
|
133
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
134
|
+
</Signal>
|
|
135
|
+
<Signal name="FW_datecode_9" offset="16" length="8">
|
|
136
|
+
<Notes>Character 9</Notes>
|
|
137
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
138
|
+
</Signal>
|
|
139
|
+
<Signal name="FW_datecode_10" offset="24" length="8">
|
|
140
|
+
<Notes>Character 10</Notes>
|
|
141
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
142
|
+
</Signal>
|
|
143
|
+
<Signal name="FW_datecode_11" offset="32" length="8">
|
|
144
|
+
<Notes>Character 11</Notes>
|
|
145
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
146
|
+
</Signal>
|
|
147
|
+
<Signal name="FW_datecode_12" offset="40" length="8">
|
|
148
|
+
<Notes>Character 12</Notes>
|
|
149
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
150
|
+
</Signal>
|
|
151
|
+
<Signal name="FW_datecode_13" offset="48" length="8">
|
|
152
|
+
<Notes>Character 13</Notes>
|
|
153
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
154
|
+
</Signal>
|
|
155
|
+
</MuxGroup>
|
|
156
|
+
</Multiplex>
|
|
157
|
+
</Message>
|
|
158
|
+
|
|
159
|
+
<Message id="0x8002" length="8" name="Bootloader_Debug" interval="1000" format="extended">
|
|
160
|
+
<Notes>Values for debugging of HW/SW problems</Notes>
|
|
161
|
+
<Producer> <NodeRef id="5"/> </Producer>
|
|
162
|
+
<Signal name="Status_Error_Code" offset="0" length="16">
|
|
163
|
+
<Notes>Main status / error code as defined in errno/errno.h</Notes>
|
|
164
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
165
|
+
</Signal>
|
|
166
|
+
<Signal name="Data_1" offset="16" length="16">
|
|
167
|
+
<Notes>Additional information for the error/status</Notes>
|
|
168
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
169
|
+
</Signal>
|
|
170
|
+
<Signal name="Data_2" offset="32" length="16">
|
|
171
|
+
<Notes>Additional information for the error/status</Notes>
|
|
172
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
173
|
+
</Signal>
|
|
174
|
+
<Signal name="Data_3" offset="48" length="16">
|
|
175
|
+
<Notes>Additional information for the error/status</Notes>
|
|
176
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
177
|
+
</Signal>
|
|
178
|
+
</Message>
|
|
179
|
+
|
|
180
|
+
<Message id="0x80A5" length="5" name="Bootloader_Info" interval="5" format="extended">
|
|
181
|
+
<Producer> <NodeRef id="5"/> </Producer>
|
|
182
|
+
<Signal name="Status" offset="0" length="8">
|
|
183
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
184
|
+
<LabelSet>
|
|
185
|
+
<Label name="Bootloader_Idle" value="0"/>
|
|
186
|
+
<Label name="Bootloader_Prog" value="1"/>
|
|
187
|
+
<Label name="Bootloader_Get_Len" value="2"/>
|
|
188
|
+
<Label name="Bootloader_Flash" value="3"/>
|
|
189
|
+
<Label name="Bootloader_Erase" value="4"/>
|
|
190
|
+
<Label name="Bootloader_Flash_Error" value="5"/>
|
|
191
|
+
<Label name="Bootloader_Erase_Error" value="6"/>
|
|
192
|
+
<Label name="Bootloader_Download" value="7"/>
|
|
193
|
+
<Label name="Bootloader_Download_Start" value="8"/>
|
|
194
|
+
<Label name="Bootloader_Flash_End" value="9"/>
|
|
195
|
+
<Label name="Bootloader_Prog_Erased" value="10"/>
|
|
196
|
+
<Label name="Bootloader_Write_Module" value="11"/>
|
|
197
|
+
<Label name="Bootloader_Module_Written" value="12"/>
|
|
198
|
+
<Label name="Bootloader_Module_Write_Error" value="13"/>
|
|
199
|
+
<Label name="Bootloader_Make_Virgin_Done" value="14"/>
|
|
200
|
+
<Label name="Bootloader_Make_Virgin_Error" value="15"/>
|
|
201
|
+
</LabelSet>
|
|
202
|
+
</Signal>
|
|
203
|
+
<Signal name="Error" offset="8" length="16">
|
|
204
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
205
|
+
</Signal>
|
|
206
|
+
<Signal name="Seq_num" offset="24" length="16">
|
|
207
|
+
<Consumer> <NodeRef id="0"/> </Consumer>
|
|
208
|
+
</Signal>
|
|
209
|
+
</Message>
|
|
210
|
+
|
|
211
|
+
<Message id="0x00A5" length="8" name="Bootloader_Command" format="extended">
|
|
212
|
+
<Notes>Single message is used for all Bootloader commands</Notes>
|
|
213
|
+
<Producer> <NodeRef id="0"/> </Producer>
|
|
214
|
+
<Multiplex name="Bootloader_command_id" offset="0" length="8">
|
|
215
|
+
<MuxGroup count="85">
|
|
216
|
+
<Signal name="Flash_address" offset="8" length="32">
|
|
217
|
+
<Notes> Start address of sector to FLASH. </Notes>
|
|
218
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
219
|
+
</Signal>
|
|
220
|
+
<Signal name="Flash_Request" offset="40" length="1">
|
|
221
|
+
<Notes>
|
|
222
|
+
This is not required by bootloader to execute,
|
|
223
|
+
put here to validate KCD.
|
|
224
|
+
(I.e. value is _DON'T CARE_)
|
|
225
|
+
</Notes>
|
|
226
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
227
|
+
</Signal>
|
|
228
|
+
</MuxGroup>
|
|
229
|
+
<MuxGroup count="165">
|
|
230
|
+
<Signal name="Stop_Boot" offset="8" length="1">
|
|
231
|
+
<Notes>
|
|
232
|
+
This is not required by bootloader to execute,
|
|
233
|
+
put here to validate KCD.
|
|
234
|
+
(I.e. value is _DON'T CARE_)
|
|
235
|
+
</Notes>
|
|
236
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
237
|
+
</Signal>
|
|
238
|
+
</MuxGroup>
|
|
239
|
+
<MuxGroup count="170">
|
|
240
|
+
<Signal name="Clear_Errors" offset="8" length="1">
|
|
241
|
+
<Notes>
|
|
242
|
+
This is not required by bootloader to execute,
|
|
243
|
+
put here to validate KCD.
|
|
244
|
+
(I.e. value is _DON'T CARE_)
|
|
245
|
+
</Notes>
|
|
246
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
247
|
+
</Signal>
|
|
248
|
+
</MuxGroup>
|
|
249
|
+
<MuxGroup count="90">
|
|
250
|
+
<Signal name="Resume_Boot" offset="8" length="1">
|
|
251
|
+
<Notes>
|
|
252
|
+
This is not required by bootloader to execute,
|
|
253
|
+
put here to validate KCD.
|
|
254
|
+
(I.e. value is _DON'T CARE_)
|
|
255
|
+
</Notes>
|
|
256
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
257
|
+
</Signal>
|
|
258
|
+
</MuxGroup>
|
|
259
|
+
<MuxGroup count="17">
|
|
260
|
+
<Signal name="Flash_sector" offset="8" length="32">
|
|
261
|
+
<Notes> Start address of sector to ERASE. </Notes>
|
|
262
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
263
|
+
</Signal>
|
|
264
|
+
<Signal name="Erase_Sector" offset="40" length="1">
|
|
265
|
+
<Notes>
|
|
266
|
+
This is not required by bootloader to execute,
|
|
267
|
+
put here to validate KCD.
|
|
268
|
+
(I.e. value is _DON'T CARE_)
|
|
269
|
+
</Notes>
|
|
270
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
271
|
+
</Signal>
|
|
272
|
+
</MuxGroup>
|
|
273
|
+
<MuxGroup count="18">
|
|
274
|
+
<Signal name="Flash_len" offset="8" length="32">
|
|
275
|
+
<Notes> Length of the data to flash. </Notes>
|
|
276
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
277
|
+
</Signal>
|
|
278
|
+
<Signal name="Set_Flash_Length" offset="40" length="1">
|
|
279
|
+
<Notes>
|
|
280
|
+
This is not required by bootloader to execute,
|
|
281
|
+
put here to validate KCD.
|
|
282
|
+
(I.e. value is _DON'T CARE_)
|
|
283
|
+
</Notes>
|
|
284
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
285
|
+
</Signal>
|
|
286
|
+
</MuxGroup>
|
|
287
|
+
<MuxGroup count="19">
|
|
288
|
+
<Signal name="Device_type" offset="8" length="8">
|
|
289
|
+
<Notes>The hardware id</Notes>
|
|
290
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
291
|
+
</Signal>
|
|
292
|
+
<Signal name="HW_variant" offset="16" length="8">
|
|
293
|
+
<Notes>The hardware variant number</Notes>
|
|
294
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
295
|
+
</Signal>
|
|
296
|
+
<Signal name="HW_revision" offset="24" length="8">
|
|
297
|
+
<Notes>The hardware revision number</Notes>
|
|
298
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
299
|
+
</Signal>
|
|
300
|
+
<Signal name="Stack_position" offset="32" length="8">
|
|
301
|
+
<Notes>Position of the module within the stack</Notes>
|
|
302
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
303
|
+
</Signal>
|
|
304
|
+
<Signal name="Stack_size" offset="40" length="16">
|
|
305
|
+
<Notes>Stack module count</Notes>
|
|
306
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
307
|
+
</Signal>
|
|
308
|
+
<Signal name="Init_Module" offset="56" length="1">
|
|
309
|
+
<Notes>
|
|
310
|
+
This is not required by bootloader to execute,
|
|
311
|
+
put here to validate KCD.
|
|
312
|
+
(I.e. value is _DON'T CARE_)
|
|
313
|
+
</Notes>
|
|
314
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
315
|
+
</Signal>
|
|
316
|
+
</MuxGroup>
|
|
317
|
+
<MuxGroup count="20">
|
|
318
|
+
<Signal name="Make_Virgin" offset="8" length="1">
|
|
319
|
+
<Notes>
|
|
320
|
+
This is not required by bootloader to execute,
|
|
321
|
+
put here to validate KCD.
|
|
322
|
+
(I.e. value is _DON'T CARE_)
|
|
323
|
+
</Notes>
|
|
324
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
325
|
+
</Signal>
|
|
326
|
+
</MuxGroup>
|
|
327
|
+
<MuxGroup count="21">
|
|
328
|
+
<Signal name="Serial_Number" offset="8" length="32">
|
|
329
|
+
<Notes>
|
|
330
|
+
This is the serial number to be programmed into the EEPROM. This
|
|
331
|
+
will only work in those units whose EEPROM does not come with a
|
|
332
|
+
preprogrammed serial number.
|
|
333
|
+
</Notes>
|
|
334
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
335
|
+
</Signal>
|
|
336
|
+
<Signal name="Program_SN" offset="40" length="1">
|
|
337
|
+
<Notes>
|
|
338
|
+
This is not required by bootloader to execute,
|
|
339
|
+
put here to validate KCD.
|
|
340
|
+
(I.e. value is _DON'T CARE_)
|
|
341
|
+
</Notes>
|
|
342
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
343
|
+
</Signal>
|
|
344
|
+
</MuxGroup>
|
|
345
|
+
<LabelSet>
|
|
346
|
+
<Label name="Flash_Request" value="85"/>
|
|
347
|
+
<Label name="Stop_Boot" value="165"/>
|
|
348
|
+
<Label name="Clear_Errors" value="170"/>
|
|
349
|
+
<Label name="Resume_Boot" value="90"/>
|
|
350
|
+
<Label name="Flash_Erase" value="17"/>
|
|
351
|
+
<Label name="Flash_Length" value="18"/>
|
|
352
|
+
<Label name="Init_Module" value="19"/>
|
|
353
|
+
<Label name="Make_Virgin" value="20"/>
|
|
354
|
+
<Label name="Program_SN" value="21"/>
|
|
355
|
+
</LabelSet>
|
|
356
|
+
</Multiplex>
|
|
357
|
+
</Message>
|
|
358
|
+
|
|
359
|
+
<Message id="0x00A6" length="8" name="Bootloader_Download" format="extended">
|
|
360
|
+
<Producer> <NodeRef id="0"/> </Producer>
|
|
361
|
+
<Signal name="Seq_num" length="16" offset="48">
|
|
362
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
363
|
+
</Signal>
|
|
364
|
+
<Signal name="Data_0" length="16" offset="0">
|
|
365
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
366
|
+
</Signal>
|
|
367
|
+
<Signal name="Data_1" length="16" offset="16">
|
|
368
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
369
|
+
</Signal>
|
|
370
|
+
<Signal name="Data_2" length="16" offset="32">
|
|
371
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
372
|
+
</Signal>
|
|
373
|
+
</Message>
|
|
374
|
+
|
|
375
|
+
<Message id="0x0050" length="1" name="Bootloader_Fault_Control" format="extended">
|
|
376
|
+
<Notes>Fault Control: actions to clear faults and reset the system</Notes>
|
|
377
|
+
<Producer> <NodeRef id="0"/> </Producer>
|
|
378
|
+
<Signal name="Reset_Processor" offset="1" length="1" endianess="little">
|
|
379
|
+
<Notes>Reset the filter DSP</Notes>
|
|
380
|
+
<Consumer> <NodeRef id="5"/> </Consumer>
|
|
381
|
+
</Signal>
|
|
382
|
+
</Message>
|
|
383
|
+
</Bus>
|
|
384
|
+
</NetworkDefinition>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: can-api-generator
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: Program to generate a 'signal' style CAN API in C
|
|
5
5
|
Project-URL: Documentation, https://sr.ht/~laplace/can-api-generator#readme
|
|
6
6
|
Project-URL: Issues, https://sr.ht/~laplace/can-api-generator/issues
|
|
@@ -45,6 +45,7 @@ Description-Content-Type: text/markdown
|
|
|
45
45
|
- [Double-buffered signal access](#double-buffered-signal-access)
|
|
46
46
|
- [RX/TX callback context](#rxtx-callback-context)
|
|
47
47
|
- [Message signals as RX callback argument](#message-signals-as-rx-callback-argument)
|
|
48
|
+
- [Using your own frame type](#using-your-own-frame-type)
|
|
48
49
|
- [Example Use](#example-use)
|
|
49
50
|
- [Dynamic decoding](#dynamic-decoding)
|
|
50
51
|
- [Preparing a database (`cbdb`)](#preparing-a-database-cbdb)
|
|
@@ -200,9 +201,10 @@ struct MsgTxContext {
|
|
|
200
201
|
critical signal has just changed and you want it on the bus on the very next tick instead of waiting out the remainder of the period.
|
|
201
202
|
|
|
202
203
|
By default (with `-p` alone) periodic TX is **callback-only**: `TxSignals` holds only a `MsgTxContext` per message (no `_signals` storage), and each scheduled message's
|
|
203
|
-
`tx_callback` produces the frame. When a message's schedule fires, `<api>_periodic_tx` clears `send_now
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
`tx_callback` produces the frame. When a message's schedule fires, `<api>_periodic_tx` clears `send_now`, then calls the callback only if it is registered; it
|
|
205
|
+
encodes and reports the frame, and updates `last_tx`, only if the callback returns a non-`NULL` struct pointer. A missing callback or a `NULL` return sends nothing for
|
|
206
|
+
that message and leaves `last_tx` untouched, so the message is offered again at its next slot; the call falls through, so another scheduled message whose callback
|
|
207
|
+
returns data can still be sent on the same call.
|
|
206
208
|
Multiplex variant scheduling is the application's responsibility in this mode (the callback returns whichever variant it wants to send).
|
|
207
209
|
|
|
208
210
|
In plain callback-only mode (no `--msg-as-tx-callback-arg`) the callback returns a pointer to the signal struct to be encoded, so **the application must provide the
|
|
@@ -219,6 +221,26 @@ value ignored), the generator handles multiplex rotation, and (with `--double-bu
|
|
|
219
221
|
`--msg-as-tx-callback-arg` passes a `void *` to that message's store struct as the callback's first argument (context second, if `--tx-callback-context`), so the callback
|
|
220
222
|
need not look the struct up before editing it in place.
|
|
221
223
|
|
|
224
|
+
#### Queueing frames through a bound TX function
|
|
225
|
+
By default `<api>_periodic_tx` returns at most one frame per call, so it has to be called often enough to drain every due message. Passing `--tx-function` binds a frame
|
|
226
|
+
sink to the API instead, so a single call hands every due message to it:
|
|
227
|
+
```c
|
|
228
|
+
struct <Prefix>TxSignals {
|
|
229
|
+
...
|
|
230
|
+
uint16_t (*tx_function)(void *tx_function_context, const CanFrame *frame);
|
|
231
|
+
void *tx_function_context;
|
|
232
|
+
};
|
|
233
|
+
void <api>_periodic_tx_init(struct <Prefix>TxSignals *tx_signals, uint64_t now,
|
|
234
|
+
uint16_t (*tx_function)(void *, const CanFrame *), void *tx_function_context);
|
|
235
|
+
uint16_t <api>_periodic_tx(struct <Prefix>TxSignals *tx_signals, uint64_t now); // returns the number of frames accepted
|
|
236
|
+
```
|
|
237
|
+
`<api>_periodic_tx` encodes each due message into a frame on its stack and calls `tx_function(tx_function_context, &frame)`, in the caller's context. The frame is only
|
|
238
|
+
valid during that call, so the function copies it (typically into a TX queue or mailbox). It returns nonzero if it accepted the frame; only then are `send_now` cleared,
|
|
239
|
+
`last_tx` updated and (with `--tx-signal-store`) the multiplex variant rotated. On a 0 return (queue full) nothing changes: a pending `send_now` is retried on the next call, a periodic message waits for its next
|
|
240
|
+
slot (`now % period == offset`); the missed slot is skipped, not caught up.
|
|
241
|
+
The `tx_callback` rules are unchanged: in callback-only mode a `NULL` return queues nothing, and `send_now` stays set as well. Works with and without
|
|
242
|
+
`--tx-signal-store`.
|
|
243
|
+
|
|
222
244
|
### Encode All Signals
|
|
223
245
|
Some messages use multiplexes combining many signals in to a single message. This may be particularly true for configuration messages that have many related parameters and use
|
|
224
246
|
multiplexes to fit all parameters in to a single message using many mux groups. If the entire config should be read out and the read back happens periodically, the supervisory controller
|
|
@@ -331,6 +353,45 @@ Passing `--msg-as-rx-callback-arg` instead hands the callback a `void *` pointin
|
|
|
331
353
|
|
|
332
354
|
`struct MsgRxContext` remains a single shared type, which is why the signal struct is passed as `void *` rather than a typed pointer.
|
|
333
355
|
|
|
356
|
+
### Using your own frame type
|
|
357
|
+
|
|
358
|
+
By default every generated function takes a `CanFrame *`, and the generator writes a sibling `canframe.h` that defines `CanFrame`. If the application already has a
|
|
359
|
+
frame struct (for example the one its CAN driver fills), the API can use that type directly instead, so no copy between two frame structs is needed:
|
|
360
|
+
|
|
361
|
+
* `-ct`, `--canframe-type` sets the type name used in every generated signature. Include the `struct` keyword if the type is not a typedef, e.g.
|
|
362
|
+
`-ct "struct DriverFrame"`.
|
|
363
|
+
* `-ch`, `--canframe-header` sets the header the generated `.h` includes to get that type, e.g. `-ch driver_frame.h`.
|
|
364
|
+
* `-im` / `-lm` / `-pm` rename the members the API reads and writes, so they match your struct (see the [command-line reference](#api)).
|
|
365
|
+
|
|
366
|
+
If either `-ct` or `-ch` is given, **`canframe.h` is not generated**. Giving either option means the application provides the frame definition, and writing our
|
|
367
|
+
`canframe.h` would at best go unused and at worst overwrite the application's own `canframe.h`. This holds even if the value passed equals the default (e.g.
|
|
368
|
+
`-ch canframe.h`), so supply your own header whenever you pass either flag.
|
|
369
|
+
|
|
370
|
+
Your type must provide three members, accessed as plain scalars:
|
|
371
|
+
|
|
372
|
+
| Member (default name) | Use | Requirement |
|
|
373
|
+
|---|---|---|
|
|
374
|
+
| `arbitration_id` (`-im`) | compared against / set to the message id | integer wide enough for the id (`uint32_t` for extended ids) |
|
|
375
|
+
| `length` (`-lm`) | compared against / set to the message DLC | integer |
|
|
376
|
+
| `payload` (`-pm`) | the whole 8-byte payload in one access | a single `uint64_t`, **not** a byte array |
|
|
377
|
+
|
|
378
|
+
The payload requirement rules out structs such as Linux's `struct can_frame`, whose data is a `__u8 data[8]` array. Wrap such frames in a struct with a `uint64_t`
|
|
379
|
+
payload (or a union with one) instead.
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
can-api-gen api bus.kcd my_api DUT -r -p -ct DriverFrame -ch driver_frame.h -im id -lm dlc -pm data
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
```c
|
|
386
|
+
/* driver_frame.h — supplied by the application */
|
|
387
|
+
#include <stdint.h>
|
|
388
|
+
typedef struct DriverFrame {
|
|
389
|
+
uint32_t id;
|
|
390
|
+
uint8_t dlc;
|
|
391
|
+
uint64_t data;
|
|
392
|
+
} DriverFrame;
|
|
393
|
+
```
|
|
394
|
+
|
|
334
395
|
## Example Use
|
|
335
396
|
|
|
336
397
|
As an example the following KCD definition of all messages on a CAN bus is converted:
|
|
@@ -547,7 +608,8 @@ Generate the static, per-node C API (see [Example Use](#example-use)).
|
|
|
547
608
|
|
|
548
609
|
Positional arguments:
|
|
549
610
|
* `DB_FILE` — path to the bus description, either a KCD (XML) or a `can-db-model` YAML file.
|
|
550
|
-
* `LIBRARY_NAME` — stem of the generated library. The output files are `<LIBRARY_NAME>.c`, `<LIBRARY_NAME>.h`, and a sibling `canframe.h
|
|
611
|
+
* `LIBRARY_NAME` — stem of the generated library. The output files are `<LIBRARY_NAME>.c`, `<LIBRARY_NAME>.h`, and a sibling `canframe.h` (omitted when `-ct` or
|
|
612
|
+
`-ch` is given). The stem is also used as
|
|
551
613
|
the prefix for every generated function so multiple APIs can coexist in the same project.
|
|
552
614
|
* `NODE_NAME` — name of the node the API is being generated for. Only messages that this node produces or consumes are emitted, so the binary size stays small for
|
|
553
615
|
embedded targets.
|
|
@@ -581,6 +643,10 @@ Options:
|
|
|
581
643
|
`--tx-signal-store` the pointer is the message's store struct, which the callback edits in place before encode; in callback-only mode `<api>_periodic_tx` stack-allocates
|
|
582
644
|
the struct, and the callback fills it and returns it (or `NULL` to skip), so no application-provided storage is needed. See [Periodic TX](#periodic-tx). Only meaningful
|
|
583
645
|
together with `-p`.
|
|
646
|
+
* `--tx-function` — bind a `uint16_t (*tx_function)(void *, const <frame> *)` and its context to the periodic-TX API through `<api>_periodic_tx_init`;
|
|
647
|
+
`<api>_periodic_tx(tx_signals, now)` then queues every due message through it in one pass and returns the number accepted. A 0 return leaves `last_tx` and
|
|
648
|
+
`send_now` untouched so the message is retried. See [Queueing frames through a bound TX function](#queueing-frames-through-a-bound-tx-function). Only meaningful
|
|
649
|
+
together with `-p`.
|
|
584
650
|
* `--rx-signal-store` — generate the permanent per-message RX signal store (the pre-2.0 default). Without it, global RX is callback-only: no store is
|
|
585
651
|
generated and decoded signals reach the application only through the RX callback. See [Global RX](#global-rx). Only meaningful together with `-r`.
|
|
586
652
|
* `--with-rx-valid` — in callback-only mode, add a `valid` field to `MsgRxContext` and set it on each matched frame, for struct-layout compatibility with
|
|
@@ -589,6 +655,10 @@ Options:
|
|
|
589
655
|
`<Prefix>TxSignals`). Lets two similar APIs (e.g. two versions of one database) coexist in a single translation unit with distinct struct names. Off by default.
|
|
590
656
|
* `--prefix-context-struct-names` — prefix the `MsgRxContext` / `MsgTxContext` type names and their include-guard tokens with the CamelCase API prefix, so the
|
|
591
657
|
context structs of two coexisting APIs do not share a single definition. Off by default.
|
|
658
|
+
* `-ct`, `--canframe-type TEXT` — the frame type used in every generated signature (default `CanFrame`). Include `struct` if it is not a typedef. Giving this
|
|
659
|
+
or `-ch` suppresses `canframe.h`. See [Using your own frame type](#using-your-own-frame-type).
|
|
660
|
+
* `-ch`, `--canframe-header TEXT` — the header the generated `.h` includes for the frame type (default `canframe.h`). Giving this or `-ct` suppresses
|
|
661
|
+
`canframe.h`. See [Using your own frame type](#using-your-own-frame-type).
|
|
592
662
|
* `-im`, `--id-member-name TEXT` — override the name of the `CanFrame` member that carries the arbitration id (default `arbitration_id`). Used to adapt the API
|
|
593
663
|
to an existing project's frame struct naming.
|
|
594
664
|
* `-lm`, `--length-member-name TEXT` — override the name of the `CanFrame` length member (default `length`).
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
- [Double-buffered signal access](#double-buffered-signal-access)
|
|
21
21
|
- [RX/TX callback context](#rxtx-callback-context)
|
|
22
22
|
- [Message signals as RX callback argument](#message-signals-as-rx-callback-argument)
|
|
23
|
+
- [Using your own frame type](#using-your-own-frame-type)
|
|
23
24
|
- [Example Use](#example-use)
|
|
24
25
|
- [Dynamic decoding](#dynamic-decoding)
|
|
25
26
|
- [Preparing a database (`cbdb`)](#preparing-a-database-cbdb)
|
|
@@ -175,9 +176,10 @@ struct MsgTxContext {
|
|
|
175
176
|
critical signal has just changed and you want it on the bus on the very next tick instead of waiting out the remainder of the period.
|
|
176
177
|
|
|
177
178
|
By default (with `-p` alone) periodic TX is **callback-only**: `TxSignals` holds only a `MsgTxContext` per message (no `_signals` storage), and each scheduled message's
|
|
178
|
-
`tx_callback` produces the frame. When a message's schedule fires, `<api>_periodic_tx` clears `send_now
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
`tx_callback` produces the frame. When a message's schedule fires, `<api>_periodic_tx` clears `send_now`, then calls the callback only if it is registered; it
|
|
180
|
+
encodes and reports the frame, and updates `last_tx`, only if the callback returns a non-`NULL` struct pointer. A missing callback or a `NULL` return sends nothing for
|
|
181
|
+
that message and leaves `last_tx` untouched, so the message is offered again at its next slot; the call falls through, so another scheduled message whose callback
|
|
182
|
+
returns data can still be sent on the same call.
|
|
181
183
|
Multiplex variant scheduling is the application's responsibility in this mode (the callback returns whichever variant it wants to send).
|
|
182
184
|
|
|
183
185
|
In plain callback-only mode (no `--msg-as-tx-callback-arg`) the callback returns a pointer to the signal struct to be encoded, so **the application must provide the
|
|
@@ -194,6 +196,26 @@ value ignored), the generator handles multiplex rotation, and (with `--double-bu
|
|
|
194
196
|
`--msg-as-tx-callback-arg` passes a `void *` to that message's store struct as the callback's first argument (context second, if `--tx-callback-context`), so the callback
|
|
195
197
|
need not look the struct up before editing it in place.
|
|
196
198
|
|
|
199
|
+
#### Queueing frames through a bound TX function
|
|
200
|
+
By default `<api>_periodic_tx` returns at most one frame per call, so it has to be called often enough to drain every due message. Passing `--tx-function` binds a frame
|
|
201
|
+
sink to the API instead, so a single call hands every due message to it:
|
|
202
|
+
```c
|
|
203
|
+
struct <Prefix>TxSignals {
|
|
204
|
+
...
|
|
205
|
+
uint16_t (*tx_function)(void *tx_function_context, const CanFrame *frame);
|
|
206
|
+
void *tx_function_context;
|
|
207
|
+
};
|
|
208
|
+
void <api>_periodic_tx_init(struct <Prefix>TxSignals *tx_signals, uint64_t now,
|
|
209
|
+
uint16_t (*tx_function)(void *, const CanFrame *), void *tx_function_context);
|
|
210
|
+
uint16_t <api>_periodic_tx(struct <Prefix>TxSignals *tx_signals, uint64_t now); // returns the number of frames accepted
|
|
211
|
+
```
|
|
212
|
+
`<api>_periodic_tx` encodes each due message into a frame on its stack and calls `tx_function(tx_function_context, &frame)`, in the caller's context. The frame is only
|
|
213
|
+
valid during that call, so the function copies it (typically into a TX queue or mailbox). It returns nonzero if it accepted the frame; only then are `send_now` cleared,
|
|
214
|
+
`last_tx` updated and (with `--tx-signal-store`) the multiplex variant rotated. On a 0 return (queue full) nothing changes: a pending `send_now` is retried on the next call, a periodic message waits for its next
|
|
215
|
+
slot (`now % period == offset`); the missed slot is skipped, not caught up.
|
|
216
|
+
The `tx_callback` rules are unchanged: in callback-only mode a `NULL` return queues nothing, and `send_now` stays set as well. Works with and without
|
|
217
|
+
`--tx-signal-store`.
|
|
218
|
+
|
|
197
219
|
### Encode All Signals
|
|
198
220
|
Some messages use multiplexes combining many signals in to a single message. This may be particularly true for configuration messages that have many related parameters and use
|
|
199
221
|
multiplexes to fit all parameters in to a single message using many mux groups. If the entire config should be read out and the read back happens periodically, the supervisory controller
|
|
@@ -306,6 +328,45 @@ Passing `--msg-as-rx-callback-arg` instead hands the callback a `void *` pointin
|
|
|
306
328
|
|
|
307
329
|
`struct MsgRxContext` remains a single shared type, which is why the signal struct is passed as `void *` rather than a typed pointer.
|
|
308
330
|
|
|
331
|
+
### Using your own frame type
|
|
332
|
+
|
|
333
|
+
By default every generated function takes a `CanFrame *`, and the generator writes a sibling `canframe.h` that defines `CanFrame`. If the application already has a
|
|
334
|
+
frame struct (for example the one its CAN driver fills), the API can use that type directly instead, so no copy between two frame structs is needed:
|
|
335
|
+
|
|
336
|
+
* `-ct`, `--canframe-type` sets the type name used in every generated signature. Include the `struct` keyword if the type is not a typedef, e.g.
|
|
337
|
+
`-ct "struct DriverFrame"`.
|
|
338
|
+
* `-ch`, `--canframe-header` sets the header the generated `.h` includes to get that type, e.g. `-ch driver_frame.h`.
|
|
339
|
+
* `-im` / `-lm` / `-pm` rename the members the API reads and writes, so they match your struct (see the [command-line reference](#api)).
|
|
340
|
+
|
|
341
|
+
If either `-ct` or `-ch` is given, **`canframe.h` is not generated**. Giving either option means the application provides the frame definition, and writing our
|
|
342
|
+
`canframe.h` would at best go unused and at worst overwrite the application's own `canframe.h`. This holds even if the value passed equals the default (e.g.
|
|
343
|
+
`-ch canframe.h`), so supply your own header whenever you pass either flag.
|
|
344
|
+
|
|
345
|
+
Your type must provide three members, accessed as plain scalars:
|
|
346
|
+
|
|
347
|
+
| Member (default name) | Use | Requirement |
|
|
348
|
+
|---|---|---|
|
|
349
|
+
| `arbitration_id` (`-im`) | compared against / set to the message id | integer wide enough for the id (`uint32_t` for extended ids) |
|
|
350
|
+
| `length` (`-lm`) | compared against / set to the message DLC | integer |
|
|
351
|
+
| `payload` (`-pm`) | the whole 8-byte payload in one access | a single `uint64_t`, **not** a byte array |
|
|
352
|
+
|
|
353
|
+
The payload requirement rules out structs such as Linux's `struct can_frame`, whose data is a `__u8 data[8]` array. Wrap such frames in a struct with a `uint64_t`
|
|
354
|
+
payload (or a union with one) instead.
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
can-api-gen api bus.kcd my_api DUT -r -p -ct DriverFrame -ch driver_frame.h -im id -lm dlc -pm data
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
```c
|
|
361
|
+
/* driver_frame.h — supplied by the application */
|
|
362
|
+
#include <stdint.h>
|
|
363
|
+
typedef struct DriverFrame {
|
|
364
|
+
uint32_t id;
|
|
365
|
+
uint8_t dlc;
|
|
366
|
+
uint64_t data;
|
|
367
|
+
} DriverFrame;
|
|
368
|
+
```
|
|
369
|
+
|
|
309
370
|
## Example Use
|
|
310
371
|
|
|
311
372
|
As an example the following KCD definition of all messages on a CAN bus is converted:
|
|
@@ -522,7 +583,8 @@ Generate the static, per-node C API (see [Example Use](#example-use)).
|
|
|
522
583
|
|
|
523
584
|
Positional arguments:
|
|
524
585
|
* `DB_FILE` — path to the bus description, either a KCD (XML) or a `can-db-model` YAML file.
|
|
525
|
-
* `LIBRARY_NAME` — stem of the generated library. The output files are `<LIBRARY_NAME>.c`, `<LIBRARY_NAME>.h`, and a sibling `canframe.h
|
|
586
|
+
* `LIBRARY_NAME` — stem of the generated library. The output files are `<LIBRARY_NAME>.c`, `<LIBRARY_NAME>.h`, and a sibling `canframe.h` (omitted when `-ct` or
|
|
587
|
+
`-ch` is given). The stem is also used as
|
|
526
588
|
the prefix for every generated function so multiple APIs can coexist in the same project.
|
|
527
589
|
* `NODE_NAME` — name of the node the API is being generated for. Only messages that this node produces or consumes are emitted, so the binary size stays small for
|
|
528
590
|
embedded targets.
|
|
@@ -556,6 +618,10 @@ Options:
|
|
|
556
618
|
`--tx-signal-store` the pointer is the message's store struct, which the callback edits in place before encode; in callback-only mode `<api>_periodic_tx` stack-allocates
|
|
557
619
|
the struct, and the callback fills it and returns it (or `NULL` to skip), so no application-provided storage is needed. See [Periodic TX](#periodic-tx). Only meaningful
|
|
558
620
|
together with `-p`.
|
|
621
|
+
* `--tx-function` — bind a `uint16_t (*tx_function)(void *, const <frame> *)` and its context to the periodic-TX API through `<api>_periodic_tx_init`;
|
|
622
|
+
`<api>_periodic_tx(tx_signals, now)` then queues every due message through it in one pass and returns the number accepted. A 0 return leaves `last_tx` and
|
|
623
|
+
`send_now` untouched so the message is retried. See [Queueing frames through a bound TX function](#queueing-frames-through-a-bound-tx-function). Only meaningful
|
|
624
|
+
together with `-p`.
|
|
559
625
|
* `--rx-signal-store` — generate the permanent per-message RX signal store (the pre-2.0 default). Without it, global RX is callback-only: no store is
|
|
560
626
|
generated and decoded signals reach the application only through the RX callback. See [Global RX](#global-rx). Only meaningful together with `-r`.
|
|
561
627
|
* `--with-rx-valid` — in callback-only mode, add a `valid` field to `MsgRxContext` and set it on each matched frame, for struct-layout compatibility with
|
|
@@ -564,6 +630,10 @@ Options:
|
|
|
564
630
|
`<Prefix>TxSignals`). Lets two similar APIs (e.g. two versions of one database) coexist in a single translation unit with distinct struct names. Off by default.
|
|
565
631
|
* `--prefix-context-struct-names` — prefix the `MsgRxContext` / `MsgTxContext` type names and their include-guard tokens with the CamelCase API prefix, so the
|
|
566
632
|
context structs of two coexisting APIs do not share a single definition. Off by default.
|
|
633
|
+
* `-ct`, `--canframe-type TEXT` — the frame type used in every generated signature (default `CanFrame`). Include `struct` if it is not a typedef. Giving this
|
|
634
|
+
or `-ch` suppresses `canframe.h`. See [Using your own frame type](#using-your-own-frame-type).
|
|
635
|
+
* `-ch`, `--canframe-header TEXT` — the header the generated `.h` includes for the frame type (default `canframe.h`). Giving this or `-ct` suppresses
|
|
636
|
+
`canframe.h`. See [Using your own frame type](#using-your-own-frame-type).
|
|
567
637
|
* `-im`, `--id-member-name TEXT` — override the name of the `CanFrame` member that carries the arbitration id (default `arbitration_id`). Used to adapt the API
|
|
568
638
|
to an existing project's frame struct naming.
|
|
569
639
|
* `-lm`, `--length-member-name TEXT` — override the name of the `CanFrame` length member (default `length`).
|