8000 Merge pull request #194 from arduino/fix-11-bit-can-id · stm32duino/ArduinoCore-API@fbc0646 · GitHub
[go: up one dir, main page]

Skip to content
< 8000 header class="HeaderMktg header-logged-out js-details-container js-header Details f4 py-3" role="banner" data-is-top="true" data-color-mode=light data-light-theme=light data-dark-theme=dark>

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fbc0646

Browse files
authored
Merge pull request arduino#194 from arduino/fix-11-bit-can-id
Extend CanMsg to allow to distinguish between standard and extended ids …
2 parents 68d3e0d + 3733659 commit fbc0646

12 files changed

+435
-12
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.vscode/
2+
.idea/

api/CanMsg.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* This file is free software; you can redistribute it and/or modify
3+
* it under the terms of either the GNU General Public License version 2
4+
* or the GNU Lesser General Public License version 2.1, both as
5+
* published by the Free Software Foundation.
6+
*/
7+
8+
/**************************************************************************************
9+
* INCLUDE
10+
**************************************************************************************/
11+
12+
#include "CanMsg.h"
13+
14+
/**************************************************************************************
15+
* NAMESPACE
16+
**************************************************************************************/
17+
18+
namespace arduino
19+
{
20+
21+
/**************************************************************************************
22+
* STATIC CONST DEFINITION
23+
**************************************************************************************/
24+
25+
uint8_t const CanMsg::MAX_DATA_LENGTH;
26+
uint32_t const CanMsg::CAN_EFF_FLAG;
27+
uint32_t const CanMsg::CAN_SFF_MASK;
28+
uint32_t const CanMsg::CAN_EFF_MASK;
29+
30+
/**************************************************************************************
31+
* NAMESPACE
32+
**************************************************************************************/
33+
34+
} /* arduino */

api/CanMsg.h

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
#include <inttypes.h>
1616
#include <string.h>
1717

18-
#include <Arduino.h>
18+
#include "Print.h"
19+
#include "Printable.h"
20+
#include "Common.h"
1921

2022
/**************************************************************************************
2123
* NAMESPACE
@@ -31,14 +33,19 @@ namespace arduino
3133
class CanMsg : public Printable
3234
{
3335
public:
34-
static size_t constexpr MAX_DATA_LENGTH = 8;
36+
static uint8_t constexpr MAX_DATA_LENGTH = 8;
37+
38+
static uint32_t constexpr CAN_EFF_FLAG = 0x80000000U;
39 F438 +
static uint32_t constexpr CAN_SFF_MASK = 0x000007FFU; /* standard frame format (SFF) */
40+
static uint32_t constexpr CAN_EFF_MASK = 0x1FFFFFFFU; /* extended frame format (EFF) */
41+
3542

3643
CanMsg(uint32_t const can_id, uint8_t const can_data_len, uint8_t const * can_data_ptr)
3744
: id{can_id}
38-
, data_length{can_data_len}
45+
, data_length{min(can_data_len, MAX_DATA_LENGTH)}
3946
, data{0}
4047
{
41-
memcpy(data, can_data_ptr, min(can_data_len, MAX_DATA_LENGTH));
48+
memcpy(data, can_data_ptr, data_length);
4249
}
4350

4451
CanMsg() : CanMsg(0, 0, nullptr) { }
@@ -52,14 +59,15 @@ class CanMsg : public Printable
5259

5360
virtual ~CanMsg() { }
5461

55-
void operator = (CanMsg const & other)
62+
CanMsg & operator = (CanMsg const & other)
5663
{
57-
if (this == &other)
58-
return;
59-
60-
this->id = other.id;
61-
this->data_length = other.data_length;
62-
memcpy(this->data, other.data, this->data_length);
64+
if (this != &other)
65+
{
66+
this->id = other.id;
67+
this->data_length = other.data_length;
68+
memcpy(this->data, other.data, this->data_length);
69+
}
70+
return (*this);
6371
}
6472

6573
virtual size_t printTo(Print & p) const override
@@ -68,7 +76,10 @@ class CanMsg : public Printable
6876
size_t len = 0;
6977

