Skip to content

Commit

Permalink
Merge pull request #87 from 107-systems/error-callback
Browse files Browse the repository at this point in the history
Allow registration of callbacks for CAN bus errors/warnings.
  • Loading branch information
aentinger authored May 2, 2023
2 parents 264d623 + 7b71e7a commit 3654f4a
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 7 deletions.
4 changes: 3 additions & 1 deletion examples/MCP2515-CAN-Sniffer/MCP2515-CAN-Sniffer.ino
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ ArduinoMCP2515 mcp2515([]() { digitalWrite(MKRCAN_MCP2515_CS_PIN, LOW); },
[](uint8_t const d) { return SPI.transfer(d); },
micros,
onReceiveBufferFull,
nullptr);
nullptr,
[](MCP2515::EFLG const err_flag) { Serial.print("MCP2515::OnError, error code = "); Serial.println(MCP2515::toStr(err_flag)); },
[](MCP2515::EFLG const err_flag) { Serial.print("MCP2515::OnError, error code = "); Serial.println(MCP2515::toStr(err_flag)); });

/**************************************************************************************
* SETUP/LOOP
Expand Down
2 changes: 2 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ArduinoMCP2515 KEYWORD1
CanBitRate KEYWORD1
MCP2515 KEYWORD1
EFLG KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
Expand All @@ -24,6 +25,7 @@ setConfigMode KEYWORD2
enableFilter KEYWORD2
transmit KEYWORD2
onExternalEventHandler KEYWORD2
toStr KEYWORD2

#######################################
# Constants (LITERAL1)
Expand Down
56 changes: 55 additions & 1 deletion src/ArduinoMCP2515.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,17 @@ ArduinoMCP2515::ArduinoMCP2515(SpiSelectFunc select,
SpiTransferFunc transfer,
MicroSecondFunc micros,
OnReceiveBufferFullFunc on_rx_buf_full,
OnTransmitBufferEmptyFunc on_tx_buf_empty)
OnTransmitBufferEmptyFunc on_tx_buf_empty,
OnCanErrorFunc on_error,
OnCanWarningFunc on_warning)
: _io{select, deselect, transfer}
, _cfg{_io}
, _ctrl{_io}
, _micros{micros}
, _on_rx_buf_full{on_rx_buf_full}
, _on_tx_buf_empty{on_tx_buf_empty}
, _on_error{on_error}
, _on_warning{on_warning}
{

}
Expand Down Expand Up @@ -121,6 +125,13 @@ void ArduinoMCP2515::begin()
_cfg.enableIntFlag(CANINTE::RX0IE);
_cfg.enableIntFlag(CANINTE::RX1IE);
}

/* Conditionally enable error interrupt
* only if we have error callbacks
* registered.
*/
if (_on_error || _on_warning)
_cfg.enableIntFlag(CANINTE::ERRIE);
}

