Skip to content

Commit 3c75fe4

Browse files
SILKIT-1743 can xl: update docs, tests and demo (#200)
Ensure CNA XL is used in tests and the demo. Update the docs to reflect that we support CAN XL. --------- Co-authored-by: Daniel Edwards <daniel.edwards@vector.com>
1 parent 30a2dbd commit 3c75fe4

8 files changed

Lines changed: 123 additions & 34 deletions

File tree

Demos/communication/Can/CanDemoCommon.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ void FrameHandler(const CanFrameEvent& canFrameEvent, ILogger* logger, bool prin
2525
{
2626
frameTypeHint = "FD ";
2727
}
28-
28+
if ((canFrameEvent.frame.flags & static_cast<CanFrameFlagMask>(CanFrameFlag::Xlf)) != 0)
29+
{
30+
frameTypeHint = "XL ";
31+
}
2932
std::stringstream ss;
3033
ss << "Receive CAN " << frameTypeHint << "frame: canId=" << canFrameEvent.frame.canId << ", data=";
3134
if (printHex)

SilKit/IntegrationTests/FTest_CanWithoutSync.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ class FTest_CanWithoutSync : public testing::Test
7676
canmsg.frame.dlc = static_cast<uint16_t>(canmsg.frame.dataField.size());
7777
canmsg.frame.flags |=
7878
static_cast<CanFrameFlagMask>(CanFrameFlag::Ide) | static_cast<CanFrameFlagMask>(CanFrameFlag::Fdf)
79-
| static_cast<CanFrameFlagMask>(CanFrameFlag::Esi) | static_cast<CanFrameFlagMask>(CanFrameFlag::Sec);
79+
| static_cast<CanFrameFlagMask>(CanFrameFlag::Esi) | static_cast<CanFrameFlagMask>(CanFrameFlag::Sec)
80+
| static_cast<CanFrameFlagMask>(CanFrameFlag::Xlf);
8081
canmsg.timestamp = 1s;
8182
canmsg.direction = SilKit::Services::TransmitDirection::RX;
8283
canmsg.userContext = 0;

SilKit/IntegrationTests/ITest_CanDemo.cpp

Lines changed: 107 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,68 @@ struct TestState
5757
bool readerReceivedErrorActive = false;
5858
bool monitorReceivedErrorActive = false;
5959
std::atomic<uint32_t> monitorReceiveCount{0};
60+
std::atomic<uint32_t> monitorReceiveCountXlf{0};
61+
std::atomic<uint32_t> monitorReceiveCountFdf{0};
6062

61-
std::vector<uint8_t> payloadBytes;
6263

63-
CanFrame msg;
64+
struct OwningCanFrame : CanFrame
65+
{
66+
OwningCanFrame()
67+
{
68+
this->af = {};
69+
this->canId = {};
70+
this->dataField = {};
71+
this->dlc = {};
72+
this->flags = {};
73+
this->sdt = {};
74+
this->vcid = {};
75+
}
76+
std::vector<uint8_t> payloadBytes;
77+
};
78+
79+
OwningCanFrame msg{};
80+
OwningCanFrame fdFrame{};
81+
OwningCanFrame xlFrame{};
82+
83+
static constexpr uint32_t canId = 123;
84+
static constexpr uint32_t fdId = 0xcafecafe;
85+
static constexpr uint32_t xlId = 0xcacacaca;
6486

6587
//Reader variables
6688
bool result = false;
6789
std::chrono::milliseconds receiveTime = 0ms;
6890
size_t messageCount{0};
91+
92+
TestState()
93+
{
94+
auto fillData = [](auto& frame, size_t size) {
95+
frame.payloadBytes.resize(size);
96+
for (size_t i = 0; i < frame.payloadBytes.size(); i++)
97+
{
98+
frame.payloadBytes[i] = 'A' + (i % 26);
99+
}
100+
frame.dataField = frame.payloadBytes;
101+
};
102+
//Test data, CAN
103+
msg.canId = canId;
104+
fillData(msg, 8);
105+
msg.dlc = 8;
106+
107+
// Test data, CAN FD
108+
fillData(fdFrame, 64);
109+
fdFrame.canId = fdId;
110+
fdFrame.dlc = 15;
111+
fdFrame.flags |= SilKit_CanFrameFlag_fdf | SilKit_CanFrameFlag_ide;
112+
113+
// Test data, CAN XL
114+
fillData(xlFrame, 2048);
115+
xlFrame.canId = xlId;
116+
xlFrame.dlc = 2048;
117+
xlFrame.flags |= SilKit_CanFrameFlag_fdf | SilKit_CanFrameFlag_ide | SilKit_CanFrameFlag_xlf;
118+
xlFrame.af = 0xdeadbeef;
119+
xlFrame.vcid = 234;
120+
xlFrame.sdt = 1;
121+
}
69122
};
70123

71124
TEST_F(ITest_CanDemo, can_demo)
@@ -76,15 +129,6 @@ TEST_F(ITest_CanDemo, can_demo)
76129
//Test Results
77130
auto state = std::make_shared<TestState>();
78131

79-
//Test data
80-
const std::string payload = "Hallo Welt";
81-
82-
state->payloadBytes.resize(payload.size());
83-
std::copy(payload.begin(), payload.end(), state->payloadBytes.begin());
84-
85-
state->msg = CanFrame{};
86-
state->msg.canId = 123;
87-
state->msg.dataField = state->payloadBytes;
88132

89133
//Set up the Sending and receiving participants
90134
{
@@ -146,14 +190,28 @@ TEST_F(ITest_CanDemo, can_demo)
146190
}
147191

148192
//Normal transmission
149-
if (now > 20ms)
193+
if (now > 20ms && now <= 30ms)
150194
{
151195
Log() << "--- CanWriter sending CanFrame";
152196
canController->SendFrame(state->msg, (void*)(intptr_t)(0xDEADBEEF));
153197
}
154-
}, 1ms);
198+
// CAN FD
199+
if (now > 30ms && now <= 40ms)
200+
{
201+
Log() << "--- CanWriter sending FD Frame";
202+
canController->SendFrame(state->fdFrame, (void*)(intptr_t)(0xFDFDFDFD));
203+
}
204+
// CAN XL
205+
if (now > 40ms)
206+
{
207+
Log() << "--- CanWriter sending XL Frame";
208+
canController->SendFrame(state->xlFrame, (void*)(intptr_t)(0xFDFDFDFD));
209+
}
210+
},
211+
1ms);
155212

