mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
can stm32: add a driver for STM32 bxCAN peripheral
This driver is compliant with the candev interface. It has been tested with STM32F0 and STM32F2 and STM32F413 ONLY at this time but should be compliant with other STM32Fx devices
This commit is contained in:
parent
14f47bf220
commit
ae95137f95
138
cpu/stm32_common/include/can_params.h
Normal file
138
cpu/stm32_common/include/can_params.h
Normal file
@ -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 CANDEV_STM32_PARAMS_H
|
||||
#define CANDEV_STM32_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 /* CANDEV_STM32_PARAMS_H */
|
193
cpu/stm32_common/include/candev_stm32.h
Normal file
193
cpu/stm32_common/include/candev_stm32.h
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#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;
|
||||
#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;
|
||||
#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 */
|
@ -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
|
||||
|
1263
cpu/stm32_common/periph/can.c
Normal file
1263
cpu/stm32_common/periph/can.c
Normal file
File diff suppressed because it is too large
Load Diff
57
drivers/include/periph/can.h
Normal file
57
drivers/include/periph/can.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_periph_can CAN
|
||||
* @ingroup drivers_periph
|
||||
* @brief Low-level CAN peripheral driver interface
|
||||
*
|
||||
* This is a basic abstract peripheral to be used with candev.
|
||||
*
|
||||
* The @p can_t type should be compatible with @p candev_t to be used by the
|
||||
* candev interface.
|
||||
*
|
||||
* See auto init for more details how the can_t is used.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level CAN peripheral driver interface definitions
|
||||
*
|
||||
* @author Vincent Dupont <vincent@otakeys.com>
|
||||
*/
|
||||
|
||||
#ifndef PERIPH_CAN_H
|
||||
#define PERIPH_CAN_H
|
||||
|
||||
#include "periph_cpu.h"
|
||||
#include "can/candev.h"
|
||||
|
||||
#ifndef HAVE_CAN_T
|
||||
/**
|
||||
* @brief CAN device descriptor identifier
|
||||
*/
|
||||
typedef candev_t can_t;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_CAN_CONF_T
|
||||
/**
|
||||
* @brief CAN configuration identifier
|
||||
*/
|
||||
typedef void can_conf_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize a periph CAN device with the given configuration
|
||||
*
|
||||
* @param[in,out] dev device descriptor
|
||||
* @param[in] conf device vonfiguration
|
||||
*/
|
||||
void can_init(can_t *dev, const can_conf_t *conf);
|
||||
|
||||
#endif /* PERIPH_CAN_H */
|
@ -54,8 +54,18 @@ void auto_init_candev(void)
|
||||
auto_init_can_native();
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_PERIPH_CAN
|
||||
extern void auto_init_periph_can(void);
|
||||
auto_init_periph_can();
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_ESP_CAN
|
||||
extern void auto_init_esp_can(void);
|
||||
auto_init_esp_can();
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_CAN_STM32
|
||||
extern void auto_init_can_stm32(void);
|
||||
auto_init_can_stm32();
|
||||
#endif
|
||||
}
|
||||
|
57
sys/auto_init/can/auto_init_periph_can.c
Normal file
57
sys/auto_init/can/auto_init_periph_can.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2018 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 auto_init
|
||||
* @{
|
||||
* @file
|
||||
* @brief initializes periph_can devices
|
||||
*
|
||||
* @author Vincent Dupont <vincent@otakeys.com>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef MODULE_PERIPH_CAN
|
||||
#include "can/device.h"
|
||||
#include "can_params.h"
|
||||
|
||||
#define CANDEV_NUMOF ((sizeof(candev_params) / sizeof(candev_params[0])))
|
||||
|
||||
#ifndef CANDEV_STACKSIZE
|
||||
#define CANDEV_STACKSIZE (THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE_PRINTF)
|
||||
#endif
|
||||
|
||||
#ifndef CANDEV_BASE_PRIORITY
|
||||
#define CANDEV_BASE_PRIORITY (THREAD_PRIORITY_MAIN - CANDEV_NUMOF - 2)
|
||||
#endif
|
||||
|
||||
static candev_dev_t candev_dev[CANDEV_NUMOF];
|
||||
static char _can_stacks[CANDEV_NUMOF][CANDEV_STACKSIZE];
|
||||
static can_t candev[CANDEV_NUMOF];
|
||||
|
||||
void auto_init_periph_can(void) {
|
||||
|
||||
for (size_t i = 0; i < CANDEV_NUMOF; i++) {
|
||||
can_init(&candev[i], &candev_conf[i]);
|
||||
candev_dev[i].dev = (candev_t *)&candev[i];
|
||||
candev_dev[i].name = candev_params[i].name;
|
||||
#ifdef MODULE_CAN_TRX
|
||||
candev_dev[i].trx = candev_params[i].trx;
|
||||
#endif
|
||||
#ifdef MODULE_CAN_PM
|
||||
candev_dev[i].rx_inactivity_timeout = candev_params[i].rx_inactivity_timeout;
|
||||
candev_dev[i].tx_wakeup_timeout = candev_params[i].tx_wakeup_timeout;
|
||||
#endif
|
||||
|
||||
can_device_init(_can_stacks[i], CANDEV_STACKSIZE, CANDEV_BASE_PRIORITY + i,
|
||||
candev_params[i].name, &candev_dev[i]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
typedef int dont_be_pedantic;
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user