1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/stm32/include/candev_stm32.h
Benjamin Valentin dde3ca5f46 cpu/stm32: candev: derive number of CAN interfaces from vendor header
We can deduce the number of available CAN interfaces from the vendor headers
so no need to hard-code this number for individual part numbers.
2021-03-09 11:30:21 +01:00

204 lines
6.5 KiB
C

/*
* 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
* @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.
*
* The default bitrate is set to 500 kbps and the default sample point is set to
* 87.5%.
* @{
*
* @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"
/** Number of channels in the device (up to 3) */
#if defined(CAN3)
#define CANDEV_STM32_CHAN_NUMOF 3
#elif defined(CAN2)
#define CANDEV_STM32_CHAN_NUMOF 2
#elif defined(CAN1) || defined(CAN) || DOXYGEN
#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
bool en_deep_sleep_wake_up; /**< Enable deep-sleep wake-up interrupt */
#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 */