void ArduinoMCP2515::setBitRate(CanBitRate const bit_rate)
Expand Down Expand Up @@ -164,13 +175,56 @@ bool ArduinoMCP2515::transmit(uint32_t const id, uint8_t const * data, uint8_t c

void ArduinoMCP2515::onExternalEventHandler()
{
/* Obtain current status and call the appropriate callback
* handlers to facilitate the necessary actions.
*/
uint8_t const status = _ctrl.status();

if(isBitSet(status, bp(STATUS::RX0IF))) onReceiveBuffer_0_Full();
if(isBitSet(status, bp(STATUS::RX1IF))) onReceiveBuffer_1_Full();
if(isBitSet(status, bp(STATUS::TX0IF))) onTransmitBuffer_0_Empty();
if(isBitSet(status, bp(STATUS::TX1IF))) onTransmitBuffer_1_Empty();
if(isBitSet(status, bp(STATUS::TX2IF))) onTransmitBuffer_2_Empty();


/* Only perform error checks if a callback has been
* registered. Otherwise, it's an unnecessary SPI
* transaction which consumes valuable processing
* time.
*/
if (!_on_error && !_on_warning)
return;

/* Check if an error flag is set and - should an error flag
* be set - deal with it.
*/
uint8_t const error_flag = _ctrl.error();

bool const is_error = (error_flag > EFLG_ERR_MASK) > 0;
if (is_error && _on_error)
{
_on_error(static_cast<EFLG>(error_flag & EFLG_ERR_MASK));

/* RX0OVR and RX1OVR need to be cleared manually,
* otherwise the error will persist and we will
* not be able to ever again obtain received
* CAN frames.
*/
if (isBitSet(error_flag, bp(EFLG::RX0OVR)))
_ctrl.clearErrFlag(EFLG::RX0OVR);

if (isBitSet(error_flag, bp(EFLG::RX1OVR)))
_ctrl.clearErrFlag(EFLG::RX1OVR);
}

bool const is_warning = (error_flag > EFLG_WAR_MASK) > 0;
if (is_warning && _on_warning)
_on_warning(static_cast<EFLG>(error_flag & EFLG_WAR_MASK));

/* Finally clear the error interrupt flag so that we are not
* continuously caught in the ERROR handling loop.
*/
_ctrl.clearIntFlag(CANINTF::ERRIF);
}

/**************************************************************************************
Expand Down
17 changes: 16 additions & 1 deletion src/ArduinoMCP2515.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ typedef std::function<void(uint32_t const, uint32_t const, uint8_t const *, uint
#endif
class ArduinoMCP2515;
typedef std::function<void(ArduinoMCP2515 *)> OnTransmitBufferEmptyFunc;
typedef std::function<void(MCP2515::EFLG const)> OnCanErrorFunc;
typedef std::function<void(MCP2515::EFLG const)> OnCanWarningFunc;

/**************************************************************************************
* CLASS DECLARATION
Expand All @@ -105,7 +107,18 @@ class ArduinoMCP2515
MCP2515::SpiTransferFunc transfer,
MicroSecondFunc micros,
OnReceiveBufferFullFunc on_rx_buf_full,
OnTransmitBufferEmptyFunc on_tx_buf_empty);
OnTransmitBufferEmptyFunc on_tx_buf_empty,
OnCanErrorFunc on_error,
OnCanWarningFunc on_warning);

ArduinoMCP2515(MCP2515::SpiSelectFunc select,
MCP2515::SpiDeselectFunc deselect,
MCP2515::SpiTransferFunc transfer,
MicroSecondFunc micros,
OnReceiveBufferFullFunc on_rx_buf_full,
OnTransmitBufferEmptyFunc on_tx_buf_empty)
: ArduinoMCP2515{select, deselect, transfer, micros, on_rx_buf_full, on_tx_buf_empty, nullptr, nullptr}
{ }


void begin();
Expand Down Expand Up @@ -137,6 +150,8 @@ class ArduinoMCP2515
MicroSecondFunc _micros;
OnReceiveBufferFullFunc _on_rx_buf_full;
OnTransmitBufferEmptyFunc _on_tx_buf_empty;
OnCanErrorFunc _on_error;
OnCanWarningFunc _on_warning;

bool transmitCANFrame (uint32_t const id, uint8_t const * data, uint8_t const len);
void onReceiveBuffer_0_Full ();
Expand Down
45 changes: 45 additions & 0 deletions src/MCP2515/MCP2515_Const.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* This software is distributed under the terms of the MIT License.
* Copyright (c) 2020 LXRobotics.
* Author: Alexander Entinger <[email protected]>
* Contributors: https://github.com/107-systems/107-Arduino-MCP2515/graphs/contributors.
*/

/**************************************************************************************
* INCLUDE
**************************************************************************************/

#include "MCP2515_Const.h"

/**************************************************************************************
* NAMESPACE
**************************************************************************************/

namespace MCP2515
{

/**************************************************************************************
* FUNCTION DEFINITION
**************************************************************************************/

const char * toStr(EFLG const err_flag)
{
switch(err_flag)
{
case EFLG::RX1OVR: return "RX1OVR"; break;
case EFLG::RX0OVR: return "RX0OVR"; break;
case EFLG::TXBO : return "TXBO"; break;
case EFLG::TXEP : return "TXEP"; break;
case EFLG::RXEP : return "RXEP"; break;
case EFLG::TXWAR : return "TXWAR"; break;
case EFLG::RXWAR : return "RXWAR"; break;
case EFLG::EWARN : return "EWARN"; break;
default: __builtin_unreachable(); return ""; break;
}
}

/**************************************************************************************
* NAMESPACE
**************************************************************************************/

} /* MCP2515 */
22 changes: 22 additions & 0 deletions src/MCP2515/MCP2515_Const.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ enum class STATUS : uint8_t

enum class CANINTE : uint8_t
{
ERRIE = 5,
TX2IE = 4,
TX1IE = 3,
TX0IE = 2,
Expand Down Expand Up @@ -222,6 +223,18 @@ enum class TXBnCTRL : uint8_t
TXREQ = 3,
};

enum class EFLG : uint8_t
{
RX1OVR = 7,
RX0OVR = 6,
TXBO = 5,
TXEP = 4,
RXEP = 3,
TXWAR = 2,
RXWAR = 1,
EWARN = 0,
};

/**************************************************************************************
* CONVERSION FUNCTIONS
**************************************************************************************/
Expand All @@ -238,6 +251,12 @@ constexpr auto bm(Enumeration const value) -> typename std::underlying_type<Enum
return (1 << bp(value));
}

