Skip to content

Commit

Permalink
Merge pull request #6178 from OTAkeys/pr/can_stm32
Browse files Browse the repository at this point in the history
can stm32: add a driver for STM32 bxCAN peripheral
  • Loading branch information
smlng authored Apr 8, 2019
2 parents 2ef1451 + 2cb8c4b commit 4dd09ea
Show file tree
Hide file tree
Showing 10 changed files with 1,745 additions and 3 deletions.
4 changes: 3 additions & 1 deletion boards/esp32-olimex-evb/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ FEATURES_PROVIDED += periph_spi

# unique features of the board
FEATURES_PROVIDED += periph_eth # Ethernet MAC (EMAC)
FEATURES_PROVIDED += periph_can # CAN peripheral interface
# FEATURES_PROVIDED += periph_can # CAN peripheral interface
FEATURES_PROVIDED += esp_can # Do not use periph_can but esp_can while common init
# is not updated
FEATURES_PROVIDED += periph_ir # IR peripheral interface

FEATURES_PROVIDED += arduino
1 change: 1 addition & 0 deletions boards/nucleo-f413zh/Makefile.features
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_adc
FEATURES_PROVIDED += periph_can
FEATURES_PROVIDED += periph_dma
FEATURES_PROVIDED += periph_i2c
FEATURES_PROVIDED += periph_pwm
Expand Down
138 changes: 138 additions & 0 deletions cpu/stm32_common/include/can_params.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* 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 candev_stm32
* @{
*
* @file
* @brief STM32 CAN controller driver (bxCAN) default parameters
*
* @author Vincent Dupont <vincent@otakeys.com>
* @}
*/

#ifndef CAN_PARAMS_H
#define CAN_PARAMS_H

#include "can/device.h"
#include "periph/can.h"

#ifdef __cplusplus
extern "C" {
#endif

/** Default STM32 CAN devices config */
static const can_conf_t candev_conf[] = {
{
#if defined(CPU_FAM_STM32F0)
.can = CAN,
.rcc_mask = RCC_APB1ENR_CANEN,
.rx_pin = GPIO_PIN(PORT_A, 11),
.tx_pin = GPIO_PIN(PORT_A, 12),
.af = GPIO_AF4,
.irqn = CEC_CAN_IRQn,
#else
.can = CAN1,
.rcc_mask = RCC_APB1ENR_CAN1EN,
.can_master = CAN1,
.master_rcc_mask = RCC_APB1ENR_CAN1EN,
.first_filter = 0,
.nb_filters = 14,
#ifndef CPU_FAM_STM32F1
.rx_pin = GPIO_PIN(PORT_D, 0),
.tx_pin = GPIO_PIN(PORT_D, 1),
.af = GPIO_AF9,
#else
.rx_pin = GPIO_PIN(PORT_A, 11),
.tx_pin = GPIO_PIN(PORT_A, 12),
#endif
.tx_irqn = CAN1_TX_IRQn,
.rx0_irqn = CAN1_RX0_IRQn,
.rx1_irqn = CAN1_RX1_IRQn,
.sce_irqn = CAN1_SCE_IRQn,
#endif
.ttcm = 0,
.abom = 1,
.awum = 1,
.nart = 0,
.rflm = 0,
.txfp = 0,
},
#if (CANDEV_STM32_CHAN_NUMOF >= 2) && (CAN_DLL_NUMOF >= 2)
{
.can = CAN2,
.rcc_mask = RCC_APB1ENR_CAN2EN,
.can_master = CAN1,
.master_rcc_mask = RCC_APB1ENR_CAN1EN,
.first_filter = 14,
.nb_filters = 14,
.rx_pin = GPIO_PIN(PORT_B, 5),
.tx_pin = GPIO_PIN(PORT_B, 6),
#ifndef CPU_FAM_STM32F1
.af = GPIO_AF9,
#endif
.tx_irqn = CAN2_TX_IRQn,
.rx0_irqn = CAN2_RX0_IRQn,
.rx1_irqn = CAN2_RX1_IRQn,
.sce_irqn = CAN2_SCE_IRQn,
.ttcm = 0,
.abom = 1,
.awum = 1,
.nart = 0,
.rflm = 0,
.txfp = 0,
},
#endif
#if (CANDEV_STM32_CHAN_NUMOF >= 3) && (CAN_DLL_NUMOF >= 3)
{
.can = CAN3,
.rcc_mask = RCC_APB1ENR_CAN3EN,
.can_master = CAN3,
.master_rcc_mask = RCC_APB1ENR_CAN3EN,
.first_filter = 0,
.nb_filters = 14,
.rx_pin = GPIO_PIN(PORT_B, 3),
.tx_pin = GPIO_PIN(PORT_B, 4),
.af = GPIO_AF11,
.tx_irqn = CAN3_TX_IRQn,
.rx0_irqn = CAN3_RX0_IRQn,
.rx1_irqn = CAN3_RX1_IRQn,
.sce_irqn = CAN3_SCE_IRQn,
.ttcm = 0,
.abom = 1,
.awum = 1,
.nart = 0,
.rflm = 0,
.txfp = 0,
},
#endif
};

/** Default STM32 CAN devices parameters */
static const candev_params_t candev_params[] = {
{
.name = "can_stm32_0",
},
#if (CANDEV_STM32_CHAN_NUMOF >= 2) && (CAN_DLL_NUMOF >= 2)
{
.name = "can_stm32_1",
},
#endif
#if (CANDEV_STM32_CHAN_NUMOF >= 3) && (CAN_DLL_NUMOF >= 3)
{
.name = "can_stm32_2",
},
#endif
};

#ifdef __cplusplus
}
#endif

