1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers/mcp2515: complete driver + adapt to 2020 RIOT API

This commit is contained in:
Wouter Symons 2020-01-31 15:18:16 +01:00
parent 62a9929f9b
commit 757f810118
13 changed files with 591 additions and 318 deletions

View File

@ -77,6 +77,7 @@
/drivers/dose/ @jue89
/drivers/ds18/ @leandrolanzieri
/drivers/itg320x/ @gschorcht
/drivers/mcp2515/ @wosym
/drivers/mrf24j40/ @bergzand
/drivers/pca9685/ @gschorcht
/drivers/sht3x/ @gschorcht

View File

@ -72,6 +72,11 @@ ifneq (,$(filter ltc4150_%,$(USEMODULE)))
USEMODULE += ltc4150
endif
ifneq (,$(filter mcp2515,$(USEMODULE)))
USEMODULE += xtimer
FEATURES_REQUIRED += periph_gpio periph_spi periph_gpio_irq
endif
ifneq (,$(filter mhz19_%,$(USEMODULE)))
USEMODULE += mhz19
endif

View File

@ -19,6 +19,7 @@
*
* @author Toon Stegen <toon.stegen@altran.com>
* @author Vincent Dupont <vincent@otakeys.com>
* @author Wouter Symons <wosym@airsantelmo.com>
*/
#ifndef CANDEV_MCP2515_H
@ -37,6 +38,20 @@
extern "C" {
#endif
/**
* Default CAN bitrate
*/
#ifndef CANDEV_MCP2515_DEFAULT_BITRATE
#define CANDEV_MCP2515_DEFAULT_BITRATE 125000
#endif
/**
* Default sampling point setup
*/
#ifndef CANDEV_MCP2515_DEFAULT_SPT
#define CANDEV_MCP2515_DEFAULT_SPT 875
#endif
/**
* Number of transmit mailboxes
*/
@ -75,13 +90,13 @@ typedef struct candev_mcp2515 candev_mcp2515_t;
* @brief MCP2515 configuration descriptor
*/
typedef struct candev_mcp2515_conf {
spi_t spi; /**< SPI bus */
spi_mode_t spi_mode; /**< SPI mode */
spi_clk_t spi_clk; /**< SPI clock speed */
gpio_t cs_pin; /**< Slave select pin */
gpio_t rst_pin; /**< Reset pin */
gpio_t int_pin; /**< Interrupt pin */
uint32_t clk; /**< External clock frequency */
spi_t spi; /**< SPI bus */
spi_mode_t spi_mode; /**< SPI mode */
spi_clk_t spi_clk; /**< SPI clock speed */
gpio_t cs_pin; /**< Slave select pin */
gpio_t rst_pin; /**< Reset pin */
gpio_t int_pin; /**< Interrupt pin */
uint32_t clk; /**< External clock frequency */
} candev_mcp2515_conf_t;
/**
@ -111,7 +126,8 @@ struct candev_mcp2515 {
* @param[out] dev mcp2515 device descriptor
* @param[in] conf mcp2515 configuration
*/
void candev_mcp2515_init(candev_mcp2515_t *dev, const candev_mcp2515_conf_t *conf);
void candev_mcp2515_init(candev_mcp2515_t *dev,
const candev_mcp2515_conf_t *conf);
#ifdef __cplusplus
}

View File

@ -1,3 +1 @@
MODULE = mcp2515
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,2 @@
USEMODULE_INCLUDES_mcp2515 := $(LAST_MAKEFILEDIR)/include
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_mcp2515)

View File