156-
canController->AddFrameHandler([state](auto, const Can::CanFrameEvent& frameEvent) {
213+
canController->AddFrameHandler(
214+
[state](auto, const Can::CanFrameEvent& frameEvent) {
157215
//ignore early test messages
158216
if (frameEvent.direction == SilKit::Services::TransmitDirection::TX)
159217
{
@@ -164,7 +222,8 @@ TEST_F(ITest_CanDemo, can_demo)
164222
{
165223
state->writerHasReceivedRx = true;
166224
}
167-
}, ((DirectionMask)TransmitDirection::RX | (DirectionMask)TransmitDirection::TX));
225+
},
226+
((DirectionMask)TransmitDirection::RX | (DirectionMask)TransmitDirection::TX));
168227
}
169228

170229
{
@@ -192,7 +251,8 @@ TEST_F(ITest_CanDemo, can_demo)
192251
{
193252
canController->SendFrame(state->msg);
194253
}
195-
}, 1ms);
254+
},
255+
1ms);
196256

197257
canController->AddFrameHandler([state, lifecycleService](auto, const Can::CanFrameEvent& frameEvent) {
198258
if (frameEvent.timestamp < 20ms)
@@ -201,15 +261,15 @@ TEST_F(ITest_CanDemo, can_demo)
201261
return;
202262
}
203263
EXPECT_EQ(frameEvent.direction, SilKit::Services::TransmitDirection::RX);
204-
205-
EXPECT_EQ(frameEvent.frame.canId, 123u);
206-
207264
EXPECT_TRUE(frameEvent.userContext == (void*)((size_t)(0)));
208265

209-
if (state->messageCount++ == 10)
266+
if (frameEvent.frame.canId == TestState::xlId)
210267
{
211-
lifecycleService->Stop("Test done");
212-
Log() << "--- CanReader: Sending Stop from";
268+
if (state->messageCount++ == 10)
269+
{
270+
lifecycleService->Stop("Test done");
271+
Log() << "--- CanReader: Sending Stop from";
272+
}
213273
}
214274
state->result = true;
215275
});
@@ -247,10 +307,31 @@ TEST_F(ITest_CanDemo, can_demo)
247307
}
248308
});
249309