#endif /* CAN_PARAMS_H */
200 changes: 200 additions & 0 deletions cpu/stm32_common/include/candev_stm32.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/*
* 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 cpu_stm32_common
* @ingroup drivers_can
* @defgroup candev_stm32 STM32 CAN controller
* @brief STM32 CAN controller driver (bxCAN)
*
* The STM32Fx microcontroller can have an integrated CAN controller (bxCAN)
*
* This driver has been tested with a STM32F0,STM32F2 and STM32F4 MCU
* but should work on others
* @{
*
* @file
* @brief bxCAN specific definitions
*
* @author Vincent Dupont <vincent@otakeys.com>
* @}
*/

#ifndef CANDEV_STM32_H
#define CANDEV_STM32_H

#ifdef __cplusplus
extern "C" {
#endif

#include "can/candev.h"

#if defined(CPU_LINE_STM32F413xx) || defined(CPU_LINE_STM32F423xx)
#define CANDEV_STM32_CHAN_NUMOF 3
#elif defined(CPU_FAM_STM32F1) || defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4)
#define CANDEV_STM32_CHAN_NUMOF 2
#elif defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || DOXYGEN
/** Number of channels in the device (up to 3) */
#define CANDEV_STM32_CHAN_NUMOF 1
#else
#error "CAN STM32: CPU not supported"
#endif

/**
* @name ISR functions
* @{
*/
#if defined(CPU_FAM_STM32F1)
#define ISR_CAN1_TX isr_usb_hp_can1_tx
#define ISR_CAN1_RX0 isr_usb_lp_can1_rx0
#define ISR_CAN1_RX1 isr_can1_rx1
#define ISR_CAN1_SCE isr_can1_sce
#else
#define ISR_CAN1_TX isr_can1_tx
#define ISR_CAN1_RX0 isr_can1_rx0
#define ISR_CAN1_RX1 isr_can1_rx1
#define ISR_CAN1_SCE isr_can1_sce
#define ISR_CAN2_TX isr_can2_tx
#define ISR_CAN2_RX0 isr_can2_rx0
#define ISR_CAN2_RX1 isr_can2_rx1
#define ISR_CAN2_SCE isr_can2_sce
#define ISR_CAN3_TX isr_can3_tx
#define ISR_CAN3_RX0 isr_can3_rx0
#define ISR_CAN3_RX1 isr_can3_rx1
#define ISR_CAN3_SCE isr_can3_sce
#endif
/** @} */

#if CANDEV_STM32_CHAN_NUMOF > 1 || DOXYGEN
/** The maximum number of filters: 28 for dual channel, 14 for single channel */
#define CAN_STM32_NB_FILTER 28
#else
#define CAN_STM32_NB_FILTER 14
#endif

#ifndef CANDEV_STM32_DEFAULT_BITRATE
/** Default bitrate */
#define CANDEV_STM32_DEFAULT_BITRATE 500000U
#endif

#ifndef CANDEV_STM32_DEFAULT_SPT
/** Default sampling-point */
#define CANDEV_STM32_DEFAULT_SPT 875
#endif

/** bxCAN device configuration */
typedef struct {
CAN_TypeDef *can; /**< CAN device */
uint32_t rcc_mask; /**< RCC mask to enable clock */
gpio_t rx_pin; /**< RX pin */
gpio_t tx_pin; /**< TX pin */
#ifndef CPU_FAM_STM32F1
gpio_af_t af; /**< Alternate pin function to use */
#endif
#if CANDEV_STM32_CHAN_NUMOF > 1 || defined(DOXYGEN)
CAN_TypeDef *can_master; /**< Master CAN device */
uint32_t master_rcc_mask; /**< Master device RCC mask */
/** First filter in the bank. For a master channel it must be 0.
* For a slave channel, it is used without checking with the master channel,
* beware bot to overwrite the master config. */
uint8_t first_filter;
/** Number of filters to use. Must be less or equal
* to CAN_STM32_NB_FILTER - first_filter */
uint8_t nb_filters;
#endif
#if defined(CPU_FAM_STM32F0)
uint8_t irqn; /**< CAN common IRQ channel */
#else
uint8_t tx_irqn; /**< TX IRQ channel */
uint8_t rx0_irqn; /**< RX0 IRQ channel */
uint8_t rx1_irqn; /**< RX1 IRQ channel */
uint8_t sce_irqn; /**< SCE IRQ channel */
#endif
uint8_t ttcm : 1; /**< Time triggered communication mode */
uint8_t abom : 1; /**< Automatic bus-off management */
uint8_t awum : 1; /**< Automatic wakeup mode */
uint8_t nart : 1; /**< No automatic retransmission */
uint8_t rflm : 1; /**< Receive FIFO locked mode */
uint8_t txfp : 1; /**< Transmit FIFO priority */
uint8_t lbkm : 1; /**< Loopback mode */
uint8_t silm : 1; /**< Silent mode */
} can_conf_t;
/** can_conf_t is re-defined */
#define HAVE_CAN_CONF_T

/** The number of transmit mailboxes */
#define CAN_STM32_TX_MAILBOXES 3
/** The number of receive FIFO */
#define CAN_STM32_RX_MAILBOXES 2


#ifndef CAN_STM32_RX_MAIL_FIFO
/** This is the maximum number of frame the driver can receive simultaneously */
#define CAN_STM32_RX_MAIL_FIFO 12
#endif

/** bxCAN candev descriptor */
typedef struct can can_t;
/** can_t is re-defined */
#define HAVE_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 */
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 */
} candev_stm32_rx_fifo_t;