@ -7,7 +7,7 @@
*/
/**
* @ingroup drivers_mcp2515 Stand-Alone CAN Controller With SPI Interface
* @ingroup drivers_mcp2515
* @{
*
* @file
@ -15,38 +15,30 @@
*
* @author Toon Stegen <toon.stegen@altran.com>
* @author Vincent Dupont <vincent@otakeys.com>
* @author Wouter Symons <wosym@airsantelmo.com>
* @}
*/
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <can/common.h>
#include <stdbool.h>
#include <string.h>
#include "candev_mcp2515.h"
#include "can/common.h"
#include "can/device.h"
#include "mcp2515.h"
#include "mutex.h"
#include "periph_conf.h"
#include "thread.h"
#include "sched.h"
#include "mutex.h"
#include "xtimer.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define MAILBOX_USED 1
#define MAILBOX_EMPTY 0
#define MAILBOX_TO_INTR(mailbox) (INT_RX0 + (mailbox))
#ifndef CANDEV_MCP2515_DEFAULT_BITRATE
#define CANDEV_MCP2515_DEFAULT_BITRATE 500000
#endif
#ifndef CANDEV_MCP2515_DEFAULT_SPT
#define CANDEV_MCP2515_DEFAULT_SPT 875
#endif
static mutex_t _mcp_mutex;
static int _neednewisr = 0;
static int _init(candev_t *candev);
static int _send(candev_t *candev, const struct can_frame *frame);
@ -54,15 +46,16 @@ static void _isr(candev_t *candev);
static int _set(candev_t *candev, canopt_t opt, void *value, size_t value_len);
static int _get(candev_t *candev, canopt_t opt, void *value, size_t max_len);
static int _abort(candev_t *candev, const struct can_frame *frame);
static int _set_filter(candev_t *dev, const struct can_filter * filter);
static int _remove_filter(candev_t *dev, const struct can_filter * filter);
static int _set_filter(candev_t *dev, const struct can_filter *filter);
static int _remove_filter(candev_t *dev, const struct can_filter *filter);
static void _irq_rx(candev_mcp2515_t *dev, int handle);
static void _irq_tx(candev_mcp2515_t *dev, int handle);
static void _irq_error(candev_mcp2515_t *dev);
static void _irq_message_error(candev_mcp2515_t *dev);
static void _irq_wakeup(const candev_mcp2515_t *dev);
static void _send_event(const candev_mcp2515_t *dev, candev_event_t event, void *arg);
static void _send_event(const candev_mcp2515_t *dev, candev_event_t event,
void *arg);
static const candev_driver_t candev_mcp2515_driver = {
.send = _send,
@ -76,14 +69,14 @@ static const candev_driver_t candev_mcp2515_driver = {
};
static const struct can_bittiming_const bittiming_const = {
.tseg1_min = 3,
.tseg1_max = 16,
.tseg2_min = 2,
.tseg2_max = 8,
.sjw_max = 4,
.brp_min = 1,
.brp_max = 64,
.brp_inc = 1,
.tseg1_min = 3, /**< Time segment 1 = prop_seg + phase_seg1, min value */
.tseg1_max = 16, /**< Time segment 1, max value */
.tseg2_min = 2, /**< Time segment 2 = phase_seg2, min value */
.tseg2_max = 8, /**< Time segment 2, max value */
.sjw_max = 4, /**< Synchronisation jump width */
.brp_min = 1, /**< Bit-rate prescaler, min value */
.brp_max = 64, /**< Bit-rate prescaler, max value */
.brp_inc = 1, /**< Bit-rate prescaler, increment */
};
static inline int _max_filters(int mailbox)
@ -91,13 +84,17 @@ static inline int _max_filters(int mailbox)
return mailbox == 0 ? MCP2515_FILTERS_MB0 : MCP2515_FILTERS_MB1;
}
void candev_mcp2515_init(candev_mcp2515_t *dev, const candev_mcp2515_conf_t *conf)
void candev_mcp2515_init(candev_mcp2515_t *dev,
const candev_mcp2515_conf_t *conf)
{
memset(dev, 0, sizeof(*dev));
dev->candev.driver = &candev_mcp2515_driver;
struct can_bittiming timing = { .bitrate = CANDEV_MCP2515_DEFAULT_BITRATE,
.sample_point = CANDEV_MCP2515_DEFAULT_SPT };
.sample_point =
CANDEV_MCP2515_DEFAULT_SPT };
/* f_quantum = f_osc / 2 */
can_device_calc_bittiming(conf->clk / 2, &bittiming_const, &timing);
memcpy(&dev->candev.bittiming, &timing, sizeof(timing));
@ -114,7 +111,8 @@ void candev_mcp2515_init(candev_mcp2515_t *dev, const candev_mcp2515_conf_t *con
static void _mcp2515_irq_handler(void *arg)
{
candev_mcp2515_t *candev = (candev_mcp2515_t *) arg;
candev_mcp2515_t *candev = (candev_mcp2515_t *)arg;
_send_event(candev, CANDEV_EVENT_ISR, NULL);
}
@ -131,15 +129,23 @@ static int _init(candev_t *candev)
mcp2515_configure_bittiming(dev);
mcp2515_init_irqs(dev);
/* configure filters to be closed */
for (int mailbox = 0; mailbox < MCP2515_RX_MAILBOXES; mailbox++) {
mcp2515_set_mask(dev, mailbox, dev->masks[mailbox]);
for (int filter = 0; filter < _max_filters(mailbox); filter++) {
mcp2515_set_filter(dev, mailbox * MCP2515_FILTERS_MB0 + filter,
dev->filter_ids[mailbox][filter]);
if (mutex_trylock(&_mcp_mutex)) {
/* configure filters to be closed */
for (int mailbox = 0; mailbox < MCP2515_RX_MAILBOXES; mailbox++) {
mcp2515_set_mask(dev, mailbox, dev->masks[mailbox]);
for (int filter = 0; filter < _max_filters(mailbox); filter++) {
mcp2515_set_filter(dev, mailbox * MCP2515_FILTERS_MB0 + filter,
dev->filter_ids[mailbox][filter]);
}
}
res = mcp2515_set_mode(dev, MODE_NORMAL);
mutex_unlock(&_mcp_mutex);
}
else {
/* locking failed */
DEBUG("failed to lock mutex_init");
return -1;
}
res = mcp2515_set_mode(dev, MODE_NORMAL);
return res;
}
@ -147,11 +153,24 @@ static int _send(candev_t *candev, const struct can_frame *frame)
{
candev_mcp2515_t *dev = (candev_mcp2515_t *)candev;
int box;
int ret = 0;
enum mcp2515_mode mode;
mode = mcp2515_get_mode(dev);
if (frame->can_id > 0x1FFFFFFF) {
DEBUG("Illegal CAN-ID!\n");
return -EINVAL;
}
if (mutex_trylock(&_mcp_mutex)) {
mode = mcp2515_get_mode(dev);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("failed to lock mutex_send\n");
return -1;
}
if (mode != MODE_NORMAL && mode != MODE_LOOPBACK) {
return -EINVAL;
return -EINVAL;
}
DEBUG("Inside mcp2515 send\n");
@ -168,7 +187,23 @@ static int _send(candev_t *candev, const struct can_frame *frame)
dev->tx_mailbox[box] = frame;
mcp2515_send(dev, frame, box);
if (mutex_trylock(&_mcp_mutex)) {
ret = mcp2515_send(dev, frame, box);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("send_failed to lock mutex\n");
return -1;
}
if (ret < 0) {
return -1;
}
if (_neednewisr) {
DEBUG("Calling _isr() again on request\n");
_isr(candev);
_neednewisr = 0;
}
return box;
}
@ -190,7 +225,14 @@ static int _abort(candev_t *candev, const struct can_frame *frame)
return -EBUSY;
}
mcp2515_abort(dev, box);
if (mutex_trylock(&_mcp_mutex)) {
mcp2515_abort(dev, box);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("abort_Failed to lock mutex\n");
return -1;
}
dev->tx_mailbox[box] = NULL;
return 0;
@ -201,7 +243,17 @@ static void _isr(candev_t *candev)
uint8_t flag;
candev_mcp2515_t *dev = (candev_mcp2515_t *)candev;
while((flag = mcp2515_get_irq(dev))) {
if (mutex_trylock(&_mcp_mutex)) {
flag = mcp2515_get_irq(dev);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("isr: Failed to lock mutex\n");
_neednewisr = 1;
return;
}
while ((flag)) {
if (flag & INT_WAKEUP) {
if (dev->wakeup_src == MCP2515_WKUP_SRC_INTERNAL) {
dev->wakeup_src = 0;
@ -232,8 +284,26 @@ static void _isr(candev_t *candev)
_irq_message_error(dev);
}
if (mutex_trylock(&_mcp_mutex)) {
flag = mcp2515_get_irq(dev);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("isr2: Failed to lock mutex\n");
_neednewisr = 1;
return;
}
/* clear all flags except for RX flags, which are cleared by receiving */
mcp2515_clear_irq(dev, flag & ~INT_RX0 & ~INT_RX1);
if (mutex_trylock(&_mcp_mutex)) {
mcp2515_clear_irq(dev, flag & ~(INT_RX0 | INT_RX1));
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("isr3: failed to lock mutex\n");
_neednewisr = 1;
return;
}
}
}
@ -264,14 +334,35 @@ static int _set(candev_t *candev, canopt_t opt, void *value, size_t value_len)
else {
switch (*((canopt_state_t *)value)) {
case CANOPT_STATE_LISTEN_ONLY:
res = mcp2515_set_mode(dev, MODE_LISTEN_ONLY);
if (mutex_trylock(&_mcp_mutex)) {
res = mcp2515_set_mode(dev, MODE_LISTEN_ONLY);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("set1_Failed to lock mutex\n");
return -1;
}
break;
case CANOPT_STATE_OFF:
case CANOPT_STATE_SLEEP:
res = mcp2515_set_mode(dev, MODE_SLEEP);
if (mutex_trylock(&_mcp_mutex)) {
res = mcp2515_set_mode(dev, MODE_SLEEP);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("set2_Failed to lock mutex\n");
return -1;
}
break;
case CANOPT_STATE_ON:
res = mcp2515_set_mode(dev, MODE_NORMAL);
if (mutex_trylock(&_mcp_mutex)) {
res = mcp2515_set_mode(dev, MODE_NORMAL);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("set3_Failed to lock mutex\n");
return -1;
}
break;
default:
res = -ENOTSUP;
@ -307,7 +398,8 @@ static int _get(candev_t *candev, canopt_t opt, void *value, size_t max_len)
res = -EOVERFLOW;
}
else {
res = 1;
/* Not implemented (yet...) */
res = -ENOTSUP;
}
break;
case CANOPT_BITTIMING_CONST:
@ -339,19 +431,28 @@ static int _get(candev_t *candev, canopt_t opt, void *value, size_t max_len)
static int _set_filter(candev_t *dev, const struct can_filter *filter)
{
DEBUG("inside _set_filter of MCP2515\n");
int filter_added = -1;
bool filter_added = true;
struct can_filter f = *filter;
int res = -1;
enum mcp2515_mode mode;
candev_mcp2515_t *dev_mcp = (candev_mcp2515_t *) dev;
candev_mcp2515_t *dev_mcp = (candev_mcp2515_t *)dev;
if (f.can_mask == 0) {
return -EINVAL; /* invalid mask */
}
mode = mcp2515_get_mode(dev_mcp);
res = mcp2515_set_mode(dev_mcp, MODE_CONFIG);
if (mutex_trylock(&_mcp_mutex)) {
mode = mcp2515_get_mode(dev_mcp);
res = mcp2515_set_mode(dev_mcp, MODE_CONFIG);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("setfilt_Failed to lock mutex\n");
return -1;
}
if (res != MODE_CONFIG) {
return -1;
}
@ -365,20 +466,22 @@ static int _set_filter(candev_t *dev, const struct can_filter *filter)
/* Browse on each mailbox to find an empty space */
int mailbox_index = 0;
while (mailbox_index < MCP2515_RX_MAILBOXES && filter_added == -1) {
while (mailbox_index < MCP2515_RX_MAILBOXES && !filter_added) {
/* mask unused */
if (dev_mcp->masks[mailbox_index] == 0) {
/* set mask */
mcp2515_set_mask(dev_mcp, mailbox_index, f.can_mask);
/* set filter */
mcp2515_set_filter(dev_mcp, MCP2515_FILTERS_MB0 * mailbox_index, f.can_id);
mcp2515_set_filter(dev_mcp, MCP2515_FILTERS_MB0 * mailbox_index,
f.can_id);
/* save filter */
dev_mcp->masks[mailbox_index] = f.can_mask;
dev_mcp->filter_ids[mailbox_index][0] = f.can_id;
/* function succeeded */
filter_added = 1;
filter_added = true;
}
/* mask existed and same mask */
@ -394,19 +497,35 @@ static int _set_filter(candev_t *dev, const struct can_filter *filter)
/* an empty space is found */
if (filter_pos < _max_filters(mailbox_index)) {
/* set filter on this memory space */
mcp2515_set_filter(dev_mcp, MCP2515_FILTERS_MB0 * mailbox_index + filter_pos, f.can_id);
if (mutex_trylock(&_mcp_mutex)) {
mcp2515_set_filter(dev_mcp,
MCP2515_FILTERS_MB0 * mailbox_index + filter_pos,
f.can_id);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("setfilt2_Failed to lock mutex");
return -1;
}
/* save filter */
dev_mcp->filter_ids[mailbox_index][filter_pos] = f.can_id;
/* function succeeded */
filter_added = 1;
filter_added = true;
}
}
mailbox_index++;
}
mcp2515_set_mode(dev_mcp, mode);
if (mutex_trylock(&_mcp_mutex)) {
mcp2515_set_mode(dev_mcp, mode);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("setfilt3_Failed to lock mutex");
return -1;
}
return filter_added;
}
@ -414,20 +533,28 @@ static int _set_filter(candev_t *dev, const struct can_filter *filter)
static int _remove_filter(candev_t *dev, const struct can_filter *filter)
{
DEBUG("inside _remove_filter of MCP2515\n");
int filter_removed = -1;
bool filter_removed;
struct can_filter f = *filter;
int res = 0;
enum mcp2515_mode mode;
candev_mcp2515_t *dev_mcp = (candev_mcp2515_t *) dev;
candev_mcp2515_t *dev_mcp = (candev_mcp2515_t *)dev;
if (f.can_mask == 0) {
return -1; /* invalid mask */
}
mode = mcp2515_get_mode(dev_mcp);
res = mcp2515_set_mode(dev_mcp, MODE_CONFIG);
if(res < 0) {
if (mutex_trylock(&_mcp_mutex)) {
mode = mcp2515_get_mode(dev_mcp);
res = mcp2515_set_mode(dev_mcp, MODE_CONFIG);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("remfilt_Failed to lock mutex\n");
return -1;
}
if (res < 0) {
return -1;
}
@ -439,8 +566,9 @@ static int _remove_filter(candev_t *dev, const struct can_filter *filter)
}
int mailbox_index = 0;
/* Browse on each mailbox to find the right filter id */
while (mailbox_index < MCP2515_RX_MAILBOXES && filter_removed == -1) {
while (mailbox_index < MCP2515_RX_MAILBOXES && !filter_removed) {
/* same mask */
if (dev_mcp->masks[mailbox_index] == f.can_mask) {
int filter_pos = 0;
@ -453,7 +581,16 @@ static int _remove_filter(candev_t *dev, const struct can_filter *filter)
/* filter id found */
if (filter_pos < _max_filters(mailbox_index)) {
/* remove filter */
mcp2515_set_filter(dev_mcp, MCP2515_FILTERS_MB0 * mailbox_index + filter_pos, CAN_EFF_MASK);
if (mutex_trylock(&_mcp_mutex)) {
mcp2515_set_filter(dev_mcp,
MCP2515_FILTERS_MB0 * mailbox_index + filter_pos,
CAN_EFF_MASK);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("remfilt2_Failed to lock mutex\n");
return -1;
}
/* save modification */
dev_mcp->filter_ids[mailbox_index][filter_pos] = 0;
@ -478,7 +615,14 @@ static int _remove_filter(candev_t *dev, const struct can_filter *filter)
}
mailbox_index++;
}
mcp2515_set_mode(dev_mcp, mode);
if (mutex_trylock(&_mcp_mutex)) {
mcp2515_set_mode(dev_mcp, mode);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("remfilt3_Failed to lock mutex\n");
return -1;
}
return filter_removed;
}
@ -487,7 +631,14 @@ static void _irq_rx(candev_mcp2515_t *dev, int box)
{
DEBUG("Inside mcp2515 rx irq, box=%d\n", box);
mcp2515_receive(dev, &dev->rx_buf[box], box);
if (mutex_trylock(&_mcp_mutex)) {
mcp2515_receive(dev, &dev->rx_buf[box], box);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("irqrx_Failed to lock mutex\n");
return;
}
_send_event(dev, CANDEV_EVENT_RX_INDICATION, &dev->rx_buf[box]);
}
@ -496,6 +647,7 @@ static void _irq_tx(candev_mcp2515_t *dev, int box)
{
DEBUG("Inside mcp2515 tx irq\n");
const struct can_frame *frame = dev->tx_mailbox[box];
dev->tx_mailbox[box] = NULL;
_send_event(dev, CANDEV_EVENT_TX_CONFIRMATION, (void *)frame);
@ -504,23 +656,31 @@ static void _irq_tx(candev_mcp2515_t *dev, int box)
static void _irq_error(candev_mcp2515_t *dev)
{
uint8_t err;
DEBUG("Inside mcp2515 error irq\n");
err = mcp2515_get_errors(dev);
if (mutex_trylock(&_mcp_mutex)) {
err = mcp2515_get_errors(dev);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("erqerr_Failed to lock mutex\n");
return;
}
if(err & (ERR_WARNING | ERR_RX_WARNING | ERR_TX_WARNING)) {
if (err & (ERR_WARNING | ERR_RX_WARNING | ERR_TX_WARNING)) {
DEBUG("Error Warning\n");
_send_event(dev, CANDEV_EVENT_ERROR_WARNING, NULL);
}
else if(err & (ERR_RX_PASSIVE | ERR_TX_PASSIVE)) {
else if (err & (ERR_RX_PASSIVE | ERR_TX_PASSIVE)) {
DEBUG("Error Passive\n");
_send_event(dev, CANDEV_EVENT_ERROR_PASSIVE, NULL);
}
else if(err & ERR_TX_BUS_OFF) {
DEBUG("Buss Off\n");
else if (err & ERR_TX_BUS_OFF) {
DEBUG("Bus Off\n");
_send_event(dev, CANDEV_EVENT_BUS_OFF, NULL);
}
else if(err & (ERR_RX_0_OVERFLOW | ERR_RX_1_OVERFLOW)) {
else if (err & (ERR_RX_0_OVERFLOW | ERR_RX_1_OVERFLOW)) {
DEBUG("RX overflow\n");
_send_event(dev, CANDEV_EVENT_RX_ERROR, NULL);
}
@ -528,8 +688,6 @@ static void _irq_error(candev_mcp2515_t *dev)
static void _irq_message_error(candev_mcp2515_t *dev)
{
(void) dev;
#if(0)
int box;
DEBUG("Inside mcp2515 message error irq\n");
@ -538,19 +696,19 @@ static void _irq_message_error(candev_mcp2515_t *dev)
if (mcp2515_tx_err_occurred(dev, box)) {
DEBUG("Box: %d\n", box);
mutex_lock(&dev->tx_mutex);
mcp2515_abort(dev, box);
xtimer_remove(&dev->tx_mailbox[box].timer);
mutex_unlock(&dev->tx_mutex);
if (mutex_trylock(&_mcp_mutex)) {
mcp2515_abort(dev, box);
mutex_unlock(&_mcp_mutex);
}
else {
DEBUG("irqmsg_Failed to lock mutex\n");
return;
}
_send_event(dev, CANDEV_EVENT_TIMEOUT_TX_CONF,
NULL);
_send_event(dev, CANDEV_EVENT_TIMEOUT_TX_CONF, (void *) dev->tx_mailbox[box].pkt);
mutex_lock(&dev->tx_mutex);
dev->tx_mailbox[box].pkt = NULL;
mutex_unlock(&dev->tx_mutex);
}
}
#endif
}
static void _irq_wakeup(const candev_mcp2515_t *dev)
@ -560,9 +718,10 @@ static void _irq_wakeup(const candev_mcp2515_t *dev)
_send_event(dev, CANDEV_EVENT_WAKE_UP, NULL);
}
static void _send_event(const candev_mcp2515_t *dev, candev_event_t event, void *arg)
static void _send_event(const candev_mcp2515_t *dev, candev_event_t event,
void *arg)
{
candev_t *candev = (candev_t *) dev;
candev_t *candev = (candev_t *)dev;
if (candev->event_callback) {
candev->event_callback(candev, event, arg);

View File

@ -1,3 +1,23 @@
/*
* Copyright (C) 2016 OTA keys S.A.
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_mcp2515
* @{
*
* @file
* @brief Parameters for the CAN driver implementation
*
* @author Vincent Dupont <vincent@otakeys.com>
* @author Wouter Symons <wosym@airsantelmo.com>
* @}
*/
#ifndef MCP2515_PARAMS_H
#define MCP2515_PARAMS_H
@ -10,6 +30,10 @@ extern "C" {
#include "board.h"
/**
* @name Set default configuration parameters for the MCP2515
* @{
*/
#ifndef MCP2515_PARAM_SPI
#define MCP2515_PARAM_SPI SPI_DEV(0)
#endif
@ -23,7 +47,7 @@ extern "C" {
#endif
#ifndef MCP2515_PARAM_CS
#define MCP2515_PARAM_CS SPI_HWCS(0)
#define MCP2515_PARAM_CS GPIO_PIN(1, 9)
#endif
#ifndef MCP2515_PARAM_RST
@ -31,11 +55,12 @@ extern "C" {
#endif
#ifndef MCP2515_PARAM_INT
#define MCP2515_PARAM_INT GPIO_PIN(0, 1)
#define MCP2515_PARAM_INT GPIO_PIN(1, 8)
#endif
#ifndef MCP2515_PARAM_CLK
#define MCP2515_PARAM_CLK (8000000ul)
#define MCP2515_PARAM_CLK (8000000ul) /**< External clock frequency */
#endif
#define MCP2515_DEFAULT_CONFIG \
@ -48,14 +73,21 @@ extern "C" {
.int_pin = MCP2515_PARAM_INT, \
.clk = MCP2515_PARAM_CLK, \
}
/**@*/
const static candev_mcp2515_conf_t candev_mcp2515_conf[] = {
/**
* @brief Set default configuration
*/
static const candev_mcp2515_conf_t candev_mcp2515_conf[] = {
MCP2515_DEFAULT_CONFIG
};
const static candev_params_t candev_mcp2515_params[] = {
/**
* @brief set candev parameters
*/
static const candev_params_t candev_mcp2515_params[] = {
{
.name = "can_cmp2515_0",
.name = "can_mcp2515_0",
},
};

View File

@ -14,12 +14,13 @@
* @brief mcp2515 can spi driver
*
* @author Toon Stegen <toon.stegen@altran.com>
* @author Wouter Symons <wosym@airsantelmo.com>
* @}
*/
#include "xtimer.h"
#include <string.h>
#include "xtimer.h"
#include "mcp2515.h"
#include "mcp2515_spi.h"
#include "mcp2515_defines.h"
@ -30,18 +31,21 @@
#include "debug.h"
/* reset delay should be at least 2 microseconds */
#define RESET_DELAY 2
#define RESET_DELAY_US 2
/* size of transmission and reception buffers in mcp2515 */
#define BUFFER_SIZE 13
/* macros for getting the TX and RX control registers */
#define TX_CTRL(mailbox) ((MCP2515_TXB0CTRL) + ((mailbox) << 4))
#define RX_CTRL(mailbox) ((MCP2515_RXB0CTRL) + ((mailbox) << 4))
#define MCP2515_TX_CTRL(mailbox) ((MCP2515_TXB0CTRL) + ((mailbox) << 4))
#define MCP2515_RX_CTRL(mailbox) ((MCP2515_RXB0CTRL) + ((mailbox) << 4))
/* length of the fixed part of a can message: 4 bytes can_id + 1 byte can_dlc */
#define CAN_FIXED_LEN 5
/* oscillator startup time
* 128 cycles @ clock freq + some extra */
static inline uint32_t ost_delay(candev_mcp2515_t *dev)
static inline uint32_t _osc_startup(candev_mcp2515_t *dev)
{
return (128 / (dev->conf->clk / 1000000) + 2);
}
@ -55,7 +59,7 @@ static inline uint32_t ost_delay(candev_mcp2515_t *dev)
* @return 0 on success
* @return <0 on error
*/
static int mcp2515_enable_irq(candev_mcp2515_t *dev, uint8_t irq);
static int _mcp2515_enable_irq(candev_mcp2515_t *dev, uint8_t irq);
/**
* @brief Fill tx/rx standard buffer instruction from filter identifier @p id
@ -73,27 +77,40 @@ static int mcp2515_enable_irq(candev_mcp2515_t *dev, uint8_t irq);
* @param[in] id filter identifier in the MCP2515 mailbox
* @param|out] bytebuf buffer instruction
*/
static void fill_standard_id(uint32_t id, uint8_t *bytebuf);
static void _fill_standard_id(uint32_t id, uint8_t *bytebuf);
/**
* @brief Fill tx/rx extended buffer instruction from filter identifier @p id
*
* for more details see fill_standard_id.
* for more details see _fill_standard_id.
*
* @param[in] id filter identifier in the MCP2515 mailbox
* @param|out] bytebuf buffer instruction
*/
static void fill_extended_id(uint32_t id, uint8_t *bytebuf);
static void _fill_extended_id(uint32_t id, uint8_t *bytebuf);
int mcp2515_init(candev_mcp2515_t *dev, void(*irq_handler_cb)(void*))
int mcp2515_init(candev_mcp2515_t *dev, void (*irq_handler_cb)(void *))
{
int res;
gpio_init_int(dev->conf->int_pin, GPIO_IN_PU, GPIO_FALLING, (gpio_cb_t)irq_handler_cb, (void *)dev);
res = gpio_init_int(dev->conf->int_pin, GPIO_IN_PU, GPIO_FALLING,
(gpio_cb_t)irq_handler_cb, (void *)dev);
if (res != 0) {
DEBUG("Error setting interrupt pin!\n");
return -1;
}
gpio_init(dev->conf->rst_pin, GPIO_OUT);
/*the CS pin should be initialized & set in board.c to avoid conflict with other SPI devices */
res = mcp2515_spi_init(dev);
if (res < 0){
if (res < 0) {
return -1;
}
uint8_t cmd = MCP2515_RXB0CTRL_MODE_RECV_ALL;
res = mcp2515_spi_write(dev, MCP2515_RXB0CTRL, &cmd, 1);
if (res < 0) {
DEBUG("failed to set acceptance mode\n");
return -1;
}
return 0;
@ -102,57 +119,73 @@ int mcp2515_init(candev_mcp2515_t *dev, void(*irq_handler_cb)(void*))
void mcp2515_reset(candev_mcp2515_t *dev)
{
gpio_clear(dev->conf->rst_pin);
xtimer_usleep(RESET_DELAY);
xtimer_usleep(RESET_DELAY_US);
gpio_set(dev->conf->rst_pin);
xtimer_usleep(ost_delay(dev));
xtimer_usleep(_osc_startup(dev));
}
static void fill_standard_id(uint32_t id, uint8_t *bytebuf)
static void _fill_standard_id(uint32_t id, uint8_t *bytebuf)
{
bytebuf[0] = (uint8_t) ((id & 0x000007F8UL) >> 3); /* T/RXBnSIDH */
bytebuf[1] = (uint8_t) ((id & 0x00000007UL) << 5); /* T/RXBnSIDL */
bytebuf[2] = (uint8_t) ((id & 0xFF000000UL) >> 24); /* T/RXBnEID8 */
bytebuf[3] = (uint8_t) ((id & 0x00FF0000UL) >> 16); /* T/RXBnEID0 */
bytebuf[0] = (uint8_t)((id & 0x000007F8UL) >> 3); /* T/RXBnSIDH */
bytebuf[1] = (uint8_t)((id & 0x00000007UL) << 5); /* T/RXBnSIDL */
bytebuf[2] = (uint8_t)((id & 0xFF000000UL) >> 24); /* T/RXBnEID8 */
bytebuf[3] = (uint8_t)((id & 0x00FF0000UL) >> 16); /* T/RXBnEID0 */
}
static void fill_extended_id(uint32_t id, uint8_t *bytebuf)
static void _fill_extended_id(uint32_t id, uint8_t *bytebuf)
{
bytebuf[0] = (uint8_t) ((id & 0x1FE00000UL) >> 21); /* T/RXBnSIDH */
bytebuf[1] = (uint8_t) ((id & 0x001C0000UL) >> 12)
| (uint8_t) ((id & 0x00030000UL) >> 16) | 0x08; /* T/RXBnSIDL */
bytebuf[2] = (uint8_t) ((id & 0x0000FF00UL) >> 8); /* T/RXBnEID8 */
bytebuf[3] = (uint8_t) (id & 0x000000FFUL); /* T/RXBnEID0 */
bytebuf[0] = (uint8_t)((id & 0x1FE00000UL) >> 21); /* T/RXBnSIDH */
bytebuf[1] = (uint8_t)((id & 0x001C0000UL) >> 13)
| (uint8_t)((id & 0x00030000UL) >> 16) | 0x08; /* T/RXBnSIDL */
bytebuf[2] = (uint8_t)((id & 0x0000FF00UL) >> 8); /* T/RXBnEID8 */
bytebuf[3] = (uint8_t)(id & 0x000000FFUL); /* T/RXBnEID0 */
}
int mcp2515_send(candev_mcp2515_t *dev, const struct can_frame *frame, int mailbox)
int mcp2515_send(candev_mcp2515_t *dev, const struct can_frame *frame,
int mailbox)
{
uint8_t prio = 1; /* TODO: adjust priority */
uint8_t prio = 1;
uint8_t outbuf[BUFFER_SIZE];
uint8_t ctrl;
//TODO: for speedup, remove this check
mcp2515_spi_read(dev, TX_CTRL(mailbox), &ctrl, 1);
struct can_frame framebuf;
if (frame->can_dlc > CAN_MAX_DLEN) {
return -1;
}
framebuf.can_id = frame->can_id;
framebuf.can_dlc = frame->can_dlc;
for (int i = 0; i < framebuf.can_dlc; i++) {
framebuf.data[i] = frame->data[i];
}
mcp2515_spi_read(dev, MCP2515_TX_CTRL(mailbox), &ctrl, 1);
if (ctrl & MCP2515_TXBCTRL_TXREQ) {
DEBUG("Mailbox in use, TXB%dCTRL: 0x%02x\n", mailbox, ctrl);
return -1;
}
if ((frame->can_id & CAN_EFF_FLAG) == CAN_EFF_FLAG) {
fill_extended_id(frame->can_id, outbuf);
if (framebuf.can_id > CAN_SFF_MASK) {
framebuf.can_id |= CAN_EFF_FLAG;
}
if ((framebuf.can_id & CAN_EFF_FLAG) == CAN_EFF_FLAG) {
_fill_extended_id(framebuf.can_id, outbuf);
}
else {
fill_standard_id(frame->can_id, outbuf);
_fill_standard_id(framebuf.can_id, outbuf);
}
outbuf[4] = frame->can_dlc;
memcpy(outbuf+5, frame->data, frame->can_dlc);
outbuf[4] = framebuf.can_dlc;
memcpy(&outbuf[CAN_FIXED_LEN], framebuf.data, framebuf.can_dlc);
/* set mailbox priority */
mcp2515_spi_write(dev, TX_CTRL(mailbox), &prio, 1);
mcp2515_spi_write(dev, MCP2515_TX_CTRL(mailbox), &prio, 1);
mcp2515_spi_write_txbuf(dev, mailbox, outbuf, 5 + frame->can_dlc);
mcp2515_enable_irq(dev, MCP2515_CANINTE_TX0IE << mailbox);
//mcp2515_spi_bitmod(dev, TX_CTRL(mailbox), MCP2515_TXBCTRL_TXREQ, MCP2515_TXBCTRL_TXREQ);
mcp2515_spi_write_txbuf(dev, mailbox, outbuf,
CAN_FIXED_LEN + framebuf.can_dlc);
_mcp2515_enable_irq(dev, MCP2515_CANINTE_TX0IE << mailbox);
mcp2515_spi_rts(dev, mailbox);
return mailbox;
@ -166,17 +199,18 @@ int mcp2515_receive(candev_mcp2515_t *dev, struct can_frame *frame, int mailbox)
/* extended id */
if (inbuf[1] & MCP2515_RX_IDE) {
frame->can_id = (inbuf[0] << 21) +
(((uint32_t)inbuf[1] & 0xE0) << 13) +
(((uint32_t)inbuf[1] & 0x03) << 16) +
((uint32_t)inbuf[2] << 8) +
inbuf[3];
frame->can_id = ((uint32_t)inbuf[0] << 21) +
(((uint32_t)inbuf[1] & 0xE0) << 13) +
(((uint32_t)inbuf[1] & 0x03) << 16) +
((uint32_t)inbuf[2] << 8) +
inbuf[3];
frame->can_id |= CAN_EFF_FLAG;
}
/* standard id */
else {
frame->can_id = ((uint32_t)inbuf[0] << 3) + (((uint32_t)inbuf[1] & 0xE0) >> 5);
frame->can_id = ((uint32_t)inbuf[0] << 3) +
(((uint32_t)inbuf[1] & 0xE0) >> 5);
}
frame->can_dlc = inbuf[4];
@ -186,7 +220,7 @@ int mcp2515_receive(candev_mcp2515_t *dev, struct can_frame *frame, int mailbox)
int mcp2515_abort(candev_mcp2515_t *dev, int mailbox)
{
return mcp2515_spi_bitmod(dev, TX_CTRL(mailbox), MCP2515_TXBCTRL_TXREQ, 0);
return mcp2515_spi_bitmod(dev, MCP2515_TX_CTRL(mailbox), MCP2515_TXBCTRL_TXREQ, 0);
}
enum mcp2515_mode mcp2515_get_mode(candev_mcp2515_t *dev)
@ -195,9 +229,9 @@ enum mcp2515_mode mcp2515_get_mode(candev_mcp2515_t *dev)
uint8_t mode;
int res = mcp2515_spi_read(dev, MCP2515_CANSTAT, &mode, 1);
if (res == 0) {
//TODO: error handling of extra information in mode result
result = (enum mcp2515_mode) mode & MCP2515_CANSTAT_OPMOD_MASK;
result = (enum mcp2515_mode)mode & MCP2515_CANSTAT_OPMOD_MASK;
}
DEBUG("mcp2515_get_mode: mode=%x\n", result);
@ -205,7 +239,8 @@ enum mcp2515_mode mcp2515_get_mode(candev_mcp2515_t *dev)
return result;
}
enum mcp2515_mode mcp2515_set_mode(candev_mcp2515_t *dev, enum mcp2515_mode mode)
enum mcp2515_mode mcp2515_set_mode(candev_mcp2515_t *dev,
enum mcp2515_mode mode)
{
DEBUG("mcp2515_set_mode: mode=%x\n", mode);
@ -214,6 +249,7 @@ enum mcp2515_mode mcp2515_set_mode(candev_mcp2515_t *dev, enum mcp2515_mode mode
}
enum mcp2515_mode cur_mode = mcp2515_get_mode(dev);
if (cur_mode == mode) {
return mode;
}
@ -221,8 +257,11 @@ enum mcp2515_mode mcp2515_set_mode(candev_mcp2515_t *dev, enum mcp2515_mode mode
mcp2515_wake_up(dev);
}
mcp2515_spi_bitmod(dev, MCP2515_CANCTRL, MCP2515_CANCTRL_REQOP_MASK, (uint8_t) mode);
mcp2515_spi_bitmod(dev, MCP2515_CANCTRL, MCP2515_CANCTRL_REQOP_MASK,
(uint8_t)mode);
int cnt = 0;
/* allow for two retries to set the mode */
while (cur_mode != mode && cnt++ < 2) {
cur_mode = mcp2515_get_mode(dev);
}
@ -232,10 +271,12 @@ enum mcp2515_mode mcp2515_set_mode(candev_mcp2515_t *dev, enum mcp2515_mode mode
void mcp2515_wake_up(candev_mcp2515_t *dev)
{
dev->wakeup_src = MCP2515_WKUP_SRC_INTERNAL;
mcp2515_spi_bitmod(dev, MCP2515_CANINTF, MCP2515_CANINTF_WAKIF, MCP2515_CANINTF_WAKIF);
xtimer_usleep(ost_delay(dev));
mcp2515_spi_bitmod(dev, MCP2515_CANINTF, MCP2515_CANINTF_WAKIF,
MCP2515_CANINTF_WAKIF);
xtimer_usleep(_osc_startup(dev));
uint8_t flag = mcp2515_get_irq(dev);
if (flag & INT_WAKEUP) {
DEBUG("wakeup, irq raised\n");
dev->wakeup_src = 0;
@ -243,7 +284,7 @@ void mcp2515_wake_up(candev_mcp2515_t *dev)
}
}
static int mcp2515_enable_irq(candev_mcp2515_t *dev, uint8_t irq)
static int _mcp2515_enable_irq(candev_mcp2515_t *dev, uint8_t irq)
{
return mcp2515_spi_bitmod(dev, MCP2515_CANINTE, irq, irq);
}
@ -256,7 +297,8 @@ int mcp2515_configure_bittiming(candev_mcp2515_t *dev)
enum mcp2515_mode mode;
DEBUG("mcp2515_configure_bittiming: brp=%" PRIu32 ", prop_seg=%" PRIu32
", phase_seg1=%" PRIu32 ", phase_seg2=%" PRIu32 "\n", tim->brp, tim->prop_seg,
", phase_seg1=%" PRIu32 ", phase_seg2=%" PRIu32 "\n", tim->brp,
tim->prop_seg,
tim->phase_seg1, tim->phase_seg2);
mode = mcp2515_get_mode(dev);
@ -266,14 +308,17 @@ int mcp2515_configure_bittiming(candev_mcp2515_t *dev)
}
}
/* set Synchronization Jump Width Length */
c = ((tim->brp - 1) & 0x3F) | ((tim->sjw - 1) << 6);
mcp2515_spi_write(dev, MCP2515_CNF1, &c, 1);
mcp2515_spi_bitmod(dev, MCP2515_CNF2, MCP2515_CNF2_PRSEG_MASK |
MCP2515_CNF2_PHSEG_MASK | MCP2515_CNF2_BTLMODE,
MCP2515_CNF2_BTLMODE | (tim->prop_seg - 1) | ((tim->phase_seg1 - 1) << 3));
mcp2515_spi_bitmod(dev, MCP2515_CNF3, MCP2515_CNF3_PHSEG_MASK | MCP2515_CNF3_WAKFIL,
MCP2515_CNF2_BTLMODE | (tim->prop_seg - 1) |
((tim->phase_seg1 - 1) << 3));
mcp2515_spi_bitmod(dev, MCP2515_CNF3,
MCP2515_CNF3_PHSEG_MASK | MCP2515_CNF3_WAKFIL,
(tim->phase_seg2 - 1) | MCP2515_CNF3_WAKFIL);
if (mode != MODE_CONFIG) {
@ -285,27 +330,24 @@ int mcp2515_configure_bittiming(candev_mcp2515_t *dev)
int mcp2515_init_irqs(candev_mcp2515_t *dev)
{
return mcp2515_enable_irq(dev,
MCP2515_CANINTE_RX0IE |
MCP2515_CANINTE_RX1IE |
//MCP2515_CANINTE_TX0IE |
//MCP2515_CANINTE_TX1IE |
//MCP2515_CANINTE_TX2IE |
MCP2515_CANINTE_ERRIE |
//MCP2515_CANINTE_MERRE |
MCP2515_CANINTE_WAKIE);
return _mcp2515_enable_irq(dev,
MCP2515_CANINTE_RX0IE |
MCP2515_CANINTE_RX1IE |
MCP2515_CANINTE_ERRIE |
MCP2515_CANINTE_WAKIE);
}
enum mcp2515_interrupt mcp2515_get_irq(candev_mcp2515_t *dev)
{
uint8_t flag;
mcp2515_spi_read(dev, MCP2515_CANINTF, &flag, 1);
return (enum mcp2515_interrupt) flag;
return (enum mcp2515_interrupt)flag;
}
int mcp2515_clear_irq(candev_mcp2515_t *dev, enum mcp2515_interrupt irq)
{
if(!irq) { /* no irq's to be cleared */
if (!irq) { /* no irq's to be cleared */
return 0;
}
else {
@ -316,7 +358,8 @@ int mcp2515_clear_irq(candev_mcp2515_t *dev, enum mcp2515_interrupt irq)
int mcp2515_tx_err_occurred(candev_mcp2515_t *dev, int mailbox)
{
uint8_t ctrl_reg;
mcp2515_spi_read(dev, TX_CTRL(mailbox), &ctrl_reg, 1);
mcp2515_spi_read(dev, MCP2515_TX_CTRL(mailbox), &ctrl_reg, 1);
if (ctrl_reg & MCP2515_TXBCTRL_TXERR) {
return 1;
}
@ -328,6 +371,7 @@ int mcp2515_tx_err_occurred(candev_mcp2515_t *dev, int mailbox)
uint8_t mcp2515_get_errors(candev_mcp2515_t *dev)
{
uint8_t eflg;
mcp2515_spi_read(dev, MCP2515_EFLG, &eflg, 1);
return eflg;
}
@ -336,29 +380,31 @@ int mcp2515_set_filter(candev_mcp2515_t *dev, int filter_id, uint32_t filter)
{
uint8_t buf[4];
uint8_t reg;
if ((filter & CAN_EFF_FLAG) == CAN_EFF_FLAG) {
fill_extended_id(filter, buf);
_fill_extended_id(filter, buf);
}
else {
fill_standard_id(filter, buf);
_fill_standard_id(filter, buf);
}
if(filter_id < 3) {
if (filter_id < 3) {
reg = MCP2515_RXF0SIDH + (filter_id << 2);
}
else {
reg = MCP2515_RXF3SIDH + ((filter_id - 3) << 2);
}
return mcp2515_spi_write(dev, reg, buf, 4);
return mcp2515_spi_write(dev, reg, buf, sizeof(buf));
}
int mcp2515_set_mask(candev_mcp2515_t *dev, int mailbox, uint32_t mask)
{
uint8_t buf[4];
if ((mask & CAN_EFF_FLAG) == CAN_EFF_FLAG) {
fill_extended_id(mask, buf);
_fill_extended_id(mask, buf);
}
else {
fill_standard_id(mask, buf);
_fill_standard_id(mask, buf);
}
return mcp2515_spi_write(dev, MCP2515_RXM0SIDH + (mailbox << 2), buf, 4);
}

View File

@ -32,40 +32,40 @@ extern "C" {
* @brief MCP2515 mode
*/
enum mcp2515_mode {
MODE_NORMAL = MCP2515_CANSTAT_OPMOD_NORMAL,
MODE_SLEEP = MCP2515_CANSTAT_OPMOD_SLEEP,
MODE_LOOPBACK = MCP2515_CANSTAT_OPMOD_LOOPBACK,
MODE_LISTEN_ONLY = MCP2515_CANSTAT_OPMOD_LISTEN_ONLY,
MODE_CONFIG = MCP2515_CANSTAT_OPMOD_CONFIGURATION,
MODE_UNKNOWN = -1
MODE_NORMAL = MCP2515_CANSTAT_OPMOD_NORMAL,
MODE_SLEEP = MCP2515_CANSTAT_OPMOD_SLEEP,
MODE_LOOPBACK = MCP2515_CANSTAT_OPMOD_LOOPBACK,
MODE_LISTEN_ONLY = MCP2515_CANSTAT_OPMOD_LISTEN_ONLY,
MODE_CONFIG = MCP2515_CANSTAT_OPMOD_CONFIGURATION,
MODE_UNKNOWN = -1
};
/**
* @brief MCP2515 interrupt
*/
enum mcp2515_interrupt {
INT_RX0 = MCP2515_CANINTF_RX0IF,
INT_RX1 = MCP2515_CANINTF_RX1IF,
INT_TX0 = MCP2515_CANINTF_TX0IF,
INT_TX1 = MCP2515_CANINTF_TX1IF,
INT_TX2 = MCP2515_CANINTF_TX2IF,
INT_ERROR = MCP2515_CANINTF_ERRIF,
INT_WAKEUP = MCP2515_CANINTF_WAKIF,
INT_MESSAGE_ERROR = MCP2515_CANINTF_MERRF,
INT_RX0 = MCP2515_CANINTF_RX0IF,
INT_RX1 = MCP2515_CANINTF_RX1IF,
INT_TX0 = MCP2515_CANINTF_TX0IF,
INT_TX1 = MCP2515_CANINTF_TX1IF,
INT_TX2 = MCP2515_CANINTF_TX2IF,
INT_ERROR = MCP2515_CANINTF_ERRIF,
INT_WAKEUP = MCP2515_CANINTF_WAKIF,
INT_MESSAGE_ERROR = MCP2515_CANINTF_MERRF,
};
/**
* @brief MCP2515 error
*/
enum mcp2515_error {
ERR_WARNING = MCP2515_EFLG_EWARN,
ERR_RX_WARNING = MCP2515_EFLG_RXWAR,
ERR_TX_WARNING = MCP2515_EFLG_TXWAR,
ERR_RX_PASSIVE = MCP2515_EFLG_RXEP,
ERR_TX_PASSIVE = MCP2515_EFLG_TXEP,
ERR_TX_BUS_OFF = MCP2515_EFLG_TXBO,
ERR_RX_0_OVERFLOW = MCP2515_EFLG_RX0OVR,
ERR_RX_1_OVERFLOW = MCP2515_EFLG_RX1OVR,
ERR_WARNING = MCP2515_EFLG_EWARN,
ERR_RX_WARNING = MCP2515_EFLG_RXWAR,
ERR_TX_WARNING = MCP2515_EFLG_TXWAR,
ERR_RX_PASSIVE = MCP2515_EFLG_RXEP,
ERR_TX_PASSIVE = MCP2515_EFLG_TXEP,
ERR_TX_BUS_OFF = MCP2515_EFLG_TXBO,
ERR_RX_0_OVERFLOW = MCP2515_EFLG_RX0OVR,
ERR_RX_1_OVERFLOW = MCP2515_EFLG_RX1OVR,
};
/** Wake up source */
@ -74,7 +74,7 @@ enum mcp2515_error {
/**
* @brief Initialize pins and SPI interface
*
* The device descriptor contains all informations related to pins and SPI
* The device descriptor contains all information related to pins and SPI
* interface. This function initialize all corresponding fields and relies
* the @p irq_cb callback function to the pin interruption. The pin
* interruption should be configured in the device descriptor.
@ -87,7 +87,7 @@ enum mcp2515_error {
* @return 0 on success
* @return <0 on error
*/
int mcp2515_init(candev_mcp2515_t *dev, void(*irq_cb)(void*));
int mcp2515_init(candev_mcp2515_t *dev, void (*irq_cb)(void *));
/**
* @brief Reset MCP2515 device with dedicated pin
@ -118,7 +118,8 @@ int mcp2515_init_irqs(candev_mcp2515_t *dev);
* @return 0 on success
* @return <0 on error
*/
int mcp2515_send(candev_mcp2515_t *dev, const struct can_frame *frame, int mailbox);
int mcp2515_send(candev_mcp2515_t *dev, const struct can_frame *frame,
int mailbox);
/**
* @brief Receive frame from the corresponding rx @p mailbox.
@ -130,7 +131,8 @@ int mcp2515_send(candev_mcp2515_t *dev, const struct can_frame *frame, int mailb
* @return 0 on success
* @return <0 on error
*/
int mcp2515_receive(candev_mcp2515_t *dev, struct can_frame *frame, int mailbox);
int mcp2515_receive(candev_mcp2515_t *dev, struct can_frame *frame,
int mailbox);
/**
* @brief Abort communication.
@ -160,7 +162,8 @@ enum mcp2515_mode mcp2515_get_mode(candev_mcp2515_t *dev);
*
* @return The mode actually set
*/
enum mcp2515_mode mcp2515_set_mode(candev_mcp2515_t *dev, enum mcp2515_mode mode);
enum mcp2515_mode mcp2515_set_mode(candev_mcp2515_t *dev,
enum mcp2515_mode mode);
/**
* @brief Wake up MCP2515
@ -203,7 +206,7 @@ int mcp2515_tx_err_occurred(candev_mcp2515_t *dev, int mailbox);
/**
* @brief Configure the bit timing of the MCP2515.
*
* The informations about the bit timing should be contained in dev descriptor.
* The information about the bit timing should be contained in dev descriptor.
*
* @param[in] dev device descriptor
*

View File

@ -28,28 +28,6 @@
extern "C" {
#endif
/**
* User configuration
* @{
*/
#define CAN_SPI_CS_PORTBIT BIT4
#define CAN_SPI_CS_PORTOUT P2OUT
#define CAN_SPI_CS_PORTDIR P2DIR
#define CAN_IRQ_PORTBIT BIT3
#define CAN_IRQ_PORTOUT P1OUT
#define CAN_IRQ_PORTDIR P1DIR
#define CAN_IRQ_PORTREN P1REN
#define CAN_IRQ_PORTIES P1IES
#define CAN_IRQ_PORTIE P1IE
#define CAN_IRQ_PORTIFG P1IFG
/** @} */
/**
* BoosterPack contains 8MHz crystal w/ 22pF load caps
*/
#define CAN_OSC_FREQUENCY 8000000
/**
* @name MCP2515 Register Memory Map
* {
@ -214,12 +192,13 @@ extern "C" {
#define MCP2515_CANSTAT_ICOD_MASK 0x0E
#define MCP2515_CANSTAT_OPMOD_MASK 0xE0
#define MCP2515_CANSTAT_OPMOD_MASK 0xE0
#define MCP2515_CANSTAT_OPMOD_CONFIGURATION MCP2515_CANSTAT_OPMOD2
#define MCP2515_CANSTAT_OPMOD_NORMAL 0x00
#define MCP2515_CANSTAT_OPMOD_SLEEP MCP2515_CANSTAT_OPMOD0
#define MCP2515_CANSTAT_OPMOD_LOOPBACK MCP2515_CANSTAT_OPMOD1
#define MCP2515_CANSTAT_OPMOD_LISTEN_ONLY (MCP2515_CANSTAT_OPMOD1 | MCP2515_CANSTAT_OPMOD0)
#define MCP2515_CANSTAT_OPMOD_NORMAL 0x00
#define MCP2515_CANSTAT_OPMOD_SLEEP MCP2515_CANSTAT_OPMOD0
#define MCP2515_CANSTAT_OPMOD_LOOPBACK MCP2515_CANSTAT_OPMOD1
#define MCP2515_CANSTAT_OPMOD_LISTEN_ONLY (MCP2515_CANSTAT_OPMOD1 | \
MCP2515_CANSTAT_OPMOD0)
#define MCP2515_CANCTRL_CLKPRE0 0x01
#define MCP2515_CANCTRL_CLKPRE1 0x02
@ -230,14 +209,16 @@ extern "C" {
#define MCP2515_CANCTRL_REQOP1 0x40
#define MCP2515_CANCTRL_REQOP2 0x80
#define MCP2515_CANCTRL_CLKPRE_MASK (MCP2515_CANCTRL_CLKPRE1 | MCP2515_CANCTRL_CLKPRE0)
#define MCP2515_CANCTRL_CLKPRE_MASK (MCP2515_CANCTRL_CLKPRE1 | \
MCP2515_CANCTRL_CLKPRE0)
#define MCP2515_CANCTRL_REQOP_MASK 0xE0
#define MCP2515_CANCTRL_REQOP_MASK 0xE0
#define MCP2515_CANCTRL_REQOP_CONFIGURATION MCP2515_CANCTRL_REQOP2
#define MCP2515_CANCTRL_REQOP_NORMAL 0x00
#define MCP2515_CANCTRL_REQOP_SLEEP MCP2515_CANCTRL_REQOP0
#define MCP2515_CANCTRL_REQOP_LOOPBACK MCP2515_CANCTRL_REQOP1
#define MCP2515_CANCTRL_REQOP_LISTEN_ONLY (MCP2515_CANCTRL_REQOP1 | MCP2515_CANCTRL_REQOP0)
#define MCP2515_CANCTRL_REQOP_NORMAL 0x00
#define MCP2515_CANCTRL_REQOP_SLEEP MCP2515_CANCTRL_REQOP0
#define MCP2515_CANCTRL_REQOP_LOOPBACK MCP2515_CANCTRL_REQOP1
#define MCP2515_CANCTRL_REQOP_LISTEN_ONLY (MCP2515_CANCTRL_REQOP1 | \
MCP2515_CANCTRL_REQOP0)
#define MCP2515_CNF3_PHSEG20 0x01
#define MCP2515_CNF3_PHSEG21 0x02
@ -315,27 +296,29 @@ extern "C" {
#define MCP2515_TXBCTRL_MLOA 0x20
#define MCP2515_TXBCTRL_ABTF 0x40
#define MCP2515_RXB0CTRL_FILHIT0 0x01
#define MCP2515_RXB0CTRL_BUKT1 0x02
#define MCP2515_RXB0CTRL_BUKT 0x04
#define MCP2515_RXB0CTRL_RXRTR 0x08
#define MCP2515_RXB0CTRL_RXM0 0x20
#define MCP2515_RXB0CTRL_RXM1 0x40
#define MCP2515_RXB0CTRL_MODE_RECV_STD_OR_EXT 0x00
#define MCP2515_RXB0CTRL_MODE_RECV_STD MCP2515_RXB0CTRL_RXM0
#define MCP2515_RXB0CTRL_MODE_RECV_EXT MCP2515_RXB0CTRL_RXM1
#define MCP2515_RXB0CTRL_MODE_RECV_ALL (MCP2515_RXB0CTRL_RXM1 | MCP2515_RXB0CTRL_RXM0)
#define MCP2515_RXB0CTRL_FILHIT0 0x01
#define MCP2515_RXB0CTRL_BUKT1 0x02
#define MCP2515_RXB0CTRL_BUKT 0x04
#define MCP2515_RXB0CTRL_RXRTR 0x08
#define MCP2515_RXB0CTRL_RXM0 0x20
#define MCP2515_RXB0CTRL_RXM1 0x40
#define MCP2515_RXB0CTRL_MODE_RECV_STD_OR_EXT 0x00
#define MCP2515_RXB0CTRL_MODE_RECV_STD MCP2515_RXB0CTRL_RXM0
#define MCP2515_RXB0CTRL_MODE_RECV_EXT MCP2515_RXB0CTRL_RXM1
#define MCP2515_RXB0CTRL_MODE_RECV_ALL (MCP2515_RXB0CTRL_RXM1 | \
MCP2515_RXB0CTRL_RXM0)
#define MCP2515_RXB1CTRL_FILHIT0 0x01
#define MCP2515_RXB1CTRL_FILHIT1 0x02
#define MCP2515_RXB1CTRL_FILHIT2 0x04
#define MCP2515_RXB1CTRL_RXRTR 0x08
#define MCP2515_RXB1CTRL_RXM0 0x20
#define MCP2515_RXB1CTRL_RXM1 0x40
#define MCP2515_RXB1CTRL_MODE_RECV_STD_OR_EXT 0x00
#define MCP2515_RXB1CTRL_MODE_RECV_STD MCP2515_RXB1CTRL_RXM0
#define MCP2515_RXB1CTRL_MODE_RECV_EXT MCP2515_RXB1CTRL_RXM1
#define MCP2515_RXB1CTRL_MODE_RECV_ALL (MCP2515_RXB1CTRL_RXM1 | MCP2515_RXB1CTRL_RXM0)
#define MCP2515_RXB1CTRL_FILHIT0 0x01
#define MCP2515_RXB1CTRL_FILHIT1 0x02
#define MCP2515_RXB1CTRL_FILHIT2 0x04
#define MCP2515_RXB1CTRL_RXRTR 0x08
#define MCP2515_RXB1CTRL_RXM0 0x20
#define MCP2515_RXB1CTRL_RXM1 0x40
#define MCP2515_RXB1CTRL_MODE_RECV_STD_OR_EXT 0x00
#define MCP2515_RXB1CTRL_MODE_RECV_STD MCP2515_RXB1CTRL_RXM0
#define MCP2515_RXB1CTRL_MODE_RECV_EXT MCP2515_RXB1CTRL_RXM1
#define MCP2515_RXB1CTRL_MODE_RECV_ALL (MCP2515_RXB1CTRL_RXM1 | \
MCP2515_RXB1CTRL_RXM0)
/** @} */
/**
@ -357,51 +340,51 @@ extern "C" {
* @name MCP2515 RX buffer id
* {
*/
#define MCP2515_RXBUF_RXB0SIDH 0x00
#define MCP2515_RXBUF_RXB0D0 0x02
#define MCP2515_RXBUF_RXB1SIDH 0x04
#define MCP2515_RXBUF_RXB1D0 0x06
#define MCP2515_RXBUF_RXB0SIDH 0x00
#define MCP2515_RXBUF_RXB0D0 0x02
#define MCP2515_RXBUF_RXB1SIDH 0x04
#define MCP2515_RXBUF_RXB1D0 0x06
/** @} */
/**
* @name MCP2515 TX buffer id
* {
*/
#define MCP2515_TXBUF_TXB0SIDH 0x00
#define MCP2515_TXBUF_TXB0D0 0x01
#define MCP2515_TXBUF_TXB1SIDH 0x02
#define MCP2515_TXBUF_TXB1D0 0x03
#define MCP2515_TXBUF_TXB2SIDH 0x04
#define MCP2515_TXBUF_TXB2D0 0x05
#define MCP2515_TXBUF_TXB0SIDH 0x00
#define MCP2515_TXBUF_TXB0D0 0x01
#define MCP2515_TXBUF_TXB1SIDH 0x02
#define MCP2515_TXBUF_TXB1D0 0x03
#define MCP2515_TXBUF_TXB2SIDH 0x04
#define MCP2515_TXBUF_TXB2D0 0x05
/** @} */
/**
* @name MCP2515 option ID for ioctl function
* {
*/
#define MCP2515_OPTION_ROLLOVER 1
#define MCP2515_OPTION_ONESHOT 2
#define MCP2515_OPTION_ABORT 3
#define MCP2515_OPTION_CLOCKOUT 4
#define MCP2515_OPTION_LOOPBACK 5
#define MCP2515_OPTION_LISTEN_ONLY 6
#define MCP2515_OPTION_SLEEP 7
#define MCP2515_OPTION_MULTISAMPLE 8
#define MCP2515_OPTION_SOFOUT 9
#define MCP2515_OPTION_WAKE_GLITCH_FILTER 10
#define MCP2515_OPTION_WAKE 11
#define MCP2515_OPTION_ROLLOVER 1
#define MCP2515_OPTION_ONESHOT 2
#define MCP2515_OPTION_ABORT 3
#define MCP2515_OPTION_CLOCKOUT 4
#define MCP2515_OPTION_LOOPBACK 5
#define MCP2515_OPTION_LISTEN_ONLY 6
#define MCP2515_OPTION_SLEEP 7
#define MCP2515_OPTION_MULTISAMPLE 8
#define MCP2515_OPTION_SOFOUT 9
#define MCP2515_OPTION_WAKE_GLITCH_FILTER 10
#define MCP2515_OPTION_WAKE 11
/** @} */
/**
* @name MCP2515 IRQ handling
* {
*/
#define MCP2515_IRQ_FLAGGED 0x80
#define MCP2515_IRQ_HANDLED 0x40
#define MCP2515_IRQ_RX 0x01
#define MCP2515_IRQ_TX 0x02
#define MCP2515_IRQ_ERROR 0x04
#define MCP2515_IRQ_WAKEUP 0x08
#define MCP2515_IRQ_FLAGGED 0x80
#define MCP2515_IRQ_HANDLED 0x40
#define MCP2515_IRQ_RX 0x01
#define MCP2515_IRQ_TX 0x02
#define MCP2515_IRQ_ERROR 0x04
#define MCP2515_IRQ_WAKEUP 0x08
/** @} */
/**

View File

@ -1,4 +1,3 @@
/*
* Copyright (C) 2016 OTA keys
*
@ -35,11 +34,12 @@
int mcp2515_spi_init(const candev_mcp2515_t *dev)
{
int res;
/* Configure SPI */
res = spi_init_cs(dev->conf->spi, dev->conf->cs_pin);
if (res != SPI_OK) {
DEBUG("spi_init_master: error initializing SPI_%i device (code %i)\n",
dev->conf->spi, res);
dev->conf->spi, res);
return -1;
}
return 0;
@ -47,8 +47,10 @@ int mcp2515_spi_init(const candev_mcp2515_t *dev)
int mcp2515_spi_reset(const candev_mcp2515_t *dev)
{
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode, dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, false, MCP2515_SPI_RESET);
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode,
dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, false,
MCP2515_SPI_RESET);
spi_release(dev->conf->spi);
return 0;
}
@ -56,9 +58,12 @@ int mcp2515_spi_reset(const candev_mcp2515_t *dev)
int mcp2515_spi_read(const candev_mcp2515_t *dev, uint8_t addr, uint8_t *buf,
unsigned int len)
{
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode, dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true, MCP2515_SPI_READ);
spi_transfer_regs(dev->conf->spi, dev->conf->cs_pin, addr, NULL, (void *)buf, len);
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode,
dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true,
MCP2515_SPI_READ);
spi_transfer_regs(dev->conf->spi, dev->conf->cs_pin, addr, NULL,
(void *)buf, len);
spi_release(dev->conf->spi);
return 0;
}
@ -66,9 +71,13 @@ int mcp2515_spi_read(const candev_mcp2515_t *dev, uint8_t addr, uint8_t *buf,
int mcp2515_spi_read_rxbuf(const candev_mcp2515_t *dev, uint8_t mailbox,
void *buf, uint8_t len)
{
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode, dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true, MCP2515_SPI_READ_RXBUF | (mailbox << 2));
spi_transfer_bytes(dev->conf->spi, dev->conf->cs_pin, false, NULL, (void *)buf, len);
/* See TABLE 12-1:SPI INSTRUCTION SET in mcp2515 datasheet */
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode,
dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true,
MCP2515_SPI_READ_RXBUF | (mailbox << 2));
spi_transfer_bytes(dev->conf->spi, dev->conf->cs_pin, false, NULL,
(void *)buf, len);
spi_release(dev->conf->spi);
return 0;
}
@ -76,9 +85,12 @@ int mcp2515_spi_read_rxbuf(const candev_mcp2515_t *dev, uint8_t mailbox,
int mcp2515_spi_write(const candev_mcp2515_t *dev, uint8_t addr, uint8_t *buf,
unsigned int len)
{
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode, dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true, MCP2515_SPI_WRITE);
spi_transfer_regs(dev->conf->spi, dev->conf->cs_pin, addr, (void *)buf, NULL, len);
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode,
dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true,
MCP2515_SPI_WRITE);
spi_transfer_regs(dev->conf->spi, dev->conf->cs_pin, addr, (void *)buf,
NULL, len);
spi_release(dev->conf->spi);
return 0;
}
@ -86,17 +98,22 @@ int mcp2515_spi_write(const candev_mcp2515_t *dev, uint8_t addr, uint8_t *buf,
int mcp2515_spi_write_txbuf(const candev_mcp2515_t *dev, uint8_t mailbox,
void *buf, uint8_t len)
{
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode, dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true, MCP2515_SPI_LOAD_TXBUF | (mailbox << 1));
spi_transfer_bytes(dev->conf->spi, dev->conf->cs_pin, false, (void *)buf, NULL, len);
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode,
dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true,
MCP2515_SPI_LOAD_TXBUF | (mailbox << 1));
spi_transfer_bytes(dev->conf->spi, dev->conf->cs_pin, false, (void *)buf,
NULL, len);
spi_release(dev->conf->spi);
return 0;
}
int mcp2515_spi_rts(const candev_mcp2515_t *dev, uint8_t mailbox)
{
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode, dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, false, MCP2515_SPI_RTS | (1 << mailbox));
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode,
dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, false,
MCP2515_SPI_RTS | (1 << mailbox));
spi_release(dev->conf->spi);
return 0;
}
@ -104,8 +121,11 @@ int mcp2515_spi_rts(const candev_mcp2515_t *dev, uint8_t mailbox)
uint8_t mcp2515_spi_read_status(const candev_mcp2515_t *dev)
{
uint8_t status;
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode, dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true, MCP2515_SPI_READ_STATUS);
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode,
dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true,
MCP2515_SPI_READ_STATUS);
status = spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, false, 0);
spi_release(dev->conf->spi);
return status;
@ -114,8 +134,11 @@ uint8_t mcp2515_spi_read_status(const candev_mcp2515_t *dev)
int mcp2515_spi_rx_status(const candev_mcp2515_t *dev)
{
uint8_t status;
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode, dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true, MCP2515_SPI_RX_STATUS);
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode,
dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true,
MCP2515_SPI_RX_STATUS);
status = spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, false, 0);
spi_release(dev->conf->spi);
return status;
@ -126,13 +149,16 @@ int mcp2515_spi_bitmod(const candev_mcp2515_t *dev, uint8_t addr, uint8_t mask,
{
uint8_t msg[2];
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode, dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true, MCP2515_SPI_BITMOD);
spi_acquire(dev->conf->spi, dev->conf->cs_pin, dev->conf->spi_mode,
dev->conf->spi_clk);
spi_transfer_byte(dev->conf->spi, dev->conf->cs_pin, true,
MCP2515_SPI_BITMOD);
msg[0] = mask;
msg[1] = buf;
spi_transfer_regs(dev->conf->spi, dev->conf->cs_pin, addr, (const void*)msg, NULL, sizeof(msg));
spi_transfer_regs(dev->conf->spi, dev->conf->cs_pin, addr,
(const void *)msg, NULL, sizeof(msg));
spi_release(dev->conf->spi);
return 0;
}

View File

@ -31,7 +31,7 @@ extern "C" {
/**
* @brief Initialize SPI interface
*
* The device descriptor contains all informations related to the SPI interface.
* The device descriptor contains all information related to the SPI interface.
*
* @param[out] dev device descriptor
*
@ -127,8 +127,7 @@ int mcp2515_spi_rts(const candev_mcp2515_t *dev, uint8_t mailbox);
*
* @param[in] dev device descriptor
*
* @return 0 on success
* @return <0 on error
* @return the read status
*/
uint8_t mcp2515_spi_read_status(const candev_mcp2515_t *dev);
@ -153,7 +152,7 @@ int mcp2515_spi_rx_status(const candev_mcp2515_t *dev);
* @param[in] dev device descriptor
* @param[in] addr register address
* @param[in] mask mask to modify individual bit
* @param[in] buf regsiter value
* @param[in] buf register value
*
* @return 0 on success
* @return <0 on error

View File

@ -7,7 +7,7 @@
*/
/**
* @ingroup auto_init
* @ingroup sys_auto_init
* @{
* @file
* @brief initializes mcp2515 can device
@ -20,7 +20,7 @@
#include "can/device.h"
#include "mcp2515_params.h"
#define CANDEV_MCP2515_NUMOF ((sizeof(candev_mcp2515_params) / sizeof(candev_params_t)))
#define CANDEV_MCP2515_NUMOF ((ARRAY_SIZE(candev_mcp2515_params) / ARRAY_SIZE(candev_params_t)))
#ifndef CANDEV_MCP2515_STACKSIZE
#define CANDEV_MCP2515_STACKSIZE (THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE_PRINTF)
@ -40,7 +40,7 @@ void auto_init_can_mcp2515(void) {
candev_mcp2515_init(&candev_mcp2515[i], &candev_mcp2515_conf[i]);
candev_dev_mcp2515[i].dev = (candev_t *)&candev_mcp2515[i];
candev_dev_mcp2515[i].name = candev_mcp2515_params[i].name;
#ifdef MODULE_TRX
#ifdef MODULE_CAN_TRX
candev_dev_mcp2515[i].trx = candev_mcp2515_params[i].trx;
#endif
#ifdef MODULE_CAN_PM
@ -48,8 +48,11 @@ void auto_init_can_mcp2515(void) {
candev_dev_mcp2515[i].tx_wakeup_timeout = candev_mcp2515_params[i].tx_wakeup_timeout;
#endif
can_device_init(_can_mcp2515_stacks[i], CANDEV_MCP2515_STACKSIZE, CANDEV_MCP2515_BASE_PRIORITY + i,
candev_mcp2515_params[i].name, &candev_dev_mcp2515[i]);
can_device_init(_can_mcp2515_stacks[i],
CANDEV_MCP2515_STACKSIZE,
CANDEV_MCP2515_BASE_PRIORITY + i,
candev_mcp2515_params[i].name,
&candev_dev_mcp2515[i]);
}
}
#else