Skip to content

Commit

Permalink
Merge pull request RIOT-OS#4 from cogip/fdcan
Browse files Browse the repository at this point in the history
Add CAN FD support to STM32G4 and native architecture
  • Loading branch information
gdoffe authored Jan 29, 2024
2 parents ee9c4ad + c910106 commit a0832e5
Show file tree
Hide file tree
Showing 37 changed files with 2,248 additions and 147 deletions.
1 change: 1 addition & 0 deletions boards/nucleo-g431rb/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ CPU = stm32
CPU_MODEL = stm32g431rb

# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_can
FEATURES_PROVIDED += periph_i2c
FEATURES_PROVIDED += periph_pwm
FEATURES_PROVIDED += periph_rtc
Expand Down
4 changes: 2 additions & 2 deletions cpu/esp32/include/can_esp.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ typedef struct can {
candev_t candev; /**< candev base structure */
canopt_state_t state; /**< current state of device */

struct can_frame *tx_frame; /**< frame in transmission */
struct can_frame rx_frames[ESP_CAN_MAX_RX_FRAMES]; /**< frames received */
can_frame_t *tx_frame; /**< frame in transmission */
can_frame_t rx_frames[ESP_CAN_MAX_RX_FRAMES]; /**< frames received */
struct can_filter rx_filters[ESP_CAN_MAX_RX_FILTERS]; /**< acceptance filter list */

uint32_t rx_frames_wptr; /**< pointer to ring buffer for write */
Expand Down
16 changes: 8 additions & 8 deletions cpu/esp32/periph/can.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@

/* driver interface functions */
static int _esp_can_init(candev_t *candev);
static int _esp_can_send(candev_t *candev, const struct can_frame *frame);
static int _esp_can_send(candev_t *candev, const can_frame_t *frame);
static void _esp_can_isr(candev_t *candev);
static int _esp_can_set(candev_t *candev, canopt_t opt, void *value, size_t value_len);
static int _esp_can_get(candev_t *candev, canopt_t opt, void *value, size_t max_len);
static int _esp_can_abort(candev_t *candev, const struct can_frame *frame);
static int _esp_can_abort(candev_t *candev, const can_frame_t *frame);
static int _esp_can_set_filter(candev_t *candev, const struct can_filter *filter);
static int _esp_can_remove_filter(candev_t *candev, const struct can_filter *filter);

Expand Down Expand Up @@ -217,7 +217,7 @@ static int _esp_can_init(candev_t *candev)
return 0;
}

static int _esp_can_send(candev_t *candev, const struct can_frame *frame)
static int _esp_can_send(candev_t *candev, const can_frame_t *frame)
{
can_t *dev = container_of(candev, can_t, candev);

Expand All @@ -235,12 +235,12 @@ static int _esp_can_send(candev_t *candev, const struct can_frame *frame)
}

/* save reference to frame in transmission (marks transmitter as busy) */
dev->tx_frame = (struct can_frame*)frame;
dev->tx_frame = (can_frame_t*)frame;

/* prepare the frame as expected by ESP32 */
twai_hal_frame_t esp_frame = { };

esp_frame.dlc = frame->can_dlc;
esp_frame.dlc = frame->len;
esp_frame.rtr = (frame->can_id & CAN_RTR_FLAG);
esp_frame.frame_format = (frame->can_id & CAN_EFF_FLAG);

Expand Down Expand Up @@ -453,7 +453,7 @@ static int _esp_can_get(candev_t *candev, canopt_t opt, void *value, size_t max_
return res;
}

