mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #14336 from AGlass0fMilk/polymorphic-can
Implement polymorphism for CAN driverpull/14661/head
commit
c02e101e9f
|
@ -21,91 +21,12 @@
|
|||
|
||||
#if DEVICE_CAN || defined(DOXYGEN_ONLY)
|
||||
|
||||
#include "interfaces/InterfaceCAN.h"
|
||||
#include "hal/can_api.h"
|
||||
#include "platform/Callback.h"
|
||||
#include "platform/PlatformMutex.h"
|
||||
#include "platform/NonCopyable.h"
|
||||
|
||||
namespace mbed {
|
||||
/** \defgroup drivers-public-api-can CAN
|
||||
* \ingroup drivers-public-api
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup drivers_CANMessage CANMessage class
|
||||
* \ingroup drivers-public-api-can
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** CANMessage class
|
||||
*
|
||||
* @note Synchronization level: Thread safe
|
||||
*/
|
||||
class CANMessage : public CAN_Message {
|
||||
|
||||
public:
|
||||
/** Creates empty CAN message.
|
||||
*/
|
||||
CANMessage() : CAN_Message()
|
||||
{
|
||||
len = 8U;
|
||||
type = CANData;
|
||||
format = CANStandard;
|
||||
id = 0U;
|
||||
memset(data, 0, 8);
|
||||
}
|
||||
|
||||
/** Creates CAN message with specific content.
|
||||
*
|
||||
* @param _id Message ID
|
||||
* @param _data Mesaage Data
|
||||
* @param _len Message Data length
|
||||
* @param _type Type of Data: Use enum CANType for valid parameter values
|
||||
* @param _format Data Format: Use enum CANFormat for valid parameter values
|
||||
*/
|
||||
CANMessage(unsigned int _id, const unsigned char *_data, unsigned char _len = 8, CANType _type = CANData, CANFormat _format = CANStandard)
|
||||
{
|
||||
len = (_len > 8) ? 8 : _len;
|
||||
type = _type;
|
||||
format = _format;
|
||||
id = _id;
|
||||
memcpy(data, _data, len);
|
||||
}
|
||||
|
||||
|
||||
/** Creates CAN message with specific content.
|
||||
*
|
||||
* @param _id Message ID
|
||||
* @param _data Mesaage Data
|
||||
* @param _len Message Data length
|
||||
* @param _type Type of Data: Use enum CANType for valid parameter values
|
||||
* @param _format Data Format: Use enum CANFormat for valid parameter values
|
||||
*/
|
||||
CANMessage(unsigned int _id, const char *_data, unsigned char _len = 8, CANType _type = CANData, CANFormat _format = CANStandard)
|
||||
{
|
||||
len = (_len > 8) ? 8 : _len;
|
||||
type = _type;
|
||||
format = _format;
|
||||
id = _id;
|
||||
memcpy(data, _data, len);
|
||||
}
|
||||
|
||||
/** Creates CAN remote message.
|
||||
*
|
||||
* @param _id Message ID
|
||||
* @param _format Data Format: Use enum CANType for valid parameter values
|
||||
*/
|
||||
CANMessage(unsigned int _id, CANFormat _format = CANStandard)
|
||||
{
|
||||
len = 0;
|
||||
type = CANRemote;
|
||||
format = _format;
|
||||
id = _id;
|
||||
memset(data, 0, 8);
|
||||
}
|
||||
};
|
||||
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* \defgroup drivers_CAN CAN class
|
||||
|
@ -115,7 +36,13 @@ public:
|
|||
|
||||
/** A can bus client, used for communicating with can devices
|
||||
*/
|
||||
class CAN : private NonCopyable<CAN> {
|
||||
class CAN
|
||||
#ifdef FEATURE_EXPERIMENTAL_API
|
||||
final : public interface::CAN
|
||||
#else
|
||||
: public interface::can
|
||||
#endif
|
||||
{
|
||||
|
||||
public:
|
||||
/** Creates a CAN interface connected to specific pins.
|
||||
|
@ -233,15 +160,6 @@ public:
|
|||
*/
|
||||
void monitor(bool silent);
|
||||
|
||||
enum Mode {
|
||||
Reset = 0,
|
||||
Normal,
|
||||
Silent,
|
||||
LocalTest,
|
||||
GlobalTest,
|
||||
SilentTest
|
||||
};
|
||||
|
||||
/** Change CAN operation to the specified mode
|
||||
*
|
||||
* @param mode The new operation mode (CAN::Normal, CAN::Silent, CAN::LocalTest, CAN::GlobalTest, CAN::SilentTest)
|
||||
|
@ -277,20 +195,6 @@ public:
|
|||
*/
|
||||
unsigned char tderror();
|
||||
|
||||
enum IrqType {
|
||||
RxIrq = 0,
|
||||
TxIrq,
|
||||
EwIrq,
|
||||
DoIrq,
|
||||
WuIrq,
|
||||
EpIrq,
|
||||
AlIrq,
|
||||
BeIrq,
|
||||
IdIrq,
|
||||
|
||||
IrqCnt
|
||||
};
|
||||
|
||||
/** Attach a function to call whenever a CAN frame received interrupt is
|
||||
* generated.
|
||||
*
|
||||
|
@ -299,7 +203,7 @@ public:
|
|||
* @param func A pointer to a void function, or 0 to set as none
|
||||
* @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)
|
||||
*/
|
||||
void attach(Callback<void()> func, IrqType type = RxIrq);
|
||||
void attach(Callback<void()> func, IrqType type = IrqType::RxIrq);
|
||||
|
||||
static void _irq_handler(uint32_t id, CanIrqType type);
|
||||
|
||||
|
@ -309,7 +213,7 @@ protected:
|
|||
virtual void unlock();
|
||||
|
||||
can_t _can;
|
||||
Callback<void()> _irq[IrqCnt];
|
||||
Callback<void()> _irq[IrqType::IrqCnt];
|
||||
PlatformMutex _mutex;
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Mbed-OS Microcontroller Library
|
||||
* Copyright (c) 2021 Embedded Planet
|
||||
* Copyright (c) 2021 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
#ifndef MBED_INTERFACE_CAN_H_
|
||||
#define MBED_INTERFACE_CAN_H_
|
||||
|
||||
#include "hal/can_helper.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "platform/Callback.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
#ifndef FEATURE_EXPERIMENTAL_API
|
||||
// Forward declare CAN
|
||||
class CAN;
|
||||
#endif
|
||||
|
||||
/** \defgroup drivers-public-api-can CAN
|
||||
* \ingroup drivers-public-api
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup drivers_CANMessage CANMessage class
|
||||
* \ingroup drivers-public-api-can
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** CANMessage class
|
||||
*
|
||||
* @note Synchronization level: Thread safe
|
||||
*/
|
||||
class CANMessage : public CAN_Message {
|
||||
|
||||
public:
|
||||
/** Creates empty CAN message.
|
||||
*/
|
||||
CANMessage() : CAN_Message()
|
||||
{
|
||||
len = 8U;
|
||||
type = CANData;
|
||||
format = CANStandard;
|
||||
id = 0U;
|
||||
memset(data, 0, 8);
|
||||
}
|
||||
|
||||
/** Creates CAN message with specific content.
|
||||
*
|
||||
* @param _id Message ID
|
||||
* @param _data Mesaage Data
|
||||
* @param _len Message Data length
|
||||
* @param _type Type of Data: Use enum CANType for valid parameter values
|
||||
* @param _format Data Format: Use enum CANFormat for valid parameter values
|
||||
*/
|
||||
CANMessage(unsigned int _id, const unsigned char *_data, unsigned char _len = 8, CANType _type = CANData, CANFormat _format = CANStandard)
|
||||
{
|
||||
len = (_len > 8) ? 8 : _len;
|
||||
type = _type;
|
||||
format = _format;
|
||||
id = _id;
|
||||
memcpy(data, _data, len);
|
||||
}
|
||||
|
||||
|
||||
/** Creates CAN message with specific content.
|
||||
*
|
||||
* @param _id Message ID
|
||||
* @param _data Mesaage Data
|
||||
* @param _len Message Data length
|
||||
* @param _type Type of Data: Use enum CANType for valid parameter values
|
||||
* @param _format Data Format: Use enum CANFormat for valid parameter values
|
||||
*/
|
||||
CANMessage(unsigned int _id, const char *_data, unsigned char _len = 8, CANType _type = CANData, CANFormat _format = CANStandard)
|
||||
{
|
||||
len = (_len > 8) ? 8 : _len;
|
||||
type = _type;
|
||||
format = _format;
|
||||
id = _id;
|
||||
memcpy(data, _data, len);
|
||||
}
|
||||
|
||||
/** Creates CAN remote message.
|
||||
*
|
||||
* @param _id Message ID
|
||||
* @param _format Data Format: Use enum CANType for valid parameter values
|
||||
*/
|
||||
CANMessage(unsigned int _id, CANFormat _format = CANStandard)
|
||||
{
|
||||
len = 0;
|
||||
type = CANRemote;
|
||||
format = _format;
|
||||
id = _id;
|
||||
memset(data, 0, 8);
|
||||
}
|
||||
};
|
||||
|
||||
/** @}*/
|
||||
|
||||
namespace interface {
|
||||
|
||||
/* Having this as a struct allows interface::CAN and/or mbed::CAN to inherit the enums */
|
||||
struct can {
|
||||
|
||||
enum Mode {
|
||||
Reset = 0,
|
||||
Normal,
|
||||
Silent,
|
||||
LocalTest,
|
||||
GlobalTest,
|
||||
SilentTest
|
||||
};
|
||||
|
||||
enum IrqType {
|
||||
RxIrq = 0,
|
||||
TxIrq,
|
||||
EwIrq,
|
||||
DoIrq,
|
||||
WuIrq,
|
||||
EpIrq,
|
||||
AlIrq,
|
||||
BeIrq,
|
||||
IdIrq,
|
||||
|
||||
IrqCnt
|
||||
};
|
||||
|
||||
// Prevent slicing and user creation of base class.
|
||||
protected:
|
||||
can() = default;
|
||||
~can() = default;
|
||||
|
||||
public:
|
||||
|
||||
/* Copy constructor and copy assignment operators will be deleted in subclasses as well */
|
||||
can(const can &) = delete;
|
||||
can &operator=(const can &) = delete;
|
||||
|
||||
};
|
||||
|
||||
#ifdef FEATURE_EXPERIMENTAL_API
|
||||
|
||||
// Pure virtual interface for CAN
|
||||
struct CAN : public interface::can {
|
||||
|
||||
virtual ~CAN() = default;
|
||||
virtual int frequency(int hz) = 0;
|
||||
virtual int write(CANMessage msg) = 0;
|
||||
virtual int read(CANMessage &msg, int handle = 0) = 0;
|
||||
virtual void reset() = 0;
|
||||
virtual void monitor(bool silent) = 0;
|
||||
virtual int mode(Mode mode) = 0;
|
||||
virtual int filter(unsigned int id, unsigned int mask, CANFormat format = CANAny, int handle = 0) = 0;
|
||||
virtual unsigned char rderror() = 0;
|
||||
virtual unsigned char tderror() = 0;
|
||||
virtual void attach(Callback<void()> func, IrqType type = IrqType::RxIrq) = 0;
|
||||
};
|
||||
|
||||
#else
|
||||
using CAN = ::mbed::CAN;
|
||||
#endif
|
||||
|
||||
} // namespace interface
|
||||
|
||||
#if defined(FEATURE_EXPERIMENTAL_API) && !DEVICE_CAN
|
||||
using CAN = interface::CAN;
|
||||
#endif
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif /* MBED_INTERFACE_CAN_H_ */
|
|
@ -55,7 +55,7 @@ CAN::~CAN()
|
|||
// No lock needed in destructor
|
||||
|
||||
// Detaching interrupts releases the sleep lock if it was locked
|
||||
for (int irq = 0; irq < IrqCnt; irq++) {
|
||||
for (int irq = 0; irq < IrqType::IrqCnt; irq++) {
|
||||
attach(nullptr, (IrqType)irq);
|
||||
}
|
||||
can_irq_free(&_can);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef MBED_CAN_HELPER_H
|
||||
#define MBED_CAN_HELPER_H
|
||||
|
||||
#if DEVICE_CAN
|
||||
#if DEVICE_CAN || FEATURE_EXPERIMENTAL_API
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
Loading…
Reference in New Issue