250-
canController->AddFrameHandler([state](auto, const Can::CanFrameEvent&) { state->monitorReceiveCount++; });
310+
canController->AddFrameHandler([state](auto, const Can::CanFrameEvent& frame) {
311+
if (frame.frame.canId == TestState::canId)
312+
{
313+
state->monitorReceiveCount++;
314+
}
315+
else if (frame.frame.canId == TestState::fdId)
316+
{
317+
state->monitorReceiveCountFdf++;
318+
EXPECT_FALSE(frame.frame.flags & SilKit_CanFrameFlag_xlf);
319+
EXPECT_TRUE(frame.frame.flags & SilKit_CanFrameFlag_fdf);
320+
}
321+
else if (frame.frame.canId == TestState::xlId)
322+
{
323+
state->monitorReceiveCountXlf++;
324+
EXPECT_EQ(frame.frame.sdt, 1);
325+
EXPECT_EQ(frame.frame.af, 0xdeadbeef);
326+
EXPECT_EQ(frame.frame.vcid, 234);
327+
EXPECT_EQ(frame.frame.dataField.size(), 2048);
328+
EXPECT_TRUE(frame.frame.flags & SilKit_CanFrameFlag_xlf);
329+
EXPECT_TRUE(frame.frame.flags & SilKit_CanFrameFlag_fdf);
330+
}
331+
});
251332
}
252333

253-
auto ok = _simTestHarness->Run(5s);
334+
auto ok = _simTestHarness->Run(500s);
254335
ASSERT_TRUE(ok) << "SimTestHarness should terminate without timeout";
255336
EXPECT_TRUE(state->result) << " Expecting a message";
256337
EXPECT_TRUE(state->writerHasReceivedTx) << " Expecting a receive Message with Direction == TX on CanWriter";
@@ -263,6 +344,8 @@ TEST_F(ITest_CanDemo, can_demo)
263344
EXPECT_FALSE(state->readerReceivedErrorActive) << " Collisions are not computed in trivial simulation";
264345
EXPECT_FALSE(state->monitorReceivedErrorActive) << " Collisions are not computed in trivial simulation";
265346
EXPECT_GT(state->monitorReceiveCount, 10u) << "All participants connected to bus must receive frames";
347+
EXPECT_GE(state->monitorReceiveCountFdf, 10u) << "All participants connected to bus must receive FD frames";
348+
EXPECT_GE(state->monitorReceiveCountXlf, 10u) << "All participants connected to bus must receive XL frames";
266349
}
267350

268351
} //end namespace