static int _esp_can_abort(candev_t *candev, const struct can_frame *frame)
static int _esp_can_abort(candev_t *candev, const can_frame_t *frame)
{
can_t *dev = container_of(candev, can_t, candev);

Expand Down Expand Up @@ -809,7 +809,7 @@ static void IRAM_ATTR _esp_can_intr_handler(void *arg)
if (twai_hal_read_rx_buffer_and_clear(&hw, &esp_frame) &&
(dev->rx_frames_num < ESP_CAN_MAX_RX_FRAMES)) {
/* prepare the CAN frame from ESP32 CAN frame */
struct can_frame frame = {};
can_frame_t frame = {};

if (esp_frame.frame_format) {
frame.can_id = esp_frame.extended.id[0];
Expand All @@ -825,7 +825,7 @@ static void IRAM_ATTR _esp_can_intr_handler(void *arg)
}
frame.can_id |= esp_frame.rtr ? CAN_RTR_FLAG : 0;
frame.can_id |= esp_frame.frame_format ? CAN_EFF_FLAG : 0;
frame.can_dlc = esp_frame.dlc;
frame.len = esp_frame.dlc;

/* apply acceptance filters only if they are set */
unsigned f_id = 0;
Expand Down
2 changes: 2 additions & 0 deletions cpu/native/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ USEMODULE += periph

# UART is needed by startup.c
USEMODULE += periph_uart

USEMODULE += fdcan
30 changes: 17 additions & 13 deletions cpu/native/periph/can.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@
#include "debug.h"

static int _init(candev_t *candev);
static int _send(candev_t *candev, const struct can_frame *frame);
static int _send(candev_t *candev, const can_frame_t *frame);
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 _abort(candev_t *candev, const can_frame_t *frame);
static int _set_filter(candev_t *candev, const struct can_filter *filter);
static int _remove_filter(candev_t *candev, const struct can_filter *filter);
static int _power_up(candev_t *candev);
Expand All @@ -67,7 +67,7 @@ static const candev_driver_t candev_linux_driver = {
.remove_filter = _remove_filter,
};

static candev_event_t _can_error_to_can_evt(struct can_frame can_frame_err);
static candev_event_t _can_error_to_can_evt(can_frame_t can_frame_err);
static void _callback_can_sigio(int sock, void *arg);

can_conf_t candev_conf[CAN_DLL_NUMOF] = {
Expand All @@ -94,7 +94,7 @@ int can_init(can_t *dev, const can_conf_t *conf)
return 0;
}

static candev_event_t _can_error_to_can_evt(struct can_frame can_frame_err)
static candev_event_t _can_error_to_can_evt(can_frame_t can_frame_err)
{
candev_event_t can_evt = CANDEV_EVENT_NOEVENT;
can_err_mask_t can_err_type = can_frame_err.can_id & CAN_ERR_MASK;
Expand All @@ -103,7 +103,7 @@ static candev_event_t _can_error_to_can_evt(struct can_frame can_frame_err)
can_evt = CANDEV_EVENT_TX_ERROR;
}
else if (can_err_type & CAN_ERR_CRTL) {
switch(can_frame_err.data[1]) {
switch (can_frame_err.data[1]) {
case CAN_ERR_CRTL_RX_OVERFLOW:
can_evt = CANDEV_EVENT_RX_ERROR;
break;
Expand Down Expand Up @@ -168,7 +168,11 @@ static int _init(candev_t *candev)
can_err_mask_t err_mask = CAN_ERR_TX_TIMEOUT |
CAN_ERR_BUSOFF |
CAN_ERR_CRTL;
ret = real_setsockopt(dev->sock, SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
ret = real_setsockopt(dev->sock, SOL_CAN_RAW,
#ifdef MODULE_FDCAN
CAN_RAW_FD_FRAMES |
#endif
CAN_RAW_ERR_FILTER,
&err_mask, sizeof(err_mask));

if (ret < 0) {
Expand Down Expand Up @@ -210,14 +214,14 @@ static int _init(candev_t *candev)
return 0;
}

static int _send(candev_t *candev, const struct can_frame *frame)
static int _send(candev_t *candev, const can_frame_t *frame)
{
int nbytes;
can_t *dev = (can_t *)candev;

nbytes = real_write(dev->sock, frame, sizeof(struct can_frame));
nbytes = real_write(dev->sock, frame, sizeof(can_frame_t));

if (nbytes < frame->can_dlc) {
if (nbytes < frame->len) {
real_printf("CAN write op failed, nbytes=%i\n", nbytes);
return -1;
}
Expand All @@ -232,22 +236,22 @@ static int _send(candev_t *candev, const struct can_frame *frame)
static void _isr(candev_t *candev)
{
int nbytes;
struct can_frame rcv_frame;
can_frame_t rcv_frame;
can_t *dev = (can_t *)candev;

if (dev == NULL) {
return;
}

DEBUG("candev_native _isr: CAN SIGIO interrupt received, sock = %i\n", dev->sock);
nbytes = real_read(dev->sock, &rcv_frame, sizeof(struct can_frame));
nbytes = real_read(dev->sock, &rcv_frame, sizeof(can_frame_t));

if (nbytes < 0) { /* SIGIO signal was probably due to an error with the socket */
DEBUG("candev_native _isr: read: error during read\n");
return;
}

if (nbytes < (int)sizeof(struct can_frame)) {
if (nbytes < (int)sizeof(can_frame_t)) {
DEBUG("candev_native _isr: read: incomplete CAN frame\n");
return;
}
Expand Down Expand Up @@ -544,7 +548,7 @@ static int _remove_filter(candev_t *candev, const struct can_filter *filter)
return 0;
}

static int _abort(candev_t *candev, const struct can_frame *frame)
static int _abort(candev_t *candev, const can_frame_t *frame)
{
(void)frame;
(void)candev;
Expand Down
6 changes: 6 additions & 0 deletions cpu/stm32/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ ifneq (,$(filter periph_adc,$(FEATURES_USED)))
endif
endif

ifneq (,$(filter periph_can,$(FEATURES_USED)))
ifneq (,$(filter g4,$(CPU_FAM)))
USEMODULE += fdcan
endif
endif

ifneq (,$(filter periph_vbat,$(USEMODULE)))
FEATURES_REQUIRED += periph_adc
endif
Expand Down
10 changes: 9 additions & 1 deletion cpu/stm32/include/can_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,15 @@ extern "C" {
/** Default STM32 CAN devices config */
static const can_conf_t candev_conf[] = {
{
#if defined(CPU_FAM_STM32F0)
#if defined(CPU_FAM_STM32G4)
.can = FDCAN1,
.rcc_mask = RCC_APB1ENR1_FDCANEN,
.rx_pin = GPIO_PIN(PORT_A, 11),
.tx_pin = GPIO_PIN(PORT_A, 12),
.af = GPIO_AF9,
.it0_irqn = FDCAN1_IT0_IRQn,
.it1_irqn = FDCAN1_IT1_IRQn,
#elif defined(CPU_FAM_STM32F0)
.can = CAN,
.rcc_mask = RCC_APB1ENR_CANEN,
.rx_pin = GPIO_PIN(PORT_A, 11),
Expand Down
7 changes: 3 additions & 4 deletions cpu/stm32/include/candev_stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ typedef struct can can_t;

/** This structure holds anything related to the receive part */
typedef struct candev_stm32_rx_fifo {
struct can_frame frame[CAN_STM32_RX_MAIL_FIFO]; /**< Receive FIFO */
can_frame_t frame[CAN_STM32_RX_MAIL_FIFO]; /**< Receive FIFO */
int write_idx; /**< Write index in the receive FIFO */
int read_idx; /**< Read index in the receive FIFO*/
int is_full; /**< Flag set when the FIFO is full */
Expand All @@ -164,12 +164,11 @@ typedef struct candev_stm32_isr {
/** STM32 CAN device descriptor */
struct can {
candev_t candev; /**< Common candev struct */
const can_conf_t *conf; /**< Configuration */
const can_conf_t *conf; /**< Configuration */
gpio_t rx_pin; /**< RX pin */
gpio_t tx_pin; /**< TX pin */
gpio_af_t af; /**< Alternate pin function to use */
/** Tx mailboxes */
const struct can_frame *tx_mailbox[CAN_STM32_TX_MAILBOXES];
const can_frame_t *tx_mailbox[CAN_STM32_TX_MAILBOXES]; /**< Tx mailboxes */
candev_stm32_rx_fifo_t rx_fifo; /**< Rx FIFOs */
candev_stm32_isr_t isr_flags; /**< ISR flags */
};
Expand Down
Loading

0 comments on commit a0832e5

Please sign in to comment.