Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide CAN library for enabling useage of CAN for ArduinoCore-mbed enabled boards. #633

Merged
merged 9 commits into from
May 2, 2023
30 changes: 30 additions & 0 deletions libraries/Arduino_CAN/examples/CANRead/CANRead.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**************************************************************************************
* INCLUDE
**************************************************************************************/

#include <Arduino_CAN.h>

/**************************************************************************************
* SETUP/LOOP
**************************************************************************************/

void setup()
{
Serial.begin(115200);
while (!Serial) { }

if (!CAN.begin(CanBitRate::BR_250k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}

void loop()
{
if (CAN.available())
{
CanMsg const msg = CAN.read();
Serial.println(msg);
}
}
55 changes: 55 additions & 0 deletions libraries/Arduino_CAN/examples/CANWrite/CANWrite.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**************************************************************************************
* INCLUDE
**************************************************************************************/

#include <Arduino_CAN.h>

/**************************************************************************************
* CONSTANTS
**************************************************************************************/

static uint32_t const CAN_ID = 0x20;

/**************************************************************************************
* SETUP/LOOP
**************************************************************************************/

void setup()
{
Serial.begin(115200);
while (!Serial) { }

if (!CAN.begin(CanBitRate::BR_250k))
{
Serial.println("CAN.begin(...) failed.");
for (;;) {}
}
}

static uint32_t msg_cnt = 0;

void loop()
{
/* Assemble a CAN message with the format of
* 0xCA 0xFE 0x00 0x00 [4 byte message counter]
*/
uint8_t const msg_data[] = {0xCA,0xFE,0,0,0,0,0,0};
memcpy((void *)(msg_data + 4), &msg_cnt, sizeof(msg_cnt));
CanMsg msg(CAN_ID, sizeof(msg_data), msg_data);

/* Transmit the CAN message, capture and display an
* error core in case of failure.
*/
if (int const rc = CAN.write(msg); rc <= 0)
{
Serial.print ("CAN.write(...) failed with error code ");
Serial.println(rc);
for (;;) { }
}

/* Increase the message counter. */
msg_cnt++;

/* Only send one message per second. */
delay(1000);
}
16 changes: 16 additions & 0 deletions libraries/Arduino_CAN/extras/scripts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
`extras/scripts`
================
This directory contains helpful shell scripts when working with CAN.

### How-to-`SocketCAN`
```bash
sudo ./setup_scan.sh
```
Display received CAN frames via [`candump`](https://manpages.ubuntu.com/manpages/jammy/man1/candump.1.html):
```bash
candump can0
```
Transmit CAN frames via [`cansend`](https://manpages.ubuntu.com/manpages/jammy/man1/cansend.1.html):
```bash
cansend can0 00001234#DEADBEEF
```
4 changes: 4 additions & 0 deletions libraries/Arduino_CAN/extras/scripts/setup_scan.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
sudo ip link set can0 type can bitrate 250000
sudo ip link set can0 up

32 changes: 32 additions & 0 deletions libraries/Arduino_CAN/keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#######################################
# Syntax Coloring Map for CAN
#######################################

#######################################
# Class (KEYWORD1)
#######################################

CAN KEYWORD1
CAN1 KEYWORD1
CanMsg KEYWORD1
CanBitRate KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################

begin KEYWORD2
end KEYWORD2
write KEYWORD2
available KEYWORD2
read KEYWORD2

#######################################
# Constants (LITERAL1)
#######################################

BR_100k LITERAL1
BR_125k LITERAL1
BR_250k LITERAL1
BR_500k LITERAL1
BR_1000k LITERAL1
10 changes: 10 additions & 0 deletions libraries/Arduino_CAN/library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name=Arduino_CAN
version=1.0.0
author=Arduino
maintainer=Arduino <[email protected]>
sentence=CAN communication library for ArduinoCore-mbed enabled boards.
paragraph=This library provides CAN for ArduinoCore-mbed enabled boards which expose CAN on their connectors.
category=Other
url=
architectures=mbed,mbed_portenta
include=Arduino_CAN.h
100 changes: 100 additions & 0 deletions libraries/Arduino_CAN/src/Arduino_CAN.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2022 by Alexander Entinger <[email protected]>
* Arduino_CAN library for Arduino.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/

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

#include "Arduino_CAN.h"

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

namespace arduino
{

/**************************************************************************************
* CTOR/DTOR
**************************************************************************************/

Arduino_CAN::Arduino_CAN(PinName const can_tx_pin, PinName const can_rx_pin)
: _can(can_rx_pin, can_tx_pin)
{

}

/**************************************************************************************
* PUBLIC MEMBER FUNCTIONS
**************************************************************************************/

bool Arduino_CAN::begin(CanBitRate const can_bitrate)
{
int const rc = _can.frequency(static_cast<int>(can_bitrate));
return (rc == 1);
}

void Arduino_CAN::end()
{
/* Nothing to do. */
}

int Arduino_CAN::write(CanMsg const & msg)
{
mbed::CANMessage const can_msg(
msg.id,
msg.data,
msg.data_length,
CANData,
CANStandard);

return _can.write(can_msg);
}

size_t Arduino_CAN::available()
{
mbed::CANMessage can_msg;
bool const msg_read = _can.read(can_msg) > 0;

if (msg_read)
{
CanMsg const msg(
can_msg.id,
can_msg.len,
can_msg.data);

_rx_msg_buf.enqueue(msg);
}

return _rx_msg_buf.available();
}

CanMsg Arduino_CAN::read()
{
return _rx_msg_buf.dequeue();
}

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

} /* arduino */

/**************************************************************************************
* OBJECT INSTANTIATION
**************************************************************************************/

#if CAN_HOWMANY > 0
arduino::Arduino_CAN CAN(PIN_CAN0_TX, PIN_CAN0_RX);
#endif

#if CAN_HOWMANY > 1
arduino::Arduino_CAN CAN1(PIN_CAN1_TX, PIN_CAN1_RX);
#endif
86 changes: 86 additions & 0 deletions libraries/Arduino_CAN/src/Arduino_CAN.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2022 by Alexander Entinger <[email protected]>
* CAN library for Arduino.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of either the GNU General Public License version 2
* or the GNU Lesser General Public License version 2.1, both as
* published by the Free Software Foundation.
*/

#ifndef ARDUINO_CORE_MBED_CAN_H_
#define ARDUINO_CORE_MBED_CAN_H_

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

#include <Arduino.h>
#include <mbed.h>

#include "api/HardwareCAN.h"

/**************************************************************************************
* COMPILE TIME CHECKS
**************************************************************************************/

#if !(defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) || defined(ARDUINO_GIGA))
# error "CAN only available on Arduino Portenta H7 and Arduino Giga (of all ArduinoCore-mbed enabled boards)."
#endif

/**************************************************************************************
* TYPEDEF
**************************************************************************************/

typedef arduino::CanMsg CanMsg;

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

namespace arduino
{

/**************************************************************************************
* CLASS DECLARATION
**************************************************************************************/

class Arduino_CAN final : public HardwareCAN
{
public:
Arduino_CAN(PinName const can_tx_pin, PinName const can_rx_pin);
virtual ~Arduino_CAN() { }


bool begin(CanBitRate const can_bitrate) override;
void end() override;


int write(CanMsg const & msg) override;
size_t available() override;
CanMsg read() override;

private:
mbed::CAN _can;
CanMsgRingbuffer _rx_msg_buf;
};

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

} /* arduino */

/**************************************************************************************
* EXTERN DECLARATION
**************************************************************************************/

#if CAN_HOWMANY > 0
extern arduino::Arduino_CAN CAN;
#endif

#if CAN_HOWMANY > 1
extern arduino::Arduino_CAN CAN1;
#endif

#endif /* ARDUINO_CORE_MBED_CAN_H_ */
8 changes: 8 additions & 0 deletions variants/GIGA/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,4 +263,12 @@ void _ontouch1200bps_();

#define USB_MAX_POWER (500)

#define CAN_HOWMANY 2

#define PIN_CAN0_TX (PB_13)
#define PIN_CAN0_RX (PB_12)

#define PIN_CAN1_TX (PH_13)
#define PIN_CAN1_RX (PB_8)

#endif //__PINS_ARDUINO__
2 changes: 1 addition & 1 deletion variants/PORTENTA_H7_M4/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
#include "../GIGA/pins_arduino.h"
#endif

#undef SERIAL_CDC
#undef SERIAL_CDC
2 changes: 1 addition & 1 deletion variants/PORTENTA_H7_M4/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@

#undef initVariant

void initVariant() {}
void initVariant() {}
5 changes: 5 additions & 0 deletions variants/PORTENTA_H7_M7/pins_arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,9 @@ void _ontouch1200bps_();

#define USB_MAX_POWER (500)

#define CAN_HOWMANY 1

#define PIN_CAN0_TX (PH_13) /* Labeled CAN1_TX on high-density connector. */
#define PIN_CAN0_RX (PB_8) /* Labeled CAN1_RX on high-density connector. */

#endif //__PINS_ARDUINO__
4 changes: 2 additions & 2 deletions variants/PORTENTA_H7_M7/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ PinDescription g_APinDescription[] = {
{ PB_5, NULL, NULL, NULL },
{ PB_6, NULL, NULL, NULL },
{ PB_7, NULL, NULL, NULL },
{ PB_8, NULL, NULL, NULL },
{ PB_8, NULL, NULL, NULL }, // HD-connector: CAN1_RX -> software object: CAN
{ PB_9, NULL, NULL, NULL },
{ PB_10, NULL, NULL, NULL },
{ PB_11, NULL, NULL, NULL },
Expand Down Expand Up @@ -179,7 +179,7 @@ PinDescription g_APinDescription[] = {
{ PH_10, NULL, NULL, NULL },
{ PH_11, NULL, NULL, NULL },
{ PH_12, NULL, NULL, NULL },
{ PH_13, NULL, NULL, NULL },
{ PH_13, NULL, NULL, NULL }, // HD-connector: CAN1_TX -> software object: CAN
{ PH_14, NULL, NULL, NULL },
{ PH_15, NULL, NULL, NULL },
{ PI_0, NULL, NULL, NULL },
Expand Down