SilKit/include/silkit/capi/Can.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ typedef SilKit_ReturnCode(SilKitFPTR* SilKit_CanController_SendFrame_t)(SilKit_C
287287
* range: 0 to 16'000'000
288288
*
289289
* \param xlRate Baud rate for CAN XL messages given in bps; valid
290-
* range: 0 to 16'000'000
290+
* range: 0 to 20'000'000
291291
*
292292
* In a detailed simulation, the baud rate is used to calculate
293293
* transmission delays of CAN messages and to determine proper

SilKit/include/silkit/services/can/ICanController.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class ICanController
7171
* range: 0 to 16'000'000
7272
*
7373
* \param xlRate Baud rate for CAN XL messages given in bps; valid
74-
* range: 0 to 16'000'000
74+
* range: 0 to 20'000'000
7575
*
7676
* NB: The baud rate of a CAN controller must be set before using it.
7777
*

SilKit/source/services/can/Test_CanSerdes.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ TEST(Test_CanSerdes, SimCan_CanMessage)
4040
in.frame.canId = 7;
4141
in.frame.flags |=
4242
static_cast<CanFrameFlagMask>(CanFrameFlag::Ide) | static_cast<CanFrameFlagMask>(CanFrameFlag::Fdf)
43-
| static_cast<CanFrameFlagMask>(CanFrameFlag::Esi) | static_cast<CanFrameFlagMask>(CanFrameFlag::Sec);
43+
| static_cast<CanFrameFlagMask>(CanFrameFlag::Esi) | static_cast<CanFrameFlagMask>(CanFrameFlag::Sec)
44+
| static_cast<CanFrameFlagMask>(CanFrameFlag::Xlf);
4445
in.frame.dlc = 5;
4546
in.frame.sdt = 123;
4647
in.frame.vcid = 89;

docs/api/services/can.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,9 @@ Then, the controller must be started explicitly by calling |Start|. Now the cont
137137
Additional control commands are |Stop| and |Reset|.
138138

139139
The following example configures a CAN controller with a baud rate of 10'000 baud for regular CAN messages and a baud
140-
rate of 1'000'000 baud for CAN |_| FD messages. Then, the controller is started::
140+
rate of 1'000'000 baud for CAN |_| FD messages and 1'000'000 baud for CAN |_| XL, respectively. Then, the controller is started::
141141

142-
canController->SetBaudRate(10000, 1000000);
142+
canController->SetBaudRate(10000, 1000000, 1000000);
143143
canController->Start();
144144

145145
.. admonition:: Note

docs/overview/overview.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Vector SIL Kit Overview
66

77
.. |_| unicode:: 0xA0
88
:trim:
9-
.. |CAN-API| replace:: :ref:`CAN / CAN FD<chap:can-service-api>`
9+
.. |CANBuses| replace:: CAN / CAN |_| FD / CAN |_| XL
10+
.. |CAN-API| replace:: :ref:`CAN / CAN FD / CAN XL<chap:can-service-api>`
1011
.. |Ethernet-API| replace:: :ref:`Ethernet<chap:ethernet-service-api>`
1112
.. |Flexray-API| replace:: :ref:`FlexRay<chap:flexray-service-api>`
1213
.. |LIN-API| replace:: :ref:`LIN<chap:lin-service-api>`
@@ -46,7 +47,7 @@ The |ProductName| supports the following services:
4647
Vehicle Networks
4748
----------------
4849

49-
The |ProductName| provides means to simulate CAN / CAN |_| FD, Ethernet, FlexRay, and LIN networks.
50+
The |ProductName| provides means to simulate |CANBuses|, Ethernet, FlexRay, and LIN networks.
5051
All networks except for FlexRay can be simulated with two different levels of detail: a simple, functional simulation or a detailed simulation.
5152
The simple simulation assumes no delay and unlimited bandwidth.
5253
The detailed simulation is enabled by using an additional |ProductName| |NetSim|, which considers these aspects as well.
@@ -67,7 +68,7 @@ The |ProductName| Registry process is required and must be started as a first st
6768
It acts as a connection broker between the actual simulation participants.
6869

6970
One or more :doc:`participants<../api/participant>` take care of the actual simulation logic and communicate via built-in :ref:`services<sec:overview-supported-services>`.
70-
|ProductName| supports common vehicle networks (CAN / CAN |_| FD, Ethernet, FlexRay, LIN), data messages for application specific communication in a publish / subscribe pattern, and Remote Procedure Calls (RPC).
71+
|ProductName| supports common vehicle networks (|CANBuses|, Ethernet, FlexRay, LIN), data messages for application specific communication in a publish / subscribe pattern, and Remote Procedure Calls (RPC).
7172
The participant and its services are created by the client application using the |ProductName| :doc:`API<../api/api>`.
7273

7374
To manage a group of participants in a simulation, |ProductName| participants can coordinate their startup behavior.

0 commit comments

Comments
 (0)