You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by da...@apache.org on 2022/01/05 14:17:13 UTC

[incubator-nuttx] branch master updated (e27962a -> a983cd2)

This is an automated email from the ASF dual-hosted git repository.

davids5 pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from e27962a  net/devif: Fix the memory leak in case of netdev isn't alive
     new 6fe95d8  stm32: add SocketCAN support, based on stm32_can.c
     new a983cd2  boards/stm32: register CAN character device if configured

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/arm/src/stm32/Kconfig                         |   14 +
 arch/arm/src/stm32/Make.defs                       |    5 +
 arch/arm/src/stm32/stm32_can.h                     |   28 +-
 .../src/stm32/{stm32_can.c => stm32_can_sock.c}    | 1929 ++++++++++----------
 boards/arm/stm32/clicker2-stm32/src/Make.defs      |    2 +-
 .../arm/stm32/clicker2-stm32/src/clicker2-stm32.h  |    2 +-
 .../arm/stm32/clicker2-stm32/src/stm32_bringup.c   |    2 +-
 boards/arm/stm32/nucleo-f303re/src/Make.defs       |    2 +-
 boards/arm/stm32/nucleo-f303re/src/nucleo-f303re.h |    2 +-
 .../stm32/nucleo-f303re/src/stm32_appinitialize.c  |    2 +-
 boards/arm/stm32/nucleo-f334r8/src/nucleo-f334r8.h |    2 +-
 boards/arm/stm32/nucleo-f446re/src/Make.defs       |    2 +-
 boards/arm/stm32/nucleo-f446re/src/nucleo-f446re.h |    2 +-
 boards/arm/stm32/nucleo-f446re/src/stm32_bringup.c |    2 +-
 boards/arm/stm32/olimex-stm32-h405/src/Make.defs   |    2 +-
 .../olimex-stm32-h405/src/olimex-stm32-h405.h      |    2 +-
 .../stm32/olimex-stm32-h405/src/stm32_appinit.c    |    2 +-
 boards/arm/stm32/olimex-stm32-h407/src/Make.defs   |    2 +-
 .../olimex-stm32-h407/src/olimex-stm32-h407.h      |    2 +-
 .../stm32/olimex-stm32-h407/src/stm32_bringup.c    |    2 +-
 boards/arm/stm32/olimex-stm32-p107/src/Make.defs   |    2 +-
 .../olimex-stm32-p107/src/olimex-stm32-p107.h      |    2 +-
 .../stm32/olimex-stm32-p107/src/stm32_appinit.c    |    2 +-
 boards/arm/stm32/olimex-stm32-p207/src/Make.defs   |    2 +-
 .../olimex-stm32-p207/src/olimex-stm32-p207.h      |    2 +-
 .../stm32/olimex-stm32-p207/src/stm32_appinit.c    |    2 +-
 boards/arm/stm32/olimex-stm32-p407/src/Make.defs   |    2 +-
 .../olimex-stm32-p407/src/olimex-stm32-p407.h      |    2 +-
 .../stm32/olimex-stm32-p407/src/stm32_bringup.c    |    2 +-
 boards/arm/stm32/olimexino-stm32/src/Make.defs     |    2 +-
 .../stm32/olimexino-stm32/src/olimexino-stm32.h    |    2 +-
 .../arm/stm32/olimexino-stm32/src/stm32_appinit.c  |    2 +-
 boards/arm/stm32/omnibusf4/src/omnibusf4.h         |    2 +-
 boards/arm/stm32/omnibusf4/src/stm32_bringup.c     |    2 +-
 boards/arm/stm32/shenzhou/src/Make.defs            |    2 +-
 boards/arm/stm32/shenzhou/src/shenzhou.h           |    2 +-
 boards/arm/stm32/shenzhou/src/stm32_appinit.c      |    2 +-
 boards/arm/stm32/stm3210e-eval/src/Make.defs       |    2 +-
 boards/arm/stm32/stm3210e-eval/src/stm3210e-eval.h |    2 +-
 boards/arm/stm32/stm3210e-eval/src/stm32_bringup.c |    2 +-
 boards/arm/stm32/stm3220g-eval/src/Make.defs       |    2 +-
 boards/arm/stm32/stm3220g-eval/src/stm3220g-eval.h |    2 +-
 boards/arm/stm32/stm3220g-eval/src/stm32_appinit.c |    2 +-
 boards/arm/stm32/stm3240g-eval/src/Make.defs       |    2 +-
 boards/arm/stm32/stm3240g-eval/src/stm3240g-eval.h |    2 +-
 boards/arm/stm32/stm3240g-eval/src/stm32_bringup.c |    2 +-
 boards/arm/stm32/stm32f334-disco/src/Make.defs     |    2 +-
 .../stm32/stm32f334-disco/src/stm32f334-disco.h    |    2 +-
 boards/arm/stm32/stm32f4discovery/src/Make.defs    |    2 +-
 .../arm/stm32/stm32f4discovery/src/stm32_bringup.c |    2 +-
 .../stm32/stm32f4discovery/src/stm32f4discovery.h  |    2 +-
 boards/arm/stm32/viewtool-stm32f107/src/Make.defs  |    2 +-
 .../stm32/viewtool-stm32f107/src/stm32_bringup.c   |    2 +-
 .../viewtool-stm32f107/src/viewtool_stm32f107.h    |    2 +-
 54 files changed, 1019 insertions(+), 1057 deletions(-)
 copy arch/arm/src/stm32/{stm32_can.c => stm32_can_sock.c} (60%)

[incubator-nuttx] 01/02: stm32: add SocketCAN support, based on stm32_can.c

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davids5 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 6fe95d831499a6c907261394023c242651b65116
Author: raiden00pl <ra...@railab.me>
AuthorDate: Wed Jan 5 10:28:47 2022 +0100

    stm32: add SocketCAN support, based on stm32_can.c
---
 arch/arm/src/stm32/Kconfig          |   14 +
 arch/arm/src/stm32/Make.defs        |    5 +
 arch/arm/src/stm32/stm32_can.h      |   28 +-
 arch/arm/src/stm32/stm32_can_sock.c | 2465 +++++++++++++++++++++++++++++++++++
 4 files changed, 2507 insertions(+), 5 deletions(-)

diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig
index 7d52339..567cc9a 100644
--- a/arch/arm/src/stm32/Kconfig
+++ b/arch/arm/src/stm32/Kconfig
@@ -10836,6 +10836,20 @@ config STM32_USB_ITRMP
 menu "CAN driver configuration"
 	depends on STM32_CAN
 
+choice
+	prompt "CAN character driver or SocketCAN support"
+	default STM32_CAN_CHARDRIVER
+
+config STM32_CAN_CHARDRIVER
+	bool "STM32 CAN character driver support"
+	select ARCH_HAVE_CAN_ERRORS
+
+config STM32_CAN_SOCKET
+	bool "STM32 CAN SocketCAN support"
+	select NET_CAN_HAVE_ERRORS
+
+endchoice # CAN character driver or SocketCAN support
+
 config STM32_CAN1_BAUD
 	int "CAN1 BAUD"
 	default 250000