/**************************************************************************************
* FUNCTION DECLARATION
**************************************************************************************/

const char * toStr(EFLG const err_flag);

/**************************************************************************************
* CONSTANTS
**************************************************************************************/
Expand All @@ -247,6 +266,9 @@ static uint8_t constexpr CANSTAT_OP_MASK = bm(CANSTAT::OPMOD2) | bm(CANSTAT::
static uint8_t constexpr RXB0CTRL_RXM_MASK = bm(RXB0CTRL::RXM1) | bm(RXB0CTRL::RXM0);
static uint8_t constexpr RXB1CTRL_RXM_MASK = bm(RXB1CTRL::RXM1) | bm(RXB1CTRL::RXM0);

static uint8_t constexpr EFLG_ERR_MASK = bm(EFLG::RX1OVR) | bm(EFLG::RX0OVR) | bm(EFLG::TXBO) | bm(EFLG::TXEP) | bm(EFLG::RXEP);
static uint8_t constexpr EFLG_WAR_MASK = bm(EFLG::TXWAR) | bm(EFLG::RXWAR) | bm(EFLG::EWARN);

static uint32_t constexpr CAN_EFF_BITMASK = 0x80000000;
static uint32_t constexpr CAN_RTR_BITMASK = 0x40000000;
static uint32_t constexpr CAN_ERR_BITMASK = 0x20000000;
Expand Down
4 changes: 4 additions & 0 deletions src/MCP2515/MCP2515_Control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ void MCP2515_Control::receive(RxB const rxb, uint32_t & id, uint8_t * data, uint
memcpy(data, rx_buffer.reg.data, std::min<uint8_t>(len, 8));
}

uint8_t MCP2515_Control::error()
{
return _io.readRegister(Register::EFLG);
}

/**************************************************************************************
* NAMESPACE
Expand Down
10 changes: 6 additions & 4 deletions src/MCP2515/MCP2515_Control.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ class MCP2515_Control
MCP2515_Control(MCP2515_Io & io);


void transmit (TxB const txb, uint32_t const id, uint8_t const * data, uint8_t const len);
void receive (RxB const rxb, uint32_t & id, uint8_t * data, uint8_t & len);
void transmit(TxB const txb, uint32_t const id, uint8_t const * data, uint8_t const len);
void receive (RxB const rxb, uint32_t & id, uint8_t * data, uint8_t & len);

uint8_t error();

inline void reset () { _io.reset(); }
inline uint8_t status () { return _io.status(); }
inline void clearIntFlag(CANINTF const int_flag) { _io.clrBit(Register::CANINTF, bp(int_flag)); }

inline void clearIntFlag(CANINTF const int_flag) { _io.clrBit(Register::CANINTF, bp(int_flag)); }
inline void clearErrFlag(EFLG const err_flag) { _io.clrBit(Register::EFLG, bp(err_flag)); }

private:

Expand Down

0 comments on commit 3654f4a

Please sign in to comment.