7078
/* Print the header. */
71-
len = snprintf(buf, sizeof(buf), "[%08" PRIX32 "] (%d) : ", id, data_length);
79+
if (isStandardId())
80+
len = snprintf(buf, sizeof(buf), "[%03" PRIX32 "] (%d) : ", getStandardId(), data_length);
81+
else
82+
len = snprintf(buf, sizeof(buf), "[%08" PRIX32 "] (%d) : ", getExtendedId(), data_length);
7283
size_t n = p.write(buf, len);
7384

7485
/* Print the data. */
@@ -82,11 +93,45 @@ class CanMsg : public Printable
8293
return n;
8394
}
8495

96+
97+
uint32_t getStandardId() const {
98+
return (id & CAN_SFF_MASK);
99+
}
100+
uint32_t getExtendedId() const {
101+
return (id & CAN_EFF_MASK);
102+
}
103+
bool isStandardId() const {
104+
return ((id & CAN_EFF_FLAG) == 0);
105+
}
106+
bool isExtendedId() const {
107+
return ((id & CAN_EFF_FLAG) == CAN_EFF_FLAG);
108+
}
109+
110+
111+
/*
112+
* CAN ID semantics (mirroring definition by linux/can.h):
113+
* |- Bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
114+
* |- Bit 30 : reserved (future remote transmission request flag)
115+
* |- Bit 29 : reserved (future error frame flag)
116+
* |- Bit 0-28 : CAN identifier (11/29 bit)
117+
*/
85118
uint32_t id;
86119
uint8_t data_length;
87120
uint8_t data[MAX_DATA_LENGTH];
88121
};
89122

123+
/**************************************************************************************
124+
* FREE FUNCTIONS
125+
**************************************************************************************/
126+
127+
inline uint32_t CanStandardId(uint32_t const id) {
128+
return (id & CanMsg::CAN_SFF_MASK);
129+
}
130+
131+
inline uint32_t CanExtendedId(uint32_t const id) {
132+
return (CanMsg::CAN_EFF_FLAG | (id & CanMsg::CAN_EFF_MASK));
133+
}
134+
90135
/**************************************************************************************
91136
* NAMESPACE
92137
**************************************************************************************/

test/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ set(TEST_TARGET ${CMAKE_PROJECT_NAME})
2525
##########################################################################
2626

