Skip to content

Commit c02e101

Browse files
authored
Merge pull request #14336 from AGlass0fMilk/polymorphic-can
Implement polymorphism for CAN driver
2 parents a104dac + d39a416 commit c02e101

File tree

4 files changed

+199
-108
lines changed

4 files changed

+199
-108
lines changed

drivers/include/drivers/CAN.h

+10-106
Original file line numberDiff line numberDiff line change
@@ -21,91 +21,12 @@
2121

2222
#if DEVICE_CAN || defined(DOXYGEN_ONLY)
2323

24+
#include "interfaces/InterfaceCAN.h"
2425
#include "hal/can_api.h"
2526
#include "platform/Callback.h"
2627
#include "platform/PlatformMutex.h"
27-
#include "platform/NonCopyable.h"
2828

2929
namespace mbed {
30-
/** \defgroup drivers-public-api-can CAN
31-
* \ingroup drivers-public-api
32-
*/
33-
34-
/**
35-
* \defgroup drivers_CANMessage CANMessage class
36-
* \ingroup drivers-public-api-can
37-
* @{
38-
*/
39-
40-
/** CANMessage class
41-
*
42-
* @note Synchronization level: Thread safe
43-
*/
44-
class CANMessage : public CAN_Message {
45-
46-
public:
47-
/** Creates empty CAN message.
48-
*/
49-
CANMessage() : CAN_Message()
50-
{
51-
len = 8U;
52-
type = CANData;
53-
format = CANStandard;
54-
id = 0U;
55-
memset(data, 0, 8);
56-
}
57-
58-
/** Creates CAN message with specific content.
59-
*
60-
* @param _id Message ID
61-
* @param _data Mesaage Data
62-
* @param _len Message Data length
63-
* @param _type Type of Data: Use enum CANType for valid parameter values
64-
* @param _format Data Format: Use enum CANFormat for valid parameter values
65-
*/
66-
CANMessage(unsigned int _id, const unsigned char *_data, unsigned char _len = 8, CANType _type = CANData, CANFormat _format = CANStandard)
67-
{
68-
len = (_len > 8) ? 8 : _len;
69-
type = _type;
70-
format = _format;
71-
id = _id;
72-
memcpy(data, _data, len);
73-
}
74-
75-
76-
/** Creates CAN message with specific content.
77-
*
78-
* @param _id Message ID
79-
* @param _data Mesaage Data
80-
* @param _len Message Data length
81-
* @param _type Type of Data: Use enum CANType for valid parameter values
82-
* @param _format Data Format: Use enum CANFormat for valid parameter values
83-
*/
84-
CANMessage(unsigned int _id, const char *_data, unsigned char _len = 8, CANType _type = CANData, CANFormat _format = CANStandard)
85-
{
86-
len = (_len > 8) ? 8 : _len;
87-
type = _type;
88-
format = _format;
89-
id = _id;
90-
memcpy(data, _data, len);
91-
}
92-
93-
/** Creates CAN remote message.
94-
*
95-
* @param _id Message ID
96-
* @param _format Data Format: Use enum CANType for valid parameter values
97-
*/
98-
CANMessage(unsigned int _id, CANFormat _format = CANStandard)
99-
{
100-
len = 0;
101-
type = CANRemote;
102-
format = _format;
103-
id = _id;
104-
memset(data, 0, 8);
105-
}
106-
};
107-
108-
/** @}*/
10930

11031
/**
11132
* \defgroup drivers_CAN CAN class
@@ -115,7 +36,13 @@ class CANMessage : public CAN_Message {
11536

11637
/** A can bus client, used for communicating with can devices
11738
*/
118-
class CAN : private NonCopyable<CAN> {
39+
class CAN
40+
#ifdef FEATURE_EXPERIMENTAL_API
41+
final : public interface::CAN
42+
#else
43+
: public interface::can
44+
#endif
45+
{
11946

12047
public:
12148
/** Creates a CAN interface connected to specific pins.
@@ -233,15 +160,6 @@ class CAN : private NonCopyable<CAN> {
233160
*/
234161
void monitor(bool silent);
235162

236-
enum Mode {
237-
Reset = 0,
238-
Normal,
239-
Silent,
240-
LocalTest,
241-
GlobalTest,
242-
SilentTest
243-
};
244-
245163
/** Change CAN operation to the specified mode
246164
*
247165
* @param mode The new operation mode (CAN::Normal, CAN::Silent, CAN::LocalTest, CAN::GlobalTest, CAN::SilentTest)
@@ -277,20 +195,6 @@ class CAN : private NonCopyable<CAN> {
277195
*/
278196
unsigned char tderror();
279197

280-
enum IrqType {
281-
RxIrq = 0,
282-
TxIrq,
283-
EwIrq,
284-
DoIrq,
285-
WuIrq,
286-
EpIrq,
287-
AlIrq,
288-
BeIrq,
289-
IdIrq,
290-
291-
IrqCnt
292-
};
293-
294198
/** Attach a function to call whenever a CAN frame received interrupt is
295199
* generated.
296200
*
@@ -299,7 +203,7 @@ class CAN : private NonCopyable<CAN> {
299203
* @param func A pointer to a void function, or 0 to set as none
300204
* @param type Which CAN interrupt to attach the member function to (CAN::RxIrq for message received, CAN::TxIrq for transmitted or aborted, CAN::EwIrq for error warning, CAN::DoIrq for data overrun, CAN::WuIrq for wake-up, CAN::EpIrq for error passive, CAN::AlIrq for arbitration lost, CAN::BeIrq for bus error)
301205
*/
302-
void attach(Callback<void()> func, IrqType type = RxIrq);
206+
void attach(Callback<void()> func, IrqType type = IrqType::RxIrq);
303207

304208
static void _irq_handler(uint32_t id, CanIrqType type);
305209

@@ -309,7 +213,7 @@ class CAN : private NonCopyable<CAN> {
309213
virtual void unlock();
310214

311215
can_t _can;
312-
Callback<void()> _irq[IrqCnt];
216+
Callback<void()> _irq[IrqType::IrqCnt];
313217
PlatformMutex _mutex;
314218
#endif
315219
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
* Mbed-OS Microcontroller Library
3+
* Copyright (c) 2021 Embedded Planet
4+
* Copyright (c) 2021 ARM Limited
5+
* SPDX-License-Identifier: Apache-2.0
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License
18+
*/
19+
20+
#ifndef MBED_INTERFACE_CAN_H_
21+
#define MBED_INTERFACE_CAN_H_
22+
23+
#include "hal/can_helper.h"
24+
25+
#include <cstring>
26+
27+
#include "platform/Callback.h"
28+
29+
namespace mbed {
30+
31+
#ifndef FEATURE_EXPERIMENTAL_API
32+
// Forward declare CAN
33+
class CAN;
34+
#endif
35+
36+
/** \defgroup drivers-public-api-can CAN
37+
* \ingroup drivers-public-api
38+
*/
39+
40+
/**
41+
* \defgroup drivers_CANMessage CANMessage class
42+
* \ingroup drivers-public-api-can
43+
* @{
44+
*/
45+
46+
/** CANMessage class
47+
*
48+
* @note Synchronization level: Thread safe
49+
*/
50+
class CANMessage : public CAN_Message {
51+
52+
public:
53+
/** Creates empty CAN message.
54+
*/
55+
CANMessage() : CAN_Message()
56+
{
57+
len = 8U;
58+
type = CANData;
59+
format = CANStandard;
60+
id = 0U;
61+
memset(data, 0, 8);
62+
}
63+
64+
/** Creates CAN message with specific content.
65+
*
66+
* @param _id Message ID
67+
* @param _data Mesaage Data
68+
* @param _len Message Data length
69+
* @param _type Type of Data: Use enum CANType for valid parameter values
70+
* @param _format Data Format: Use enum CANFormat for valid parameter values
71+
*/
72+
CANMessage(unsigned int _id, const unsigned char *_data, unsigned char _len = 8, CANType _type = CANData, CANFormat _format = CANStandard)
73+
{
74+
len = (_len > 8) ? 8 : _len;
75+
type = _type;
76+
format = _format;
77+
id = _id;
78+
memcpy(data, _data, len);
79+
}
80+
81+
82+
/** Creates CAN message with specific content.
83+
*
84+
* @param _id Message ID
85+
* @param _data Mesaage Data
86+
* @param _len Message Data length
87+
* @param _type Type of Data: Use enum CANType for valid parameter values
88+
* @param _format Data Format: Use enum CANFormat for valid parameter values
89+
*/
90+
CANMessage(unsigned int _id, const char *_data, unsigned char _len = 8, CANType _type = CANData, CANFormat _format = CANStandard)
91+
{
92+
len = (_len > 8) ? 8 : _len;
93+
type = _type;
94+
format = _format;
95+
id = _id;
96+
memcpy(data, _data, len);
97+
}
98+
99+
/** Creates CAN remote message.
100+
*
101+
* @param _id Message ID
102+
* @param _format Data Format: Use enum CANType for valid parameter values
103+
*/
104+
CANMessage(unsigned int _id, CANFormat _format = CANStandard)
105+
{
106+
len = 0;
107+
type = CANRemote;
108+
format = _format;
109+
id = _id;
110+
memset(data, 0, 8);
111+
}
112+
};
113+
114+
/** @}*/
115+
116+
namespace interface {
117+
118+
/* Having this as a struct allows interface::CAN and/or mbed::CAN to inherit the enums */
119+
struct can {
120+
121+
enum Mode {
122+
Reset = 0,
123+
Normal,
124+
Silent,
125+
LocalTest,
126+
GlobalTest,
127+
SilentTest
128+
};
129+
130+
enum IrqType {
131+
RxIrq = 0,
132+
TxIrq,
133+
EwIrq,
134+
DoIrq,
135+
WuIrq,
136+
EpIrq,
137+
AlIrq,
138+
BeIrq,
139+
IdIrq,
140+
141+
IrqCnt
142+
};
143+
144+
// Prevent slicing and user creation of base class.
145+
protected:
146+
can() = default;
147+
~can() = default;
148+
149+
public:
150+
151+
/* Copy constructor and copy assignment operators will be deleted in subclasses as well */
152+
can(const can &) = delete;
153+
can &operator=(const can &) = delete;
154+
155+
};
156+
157+
#ifdef FEATURE_EXPERIMENTAL_API
158+
159+
// Pure virtual interface for CAN
160+
struct CAN : public interface::can {
161+
162+
virtual ~CAN() = default;
163+
virtual int frequency(int hz) = 0;
164+
virtual int write(CANMessage msg) = 0;
165+
virtual int read(CANMessage &msg, int handle = 0) = 0;
166+
virtual void reset() = 0;
167+
virtual void monitor(bool silent) = 0;
168+
virtual int mode(Mode mode) = 0;
169+
virtual int filter(unsigned int id, unsigned int mask, CANFormat format = CANAny, int handle = 0) = 0;
170+
virtual unsigned char rderror() = 0;
171+
virtual unsigned char tderror() = 0;
172+
virtual void attach(Callback<void()> func, IrqType type = IrqType::RxIrq) = 0;
173+
};
174+
175+
#else
176+
using CAN = ::mbed::CAN;
177+
#endif
178+
179+
} // namespace interface
180+
181+
#if defined(FEATURE_EXPERIMENTAL_API) && !DEVICE_CAN
182+
using CAN = interface::CAN;
183+
#endif
184+
185+
} // namespace mbed
186+
187+
#endif /* MBED_INTERFACE_CAN_H_ */

drivers/source/CAN.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ CAN::~CAN()
5555
// No lock needed in destructor
5656

5757
// Detaching interrupts releases the sleep lock if it was locked
58-
for (int irq = 0; irq < IrqCnt; irq++) {
58+
for (int irq = 0; irq < IrqType::IrqCnt; irq++) {
5959
attach(nullptr, (IrqType)irq);
6060
}
6161
can_irq_free(&_can);

hal/include/hal/can_helper.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#ifndef MBED_CAN_HELPER_H
2121
#define MBED_CAN_HELPER_H
2222

23-
#if DEVICE_CAN
23+
#if DEVICE_CAN || FEATURE_EXPERIMENTAL_API
2424

2525
#ifdef __cplusplus
2626
extern "C" {

0 commit comments

Comments
 (0)