/** Internal interrupt flags */
typedef struct candev_stm32_isr {
int isr_tx : 3; /**< Tx mailboxes interrupt */
int isr_rx : 2; /**< Rx FIFO interrupt */
int isr_wkup : 1; /**< Wake up interrupt */
} candev_stm32_isr_t;

/** STM32 CAN device descriptor */
struct can {
candev_t candev; /**< Common candev struct */
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];
candev_stm32_rx_fifo_t rx_fifo; /**< Rx FIFOs */
candev_stm32_isr_t isr_flags; /**< ISR flags */
};

#ifndef CPU_FAM_STM32F1
/**
* @brief Set the pins of an stm32 CAN device
*
* @param[in,out] dev the device to set pins
* @param[in] tx_pin tx pin
* @param[in] rx_pin rx pin
* @param[in] af alternate function
*/
void candev_stm32_set_pins(can_t *dev, gpio_t tx_pin, gpio_t rx_pin,
gpio_af_t af);
#else
/**
* @brief Set the pins of an stm32 CAN device
*
* @param[in,out] dev the device to set pins
* @param[in] tx_pin tx pin
* @param[in] rx_pin rx pin
*/
void candev_stm32_set_pins(can_t *dev, gpio_t tx_pin, gpio_t rx_pin);
#endif

#ifdef __cplusplus
}
#endif

#endif /* CANDEV_STM32_H */
4 changes: 4 additions & 0 deletions cpu/stm32_common/include/periph_cpu_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,10 @@ int dma_configure(dma_t dma, int chan, const volatile void *src, volatile void *

#endif /* MODULE_PERIPH_DMA */

#ifdef MODULE_PERIPH_CAN
#include "candev_stm32.h"
#endif

#ifdef __cplusplus
}
#endif
Expand Down
Loading

0 comments on commit 4dd09ea

Please sign in to comment.