2727
set(TEST_SRCS
28+
src/CanMsg/test_CanMsg.cpp
29+
src/CanMsg/test_CanMsg_CopyCtor.cpp
30+
src/CanMsg/test_CanExtendedId.cpp
31+
src/CanMsg/test_CanStandardId.cpp
32+
src/CanMsg/test_isExtendedId.cpp
33+
src/CanMsg/test_isStandardId.cpp
34+
src/CanMsg/test_operator_assignment.cpp
35+
src/CanMsg/test_printTo.cpp
2836
src/Common/test_makeWord.cpp
2937
src/Common/test_map.cpp
3038
src/Common/test_max.cpp
@@ -95,6 +103,7 @@ set(TEST_SRCS
95103
)
96104

97105
set(TEST_DUT_SRCS
106+
../api/CanMsg.cpp
98107
../api/Common.cpp
99108
../api/IPAddress.cpp
100109
../api/String.cpp
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2020 Arduino. All rights reserved.
3+
*/
4+
5+
/**************************************************************************************
6+
* INCLUDE
7+
**************************************************************************************/
8+
9+
#include <catch.hpp>
10+
11+
#include <CanMsg.h>
12+
13+
/**************************************************************************************
14+
* NAMESPACE
15+
**************************************************************************************/
16+
17+
using namespace arduino;
18+
19+
/**************************************************************************************
20+
* TEST CODE
21+
**************************************************************************************/
22+
23+
TEST_CASE ("Verify correct conversion to 29-Bit CAN ID for lowest valid 29-Bit CAN ID", "[CanMsg-CanExtendedId-01]")
24+
{
25+
REQUIRE(CanExtendedId(0) == (CanMsg::CAN_EFF_FLAG | 0U));
26+
}
27+
28+
TEST_CASE ("Verify correct conversion to 29-Bit CAN ID for highest valid 29-Bit CAN ID", "[CanMsg-CanExtendedId-02]")
29+
{
30+
REQUIRE(CanExtendedId(0x1FFFFFFFU) == (CanMsg::CAN_EFF_FLAG | 0x1FFFFFFFU));
31+
}
32+
33+
TEST_CASE ("Verify capping of CAN IDs exceeding 29-Bit CAN ID range", "[CanMsg-CanExtendedId-03]")
34+
{
35+
REQUIRE(CanExtendedId(0x2FFFFFFFU) == (CanMsg::CAN_EFF_FLAG | 0x0FFFFFFFU));
36+
REQUIRE(CanExtendedId(0x3FFFFFFFU) == (CanMsg::CAN_EFF_FLAG | 0x1FFFFFFFU));
37+
REQUIRE(CanExtendedId(0x4FFFFFFFU) == (CanMsg::CAN_EFF_FLAG | 0x0FFFFFFFU));
38+
REQUIRE(CanExtendedId(0x5FFFFFFFU) == (CanMsg::CAN_EFF_FLAG | 0x1FFFFFFFU));
39+
/* ... */
40+
REQUIRE(CanExtendedId(0xFFFFFFFFU) == (CanMsg::CAN_EFF_FLAG | 0x1FFFFFFFU));
41+
}

test/src/CanMsg/test_CanMsg.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2020 Arduino. All rights reserved.
3+
*/
4+
5+
/**************************************************************************************
6+
* INCLUDE
7+
**************************************************************************************/
8+
9+
#include <catch.hpp>
10+
11+
#include <CanMsg.h>
12+
13+
/**************************************************************************************
14+
* NAMESPACE
15+
**************************************************************************************/
16+
17+
using namespace arduino;
18+
19+
/**************************************************************************************
20+
* TEST CODE
21+
**************************************************************************************/
22+
23+
TEST_CASE ("Test constructor with no data (data length = 0)", "[CanMsg-CanMsg-01]")
24+
{
25+
CanMsg const msg(CanStandardId(0x20), 0, nullptr);
26+
27+
REQUIRE(msg.data_length == 0);
28+
for (size_t i = 0; i < CanMsg::MAX_DATA_LENGTH; i++)
29+
REQUIRE(msg.data[i] == 0);
30+
}
31+
32+
TEST_CASE ("Test constructor with data (data length < CanMsg::MAX_DATA_LENGTH)", "[CanMsg-CanMsg-02]")
33+
{
34+
uint8_t const msg_data[4] = {0xDE, 0xAD, 0xC0, 0xDE};
35+
36+
CanMsg const msg(CanStandardId(0x20), sizeof(msg_data), msg_data);
37+
38+
REQUIRE(msg.data_length == 4);
39+
for (size_t i = 0; i < msg.data_length; i++)
40+
REQUIRE(msg.data[i] == msg_data[i]);
41+
}
42+
43+
TEST_CASE ("Test constructor with data (data length > CanMsg::MAX_DATA_LENGTH)", "[CanMsg-CanMsg-03]")
44+
{
45+
uint8_t const msg_data[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
46+
47+
CanMsg const msg(CanStandardId(0x20), sizeof(msg_data), msg_data);
48+
49+
REQUIRE(msg.data_length == 8);
50+
for (size_t i = 0; i < msg.data_length; i++)
51+
REQUIRE(msg.data[i] == msg_data[i]);
52+
}
53+
54+
TEST_CASE ("Test constructor constructing a CAN frame with standard ID", "[CanMsg-CanMsg-04]")
55+
{
56+
CanMsg const msg(CanStandardId(0x20), 0, nullptr);
57+
58+
REQUIRE(msg.id == 0x20);
59+
}
60+
61+
TEST_CASE ("Test constructor constructing a CAN frame with extended ID", "[CanMsg-CanMsg-05]")
62+
{
63+
CanMsg const msg(CanExtendedId(0x20), 0, nullptr);
64+
65+
REQUIRE(msg.id == (CanMsg::CAN_EFF_FLAG | 0x20));
66+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) 2020 Arduino. All rights reserved.
3+
*/
4+
5+
/**************************************************************************************
6+
* INCLUDE
7+
**************************************************************************************/
8+
9+
#include <catch.hpp>
10+
11+
#include <CanMsg.h>
12+
13+
/**************************************************************************************
14+
* NAMESPACE
15+
**************************************************************************************/
16+
17+
using namespace arduino;
18+
19+
/**************************************************************************************
20+
* TEST CODE
21+
**************************************************************************************/
22+
23+
TEST_CASE ("Test copy constructor", "[CanMsg-CopyCtor-01]")
24+
{
25+
uint8_t const msg_data[4] = {0xDE, 0xAD, 0xC0, 0xDE};
26+
27+
CanMsg const msg_1(CanStandardId(0x20), sizeof(msg_data), msg_data);
28+
CanMsg const msg_2(msg_1);
29+
30+
REQUIRE(msg_1.data_length == msg_2.data_length);
31+
32+
for (size_t i = 0; i < msg_1.data_length; i++)
33+
{
34+
REQUIRE(msg_1.data[i] == msg_data[i]);
35+
REQUIRE(msg_2.data[i] == msg_data[i]);
36+
}
37+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2020 Arduino. All rights reserved.
3+
*/
4+
5+
/**************************************************************************************
6+
* INCLUDE
7+
**************************************************************************************/
8+
9+
#include <catch.hpp>
10+
11+
#include <CanMsg.h>
12+
13+
/**************************************************************************************
14+
* NAMESPACE
15+
**************************************************************************************/
16+
17+
using namespace arduino;
18+
19+
/**************************************************************************************
20+
* TEST CODE
21+
**************************************************************************************/
22+
23+
TEST_CASE ("Verify correct conversion to 11-Bit CAN ID for lowest valid 11-Bit CAN ID", "[CanMsg-CanStandardId-01]")
24+
{
25+
REQUIRE(CanStandardId(0) == 0U);
26+
}
27+
28+
TEST_CASE ("Verify correct conversion to 11-Bit CAN ID for highest valid 11-Bit CAN ID", "[CanMsg-CanStandardId-02]")
29+
{
30+
REQUIRE(CanStandardId(0x7FF) == 0x7FF);
31+
}
32+
33+
TEST_CASE ("Verify capping of CAN IDs exceeding 11-Bit CAN ID range", "[CanMsg-CanStandardId-03]")
34+
{
35+
REQUIRE(CanStandardId(0x800U) == 0x000U);
36+
REQUIRE(CanStandardId(0x801U) == 0x001U);
37+
REQUIRE(CanStandardId(0x8FFU) == 0x0FFU);
38+
REQUIRE(CanStandardId(0x1FFFFFFFU) == 0x7FFU);
39+
REQUIRE(CanStandardId(0xFFFFFFFFU) == 0x7FFU);
40+
}

test/src/CanMsg/test_isExtendedId.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2020 Arduino. All rights reserved.
3+
*/
4+
5+
/**************************************************************************************
6+
* INCLUDE
7+
**************************************************************************************/
8+
9+
#include <catch.hpp>
10+
11+
#include <CanMsg.h>
12+
13+
/**************************************************************************************
14+
* NAMESPACE
15+
**************************************************************************************/
16+
17+
using namespace arduino;
18+
19+
/**************************************************************************************
20+
* TEST CODE
21+
**************************************************************************************/
22+
23+
TEST_CASE ("\"isExtendedId\" should return true for extended CAN ID", "[CanMsg-isExtendedId-01]")
24+
{
25+
CanMsg const msg_ext_id(CanExtendedId(0x020), 0, nullptr);
26+
REQUIRE(msg_ext_id.isExtendedId() == true);
27+
}
28+
29+
TEST_CASE ("\"isExtendedId\" should return false for standard CAN ID", "[CanMsg-isExtendedId-02]")
30+
{
31+
CanMsg const msg_std_id(CanStandardId(0x020), 0, nullptr);
32+
REQUIRE(msg_std_id.isExtendedId() == false);
33+
}

0 commit comments

Comments
 (0)
0