diff --git a/arch/arm/src/stm32/Make.defs b/arch/arm/src/stm32/Make.defs
index 4de2988..14e91e1 100644
--- a/arch/arm/src/stm32/Make.defs
+++ b/arch/arm/src/stm32/Make.defs
@@ -241,8 +241,13 @@ CHIP_CSRCS += stm32_hall3ph.c
 endif
 
 ifeq ($(CONFIG_STM32_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CHIP_CSRCS += stm32_can.c
 endif
+ifeq ($(CONFIG_STM32_CAN_SOCKET),y)
+CHIP_CSRCS += stm32_can_sock.c
+endif
+endif
 
 ifeq ($(CONFIG_STM32_IWDG),y)
 CHIP_CSRCS += stm32_iwdg.c
diff --git a/arch/arm/src/stm32/stm32_can.h b/arch/arm/src/stm32/stm32_can.h
index 7beefda..37ef72d 100644
--- a/arch/arm/src/stm32/stm32_can.h
+++ b/arch/arm/src/stm32/stm32_can.h
@@ -48,9 +48,6 @@
 #  undef CONFIG_STM32_CAN1
 #endif
 
-#if defined(CONFIG_CAN) && \
-    (defined(CONFIG_STM32_CAN1) || defined(CONFIG_STM32_CAN2))
-
 /* CAN BAUD */
 
 #if defined(CONFIG_STM32_CAN1) && !defined(CONFIG_STM32_CAN1_BAUD)
@@ -107,11 +104,13 @@ extern "C"
  * Public Function Prototypes
  ****************************************************************************/
 
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
+
 /****************************************************************************
  * Name: stm32_caninitialize
  *
  * Description:
- *   Initialize the selected CAN port
+ *   Initialize the selected CAN port as character device
  *
  * Input Parameters:
  *   Port number (for hardware that has multiple CAN interfaces)
@@ -123,6 +122,26 @@ extern "C"
 
 struct can_dev_s;
 FAR struct can_dev_s *stm32_caninitialize(int port);
+#endif
+
+#ifdef CONFIG_STM32_CAN_SOCKET
+
+/****************************************************************************
+ * Name: stm32_cansockinitialize
+ *
+ * Description:
+ *   Initialize the selected CAN port as SocketCAN interface
+ *
+ * Input Parameters:
+ *   Port number (for hardware that has multiple CAN interfaces)
+ *
+ * Returned Value:
+ *   OK on success; Negated errno on failure.
+ *
+ ****************************************************************************/
+
+int stm32_cansockinitialize(int port);
+#endif
 
 #undef EXTERN
 #if defined(__cplusplus)
@@ -130,5 +149,4 @@ FAR struct can_dev_s *stm32_caninitialize(int port);
 #endif
 
 #endif /* __ASSEMBLY__ */
-#endif /* CONFIG_CAN && (CONFIG_STM32_CAN1 || CONFIG_STM32_CAN2) */
 #endif /* __ARCH_ARM_SRC_STM32_STM32_CAN_H */
diff --git a/arch/arm/src/stm32/stm32_can_sock.c b/arch/arm/src/stm32/stm32_can_sock.c
new file mode 100644
index 0000000..c04505a
--- /dev/null
+++ b/arch/arm/src/stm32/stm32_can_sock.c
@@ -0,0 +1,2465 @@
+/****************************************************************************
+ * arch/arm/src/stm32/stm32_can_sock.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <arch/board/board.h>
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+
+#include <nuttx/wqueue.h>
+#include <nuttx/can.h>
+#include <nuttx/net/netdev.h>
+#include <nuttx/net/can.h>
+#include <netpacket/can.h>
+
+#include "arm_internal.h"
+#include "arm_arch.h"
+
+#include "chip.h"
+#include "stm32.h"
+#include "stm32_rcc.h"
+#include "stm32_can.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Delays *******************************************************************/
+
+/* Time out for INAK bit */
+
+#define INAK_TIMEOUT 65535
+
+/* Bit timing ***************************************************************/
+
+#define CAN_BIT_QUANTA (CONFIG_STM32_CAN_TSEG1 + CONFIG_STM32_CAN_TSEG2 + 1)
+
+#ifndef CONFIG_DEBUG_CAN_INFO
+#  undef CONFIG_STM32_CAN_REGDEBUG
+#endif
+
+/* Pool configuration *******************************************************/
+
+#define POOL_SIZE  (1)
+
+/* Work queue support is required. */
+
+#if !defined(CONFIG_SCHED_WORKQUEUE)
+#  error Work queue support is required
+#endif
+
+/* The low priority work queue is preferred.  If it is not enabled, LPWORK
+ * will be the same as HPWORK.
+ *
+ * NOTE:  However, the network should NEVER run on the high priority work
+ * queue!  That queue is intended only to service short back end interrupt
+ * processing that never suspends.  Suspending the high priority work queue
+ * may bring the system to its knees!
+ */
+
+#define CANWORK LPWORK
+
+/* CAN error interrupts */
+
+#ifdef CONFIG_NET_CAN_ERRORS
+#  define STM32_CAN_ERRINT (CAN_IER_LECIE | CAN_IER_ERRIE | \
+                            CAN_IER_BOFIE | CAN_IER_EPVIE | \
+                            CAN_IER_EWGIE)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct stm32_can_s
+{
+  uint8_t  port;     /* CAN port number (1 or 2) */
+  uint8_t  canrx[2]; /* CAN RX FIFO 0/1 IRQ number */
+  uint8_t  cantx;    /* CAN TX IRQ number */
+#ifdef CONFIG_NET_CAN_ERRORS
+  uint8_t  cansce;   /* CAN SCE IRQ number */
+#endif
+  uint8_t  filter;   /* Filter number */
+  uint32_t base;     /* Base address of the CAN control registers */
+  uint32_t fbase;    /* Base address of the CAN filter registers */
+  uint32_t baud;     /* Configured baud */
+
+  bool                bifup;  /* true:ifup false:ifdown */
+  struct net_driver_s dev;    /* Interface understood by the network */
+
+  struct work_s irqwork;  /* For deferring interrupt work to the wq */
+  struct work_s pollwork; /* For deferring poll work to the work wq */
+
+  /* A pointers to the list of TX/RX descriptors */
+
+  FAR struct can_frame *txdesc;
+  FAR struct can_frame *rxdesc;
+
+  /* TX/RX pool */
+
+  uint8_t tx_pool[sizeof(struct can_frame)*POOL_SIZE];
+  uint8_t rx_pool[sizeof(struct can_frame)*POOL_SIZE];
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* CAN Register access */
+
+static uint32_t stm32can_getreg(FAR struct stm32_can_s *priv,
+                                int offset);
+static uint32_t stm32can_getfreg(FAR struct stm32_can_s *priv,
+                                 int offset);
+static void stm32can_putreg(FAR struct stm32_can_s *priv, int offset,
+                            uint32_t value);
+static void stm32can_putfreg(FAR struct stm32_can_s *priv, int offset,
+                             uint32_t value);
+#ifdef CONFIG_STM32_CAN_REGDEBUG
+static void stm32can_dumpctrlregs(FAR struct stm32_can_s *priv,
+                                  FAR const char *msg);
+static void stm32can_dumpmbregs(FAR struct stm32_can_s *priv,
+                                FAR const char *msg);
+static void stm32can_dumpfiltregs(FAR struct stm32_can_s *priv,
+                                  FAR const char *msg);
+#else
+#  define stm32can_dumpctrlregs(priv,msg)
+#  define stm32can_dumpmbregs(priv,msg)
+#  define stm32can_dumpfiltregs(priv,msg)
+#endif
+
+/* CAN interrupt enable functions */
+
+static void stm32can_rx0int(FAR struct stm32_can_s *priv, bool enable);
+static void stm32can_rx1int(FAR struct stm32_can_s *priv, bool enable);
+static void stm32can_txint(FAR struct stm32_can_s *priv, bool enable);
+#ifdef CONFIG_NET_CAN_ERRORS
+static void stm32can_errint(FAR struct stm32_can_s *priv, bool enable);
+#endif
+
+/* Common TX logic */
+
+static int stm32can_transmit(FAR struct stm32_can_s *priv);
+static bool stm32can_txready(FAR struct stm32_can_s *priv);
+static int  stm32can_txpoll(struct net_driver_s *dev);
+
+/* CAN RX interrupt handling */
+
+static int  stm32can_rxinterrupt_work(FAR struct stm32_can_s *priv,
+                                      int rxmb);
+
+static void stm32can_rx0interrupt_work(FAR void *arg);
+static void stm32can_rx1interrupt_work(FAR void *arg);
+static int stm32can_rxinterrupt(FAR struct stm32_can_s *priv, int rxmb);
+
+static int  stm32can_rx0interrupt(int irq, FAR void *context, FAR void *arg);
+static int  stm32can_rx1interrupt(int irq, FAR void *context, FAR void *arg);
+
+/* CAN TX interrupt handling */
+
+static int  stm32can_txinterrupt(int irq, FAR void *context, FAR void *arg);
+static void stm32can_txdone_work(FAR void *arg);
+static void stm32can_txdone(FAR struct stm32_can_s *priv);
+
+#ifdef CONFIG_NET_CAN_ERRORS
+/* CAN errors interrupt handling */
+
+static void stm32can_sceinterrupt_work(FAR void *arg);
+static int  stm32can_sceinterrupt(int irq, FAR void *context, FAR void *arg);
+#endif
+
+/* Initialization */
+
+static int  stm32can_setup(FAR struct stm32_can_s *priv);
+static void  stm32can_shutdown(FAR struct stm32_can_s *priv);
+static void  stm32can_reset(FAR struct stm32_can_s *priv);
+static int  stm32can_enterinitmode(FAR struct stm32_can_s *priv);
+static int  stm32can_exitinitmode(FAR struct stm32_can_s *priv);
+static int  stm32can_bittiming(FAR struct stm32_can_s *priv);
+static int  stm32can_cellinit(FAR struct stm32_can_s *priv);
+static int  stm32can_filterinit(FAR struct stm32_can_s *priv);
+
+/* TX mailbox status */
+
+static bool stm32can_txmb0empty(uint32_t tsr_regval);
+static bool stm32can_txmb1empty(uint32_t tsr_regval);
+static bool stm32can_txmb2empty(uint32_t tsr_regval);
+
+/* NuttX callback functions */
+
+static int  stm32can_ifup(struct net_driver_s *dev);
+static int  stm32can_ifdown(struct net_driver_s *dev);
+
+static void stm32can_txavail_work(FAR void *arg);
+static int  stm32can_txavail(struct net_driver_s *dev);
+
+#ifdef CONFIG_NETDEV_IOCTL
+static int  stm32can_netdev_ioctl(struct net_driver_s *dev, int cmd,
+                                  unsigned long arg);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_CAN1
+
+static struct stm32_can_s g_can1priv =
+{
+  .port             = 1,
+  .canrx            =
+  {
+                      STM32_IRQ_CAN1RX0,
+                      STM32_IRQ_CAN1RX1,
+  },
+  .cantx            = STM32_IRQ_CAN1TX,
+#ifdef CONFIG_NET_CAN_ERRORS
+  .cansce           = STM32_IRQ_CAN1SCE,
+#endif
+  .filter           = 0,
+  .base             = STM32_CAN1_BASE,
+  .fbase            = STM32_CAN1_BASE,
+  .baud             = CONFIG_STM32_CAN1_BAUD,
+};
+
+#endif
+
+#ifdef CONFIG_STM32_CAN2
+
+static struct stm32_can_s g_can2priv =
+{
+  .port             = 2,
+  .canrx            =
+  {
+                      STM32_IRQ_CAN2RX0,
+                      STM32_IRQ_CAN2RX1,
+  },
+  .cantx            = STM32_IRQ_CAN2TX,
+#ifdef CONFIG_NET_CAN_ERRORS
+  .cansce           = STM32_IRQ_CAN2SCE,
+#endif
+  .filter           = CAN_NFILTERS / 2,
+  .base             = STM32_CAN2_BASE,
+  .fbase            = STM32_CAN1_BASE,
+  .baud             = CONFIG_STM32_CAN2_BAUD,
+};
+
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32can_getreg
+ * Name: stm32can_getfreg
+ *
+ * Description:
+ *   Read the value of a CAN register or filter block register.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_CAN_REGDEBUG
+static uint32_t stm32can_vgetreg(uint32_t addr)
+{
+  static uint32_t prevaddr = 0;
+  static uint32_t preval   = 0;
+  static uint32_t count    = 0;
+
+  /* Read the value from the register */
+
+  uint32_t val = getreg32(addr);
+
+  /* Is this the same value that we read from the same register last time?
+   * Are we polling the register?  If so, suppress some of the output.
+   */
+
+  if (addr == prevaddr && val == preval)
+    {
+      if (count == 0xffffffff || ++count > 3)
+        {
+          if (count == 4)
+            {
+              ninfo("...\n");
+            }
+
+          return val;
+        }
+    }
+
+  /* No this is a new address or value */
+
+  else
+    {
+      /* Did we print "..." for the previous value? */
+
+      if (count > 3)
+        {
+          /* Yes.. then show how many times the value repeated */
+
+          ninfo("[repeats %" PRIu32 " more times]\n", count - 3);
+        }
+
+      /* Save the new address, value, and count */
+
+      prevaddr = addr;
+      preval   = val;
+      count    = 1;
+    }
+
+  /* Show the register value read */
+
+  ninfo("%08" PRIx32 "->%08" PRIx32 "\n", addr, val);
+  return val;
+}
+
+static uint32_t stm32can_getreg(FAR struct stm32_can_s *priv, int offset)
+{
+  return stm32can_vgetreg(priv->base + offset);
+}
+
+static uint32_t stm32can_getfreg(FAR struct stm32_can_s *priv, int offset)
+{
+  return stm32can_vgetreg(priv->fbase + offset);
+}
+
+#else
+static uint32_t stm32can_getreg(FAR struct stm32_can_s *priv, int offset)
+{
+  return getreg32(priv->base + offset);
+}
+
+static uint32_t stm32can_getfreg(FAR struct stm32_can_s *priv, int offset)
+{
+  return getreg32(priv->fbase + offset);
+}
+
+#endif
+
+/****************************************************************************
+ * Name: stm32can_putreg
+ * Name: stm32can_putfreg
+ *
+ * Description:
+ *   Set the value of a CAN register or filter block register.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_CAN_REGDEBUG
+static void stm32can_vputreg(uint32_t addr, uint32_t value)
+{
+  /* Show the register value being written */
+
+  ninfo("%08" PRIx32 "->%08" PRIx32 "\n", addr, val);
+
+  /* Write the value */
+
+  putreg32(value, addr);
+}
+
+static void stm32can_putreg(FAR struct stm32_can_s *priv, int offset,
+                            uint32_t value)
+{
+  stm32can_vputreg(priv->base + offset, value);
+}
+
+static void stm32can_putfreg(FAR struct stm32_can_s *priv, int offset,
+                             uint32_t value)
+{
+  stm32can_vputreg(priv->fbase + offset, value);
+}
+
+#else
+static void stm32can_putreg(FAR struct stm32_can_s *priv, int offset,
+                            uint32_t value)
+{
+  putreg32(value, priv->base + offset);
+}
+
+static void stm32can_putfreg(FAR struct stm32_can_s *priv, int offset,
+                             uint32_t value)
+{
+  putreg32(value, priv->fbase + offset);
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32can_dumpctrlregs
+ *
+ * Description:
+ *   Dump the contents of all CAN control registers
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *   msg  - message
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_CAN_REGDEBUG
+static void stm32can_dumpctrlregs(FAR struct stm32_can_s *priv,
+                                  FAR const char *msg)
+{
+  if (msg)
+    {
+      ninfo("Control Registers: %s\n", msg);
+    }
+  else
+    {
+      ninfo("Control Registers:\n");
+    }
+
+  /* CAN control and status registers */
+
+  ninfo("  MCR: %08" PRIx32 "   MSR: %08" PRIx32 "   TSR: %08" PRIx32 "\n",
+          getreg32(priv->base + STM32_CAN_MCR_OFFSET),
+          getreg32(priv->base + STM32_CAN_MSR_OFFSET),
+          getreg32(priv->base + STM32_CAN_TSR_OFFSET));
+
+  ninfo(" RF0R: %08" PRIx32 "  RF1R: %08" PRIx32 "\n",
+          getreg32(priv->base + STM32_CAN_RF0R_OFFSET),
+          getreg32(priv->base + STM32_CAN_RF1R_OFFSET));
+
+  ninfo("  IER: %08" PRIx32 "   ESR: %08" PRIx32 "   BTR: %08" PRIx32 "\n",
+          getreg32(priv->base + STM32_CAN_IER_OFFSET),
+          getreg32(priv->base + STM32_CAN_ESR_OFFSET),
+          getreg32(priv->base + STM32_CAN_BTR_OFFSET));
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32can_dumpmbregs
+ *
+ * Description:
+ *   Dump the contents of all CAN mailbox registers
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *   msg  - message
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_CAN_REGDEBUG
+static void stm32can_dumpmbregs(FAR struct stm32_can_s *priv,
+                                FAR const char *msg)
+{
+  if (msg)
+    {
+      ninfo("Mailbox Registers: %s\n", msg);
+    }
+  else
+    {
+      ninfo("Mailbox Registers:\n");
+    }
+
+  /* CAN mailbox registers (3 TX and 2 RX) */
+
+  ninfo(" TI0R: %08" PRIx32 " TDT0R: %08" PRIx32 " TDL0R: %08"
+          PRIx32 " TDH0R: %08" PRIx32 "\n",
+          getreg32(priv->base + STM32_CAN_TI0R_OFFSET),
+          getreg32(priv->base + STM32_CAN_TDT0R_OFFSET),
+          getreg32(priv->base + STM32_CAN_TDL0R_OFFSET),
+          getreg32(priv->base + STM32_CAN_TDH0R_OFFSET));
+
+  ninfo(" TI1R: %08" PRIx32 " TDT1R: %08" PRIx32 " TDL1R: %08"
+          PRIx32 " TDH1R: %08" PRIx32 "\n",
+          getreg32(priv->base + STM32_CAN_TI1R_OFFSET),
+          getreg32(priv->base + STM32_CAN_TDT1R_OFFSET),
+          getreg32(priv->base + STM32_CAN_TDL1R_OFFSET),
+          getreg32(priv->base + STM32_CAN_TDH1R_OFFSET));
+
+  ninfo(" TI2R: %08" PRIx32 " TDT2R: %08" PRIx32 " TDL2R: %08"
+          PRIx32 " TDH2R: %08" PRIx32 "\n",
+          getreg32(priv->base + STM32_CAN_TI2R_OFFSET),
+          getreg32(priv->base + STM32_CAN_TDT2R_OFFSET),
+          getreg32(priv->base + STM32_CAN_TDL2R_OFFSET),
+          getreg32(priv->base + STM32_CAN_TDH2R_OFFSET));
+
+  ninfo(" RI0R: %08" PRIx32 " RDT0R: %08" PRIx32 " RDL0R: %08"
+          PRIx32 " RDH0R: %08" PRIx32 "\n",
+          getreg32(priv->base + STM32_CAN_RI0R_OFFSET),
+          getreg32(priv->base + STM32_CAN_RDT0R_OFFSET),
+          getreg32(priv->base + STM32_CAN_RDL0R_OFFSET),
+          getreg32(priv->base + STM32_CAN_RDH0R_OFFSET));
+
+  ninfo(" RI1R: %08" PRIx32 " RDT1R: %08" PRIx32 " RDL1R: %08"
+          PRIx32 " RDH1R: %08" PRIx32 "\n",
+          getreg32(priv->base + STM32_CAN_RI1R_OFFSET),
+          getreg32(priv->base + STM32_CAN_RDT1R_OFFSET),
+          getreg32(priv->base + STM32_CAN_RDL1R_OFFSET),
+          getreg32(priv->base + STM32_CAN_RDH1R_OFFSET));
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32can_dumpfiltregs
+ *
+ * Description:
+ *   Dump the contents of all CAN filter registers
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *   msg  - message
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_STM32_CAN_REGDEBUG
+static void stm32can_dumpfiltregs(FAR struct stm32_can_s *priv,
+                                  FAR const char *msg)
+{
+  int i;
+
+  if (msg)
+    {
+      ninfo("Filter Registers: %s\n", msg);
+    }
+  else
+    {
+      ninfo("Filter Registers:\n");
+    }
+
+  ninfo(" FMR: %08" PRIx32 "   FM1R: %08" PRIx32 "  FS1R: %08"
+          PRIx32 " FFA1R: %08" PRIx32 "  FA1R: %08" PRIx32 "\n",
+          getreg32(priv->base + STM32_CAN_FMR_OFFSET),
+          getreg32(priv->base + STM32_CAN_FM1R_OFFSET),
+          getreg32(priv->base + STM32_CAN_FS1R_OFFSET),
+          getreg32(priv->base + STM32_CAN_FFA1R_OFFSET),
+          getreg32(priv->base + STM32_CAN_FA1R_OFFSET));
+
+  for (i = 0; i < CAN_NFILTERS; i++)
+    {
+      ninfo(" F%dR1: %08" PRIx32 " F%dR2: %08" PRIx32 "\n",
+              i, getreg32(priv->base + STM32_CAN_FIR_OFFSET(i, 1)),
+              i, getreg32(priv->base + STM32_CAN_FIR_OFFSET(i, 2)));
+    }
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32can_rx0int
+ *
+ * Description:
+ *   Call to enable or disable RX0 interrupts.
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void stm32can_rx0int(FAR struct stm32_can_s *priv, bool enable)
+{
+  uint32_t regval = 0;
+
+  ninfo("CAN%" PRIu8 "RX0 enable: %d\n", priv->port, enable);
+
+  /* Enable/disable the FIFO 0 message pending interrupt */
+
+  regval = stm32can_getreg(priv, STM32_CAN_IER_OFFSET);
+  if (enable)
+    {
+      regval |= CAN_IER_FMPIE0;
+    }
+  else
+    {
+      regval &= ~CAN_IER_FMPIE0;
+    }
+
+  stm32can_putreg(priv, STM32_CAN_IER_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: stm32can_rx1int
+ *
+ * Description:
+ *   Call to enable or disable RX1 interrupts.
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void stm32can_rx1int(FAR struct stm32_can_s *priv, bool enable)
+{
+  uint32_t regval = 0;
+
+  ninfo("CAN%" PRIu8 "RX1 enable: %d\n", priv->port, enable);
+
+  /* Enable/disable the FIFO 1 message pending interrupt */
+
+  regval = stm32can_getreg(priv, STM32_CAN_IER_OFFSET);
+  if (enable)
+    {
+      regval |= CAN_IER_FMPIE1;
+    }
+  else
+    {
+      regval &= ~CAN_IER_FMPIE1;
+    }
+
+  stm32can_putreg(priv, STM32_CAN_IER_OFFSET, regval);
+}
+
+/****************************************************************************
+ * Name: stm32can_txint
+ *
+ * Description:
+ *   Call to enable or disable TX interrupts.
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void stm32can_txint(FAR struct stm32_can_s *priv, bool enable)
+{
+  uint32_t regval = 0;
+
+  ninfo("CAN%" PRIu8 " txint enable: %d\n", priv->port, enable);
+
+  /* Enable/disable the transmit mailbox interrupt */
+
+  regval  = stm32can_getreg(priv, STM32_CAN_IER_OFFSET);
+  if (enable)
+    {
+      regval |= CAN_IER_TMEIE;
+    }
+  else
+    {
+      regval &= ~CAN_IER_TMEIE;
+    }
+
+  stm32can_putreg(priv, STM32_CAN_IER_OFFSET, regval);
+}
+
+#ifdef CONFIG_NET_CAN_ERRORS
+/****************************************************************************
+ * Name: stm32can_txint
+ *
+ * Description:
+ *   Call to enable or disable CAN SCE interrupts.
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void stm32can_errint(FAR struct stm32_can_s *priv, bool enable)
+{
+  uint32_t regval = 0;
+
+  /* Enable/disable the transmit mailbox interrupt */
+
+  regval  = stm32can_getreg(priv, STM32_CAN_IER_OFFSET);
+  if (enable)
+    {
+      regval |= STM32_CAN_ERRINT;
+    }
+  else
+    {
+      regval &= ~STM32_CAN_ERRINT;
+    }
+
+  stm32can_putreg(priv, STM32_CAN_IER_OFFSET, regval);
+}
+#endif
+
+/****************************************************************************
+ * Function: stm32can_ifup
+ *
+ * Description:
+ *   NuttX Callback: Bring up the Ethernet interface when an IP address is
+ *   provided
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32can_ifup(struct net_driver_s *dev)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)dev->d_private;
+
+  /* Setup CAN */
+
+  stm32can_setup(priv);
+
+  /* Enable interrupts */
+
+  stm32can_rx0int(priv, true);
+  stm32can_rx1int(priv, true);
+  stm32can_txint(priv, true);
+#ifdef CONFIG_NET_CAN_ERRORS
+  stm32can_errint(priv, true);
+#endif
+
+  /* Enable the interrupts at the NVIC */
+
+  up_enable_irq(priv->canrx[0]);
+  up_enable_irq(priv->canrx[1]);
+  up_enable_irq(priv->cantx);
+#ifdef CONFIG_NET_CAN_ERRORS
+  up_enable_irq(priv->cansce);
+#endif
+
+  priv->bifup = true;
+
+  priv->txdesc = (struct can_frame *)priv->tx_pool;
+  priv->rxdesc = (struct can_frame *)priv->rx_pool;
+
+  priv->dev.d_buf = (uint8_t *)priv->txdesc;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Function: stm32can_ifdown
+ *
+ * Description:
+ *   NuttX Callback: Stop the interface.
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static int stm32can_ifdown(struct net_driver_s *dev)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)dev->d_private;
+
+  /* Disable CAN interrupts */
+
+  stm32can_shutdown(priv);
+
+  /* Reset CAN */
+
+  stm32can_reset(priv);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32can_txready
+ *
+ * Description:
+ *   Return true if the CAN hardware can accept another TX message.
+ *
+ ****************************************************************************/
+
+static bool stm32can_txready(FAR struct stm32_can_s *priv)
+{
+  uint32_t regval;
+
+  /* Return true if any mailbox is available */
+
+  regval = stm32can_getreg(priv, STM32_CAN_TSR_OFFSET);
+  ninfo("CAN%" PRIu8 " TSR: %08" PRIx32 "\n", priv->port, regval);
+
+  return (stm32can_txmb0empty(regval) || stm32can_txmb1empty(regval) ||
+          stm32can_txmb2empty(regval));
+}
+
+/****************************************************************************
+ * Name: stm32can_transmit
+ *
+ * Description:
+ *   Start hardware transmission.  Called either from the txdone interrupt
+ *   handling or from watchdog based polling.
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ * Assumptions:
+ *   May or may not be called from an interrupt handler.  In either case,
+ *   global interrupts are disabled, either explicitly or indirectly through
+ *   interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static int stm32can_transmit(FAR struct stm32_can_s *priv)
+{
+  struct can_frame *frame = (struct can_frame *)priv->dev.d_buf;
+  FAR uint8_t      *ptr;
+  uint32_t          regval;
+  uint32_t          tmp;
+  int               dlc;
+  int               txmb;
+
+  ninfo("CAN%" PRIu8 " ID: %" PRIu32 " DLC: %" PRIu8 "\n",
+        priv->port, (uint32_t)frame->can_id, frame->can_dlc);
+
+  /* Select one empty transmit mailbox */
+
+  regval = stm32can_getreg(priv, STM32_CAN_TSR_OFFSET);
+  if (stm32can_txmb0empty(regval))
+    {
+      txmb = 0;
+    }
+  else if (stm32can_txmb1empty(regval))
+    {
+      txmb = 1;
+    }
+  else if (stm32can_txmb2empty(regval))
+    {
+      txmb = 2;
+    }
+  else
+    {
+      canerr("ERROR: No available mailbox\n");
+      return -EBUSY;
+    }
+
+  /* Clear TXRQ, RTR, IDE, EXID, and STID fields */
+
+  regval  = stm32can_getreg(priv, STM32_CAN_TIR_OFFSET(txmb));
+  regval &= ~(CAN_TIR_TXRQ | CAN_TIR_RTR | CAN_TIR_IDE |
+              CAN_TIR_EXID_MASK | CAN_TIR_STID_MASK);
+  stm32can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval);
+
+  /* Set up the ID, standard 11-bit or extended 29-bit. */
+
+#ifdef CONFIG_CAN_EXTID
+  regval &= ~CAN_TIR_EXID_MASK;
+  if (frame->can_id & CAN_EFF_FLAG)
+    {
+      DEBUGASSERT(frame->can_id < (1 << 29));
+      regval |= (frame->can_id << CAN_TIR_EXID_SHIFT) | CAN_TIR_IDE;
+    }
+  else
+    {
+      DEBUGASSERT(frame->can_id < (1 << 11));
+      regval |= frame->can_id << CAN_TIR_STID_SHIFT;
+    }
+
+#else
+  regval |= (((uint32_t) frame->can_id << CAN_TIR_STID_SHIFT) &
+               CAN_TIR_STID_MASK);
+
+#endif
+
+#ifdef CONFIG_CAN_USE_RTR
+  regval |= ((frame->can_id & CAN_RTR_FLAG) ? CAN_TIR_RTR : 0);
+#endif
+
+  stm32can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval);
+
+  /* Set up the DLC */
+
+  dlc     = frame->can_dlc;
+  regval  = stm32can_getreg(priv, STM32_CAN_TDTR_OFFSET(txmb));
+  regval &= ~(CAN_TDTR_DLC_MASK | CAN_TDTR_TGT);
+  regval |= (uint32_t)dlc << CAN_TDTR_DLC_SHIFT;
+  stm32can_putreg(priv, STM32_CAN_TDTR_OFFSET(txmb), regval);
+
+  /* Set up the data fields */
+
+  ptr    = frame->data;
+  regval = 0;
+
+  if (dlc > 0)
+    {
+      tmp    = (uint32_t)*ptr++;
+      regval = tmp << CAN_TDLR_DATA0_SHIFT;
+
+      if (dlc > 1)
+        {
+          tmp     = (uint32_t)*ptr++;
+          regval |= tmp << CAN_TDLR_DATA1_SHIFT;
+
+          if (dlc > 2)
+            {
+              tmp     = (uint32_t)*ptr++;
+              regval |= tmp << CAN_TDLR_DATA2_SHIFT;
+
+              if (dlc > 3)
+                {
+                  tmp     = (uint32_t)*ptr++;
+                  regval |= tmp << CAN_TDLR_DATA3_SHIFT;
+                }
+            }
+        }
+    }
+
+  stm32can_putreg(priv, STM32_CAN_TDLR_OFFSET(txmb), regval);
+
+  regval = 0;
+  if (dlc > 4)
+    {
+      tmp    = (uint32_t)*ptr++;
+      regval = tmp << CAN_TDHR_DATA4_SHIFT;
+
+      if (dlc > 5)
+        {
+          tmp     = (uint32_t)*ptr++;
+          regval |= tmp << CAN_TDHR_DATA5_SHIFT;
+
+          if (dlc > 6)
+            {
+              tmp     = (uint32_t)*ptr++;
+              regval |= tmp << CAN_TDHR_DATA6_SHIFT;
+
+              if (dlc > 7)
+                {
+                  tmp     = (uint32_t)*ptr++;
+                  regval |= tmp << CAN_TDHR_DATA7_SHIFT;
+                }
+            }
+        }
+    }
+
+  stm32can_putreg(priv, STM32_CAN_TDHR_OFFSET(txmb), regval);
+
+  /* Enable the transmit mailbox empty interrupt (may already be enabled) */
+
+  regval  = stm32can_getreg(priv, STM32_CAN_IER_OFFSET);
+  regval |= CAN_IER_TMEIE;
+  stm32can_putreg(priv, STM32_CAN_IER_OFFSET, regval);
+
+  /* Request transmission */
+
+  regval  = stm32can_getreg(priv, STM32_CAN_TIR_OFFSET(txmb));
+  regval |= CAN_TIR_TXRQ;  /* Transmit Mailbox Request */
+  stm32can_putreg(priv, STM32_CAN_TIR_OFFSET(txmb), regval);
+
+  stm32can_dumpmbregs(priv, "After send");
+  return OK;
+}
+
+/****************************************************************************
+ * Function: stm32can_txpoll
+ *
+ * Description:
+ *   The transmitter is available, check if the network has any outgoing
+ *   packets ready to send.  This is a callback from devif_poll().
+ *   devif_poll() may be called:
+ *
+ *   1. When the preceding TX packet send is complete,
+ *   2. When the preceding TX packet send timesout and the interface is reset
+ *   3. During normal TX polling
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ * Assumptions:
+ *   May or may not be called from an interrupt handler.  In either case,
+ *   global interrupts are disabled, either explicitly or indirectly through
+ *   interrupt handling logic.
+ *
+ ****************************************************************************/
+
+static int stm32can_txpoll(struct net_driver_s *dev)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)dev->d_private;
+
+  /* If the polling resulted in data that should be sent out on the network,
+   * the field d_len is set to a value > 0.
+   */
+
+  if (priv->dev.d_len > 0)
+    {
+      if (!devif_loopback(&priv->dev))
+        {
+          stm32can_txdone(priv);
+
+          /* Send the packet */
+
+          stm32can_transmit(priv);
+
+          /* Check if there is room in the device to hold another packet. If
+           * not, return a non-zero value to terminate the poll.
+           */
+
+          if (stm32can_txready(priv) == false)
+            {
+              return -EBUSY;
+            }
+        }
+    }
+
+  /* If zero is returned, the polling will continue until all connections
+   * have been examined.
+   */
+
+  return 0;
+}
+
+/****************************************************************************
+ * Function: stm32can_txavail_work
+ *
+ * Description:
+ *   Perform an out-of-cycle poll on the worker thread.
+ *
+ * Input Parameters:
+ *   arg - Reference to the NuttX driver state structure (cast to void*)
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called on the higher priority worker thread.
+ *
+ ****************************************************************************/
+
+static void stm32can_txavail_work(FAR void *arg)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)arg;
+
+  /* Ignore the notification if the interface is not yet up */
+
+  net_lock();
+  if (priv->bifup)
+    {
+      /* Check if there is room in the hardware to hold another outgoing
+       * packet.
+       */
+
+      if (stm32can_txready(priv))
+        {
+          /* No, there is space for another transfer.  Poll the network for
+           * new XMIT data.
+           */
+
+          devif_timer(&priv->dev, 0, stm32can_txpoll);
+        }
+    }
+
+  net_unlock();
+}
+
+/****************************************************************************
+ * Function: stm32can_txavail
+ *
+ * Description:
+ *   Driver callback invoked when new TX data is available.  This is a
+ *   stimulus perform an out-of-cycle poll and, thereby, reduce the TX
+ *   latency.
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *   Called in normal user mode
+ *
+ ****************************************************************************/
+
+static int stm32can_txavail(struct net_driver_s *dev)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)dev->d_private;
+
+  /* Is our single work structure available?  It may not be if there are
+   * pending interrupt actions and we will have to ignore the Tx
+   * availability action.
+   */
+
+  if (work_available(&priv->pollwork))
+    {
+      /* Schedule to serialize the poll on the worker thread. */
+
+      stm32can_txavail_work(priv);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Function: stm32can_ioctl
+ *
+ * Description:
+ *   PHY ioctl command handler
+ *
+ * Input Parameters:
+ *   dev  - Reference to the NuttX driver state structure
+ *   cmd  - ioctl command
+ *   arg  - Argument accompanying the command
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_NETDEV_IOCTL
+static int stm32can_netdev_ioctl(struct net_driver_s *dev, int cmd,
+                                 unsigned long arg)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)dev->d_private;
+  int                     ret  = OK;
+
+  switch (cmd)
+    {
+      /* TODO */
+
+      default:
+        ret = -ENOTTY;
+        break;
+    }
+
+  return ret;
+}
+#endif /* CONFIG_NETDEV_IOCTL */
+
+/****************************************************************************
+ * Name: stm32can_rxinterrupt_work
+ *
+ * Description:
+ *   CAN RX FIFO 0/1 interrupt handler
+ *
+ * Input Parameters:
+ *   irq - The IRQ number of the interrupt.
+ *   context - The register state save array at the time of the interrupt.
+ *   rxmb - The RX mailbox number.
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int stm32can_rxinterrupt_work(FAR struct stm32_can_s *priv, int rxmb)
+{
+  FAR struct can_frame *frame = (struct can_frame *)priv->rxdesc;
+  uint32_t              regval;
+  int                   ret   = OK;
+
+  DEBUGASSERT(priv != NULL);
+
+  if (rxmb == 0)
+    {
+      stm32can_dumpmbregs(priv, "RX0 interrupt");
+    }
+  else
+    {
+      stm32can_dumpmbregs(priv, "RX1 interrupt");
+    }
+
+  /* Get the CAN identifier. */
+
+  regval = stm32can_getreg(priv, STM32_CAN_RIR_OFFSET(rxmb));
+
+#ifdef CONFIG_CAN_EXTID
+  if ((regval & CAN_RIR_IDE) != 0)
+    {
+      frame->can_id  = (regval & CAN_RIR_EXID_MASK) >> CAN_RIR_EXID_SHIFT;
+      frame->can_id &= ~CAN_EFF_FLAG;
+    }
+  else
+    {
+      frame->can_id  = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT;
+      frame->can_id |= CAN_EFF_FLAG;
+    }
+#else
+  if ((regval & CAN_RIR_IDE) != 0)
+    {
+      nerr("ERROR: Received message with extended identifier.  Dropped\n");
+      ret = -ENOSYS;
+      goto errout;
+    }
+
+  frame->can_id = (regval & CAN_RIR_STID_MASK) >> CAN_RIR_STID_SHIFT;
+#endif
+
+  /* Extract the RTR bit */
+
+  if ((regval & CAN_RIR_RTR) != 0)
+    {
+      frame->can_id |= CAN_RTR_FLAG;
+    }
+
+  /* Get the DLC */
+
+  regval        = stm32can_getreg(priv, STM32_CAN_RDTR_OFFSET(rxmb));
+  frame->can_dlc = (regval & CAN_RDTR_DLC_MASK) >> CAN_RDTR_DLC_SHIFT;
+
+  /* Save the message data */
+
+  regval  = stm32can_getreg(priv, STM32_CAN_RDLR_OFFSET(rxmb));
+  frame->data[0] = (regval & CAN_RDLR_DATA0_MASK) >> CAN_RDLR_DATA0_SHIFT;
+  frame->data[1] = (regval & CAN_RDLR_DATA1_MASK) >> CAN_RDLR_DATA1_SHIFT;
+  frame->data[2] = (regval & CAN_RDLR_DATA2_MASK) >> CAN_RDLR_DATA2_SHIFT;
+  frame->data[3] = (regval & CAN_RDLR_DATA3_MASK) >> CAN_RDLR_DATA3_SHIFT;
+
+  regval  = stm32can_getreg(priv, STM32_CAN_RDHR_OFFSET(rxmb));
+  frame->data[4] = (regval & CAN_RDHR_DATA4_MASK) >> CAN_RDHR_DATA4_SHIFT;
+  frame->data[5] = (regval & CAN_RDHR_DATA5_MASK) >> CAN_RDHR_DATA5_SHIFT;
+  frame->data[6] = (regval & CAN_RDHR_DATA6_MASK) >> CAN_RDHR_DATA6_SHIFT;
+  frame->data[7] = (regval & CAN_RDHR_DATA7_MASK) >> CAN_RDHR_DATA7_SHIFT;
+
+  /* Copy the buffer pointer to priv->dev..  Set amount of data
+   * in priv->dev.d_len
+   */
+
+  priv->dev.d_len = sizeof(struct can_frame);
+  priv->dev.d_buf = (uint8_t *)frame;
+
+  /* Send to socket interface */
+
+  NETDEV_RXPACKETS(&priv->dev);
+
+  can_input(&priv->dev);
+
+  /* Point the packet buffer back to the next Tx buffer that will be
+   * used during the next write.  If the write queue is full, then
+   * this will point at an active buffer, which must not be written
+   * to.  This is OK because devif_poll won't be called unless the
+   * queue is not full.
+   */
+
+  priv->dev.d_buf = (uint8_t *)priv->txdesc;
+
+  /* Release the FIFO */
+
+#ifndef CONFIG_CAN_EXTID
+errout:
+#endif
+  regval  = stm32can_getreg(priv, STM32_CAN_RFR_OFFSET(rxmb));
+  regval |= CAN_RFR_RFOM;
+  stm32can_putreg(priv, STM32_CAN_RFR_OFFSET(rxmb), regval);
+
+  /* Re-enable CAN RX interrupts */
+
+  if (rxmb == 0)
+    {
+      stm32can_rx0int(priv, true);
+    }
+  else if (rxmb == 1)
+    {
+      stm32can_rx1int(priv, true);
+    }
+  else
+    {
+      DEBUGASSERT(0);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: stm32can_rx0interrupt_work
+ ****************************************************************************/
+
+static void stm32can_rx0interrupt_work(FAR void *arg)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)arg;
+  stm32can_rxinterrupt_work(priv, 0);
+}
+
+/****************************************************************************
+ * Name: stm32can_rx1interrupt_work
+ ****************************************************************************/
+
+static void stm32can_rx1interrupt_work(FAR void *arg)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)arg;
+  stm32can_rxinterrupt_work(priv, 1);
+}
+
+/****************************************************************************
+ * Name: stm32can_rxinterrupt
+ *
+ * Description:
+ *   CAN RX FIFO common interrupt handler
+ *
+ ****************************************************************************/
+
+static int stm32can_rxinterrupt(FAR struct stm32_can_s *priv, int rxmb)
+{
+  uint32_t regval   = 0;
+  int      npending = 0;
+
+  /* Verify that a message is pending in the FIFO */
+
+  regval   = stm32can_getreg(priv, STM32_CAN_RFR_OFFSET(rxmb));
+  npending = (regval & CAN_RFR_FMP_MASK) >> CAN_RFR_FMP_SHIFT;
+  if (npending < 1)
+    {
+      nwarn("WARNING: No messages pending\n");
+      return OK;
+    }
+
+  /* Disable further CAN RX interrupts and schedule to perform the
+   * interrupt processing on the worker thread
+   */
+
+  if (rxmb == 0)
+    {
+      stm32can_rx0int(priv, false);
+      work_queue(CANWORK, &priv->irqwork,
+                 stm32can_rx0interrupt_work, priv, 0);
+    }
+  else if (rxmb == 1)
+    {
+      stm32can_rx1int(priv, false);
+      work_queue(CANWORK, &priv->irqwork,
+                 stm32can_rx1interrupt_work, priv, 0);
+    }
+  else
+    {
+      DEBUGASSERT(0);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32can_rx0interrupt
+ *
+ * Description:
+ *   CAN RX FIFO 0 interrupt handler
+ *
+ * Input Parameters:
+ *   irq - The IRQ number of the interrupt.
+ *   context - The register state save array at the time of the interrupt.
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int stm32can_rx0interrupt(int irq, FAR void *context, FAR void *arg)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)arg;
+  return stm32can_rxinterrupt(priv, 0);
+}
+
+/****************************************************************************
+ * Name: stm32can_rx1interrupt
+ *
+ * Description:
+ *   CAN RX FIFO 1 interrupt handler
+ *
+ * Input Parameters:
+ *   irq - The IRQ number of the interrupt.
+ *   context - The register state save array at the time of the interrupt.
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int stm32can_rx1interrupt(int irq, FAR void *context, FAR void *arg)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)arg;
+  return stm32can_rxinterrupt(priv, 1);
+}
+
+/****************************************************************************
+ * Name: stm32can_txinterrupt
+ *
+ * Description:
+ *   CAN TX mailbox complete interrupt handler
+ *
+ * Input Parameters:
+ *   irq - The IRQ number of the interrupt.
+ *   context - The register state save array at the time of the interrupt.
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int stm32can_txinterrupt(int irq, FAR void *context, FAR void *arg)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)arg;
+  uint32_t regval;
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Get the transmit status */
+
+  regval = stm32can_getreg(priv, STM32_CAN_TSR_OFFSET);
+
+  /* Check for RQCP0: Request completed mailbox 0 */
+
+  if ((regval & CAN_TSR_RQCP0) != 0)
+    {
+      /* Writing '1' to RCP0 clears RCP0 and all the status bits (TXOK0,
+       * ALST0 and TERR0) for Mailbox 0.
+       */
+
+      stm32can_putreg(priv, STM32_CAN_TSR_OFFSET, CAN_TSR_RQCP0);
+
+      /* Tell the upper half that the transfer is finished. */
+
+      /* Disable further TX CAN interrupts. here can be no race
+       * condition here.
+       */
+
+      stm32can_txint(priv, false);
+      work_queue(CANWORK, &priv->irqwork, stm32can_txdone_work, priv, 0);
+    }
+
+  /* Check for RQCP1: Request completed mailbox 1 */
+
+  if ((regval & CAN_TSR_RQCP1) != 0)
+    {
+      /* Writing '1' to RCP1 clears RCP1 and all the status bits (TXOK1,
+       * ALST1 and TERR1) for Mailbox 1.
+       */
+
+      stm32can_putreg(priv, STM32_CAN_TSR_OFFSET, CAN_TSR_RQCP1);
+
+      /* Tell the upper half that the transfer is finished. */
+
+      /* Disable further TX CAN interrupts. here can be no race
+       * condition here.
+       */
+
+      stm32can_txint(priv, false);
+      work_queue(CANWORK, &priv->irqwork, stm32can_txdone_work, priv, 0);
+    }
+
+  /* Check for RQCP2: Request completed mailbox 2 */
+
+  if ((regval & CAN_TSR_RQCP2) != 0)
+    {
+      /* Writing '1' to RCP2 clears RCP2 and all the status bits (TXOK2,
+       * ALST2 and TERR2) for Mailbox 2.
+       */
+
+      stm32can_putreg(priv, STM32_CAN_TSR_OFFSET, CAN_TSR_RQCP2);
+
+      /* Disable further TX CAN interrupts. here can be no race
+       * condition here.
+       */
+
+      stm32can_txint(priv, false);
+      work_queue(CANWORK, &priv->irqwork, stm32can_txdone_work, priv, 0);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32can_txdone_work
+ ****************************************************************************/
+
+static void stm32can_txdone_work(FAR void *arg)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)arg;
+
+  stm32can_txdone(priv);
+
+  /* There should be space for a new TX in any event.  Poll the network for
+   * new XMIT data
+   */
+
+  net_lock();
+  devif_timer(&priv->dev, 0, stm32can_txpoll);
+  net_unlock();
+}
+
+/****************************************************************************
+ * Name: stm32can_txdone
+ ****************************************************************************/
+
+static void stm32can_txdone(FAR struct stm32_can_s *priv)
+{
+  stm32can_txint(priv, true);
+
+  NETDEV_TXDONE(&priv->dev);
+}
+
+#ifdef CONFIG_NET_CAN_ERRORS
+
+/****************************************************************************
+ * Name: stm32can_sceinterrupt_work
+ *
+ * Description:
+ *   CAN status change interrupt work
+ *
+ * Input Parameters:
+ *   arg  - reference to the driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void stm32can_sceinterrupt_work(FAR void *arg)
+{
+  FAR struct stm32_can_s *priv    = (FAR struct stm32_can_s *)arg;
+  struct can_frame       *frame   = (struct can_frame *)priv->rxdesc;
+  uint32_t                regval  = 0;
+  uint16_t                errbits = 0;
+  uint8_t                 data[CAN_ERR_DLC];
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Check Error Interrupt flag */
+
+  regval = stm32can_getreg(priv, STM32_CAN_MSR_OFFSET);
+  if (regval & CAN_MSR_ERRI)
+    {
+      /* Encode error bits */
+
+      errbits = 0;
+      memset(data, 0, sizeof(data));
+
+      /* Get Error statur register */
+
+      regval = stm32can_getreg(priv, STM32_CAN_ESR_OFFSET);
+
+      if (regval & CAN_ESR_EWGF)
+        {
+          /* Error warning flag */
+
+          data[1] |= (CAN_ERR_CTRL_RX_WARNING | CAN_ERR_CTRL_TX_WARNING);
+          errbits |= CAN_ERR_CTRL;
+        }
+
+      if (regval & CAN_ESR_EPVF)
+        {
+          /* Error passive flag */
+
+          data[1] |= (CAN_ERR_CTRL_RX_PASSIVE | CAN_ERR_CTRL_TX_PASSIVE);
+          errbits |= CAN_ERR_CTRL;
+        }
+
+      if (regval & CAN_ESR_BOFF)
+        {
+          /* Bus-off flag */
+
+          errbits |= CAN_ERR_BUSOFF;
+        }
+
+      /* Last error code */
+
+      if (regval & CAN_ESR_LEC_MASK)
+        {
+          if (regval & CAN_ESR_STUFFERROR)
+            {
+              /* Stuff Error */
+
+              errbits |= CAN_ERR_PROT;
+              data[2] |= CAN_ERR_PROT_STUFF;
+            }
+          else if (regval & CAN_ESR_FORMERROR)
+            {
+              /* Format Error */
+
+              errbits |= CAN_ERR_PROT;
+              data[2] |= CAN_ERR_PROT_FORM;
+            }
+          else if (regval & CAN_ESR_ACKERROR)
+            {
+              /* Acknowledge Error */
+
+              errbits |= CAN_ERR_ACK;
+            }
+          else if (regval & CAN_ESR_BRECERROR)
+            {
+              /* Bit recessive Error */
+
+              errbits |= CAN_ERR_PROT;
+              data[2] |= CAN_ERR_PROT_BIT1;
+            }
+          else if (regval & CAN_ESR_BDOMERROR)
+            {
+              /* Bit dominant Error */
+
+              errbits |= CAN_ERR_PROT;
+              data[2] |= CAN_ERR_PROT_BIT0;
+            }
+          else if (regval & CAN_ESR_CRCERRPR)
+            {
+              /* Receive CRC Error */
+
+              errbits |= CAN_ERR_PROT;
+              data[3] |= CAN_ERR_PROT_LOC_CRCSEQ;
+            }
+        }
+
+      /* Get transmit status register */
+
+      regval = stm32can_getreg(priv, STM32_CAN_TSR_OFFSET);
+
+      if (regval & CAN_TSR_ALST0 || regval & CAN_TSR_ALST1 ||
+          regval & CAN_TSR_ALST2)
+        {
+          /* Lost arbitration Error */
+
+          errbits |= CAN_ERR_LOSTARB;
+        }
+
+      /* Clear TSR register */
+
+      stm32can_putreg(priv, STM32_CAN_TSR_OFFSET, regval);
+
+      /* Clear ERRI flag */
+
+      stm32can_putreg(priv, STM32_CAN_MSR_OFFSET, CAN_MSR_ERRI);
+    }
+
+  /* Report a CAN error */
+
+  if (errbits != 0)
+    {
+      canerr("ERROR: errbits = %08" PRIx16 "\n", errbits);
+
+      /* Copy frame */
+
+      frame->can_id  = errbits;
+      frame->can_dlc = CAN_ERR_DLC;
+
+      memcpy(frame->data, data, CAN_ERR_DLC);
+
+      /* Copy the buffer pointer to priv->dev..  Set amount of data
+       * in priv->dev.d_len
+       */
+
+      priv->dev.d_len = sizeof(struct can_frame);
+      priv->dev.d_buf = (uint8_t *)frame;
+
+      /* Send to socket interface */
+
+      NETDEV_ERRORS(&priv->dev);
+
+      can_input(&priv->dev);
+
+      /* Point the packet buffer back to the next Tx buffer that will be
+       * used during the next write.  If the write queue is full, then
+       * this will point at an active buffer, which must not be written
+       * to.  This is OK because devif_poll won't be called unless the
+       * queue is not full.
+       */
+
+      priv->dev.d_buf = (uint8_t *)priv->txdesc;
+    }
+
+  /* Re-enable CAN SCE interrupts */
+
+  stm32can_errint(priv, true);
+}
+
+/****************************************************************************
+ * Name: stm32can_sceinterrupt
+ *
+ * Description:
+ *   CAN status change interrupt handler
+ *
+ * Input Parameters:
+ *   irq - The IRQ number of the interrupt.
+ *   context - The register state save array at the time of the interrupt.
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int stm32can_sceinterrupt(int irq, FAR void *context, FAR void *arg)
+{
+  FAR struct stm32_can_s *priv = (FAR struct stm32_can_s *)arg;
+
+  /* Disable further CAN SCE interrupts and schedule to perform the
+   * interrupt processing on the worker thread
+   */
+
+  stm32can_errint(priv, false);
+  work_queue(CANWORK, &priv->irqwork,
+             stm32can_sceinterrupt_work, priv, 0);
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: stm32can_bittiming
+ *
+ * Description:
+ *   Set the CAN bit timing register (BTR) based on the configured BAUD.
+ *
+ * "The bit timing logic monitors the serial bus-line and performs sampling
+ *  and adjustment of the sample point by synchronizing on the start-bit edge
+ *  and resynchronizing on the following edges.
+ *
+ * "Its operation may be explained simply by splitting nominal bit time into
+ *  three segments as follows:
+ *
+ * 1. "Synchronization segment (SYNC_SEG): a bit change is expected to occur
+ *     within this time segment. It has a fixed length of one time quantum
+ *     (1 x tCAN).
+ * 2. "Bit segment 1 (BS1): defines the location of the sample point. It
+ *     includes the PROP_SEG and PHASE_SEG1 of the CAN standard. Its duration
+ *     is programmable between 1 and 16 time quanta but may be automatically
+ *     lengthened to compensate for positive phase drifts due to differences
+ *     in the frequency of the various nodes of the network.
+ * 3. "Bit segment 2 (BS2): defines the location of the transmit point. It
+ *     represents the PHASE_SEG2 of the CAN standard. Its duration is
+ *     programmable between 1 and 8 time quanta but may also be automatically
+ *     shortened to compensate for negative phase drifts."
+ *
+ * Pictorially:
+ *
+ *  |<----------------- NOMINAL BIT TIME ----------------->|
+ *  |<- SYNC_SEG ->|<------ BS1 ------>|<------ BS2 ------>|
+ *  |<---- Tq ---->|<----- Tbs1 ------>|<----- Tbs2 ------>|
+ *
+ * Where
+ *   Tbs1 is the duration of the BS1 segment
+ *   Tbs2 is the duration of the BS2 segment
+ *   Tq is the "Time Quantum"
+ *
+ * Relationships:
+ *
+ *   baud = 1 / bit_time
+ *   bit_time = Tq + Tbs1 + Tbs2
+ *   Tbs1 = Tq * ts1
+ *   Tbs2 = Tq * ts2
+ *   Tq = brp * Tpclk1
+ *   baud = Fpclk1 / (brp  * (1 + ts1 + ts2))
+ *
+ * Where:
+ *   Tpclk1 is the period of the APB1 clock (PCLK1).
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int stm32can_bittiming(FAR struct stm32_can_s *priv)
+{
+  uint32_t tmp;
+  uint32_t brp;
+  uint32_t ts1;
+  uint32_t ts2;
+
+  ninfo("CAN%" PRIu8 " PCLK1: %lu baud: %" PRIu32 "\n",
+          priv->port, (unsigned long) STM32_PCLK1_FREQUENCY, priv->baud);
+
+  /* Try to get CAN_BIT_QUANTA quanta in one bit_time.
+   *
+   *   bit_time = Tq*(ts1 + ts2 + 1)
+   *   nquanta  = bit_time / Tq
+   *   nquanta  = (ts1 + ts2 + 1)
+   *
+   *   bit_time = brp * Tpclk1 * (ts1 + ts2 + 1)
+   *   nquanta  = bit_time / brp / Tpclk1
+   *            = PCLK1 / baud / brp
+   *   brp      = PCLK1 / baud / nquanta;
+   *
+   * Example:
+   *   PCLK1 = 42,000,000 baud = 1,000,000 nquanta = 14 : brp = 3
+   *   PCLK1 = 42,000,000 baud =   700,000 nquanta = 14 : brp = 4
+   */
+
+  tmp = STM32_PCLK1_FREQUENCY / priv->baud;
+  if (tmp < CAN_BIT_QUANTA)
+    {
+      /* At the smallest brp value (1), there are already too few bit times
+       * (PCLCK1 / baud) to meet our goal.  brp must be one and we need
+       * make some reasonable guesses about ts1 and ts2.
+       */
+
+      brp = 1;
+
+      /* In this case, we have to guess a good value for ts1 and ts2 */
+
+      ts1 = (tmp - 1) >> 1;
+      ts2 = tmp - ts1 - 1;
+      if (ts1 == ts2 && ts1 > 1 && ts2 < CAN_BTR_TSEG2_MAX)
+        {
+          ts1--;
+          ts2++;
+        }
+    }
+
+  /* Otherwise, nquanta is CAN_BIT_QUANTA, ts1 is CONFIG_STM32_CAN_TSEG1,
+   * ts2 is CONFIG_STM32_CAN_TSEG2 and we calculate brp to achieve
+   * CAN_BIT_QUANTA quanta in the bit time
+   */
+
+  else
+    {
+      ts1 = CONFIG_STM32_CAN_TSEG1;
+      ts2 = CONFIG_STM32_CAN_TSEG2;
+      brp = (tmp + (CAN_BIT_QUANTA / 2)) / CAN_BIT_QUANTA;
+      DEBUGASSERT(brp >= 1 && brp <= CAN_BTR_BRP_MAX);
+    }
+
+  ninfo("TS1: %" PRIu32 " TS2: %" PRIu32 " BRP: %" PRIu32 "\n",
+               ts1, ts2, brp);
+
+  /* Configure bit timing.  This also does the following, less obvious
+   * things.  Unless loopback mode is enabled, it:
+   *
+   * - Disables silent mode.
+   * - Disables loopback mode.
+   *
+   * NOTE that for the time being, SJW is set to 1 just because I don't
+   * know any better.
+   */
+
+  tmp = ((brp - 1) << CAN_BTR_BRP_SHIFT) | ((ts1 - 1) << CAN_BTR_TS1_SHIFT) |
+        ((ts2 - 1) << CAN_BTR_TS2_SHIFT) | ((1 - 1) << CAN_BTR_SJW_SHIFT);
+#ifdef CONFIG_CAN_LOOPBACK
+  /* tmp |= (CAN_BTR_LBKM | CAN_BTR_SILM); */
+
+  tmp |= CAN_BTR_LBKM;
+#endif
+
+  stm32can_putreg(priv, STM32_CAN_BTR_OFFSET, tmp);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32can_setup
+ ****************************************************************************/
+
+static int  stm32can_setup(FAR struct stm32_can_s *priv)
+{
+  int ret;
+
+#ifdef CONFIG_NET_CAN_ERRORS
+  ninfo("CAN%" PRIu8 " RX0 irq: %" PRIu8 " RX1 irq: %" PRIu8
+        " TX irq: %" PRIu8 " SCE irq: %" PRIu8 "\n",
+        priv->port, priv->canrx[0], priv->canrx[1], priv->cantx,
+        priv->cansce);
+#else
+  ninfo("CAN%" PRIu8 " RX0 irq: %" PRIu8 " RX1 irq: %" PRIu8
+        " TX irq: %" PRIu8 "\n",
+        priv->port, priv->canrx[0], priv->canrx[1], priv->cantx);
+#endif
+
+  /* CAN cell initialization */
+
+  ret = stm32can_cellinit(priv);
+  if (ret < 0)
+    {
+      nerr("ERROR: CAN%" PRId8 " cell initialization failed: %d\n",
+             priv->port, ret);
+      return ret;
+    }
+
+  stm32can_dumpctrlregs(priv, "After cell initialization");
+  stm32can_dumpmbregs(priv, NULL);
+
+  /* CAN filter initialization */
+
+  ret = stm32can_filterinit(priv);
+  if (ret < 0)
+    {
+      nerr("ERROR: CAN%" PRIu8 " filter initialization failed: %d\n",
+             priv->port, ret);
+      return ret;
+    }
+
+  stm32can_dumpfiltregs(priv, "After filter initialization");
+
+  /* Attach the CAN RX FIFO 0/1 interrupts and TX interrupts.
+   * The others are not used.
+   */
+
+  ret = irq_attach(priv->canrx[0], stm32can_rx0interrupt, priv);
+  if (ret < 0)
+    {
+      nerr("ERROR: Failed to attach CAN%" PRIu8 " RX0 IRQ (%" PRIu8 ")",
+             priv->port, priv->canrx[0]);
+      return ret;
+    }
+
+  ret = irq_attach(priv->canrx[1], stm32can_rx1interrupt, priv);
+  if (ret < 0)
+    {
+      nerr("ERROR: Failed to attach CAN%" PRIu8 " RX1 IRQ (%" PRIu8 ")",
+             priv->port, priv->canrx[1]);
+      return ret;
+    }
+
+  ret = irq_attach(priv->cantx, stm32can_txinterrupt, priv);
+  if (ret < 0)
+    {
+      nerr("ERROR: Failed to attach CAN%" PRIu8 " TX IRQ (%" PRIu8 ")",
+             priv->port, priv->cantx);
+      return ret;
+    }
+
+#ifdef CONFIG_NET_CAN_ERRORS
+  ret = irq_attach(priv->cansce, stm32can_sceinterrupt, priv);
+  if (ret < 0)
+    {
+      nerr("ERROR: Failed to attach CAN%" PRIu8 " SCE IRQ (%" PRIu8 ")",
+           priv->port, priv->cansce);
+      return ret;
+    }
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32can_shutdown
+ ****************************************************************************/
+
+static void stm32can_shutdown(FAR struct stm32_can_s *priv)
+{
+  ninfo("CAN%" PRIu8 "\n", priv->port);
+
+  /* Disable the RX FIFO 0/1 and TX interrupts */
+
+  up_disable_irq(priv->canrx[0]);
+  up_disable_irq(priv->canrx[1]);
+  up_disable_irq(priv->cantx);
+#ifdef CONFIG_NET_CAN_ERRORS
+  up_disable_irq(priv->cansce);
+#endif
+
+  /* Detach the RX FIFO 0/1 and TX interrupts */
+
+  irq_detach(priv->canrx[0]);
+  irq_detach(priv->canrx[1]);
+  irq_detach(priv->cantx);
+#ifdef CONFIG_NET_CAN_ERRORS
+  irq_detach(priv->cansce);
+#endif
+}
+
+/****************************************************************************
+ * Name: stm32can_reset
+ *
+ * Description:
+ *   Put the CAN device in the non-operational, reset state
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void stm32can_reset(FAR struct stm32_can_s *priv)
+{
+  uint32_t regval;
+  uint32_t regbit = 0;
+  irqstate_t flags;
+
+  ninfo("CAN%" PRIu8 "\n", priv->port);
+
+  /* Get the bits in the AHB1RSTR register needed to reset this CAN device */
+
+#ifdef CONFIG_STM32_CAN1
+  if (priv->port == 1)
+    {
+      regbit = RCC_APB1RSTR_CAN1RST;
+    }
+  else
+#endif
+#ifdef CONFIG_STM32_CAN2
+  if (priv->port == 2)
+    {
+      regbit = RCC_APB1RSTR_CAN2RST;
+    }
+  else
+#endif
+    {
+      nerr("ERROR: Unsupported port %d\n", priv->port);
+      return;
+    }
+
+  /* Disable interrupts momentarily to stop any ongoing CAN event processing
+   * and to prevent any concurrent access to the AHB1RSTR register.
+   */
+
+  flags = enter_critical_section();
+
+  /* Reset the CAN */
+
+  regval  = getreg32(STM32_RCC_APB1RSTR);
+  regval |= regbit;
+  putreg32(regval, STM32_RCC_APB1RSTR);
+
+  regval &= ~regbit;
+  putreg32(regval, STM32_RCC_APB1RSTR);
+  leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Name: stm32can_enterinitmode
+ *
+ * Description:
+ *   Put the CAN cell in Initialization mode. This only disconnects the CAN
+ *   peripheral, no registers are changed. The initialization mode is
+ *   required to change the baud rate.
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32can_enterinitmode(FAR struct stm32_can_s *priv)
+{
+  uint32_t regval;
+  volatile uint32_t timeout;
+
+  ninfo("CAN%" PRIu8 "\n", priv->port);
+
+  /* Enter initialization mode */
+
+  regval  = stm32can_getreg(priv, STM32_CAN_MCR_OFFSET);
+  regval |= CAN_MCR_INRQ;
+  stm32can_putreg(priv, STM32_CAN_MCR_OFFSET, regval);
+
+  /* Wait until initialization mode is acknowledged */
+
+  for (timeout = INAK_TIMEOUT; timeout > 0; timeout--)
+    {
+      regval = stm32can_getreg(priv, STM32_CAN_MSR_OFFSET);
+      if ((regval & CAN_MSR_INAK) != 0)
+        {
+          /* We are in initialization mode */
+
+          break;
+        }
+    }
+
+  /* Check for a timeout */
+
+  if (timeout < 1)
+    {
+      nerr("ERROR: Timed out waiting to enter initialization mode\n");
+      return -ETIMEDOUT;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32can_exitinitmode
+ *
+ * Description:
+ *   Put the CAN cell out of the Initialization mode (to Normal mode)
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32can_exitinitmode(FAR struct stm32_can_s *priv)
+{
+  uint32_t regval;
+  volatile uint32_t timeout;
+
+  /* Exit Initialization mode, enter Normal mode */
+
+  regval  = stm32can_getreg(priv, STM32_CAN_MCR_OFFSET);
+  regval &= ~CAN_MCR_INRQ;
+  stm32can_putreg(priv, STM32_CAN_MCR_OFFSET, regval);
+
+  /* Wait until the initialization mode exit is acknowledged */
+
+  for (timeout = INAK_TIMEOUT; timeout > 0; timeout--)
+    {
+      regval = stm32can_getreg(priv, STM32_CAN_MSR_OFFSET);
+      if ((regval & CAN_MSR_INAK) == 0)
+        {
+          /* We are out of initialization mode */
+
+          break;
+        }
+    }
+
+  /* Check for a timeout */
+
+  if (timeout < 1)
+    {
+      nerr("ERROR: Timed out waiting to exit initialization mode: %08"
+                  PRIx32 "\n", regval);
+      return -ETIMEDOUT;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32can_cellinit
+ *
+ * Description:
+ *   CAN cell initialization
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32can_cellinit(FAR struct stm32_can_s *priv)
+{
+  uint32_t regval;
+  int ret;
+
+  ninfo("CAN%" PRIu8 "\n", priv->port);
+
+  /* Exit from sleep mode */
+
+  regval  = stm32can_getreg(priv, STM32_CAN_MCR_OFFSET);
+  regval &= ~CAN_MCR_SLEEP;
+  stm32can_putreg(priv, STM32_CAN_MCR_OFFSET, regval);
+
+  ret = stm32can_enterinitmode(priv);
+  if (ret != 0)
+    {
+      return ret;
+    }
+
+  /* Disable the following modes:
+   *
+   *  - Time triggered communication mode
+   *  - Automatic bus-off management
+   *  - Automatic wake-up mode
+   *  - No automatic retransmission
+   *  - Receive FIFO locked mode
+   *
+   * Enable:
+   *
+   *  - Transmit FIFO priority
+   */
+
+  regval  = stm32can_getreg(priv, STM32_CAN_MCR_OFFSET);
+  regval &= ~(CAN_MCR_RFLM | CAN_MCR_NART | CAN_MCR_AWUM |
+              CAN_MCR_ABOM | CAN_MCR_TTCM);
+  regval |=  CAN_MCR_TXFP;
+  stm32can_putreg(priv, STM32_CAN_MCR_OFFSET, regval);
+
+  /* Configure bit timing. */
+
+  ret = stm32can_bittiming(priv);
+  if (ret < 0)
+    {
+      nerr("ERROR: Failed to set bit timing: %d\n", ret);
+      return ret;
+    }
+
+  return stm32can_exitinitmode(priv);
+}
+
+/****************************************************************************
+ * Name: stm32can_filterinit
+ *
+ * Description:
+ *   CAN filter initialization.  CAN filters are not currently used by this
+ *   driver.  The CAN filters can be configured in a different way:
+ *
+ *   1. As a match of specific IDs in a list (IdList mode), or as
+ *   2. And ID and a mask (IdMask mode).
+ *
+ *   Filters can also be configured as:
+ *
+ *   3. 16- or 32-bit.  The advantage of 16-bit filters is that you get
+ *      more filters;  The advantage of 32-bit filters is that you get
+ *      finer control of the filtering.
+ *
+ *   One filter is set up for each CAN.  The filter resources are shared
+ *   between the two CAN modules:  CAN1 uses only filter 0 (but reserves
+ *   0 through CAN_NFILTERS/2-1); CAN2 uses only filter CAN_NFILTERS/2
+ *   (but reserves CAN_NFILTERS/2 through CAN_NFILTERS-1).
+ *
+ *   32-bit IdMask mode is configured.  However, both the ID and the MASK
+ *   are set to zero thus suppressing all filtering because anything masked
+ *   with zero matches zero.
+ *
+ * Input Parameters:
+ *   priv - reference to the private CAN driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int stm32can_filterinit(FAR struct stm32_can_s *priv)
+{
+  uint32_t regval;
+  uint32_t bitmask;
+
+  ninfo("CAN%" PRIu8 " filter: %" PRIu8 "\n", priv->port, priv->filter);
+
+  /* Get the bitmask associated with the filter used by this CAN block */
+
+  bitmask = (uint32_t)1 << priv->filter;
+
+  /* Enter filter initialization mode */
+
+  regval  = stm32can_getfreg(priv, STM32_CAN_FMR_OFFSET);
+  regval |= CAN_FMR_FINIT;
+  stm32can_putfreg(priv, STM32_CAN_FMR_OFFSET, regval);
+
+  /* Assign half the filters to CAN1, half to CAN2 */
+
+#if defined(CONFIG_STM32_CONNECTIVITYLINE) || \
+    defined(CONFIG_STM32_STM32F20XX) || \
+    defined(CONFIG_STM32_STM32F4XXX)
+  regval  = stm32can_getfreg(priv, STM32_CAN_FMR_OFFSET);
+  regval &= CAN_FMR_CAN2SB_MASK;
+  regval |= (CAN_NFILTERS / 2) << CAN_FMR_CAN2SB_SHIFT;
+  stm32can_putfreg(priv, STM32_CAN_FMR_OFFSET, regval);
+#endif
+
+  /* Disable the filter */
+
+  regval  = stm32can_getfreg(priv, STM32_CAN_FA1R_OFFSET);
+  regval &= ~bitmask;
+  stm32can_putfreg(priv, STM32_CAN_FA1R_OFFSET, regval);
+
+  /* Select the 32-bit scale for the filter */
+
+  regval  = stm32can_getfreg(priv, STM32_CAN_FS1R_OFFSET);
+  regval |= bitmask;
+  stm32can_putfreg(priv, STM32_CAN_FS1R_OFFSET, regval);
+
+  /* There are 14 or 28 filter banks (depending) on the device.
+   * Each filter bank is composed of two 32-bit registers, CAN_FiR:
+   */
+
+  stm32can_putfreg(priv, STM32_CAN_FIR_OFFSET(priv->filter, 1), 0);
+  stm32can_putfreg(priv, STM32_CAN_FIR_OFFSET(priv->filter, 2), 0);
+
+  /* Set Id/Mask mode for the filter */
+
+  regval  = stm32can_getfreg(priv, STM32_CAN_FM1R_OFFSET);
+  regval &= ~bitmask;
+  stm32can_putfreg(priv, STM32_CAN_FM1R_OFFSET, regval);
+
+  /* Assign FIFO 0 for the filter */
+
+  regval  = stm32can_getfreg(priv, STM32_CAN_FFA1R_OFFSET);
+  regval &= ~bitmask;
+  stm32can_putfreg(priv, STM32_CAN_FFA1R_OFFSET, regval);
+
+  /* Enable the filter */
+
+  regval  = stm32can_getfreg(priv, STM32_CAN_FA1R_OFFSET);
+  regval |= bitmask;
+  stm32can_putfreg(priv, STM32_CAN_FA1R_OFFSET, regval);
+
+  /* Exit filter initialization mode */
+
+  regval  = stm32can_getfreg(priv, STM32_CAN_FMR_OFFSET);
+  regval &= ~CAN_FMR_FINIT;
+  stm32can_putfreg(priv, STM32_CAN_FMR_OFFSET, regval);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32can_txmb0empty
+ *
+ * Input Parameters:
+ *   tsr_regval - value of CAN transmit status register
+ *
+ * Returned Value:
+ *   Returns true if mailbox 0 is empty and can be used for sending.
+ *
+ ****************************************************************************/
+
+static bool stm32can_txmb0empty(uint32_t tsr_regval)
+{
+  return (tsr_regval & CAN_TSR_TME0) != 0 &&
+         (tsr_regval & CAN_TSR_RQCP0) == 0;
+}
+
+/****************************************************************************
+ * Name: stm32can_txmb1empty
+ *
+ * Input Parameters:
+ *   tsr_regval - value of CAN transmit status register
+ *
+ * Returned Value:
+ *   Returns true if mailbox 1 is empty and can be used for sending.
+ *
+ ****************************************************************************/
+
+static bool stm32can_txmb1empty(uint32_t tsr_regval)
+{
+  return (tsr_regval & CAN_TSR_TME1) != 0 &&
+         (tsr_regval & CAN_TSR_RQCP1) == 0;
+}
+
+/****************************************************************************
+ * Name: stm32can_txmb2empty
+ *
+ * Input Parameters:
+ *   tsr_regval - value of CAN transmit status register
+ *
+ * Returned Value:
+ *   Returns true if mailbox 2 is empty and can be used for sending.
+ *
+ ****************************************************************************/
+
+static bool stm32can_txmb2empty(uint32_t tsr_regval)
+{
+  return (tsr_regval & CAN_TSR_TME2) != 0 &&
+         (tsr_regval & CAN_TSR_RQCP2) == 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_cansockinitialize
+ *
+ * Description:
+ *   Initialize the selected CAN port as CAN socket interface
+ *
+ * Input Parameters:
+ *   Port number (for hardware that has multiple CAN interfaces)
+ *
+ * Returned Value:
+ *   OK on success; Negated errno on failure.
+ *
+ ****************************************************************************/
+
+int stm32_cansockinitialize(int port)
+{
+  struct stm32_can_s *priv = NULL;
+  int                 ret  = OK;
+
+  ninfo("CAN%" PRIu8 "\n", port);
+
+  /* NOTE:  Peripherical clocking for CAN1 and/or CAN2 was already provided
+   * by stm32_clockconfig() early in the reset sequence.
+   */
+
+#ifdef CONFIG_STM32_CAN1
+  if (port == 1)
+    {
+      /* Select the CAN1 device structure */
+
+      priv = &g_can1priv;
+
+      /* Configure CAN1 pins.  The ambiguous settings in the stm32*_pinmap.h
+       * file must have been disambiguated in the board.h file.
+       */
+
+      stm32_configgpio(GPIO_CAN1_RX);
+      stm32_configgpio(GPIO_CAN1_TX);
+    }
+  else
+#endif
+#ifdef CONFIG_STM32_CAN2
+  if (port == 2)
+    {
+      /* Select the CAN2 device structure */
+
+      priv = &g_can2priv;
+
+      /* Configure CAN2 pins.  The ambiguous settings in the stm32*_pinmap.h
+       * file must have been disambiguated in the board.h file.
+       */
+
+      stm32_configgpio(GPIO_CAN2_RX);
+      stm32_configgpio(GPIO_CAN2_TX);
+    }
+  else
+#endif
+    {
+      nerr("ERROR: Unsupported port %d\n", port);
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  /* Initialize the driver structure */
+
+  priv->dev.d_ifup    = stm32can_ifup;
+  priv->dev.d_ifdown  = stm32can_ifdown;
+  priv->dev.d_txavail = stm32can_txavail;
+#ifdef CONFIG_NETDEV_IOCTL
+  priv->dev.d_ioctl   = stm32can_netdev_ioctl;
+#endif
+  priv->dev.d_private = priv;
+
+  /* Put the interface in the down state.  This usually amounts to resetting
+   * the device and/or calling stm32can_ifdown().
+   */
+
+  ninfo("callbacks done\n");
+
+  stm32can_ifdown(&priv->dev);
+
+  /* Register the device with the OS so that socket IOCTLs can be performed */
+
+  ret = netdev_register(&priv->dev, NET_LL_CAN);
+
+errout:
+  return ret;
+}

[incubator-nuttx] 02/02: boards/stm32: register CAN character device if configured

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davids5 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit a983cd23777fb4596a140a15375012874e81c9a0
Author: raiden00pl <ra...@railab.me>
AuthorDate: Wed Jan 5 10:47:05 2022 +0100

    boards/stm32: register CAN character device if configured
---
 boards/arm/stm32/clicker2-stm32/src/Make.defs                | 2 +-
 boards/arm/stm32/clicker2-stm32/src/clicker2-stm32.h         | 2 +-
 boards/arm/stm32/clicker2-stm32/src/stm32_bringup.c          | 2 +-
 boards/arm/stm32/nucleo-f303re/src/Make.defs                 | 2 +-
 boards/arm/stm32/nucleo-f303re/src/nucleo-f303re.h           | 2 +-
 boards/arm/stm32/nucleo-f303re/src/stm32_appinitialize.c     | 2 +-
 boards/arm/stm32/nucleo-f334r8/src/nucleo-f334r8.h           | 2 +-
 boards/arm/stm32/nucleo-f446re/src/Make.defs                 | 2 +-
 boards/arm/stm32/nucleo-f446re/src/nucleo-f446re.h           | 2 +-
 boards/arm/stm32/nucleo-f446re/src/stm32_bringup.c           | 2 +-
 boards/arm/stm32/olimex-stm32-h405/src/Make.defs             | 2 +-
 boards/arm/stm32/olimex-stm32-h405/src/olimex-stm32-h405.h   | 2 +-
 boards/arm/stm32/olimex-stm32-h405/src/stm32_appinit.c       | 2 +-
 boards/arm/stm32/olimex-stm32-h407/src/Make.defs             | 2 +-
 boards/arm/stm32/olimex-stm32-h407/src/olimex-stm32-h407.h   | 2 +-
 boards/arm/stm32/olimex-stm32-h407/src/stm32_bringup.c       | 2 +-
 boards/arm/stm32/olimex-stm32-p107/src/Make.defs             | 2 +-
 boards/arm/stm32/olimex-stm32-p107/src/olimex-stm32-p107.h   | 2 +-
 boards/arm/stm32/olimex-stm32-p107/src/stm32_appinit.c       | 2 +-
 boards/arm/stm32/olimex-stm32-p207/src/Make.defs             | 2 +-
 boards/arm/stm32/olimex-stm32-p207/src/olimex-stm32-p207.h   | 2 +-
 boards/arm/stm32/olimex-stm32-p207/src/stm32_appinit.c       | 2 +-
 boards/arm/stm32/olimex-stm32-p407/src/Make.defs             | 2 +-
 boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h   | 2 +-
 boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c       | 2 +-
 boards/arm/stm32/olimexino-stm32/src/Make.defs               | 2 +-
 boards/arm/stm32/olimexino-stm32/src/olimexino-stm32.h       | 2 +-
 boards/arm/stm32/olimexino-stm32/src/stm32_appinit.c         | 2 +-
 boards/arm/stm32/omnibusf4/src/omnibusf4.h                   | 2 +-
 boards/arm/stm32/omnibusf4/src/stm32_bringup.c               | 2 +-
 boards/arm/stm32/shenzhou/src/Make.defs                      | 2 +-
 boards/arm/stm32/shenzhou/src/shenzhou.h                     | 2 +-
 boards/arm/stm32/shenzhou/src/stm32_appinit.c                | 2 +-
 boards/arm/stm32/stm3210e-eval/src/Make.defs                 | 2 +-
 boards/arm/stm32/stm3210e-eval/src/stm3210e-eval.h           | 2 +-
 boards/arm/stm32/stm3210e-eval/src/stm32_bringup.c           | 2 +-
 boards/arm/stm32/stm3220g-eval/src/Make.defs                 | 2 +-
 boards/arm/stm32/stm3220g-eval/src/stm3220g-eval.h           | 2 +-
 boards/arm/stm32/stm3220g-eval/src/stm32_appinit.c           | 2 +-
 boards/arm/stm32/stm3240g-eval/src/Make.defs                 | 2 +-
 boards/arm/stm32/stm3240g-eval/src/stm3240g-eval.h           | 2 +-
 boards/arm/stm32/stm3240g-eval/src/stm32_bringup.c           | 2 +-
 boards/arm/stm32/stm32f334-disco/src/Make.defs               | 2 +-
 boards/arm/stm32/stm32f334-disco/src/stm32f334-disco.h       | 2 +-
 boards/arm/stm32/stm32f4discovery/src/Make.defs              | 2 +-
 boards/arm/stm32/stm32f4discovery/src/stm32_bringup.c        | 2 +-
 boards/arm/stm32/stm32f4discovery/src/stm32f4discovery.h     | 2 +-
 boards/arm/stm32/viewtool-stm32f107/src/Make.defs            | 2 +-
 boards/arm/stm32/viewtool-stm32f107/src/stm32_bringup.c      | 2 +-
 boards/arm/stm32/viewtool-stm32f107/src/viewtool_stm32f107.h | 2 +-
 50 files changed, 50 insertions(+), 50 deletions(-)

diff --git a/boards/arm/stm32/clicker2-stm32/src/Make.defs b/boards/arm/stm32/clicker2-stm32/src/Make.defs
index bab3b6e..03aeaa2 100644
--- a/boards/arm/stm32/clicker2-stm32/src/Make.defs
+++ b/boards/arm/stm32/clicker2-stm32/src/Make.defs
@@ -60,7 +60,7 @@ ifeq ($(CONFIG_ADC),y)
 CSRCS +=  stm32_adc.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/clicker2-stm32/src/clicker2-stm32.h b/boards/arm/stm32/clicker2-stm32/src/clicker2-stm32.h
index 2c894a0..c567d3d 100644
--- a/boards/arm/stm32/clicker2-stm32/src/clicker2-stm32.h
+++ b/boards/arm/stm32/clicker2-stm32/src/clicker2-stm32.h
@@ -312,7 +312,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/clicker2-stm32/src/stm32_bringup.c b/boards/arm/stm32/clicker2-stm32/src/stm32_bringup.c
index 6a9e42a..f0fd294 100644
--- a/boards/arm/stm32/clicker2-stm32/src/stm32_bringup.c
+++ b/boards/arm/stm32/clicker2-stm32/src/stm32_bringup.c
@@ -87,7 +87,7 @@ int stm32_bringup(void)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/nucleo-f303re/src/Make.defs b/boards/arm/stm32/nucleo-f303re/src/Make.defs
index fc5f15b..0df3e24 100644
--- a/boards/arm/stm32/nucleo-f303re/src/Make.defs
+++ b/boards/arm/stm32/nucleo-f303re/src/Make.defs
@@ -40,7 +40,7 @@ ifeq ($(CONFIG_ADC),y)
 CSRCS += stm32_adc.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/nucleo-f303re/src/nucleo-f303re.h b/boards/arm/stm32/nucleo-f303re/src/nucleo-f303re.h
index 447c7b5..91e8558 100644
--- a/boards/arm/stm32/nucleo-f303re/src/nucleo-f303re.h
+++ b/boards/arm/stm32/nucleo-f303re/src/nucleo-f303re.h
@@ -186,7 +186,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/nucleo-f303re/src/stm32_appinitialize.c b/boards/arm/stm32/nucleo-f303re/src/stm32_appinitialize.c
index a729566..7aa6f22 100644
--- a/boards/arm/stm32/nucleo-f303re/src/stm32_appinitialize.c
+++ b/boards/arm/stm32/nucleo-f303re/src/stm32_appinitialize.c
@@ -124,7 +124,7 @@ int board_app_initialize(uintptr_t arg)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/nucleo-f334r8/src/nucleo-f334r8.h b/boards/arm/stm32/nucleo-f334r8/src/nucleo-f334r8.h
index 9abb52d..024b529 100644
--- a/boards/arm/stm32/nucleo-f334r8/src/nucleo-f334r8.h
+++ b/boards/arm/stm32/nucleo-f334r8/src/nucleo-f334r8.h
@@ -175,7 +175,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/nucleo-f446re/src/Make.defs b/boards/arm/stm32/nucleo-f446re/src/Make.defs
index 2b19ab7..c632239 100644
--- a/boards/arm/stm32/nucleo-f446re/src/Make.defs
+++ b/boards/arm/stm32/nucleo-f446re/src/Make.defs
@@ -45,7 +45,7 @@ endif
 endif
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/nucleo-f446re/src/nucleo-f446re.h b/boards/arm/stm32/nucleo-f446re/src/nucleo-f446re.h
index c24b2a4..dee75df 100644
--- a/boards/arm/stm32/nucleo-f446re/src/nucleo-f446re.h
+++ b/boards/arm/stm32/nucleo-f446re/src/nucleo-f446re.h
@@ -320,7 +320,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/nucleo-f446re/src/stm32_bringup.c b/boards/arm/stm32/nucleo-f446re/src/stm32_bringup.c
index b262e74..2a12df5 100644
--- a/boards/arm/stm32/nucleo-f446re/src/stm32_bringup.c
+++ b/boards/arm/stm32/nucleo-f446re/src/stm32_bringup.c
@@ -151,7 +151,7 @@ int stm32_bringup(void)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/olimex-stm32-h405/src/Make.defs b/boards/arm/stm32/olimex-stm32-h405/src/Make.defs
index ad17b5d..5743e8f 100644
--- a/boards/arm/stm32/olimex-stm32-h405/src/Make.defs
+++ b/boards/arm/stm32/olimex-stm32-h405/src/Make.defs
@@ -44,7 +44,7 @@ ifeq ($(CONFIG_ADC),y)
 CSRCS +=  stm32_adc.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/olimex-stm32-h405/src/olimex-stm32-h405.h b/boards/arm/stm32/olimex-stm32-h405/src/olimex-stm32-h405.h
index 68fd5e1..5de70f2 100644
--- a/boards/arm/stm32/olimex-stm32-h405/src/olimex-stm32-h405.h
+++ b/boards/arm/stm32/olimex-stm32-h405/src/olimex-stm32-h405.h
@@ -94,7 +94,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/olimex-stm32-h405/src/stm32_appinit.c b/boards/arm/stm32/olimex-stm32-h405/src/stm32_appinit.c
index 5ca1120..a103f9d 100644
--- a/boards/arm/stm32/olimex-stm32-h405/src/stm32_appinit.c
+++ b/boards/arm/stm32/olimex-stm32-h405/src/stm32_appinit.c
@@ -100,7 +100,7 @@ int board_app_initialize(uintptr_t arg)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/olimex-stm32-h407/src/Make.defs b/boards/arm/stm32/olimex-stm32-h407/src/Make.defs
index 309cde3..941b2ad 100644
--- a/boards/arm/stm32/olimex-stm32-h407/src/Make.defs
+++ b/boards/arm/stm32/olimex-stm32-h407/src/Make.defs
@@ -56,7 +56,7 @@ ifeq ($(CONFIG_ADC),y)
 CSRCS +=  stm32_adc.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/olimex-stm32-h407/src/olimex-stm32-h407.h b/boards/arm/stm32/olimex-stm32-h407/src/olimex-stm32-h407.h
index 9df8f5a..bf20037 100644
--- a/boards/arm/stm32/olimex-stm32-h407/src/olimex-stm32-h407.h
+++ b/boards/arm/stm32/olimex-stm32-h407/src/olimex-stm32-h407.h
@@ -254,7 +254,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/olimex-stm32-h407/src/stm32_bringup.c b/boards/arm/stm32/olimex-stm32-h407/src/stm32_bringup.c
index b205c70..f112680 100644
--- a/boards/arm/stm32/olimex-stm32-h407/src/stm32_bringup.c
+++ b/boards/arm/stm32/olimex-stm32-h407/src/stm32_bringup.c
@@ -82,7 +82,7 @@ int stm32_bringup(void)
 #endif
   int ret;
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/olimex-stm32-p107/src/Make.defs b/boards/arm/stm32/olimex-stm32-p107/src/Make.defs
index d9fab81..a5a5db6 100644
--- a/boards/arm/stm32/olimex-stm32-p107/src/Make.defs
+++ b/boards/arm/stm32/olimex-stm32-p107/src/Make.defs
@@ -26,7 +26,7 @@ ifeq ($(CONFIG_BOARDCTL),y)
 CSRCS += stm32_appinit.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/olimex-stm32-p107/src/olimex-stm32-p107.h b/boards/arm/stm32/olimex-stm32-p107/src/olimex-stm32-p107.h
index d6a8350..91dae79 100644
--- a/boards/arm/stm32/olimex-stm32-p107/src/olimex-stm32-p107.h
+++ b/boards/arm/stm32/olimex-stm32-p107/src/olimex-stm32-p107.h
@@ -77,7 +77,7 @@ void weak_function stm32_spidev_initialize(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/olimex-stm32-p107/src/stm32_appinit.c b/boards/arm/stm32/olimex-stm32-p107/src/stm32_appinit.c
index c2f8f22..4926f1c 100644
--- a/boards/arm/stm32/olimex-stm32-p107/src/stm32_appinit.c
+++ b/boards/arm/stm32/olimex-stm32-p107/src/stm32_appinit.c
@@ -73,7 +73,7 @@ int board_app_initialize(uintptr_t arg)
 {
   int ret;
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/olimex-stm32-p207/src/Make.defs b/boards/arm/stm32/olimex-stm32-p207/src/Make.defs
index f39b6aa..9db929b 100644
--- a/boards/arm/stm32/olimex-stm32-p207/src/Make.defs
+++ b/boards/arm/stm32/olimex-stm32-p207/src/Make.defs
@@ -44,7 +44,7 @@ ifeq ($(CONFIG_ADC),y)
 CSRCS +=  stm32_adc.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/olimex-stm32-p207/src/olimex-stm32-p207.h b/boards/arm/stm32/olimex-stm32-p207/src/olimex-stm32-p207.h
index 605a69f..c18c868 100644
--- a/boards/arm/stm32/olimex-stm32-p207/src/olimex-stm32-p207.h
+++ b/boards/arm/stm32/olimex-stm32-p207/src/olimex-stm32-p207.h
@@ -131,7 +131,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/olimex-stm32-p207/src/stm32_appinit.c b/boards/arm/stm32/olimex-stm32-p207/src/stm32_appinit.c
index 52d0b93..9efa1ee 100644
--- a/boards/arm/stm32/olimex-stm32-p207/src/stm32_appinit.c
+++ b/boards/arm/stm32/olimex-stm32-p207/src/stm32_appinit.c
@@ -130,7 +130,7 @@ int board_app_initialize(uintptr_t arg)
 {
   int ret;
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/olimex-stm32-p407/src/Make.defs b/boards/arm/stm32/olimex-stm32-p407/src/Make.defs
index b2fee25..e70761e 100644
--- a/boards/arm/stm32/olimex-stm32-p407/src/Make.defs
+++ b/boards/arm/stm32/olimex-stm32-p407/src/Make.defs
@@ -48,7 +48,7 @@ ifeq ($(CONFIG_ADC),y)
   CSRCS +=  stm32_adc.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
   CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h b/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h
index 8dd84b0..299a226 100644
--- a/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h
+++ b/boards/arm/stm32/olimex-stm32-p407/src/olimex-stm32-p407.h
@@ -316,7 +316,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c b/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c
index 3c2aee2..208208f 100644
--- a/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c
+++ b/boards/arm/stm32/olimex-stm32-p407/src/stm32_bringup.c
@@ -137,7 +137,7 @@ int stm32_bringup(void)
   sdio_mediachange(sdio, true);
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/olimexino-stm32/src/Make.defs b/boards/arm/stm32/olimexino-stm32/src/Make.defs
index 634e052..9d6eb37 100644
--- a/boards/arm/stm32/olimexino-stm32/src/Make.defs
+++ b/boards/arm/stm32/olimexino-stm32/src/Make.defs
@@ -22,7 +22,7 @@ include $(TOPDIR)/Make.defs
 
 CSRCS = stm32_boot.c stm32_spi.c stm32_leds.c
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/olimexino-stm32/src/olimexino-stm32.h b/boards/arm/stm32/olimexino-stm32/src/olimexino-stm32.h
index a52c939..8d8700b 100644
--- a/boards/arm/stm32/olimexino-stm32/src/olimexino-stm32.h
+++ b/boards/arm/stm32/olimexino-stm32/src/olimexino-stm32.h
@@ -208,7 +208,7 @@ int board_usbmsc_initialize(int port);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/olimexino-stm32/src/stm32_appinit.c b/boards/arm/stm32/olimexino-stm32/src/stm32_appinit.c
index 8dfa03e..9c34de3 100644
--- a/boards/arm/stm32/olimexino-stm32/src/stm32_appinit.c
+++ b/boards/arm/stm32/olimexino-stm32/src/stm32_appinit.c
@@ -87,7 +87,7 @@ int board_app_initialize(uintptr_t arg)
   ret = board_composite_initialize(0);
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/omnibusf4/src/omnibusf4.h b/boards/arm/stm32/omnibusf4/src/omnibusf4.h
index 0528d9d..ab79318 100644
--- a/boards/arm/stm32/omnibusf4/src/omnibusf4.h
+++ b/boards/arm/stm32/omnibusf4/src/omnibusf4.h
@@ -167,7 +167,7 @@ int weak_function stm32_pwm_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/omnibusf4/src/stm32_bringup.c b/boards/arm/stm32/omnibusf4/src/stm32_bringup.c
index d2d7a79..5b130a2 100644
--- a/boards/arm/stm32/omnibusf4/src/stm32_bringup.c
+++ b/boards/arm/stm32/omnibusf4/src/stm32_bringup.c
@@ -187,7 +187,7 @@ int stm32_bringup(void)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/shenzhou/src/Make.defs b/boards/arm/stm32/shenzhou/src/Make.defs
index d3a175d..e22f3bb 100644
--- a/boards/arm/stm32/shenzhou/src/Make.defs
+++ b/boards/arm/stm32/shenzhou/src/Make.defs
@@ -52,7 +52,7 @@ ifeq ($(CONFIG_USBMSC),y)
 CSRCS += stm32_usbmsc.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/shenzhou/src/shenzhou.h b/boards/arm/stm32/shenzhou/src/shenzhou.h
index ed23fc9..cc2593a 100644
--- a/boards/arm/stm32/shenzhou/src/shenzhou.h
+++ b/boards/arm/stm32/shenzhou/src/shenzhou.h
@@ -486,7 +486,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/shenzhou/src/stm32_appinit.c b/boards/arm/stm32/shenzhou/src/stm32_appinit.c
index 13d49d5..cb29d93 100644
--- a/boards/arm/stm32/shenzhou/src/stm32_appinit.c
+++ b/boards/arm/stm32/shenzhou/src/stm32_appinit.c
@@ -212,7 +212,7 @@ int board_app_initialize(uintptr_t arg)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/stm3210e-eval/src/Make.defs b/boards/arm/stm32/stm3210e-eval/src/Make.defs
index 74a533e..721a877 100644
--- a/boards/arm/stm32/stm3210e-eval/src/Make.defs
+++ b/boards/arm/stm32/stm3210e-eval/src/Make.defs
@@ -44,7 +44,7 @@ ifeq ($(CONFIG_USBDEV_COMPOSITE),y)
 CSRCS += stm32_composite.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/stm3210e-eval/src/stm3210e-eval.h b/boards/arm/stm32/stm3210e-eval/src/stm3210e-eval.h
index 6903daf..4af51b8 100644
--- a/boards/arm/stm32/stm3210e-eval/src/stm3210e-eval.h
+++ b/boards/arm/stm32/stm3210e-eval/src/stm3210e-eval.h
@@ -221,7 +221,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/stm3210e-eval/src/stm32_bringup.c b/boards/arm/stm32/stm3210e-eval/src/stm32_bringup.c
index ef1d138..6e0e8a3 100644
--- a/boards/arm/stm32/stm3210e-eval/src/stm32_bringup.c
+++ b/boards/arm/stm32/stm3210e-eval/src/stm32_bringup.c
@@ -279,7 +279,7 @@ int stm32_bringup(void)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/stm3220g-eval/src/Make.defs b/boards/arm/stm32/stm3220g-eval/src/Make.defs
index bc3ce6a..8346d32 100644
--- a/boards/arm/stm32/stm3220g-eval/src/Make.defs
+++ b/boards/arm/stm32/stm3220g-eval/src/Make.defs
@@ -48,7 +48,7 @@ ifeq ($(CONFIG_PWM),y)
 CSRCS += stm32_pwm.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/stm3220g-eval/src/stm3220g-eval.h b/boards/arm/stm32/stm3220g-eval/src/stm3220g-eval.h
index e90bdd0..774f950 100644
--- a/boards/arm/stm32/stm3220g-eval/src/stm3220g-eval.h
+++ b/boards/arm/stm32/stm3220g-eval/src/stm3220g-eval.h
@@ -305,7 +305,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/stm3220g-eval/src/stm32_appinit.c b/boards/arm/stm32/stm3220g-eval/src/stm32_appinit.c
index 77a2773..4de80de 100644
--- a/boards/arm/stm32/stm3220g-eval/src/stm32_appinit.c
+++ b/boards/arm/stm32/stm3220g-eval/src/stm32_appinit.c
@@ -309,7 +309,7 @@ int board_app_initialize(uintptr_t arg)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/stm3240g-eval/src/Make.defs b/boards/arm/stm32/stm3240g-eval/src/Make.defs
index cfc00e8..bb1822e 100644
--- a/boards/arm/stm32/stm3240g-eval/src/Make.defs
+++ b/boards/arm/stm32/stm3240g-eval/src/Make.defs
@@ -49,7 +49,7 @@ ifeq ($(CONFIG_PWM),y)
 CSRCS += stm32_pwm.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/stm3240g-eval/src/stm3240g-eval.h b/boards/arm/stm32/stm3240g-eval/src/stm3240g-eval.h
index 274bd07..fbd4c23 100644
--- a/boards/arm/stm32/stm3240g-eval/src/stm3240g-eval.h
+++ b/boards/arm/stm32/stm3240g-eval/src/stm3240g-eval.h
@@ -333,7 +333,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/stm3240g-eval/src/stm32_bringup.c b/boards/arm/stm32/stm3240g-eval/src/stm32_bringup.c
index 345e8b5..6ab613d 100644
--- a/boards/arm/stm32/stm3240g-eval/src/stm32_bringup.c
+++ b/boards/arm/stm32/stm3240g-eval/src/stm32_bringup.c
@@ -376,7 +376,7 @@ int stm32_bringup(void)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/stm32f334-disco/src/Make.defs b/boards/arm/stm32/stm32f334-disco/src/Make.defs
index 8b8f06b..19c0380 100644
--- a/boards/arm/stm32/stm32f334-disco/src/Make.defs
+++ b/boards/arm/stm32/stm32f334-disco/src/Make.defs
@@ -30,7 +30,7 @@ ifeq ($(CONFIG_BOARDCTL),y)
 CSRCS += stm32_appinit.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/stm32f334-disco/src/stm32f334-disco.h b/boards/arm/stm32/stm32f334-disco/src/stm32f334-disco.h
index d7ee6cb..62b05c7 100644
--- a/boards/arm/stm32/stm32f334-disco/src/stm32f334-disco.h
+++ b/boards/arm/stm32/stm32f334-disco/src/stm32f334-disco.h
@@ -154,7 +154,7 @@ int stm32_adc_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/stm32f4discovery/src/Make.defs b/boards/arm/stm32/stm32f4discovery/src/Make.defs
index 9b118e1..f5ebaef 100644
--- a/boards/arm/stm32/stm32f4discovery/src/Make.defs
+++ b/boards/arm/stm32/stm32f4discovery/src/Make.defs
@@ -40,7 +40,7 @@ ifeq ($(CONFIG_ARCH_BUTTONS),y)
 CSRCS +=  stm32_buttons.c
 endif
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/stm32f4discovery/src/stm32_bringup.c b/boards/arm/stm32/stm32f4discovery/src/stm32_bringup.c
index d124e21..322ff1f 100644
--- a/boards/arm/stm32/stm32f4discovery/src/stm32_bringup.c
+++ b/boards/arm/stm32/stm32f4discovery/src/stm32_bringup.c
@@ -332,7 +332,7 @@ int stm32_bringup(void)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/stm32f4discovery/src/stm32f4discovery.h b/boards/arm/stm32/stm32f4discovery/src/stm32f4discovery.h
index 8bd7100..09df790 100644
--- a/boards/arm/stm32/stm32f4discovery/src/stm32f4discovery.h
+++ b/boards/arm/stm32/stm32f4discovery/src/stm32f4discovery.h
@@ -563,7 +563,7 @@ int stm32_pwm_setup(void);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif
 
diff --git a/boards/arm/stm32/viewtool-stm32f107/src/Make.defs b/boards/arm/stm32/viewtool-stm32f107/src/Make.defs
index 9590568..414ddbd 100644
--- a/boards/arm/stm32/viewtool-stm32f107/src/Make.defs
+++ b/boards/arm/stm32/viewtool-stm32f107/src/Make.defs
@@ -22,7 +22,7 @@ include $(TOPDIR)/Make.defs
 
 CSRCS = stm32_boot.c stm32_bringup.c stm32_leds.c stm32_spi.c
 
-ifeq ($(CONFIG_CAN),y)
+ifeq ($(CONFIG_STM32_CAN_CHARDRIVER),y)
 CSRCS += stm32_can.c
 endif
 
diff --git a/boards/arm/stm32/viewtool-stm32f107/src/stm32_bringup.c b/boards/arm/stm32/viewtool-stm32f107/src/stm32_bringup.c
index 0b0a853..2d6f620 100644
--- a/boards/arm/stm32/viewtool-stm32f107/src/stm32_bringup.c
+++ b/boards/arm/stm32/viewtool-stm32f107/src/stm32_bringup.c
@@ -164,7 +164,7 @@ int stm32_bringup(void)
     }
 #endif
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
   /* Initialize CAN and register the CAN driver. */
 
   ret = stm32_can_setup();
diff --git a/boards/arm/stm32/viewtool-stm32f107/src/viewtool_stm32f107.h b/boards/arm/stm32/viewtool-stm32f107/src/viewtool_stm32f107.h
index 9c83c4b..f4671e6 100644
--- a/boards/arm/stm32/viewtool-stm32f107/src/viewtool_stm32f107.h
+++ b/boards/arm/stm32/viewtool-stm32f107/src/viewtool_stm32f107.h
@@ -442,7 +442,7 @@ int stm32_sdinitialize(int minor);
  *
  ****************************************************************************/
 
-#ifdef CONFIG_CAN
+#ifdef CONFIG_STM32_CAN_CHARDRIVER
 int stm32_can_setup(void);
 #endif