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

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

commit 31996da7f778e5ad29f1edc3347da36d726163ce
Author: iamadahn <[email protected]>
AuthorDate: Fri Nov 6 15:19:49 2026 +0300

    arm/stm32g0: Add FDCAN1 character driver support.
    
    Enable the common M0 FDCAN character driver on STM32G0 with the required
    register, interrupt, clock and pin definitions.
    
    Reject FDCAN1 with TIM16 or TIM17 at compile time because they share
    interrupt vectors.
    
    Assisted-by: Codex:GPT-6-Astra
    Signed-off-by: iamadahn <[email protected]>
---
 Documentation/platforms/arm/stm32g0/index.rst     |  7 +++---
 arch/arm/include/stm32g0/irq.h                    | 12 ++++++++++
 arch/arm/src/common/stm32/stm32_fdcan_m0_v1.c     | 28 ++++++++++++-----------
 arch/arm/src/stm32g0/hardware/stm32_rcc.h         | 15 ++++++++++--
 arch/arm/src/stm32g0/hardware/stm32g0_memorymap.h |  6 +++--
 arch/arm/src/stm32g0/hardware/stm32g0_pinmap.h    |  9 ++++++++
 arch/arm/src/stm32g0/stm32.h                      |  7 ++++++
 arch/arm/src/stm32g0/stm32g0_rcc.c                | 13 +++++++++++
 8 files changed, 77 insertions(+), 20 deletions(-)

diff --git a/Documentation/platforms/arm/stm32g0/index.rst 
b/Documentation/platforms/arm/stm32g0/index.rst
index 49d51234006..e65755ea231 100644
--- a/Documentation/platforms/arm/stm32g0/index.rst
+++ b/Documentation/platforms/arm/stm32g0/index.rst
@@ -17,9 +17,9 @@ Peripheral Support
 
 The following list indicates peripherals supported in NuttX:
 
-==========  =======  =====
+==========  =======  ======
 Peripheral  Support  Notes
-==========  =======  =====
+==========  =======  ======
 FLASH       No
 PM          No
 RCC         Yes      
@@ -47,10 +47,11 @@ I2C         Yes
 USART       Yes
 LPUSART     No
 SPI         Yes
+FDCAN       Yes      FDCAN1
 UCPD        No
 USB         ?
 HDIM_CEC    No
-==========  =======  =====
+==========  =======  ======
 
 Supported Boards
 ================
diff --git a/arch/arm/include/stm32g0/irq.h b/arch/arm/include/stm32g0/irq.h
index 184204511f9..06aa1420dab 100644
--- a/arch/arm/include/stm32g0/irq.h
+++ b/arch/arm/include/stm32g0/irq.h
@@ -151,7 +151,19 @@
 #define STM32_IRQ_TIM14        (STM32_IRQ_EXTINT + 19) /* 19: TIM14 */
 #define STM32_IRQ_TIM15        (STM32_IRQ_EXTINT + 20) /* 20: TIM15 */
 #define STM32_IRQ_TIM16        (STM32_IRQ_EXTINT + 21) /* 21: TIM16 */
+
+#if defined(CONFIG_STM32_STM32G0B1) || \
+    defined(CONFIG_STM32_STM32G0C1)
+#  define STM32_IRQ_FDCAN1_0   (STM32_IRQ_EXTINT + 21) /* 21: FDCAN1 interrupt 
line 0 */
+#endif
+
 #define STM32_IRQ_TIM17        (STM32_IRQ_EXTINT + 22) /* 22: TIM17 */
+
+#if defined(CONFIG_STM32_STM32G0B1) || \
+    defined(CONFIG_STM32_STM32G0C1)
+#  define STM32_IRQ_FDCAN1_1   (STM32_IRQ_EXTINT + 22) /* 22: FDCAN1 interrupt 
line 1 */
+#endif
+
 #define STM32_IRQ_I2C1         (STM32_IRQ_EXTINT + 23) /* 23: I2C1 */
 #define STM32_IRQ_EXTI23       (STM32_IRQ_EXTINT + 23) /* 23: EXTI_23 */
 #define STM32_IRQ_I2C2         (STM32_IRQ_EXTINT + 24) /* 24: I2C2 */
diff --git a/arch/arm/src/common/stm32/stm32_fdcan_m0_v1.c 
b/arch/arm/src/common/stm32/stm32_fdcan_m0_v1.c
index 1cb8fb9a9a4..b7a2b020a5c 100644
--- a/arch/arm/src/common/stm32/stm32_fdcan_m0_v1.c
+++ b/arch/arm/src/common/stm32/stm32_fdcan_m0_v1.c
@@ -65,7 +65,7 @@
 
 /* General Configuration ****************************************************/
 
-#if defined(CONFIG_ARCH_CHIP_STM32C0)
+#if defined(CONFIG_ARCH_CHIP_STM32C0) || defined(CONFIG_ARCH_CHIP_STM32G0)
 
 /* FDCAN Message RAM */
 
@@ -587,6 +587,7 @@ static uint32_t fdcan_getreg(struct stm32_fdcan_s *priv, 
int offset)
 static uint32_t fdcan_getreg(struct stm32_fdcan_s *priv, int offset)
 {
   const struct stm32_config_s *config = priv->config;
+
   return getreg32(config->base + offset);
 }
 
@@ -629,6 +630,7 @@ static void fdcan_putreg(struct stm32_fdcan_s *priv, int 
offset,
                          uint32_t regval)
 {
   const struct stm32_config_s *config = priv->config;
+
   putreg32(regval, config->base + offset);
 }
 
@@ -1019,12 +1021,12 @@ static int fdcan_add_extfilter(struct stm32_fdcan_s 
*priv,
               regval |= (FDCAN_CCCR_INIT | FDCAN_CCCR_CCE);
               fdcan_putreg(priv, STM32_FDCAN_CCCR_OFFSET, regval);
 
-             /* Update the Global Filter Configuration so that received
-              * messages are rejected if they do not match the acceptance
-              * filter.
-              *
-              *   ANFE=2: Discard all rejected frames
-              */
+              /* Update the Global Filter Configuration so that received
+               * messages are rejected if they do not match the acceptance
+               * filter.
+               *
+               *   ANFE=2: Discard all rejected frames
+               */
 
               regval  = fdcan_getreg(priv, STM32_FDCAN_RXGFC_OFFSET);
               regval &= ~FDCAN_RXGFC_ANFE_MASK;
@@ -1269,12 +1271,12 @@ static int fdcan_add_stdfilter(struct stm32_fdcan_s 
*priv,
               regval |= (FDCAN_CCCR_INIT | FDCAN_CCCR_CCE);
               fdcan_putreg(priv, STM32_FDCAN_CCCR_OFFSET, regval);
 
-             /* Update the Global Filter Configuration so that received
-              * messages are rejected if they do not match the acceptance
-              * filter.
-              *
-              *   ANFS=2: Discard all rejected frames
-              */
+              /* Update the Global Filter Configuration so that received
+               * messages are rejected if they do not match the acceptance
+               * filter.
+               *
+               *   ANFS=2: Discard all rejected frames
+               */
 
               regval  = fdcan_getreg(priv, STM32_FDCAN_RXGFC_OFFSET);
               regval &= ~FDCAN_RXGFC_ANFS_MASK;
diff --git a/arch/arm/src/stm32g0/hardware/stm32_rcc.h 
b/arch/arm/src/stm32g0/hardware/stm32_rcc.h
index 53112d367be..57de3a9232a 100644
--- a/arch/arm/src/stm32g0/hardware/stm32_rcc.h
+++ b/arch/arm/src/stm32g0/hardware/stm32_rcc.h
@@ -49,6 +49,7 @@
 #define STM32_RCC_APB1SMENR_OFFSET      0x004C  /* APB1 peripheral clock 
enable in Sleep mode register */
 #define STM32_RCC_APB2SMENR_OFFSET      0x0050  /* APB2 peripheral clock 
enable in Sleep mode register */
 #define STM32_RCC_CCIPR_OFFSET          0x0054  /* Clock configuration 
register */
+#define STM32_RCC_CCIPR2_OFFSET         0x0058  /* Clock configuration 
register 2 */
 #define STM32_RCC_BDCR_OFFSET           0x005c  /* RTC domain control register 
*/
 #define STM32_RCC_CSR_OFFSET            0x0060  /* Control/status register */
 
@@ -74,6 +75,7 @@
 #define STM32_RCC_APB1SMENR         (STM32_RCC_BASE+STM32_RCC_APB1SMENR_OFFSET)
 #define STM32_RCC_APB2SMENR         (STM32_RCC_BASE+STM32_RCC_APB2SMENR_OFFSET)
 #define STM32_RCC_CCIPR             (STM32_RCC_BASE+STM32_RCC_CCIPR_OFFSET)
+#define STM32_RCC_CCIPR2            (STM32_RCC_BASE+STM32_RCC_CCIPR2_OFFSET)
 #define STM32_RCC_BDCR              (STM32_RCC_BASE+STM32_RCC_BDCR_OFFSET)
 #define STM32_RCC_CSR               (STM32_RCC_BASE+STM32_RCC_CSR_OFFSET)
 
@@ -220,7 +222,8 @@
                                               /* Bits 2-3: Reserved */
 #define RCC_APB1RSTR_TIM6RST        (1 << 4)  /* Bit 4:  Timer 6 reset */
 #define RCC_APB1RSTR_TIM7RST        (1 << 5)  /* Bit 5:  Timer 7 reset */
-                                              /* Bits 6-12: Reserved */
+                                              /* Bits 6-11: Reserved */
+#define RCC_APB1RSTR_FDCANRST       (1 << 12) /* Bit 12: FDCAN reset */
 #define RCC_APB1RSTR_USBRST         (1 << 13) /* Bit 13: USB reset */
 #define RCC_APB1RSTR_SPI2RST        (1 << 14) /* Bit 14: SPI 2 reset */
                                               /* Bits 15-16: Reserved */
@@ -287,7 +290,7 @@
 #define RCC_APB1ENR_TIM7EN          (1 << 5)  /* Bit 5:  Timer 7 enable */
                                               /* Bits 6-10: Reserved */
 #define RCC_APB1ENR_WWDGEN          (1 << 11) /* Bit 11: Window watchdog 
enable */
-                                              /* Bit 12: Reserved */
+#define RCC_APB1ENR_FDCANEN         (1 << 12) /* Bit 12: FDCAN enable */
 #define RCC_APB1ENR_USBEN           (1 << 13) /* Bit 13: USB enable */
 #define RCC_APB1ENR_SPI2EN          (1 << 14) /* Bit 14: SPI 2 enable */
                                               /* Bit 15: Reserved */
@@ -351,6 +354,14 @@
 #define RCC_CCIPR_ADCSEL_PLLPCLK    (1 << RCC_CCIPR_ADCSEL_SHIFT)
 #define RCC_CCIPR_ADCSEL_HSI16      (2 << RCC_CCIPR_ADCSEL_SHIFT)
 
+/* Clock configuration register 2 (STM32G0B1/G0C1) */
+
+#define RCC_CCIPR2_FDCANSEL_SHIFT   (8)
+#define RCC_CCIPR2_FDCANSEL_MASK    (3 << RCC_CCIPR2_FDCANSEL_SHIFT)
+#define RCC_CCIPR2_FDCANSEL_PCLK    (0 << RCC_CCIPR2_FDCANSEL_SHIFT)
+#define RCC_CCIPR2_FDCANSEL_PLLQ    (1 << RCC_CCIPR2_FDCANSEL_SHIFT)
+#define RCC_CCIPR2_FDCANSEL_HSE     (2 << RCC_CCIPR2_FDCANSEL_SHIFT)
+
 /* TODO: RTC domain control register */
 
 /* Control/status register */
diff --git a/arch/arm/src/stm32g0/hardware/stm32g0_memorymap.h 
b/arch/arm/src/stm32g0/hardware/stm32g0_memorymap.h
index 144d7cc6f63..8d5d6f14280 100644
--- a/arch/arm/src/stm32g0/hardware/stm32g0_memorymap.h
+++ b/arch/arm/src/stm32g0/hardware/stm32g0_memorymap.h
@@ -49,8 +49,8 @@
 
 /* Peripheral Base Addresses ************************************************/
 
-#define STM32_APB1_BASE      0x40000000     /* 0x40000000-0x4000b3ff: APB1 */
-                                            /* 0x4000b400-0x4000ffff: Reserved 
*/
+#define STM32_APB1_BASE      0x40000000     /* 0x40000000-0x4000bbff: APB1 */
+                                            /* 0x4000bc00-0x4000ffff: Reserved 
*/
 #define STM32_APB2_BASE      0x40010000     /* 0x40010000-0x40015800: APB2 */
                                             /* 0x40015c00-0x4001ffff: Reserved 
*/
 #define STM32_AHB_BASE       0x40020000     /* 0x40020000-0x400263ff: AHB */
@@ -75,6 +75,7 @@
 #define STM32_I2C1_BASE      0x40005400     /* 0x40005400-0x400057ff I2C1 */
 #define STM32_I2C2_BASE      0x40005800     /* 0x40005800-0x40005bff I2C2 */
 #define STM32_USB_BASE       0x40005c00     /* 0x40005c00-0x40005fff USB */
+#define STM32_FDCAN1_BASE    0x40006400     /* 0x40006400-0x400067ff FDCAN1 */
 #define STM32_CRS_BASE       0x40006C00     /* 0x40006C00-0x40006fff CRS */
 #define STM32_PWR_BASE       0x40007000     /* 0x40007000-0x400073ff PWR */
 #define STM32_DAC1_BASE      0x40007400     /* 0x40007400-0x400077ff DAC 1 */
@@ -87,6 +88,7 @@
 #define STM32_UCPD1_BASE     0x4000a000     /* 0x4000a000-0x4000a3ff UCPD1 */
 #define STM32_UCPD2_BASE     0x4000a400     /* 0x4000a400-0x4000a7ff UCPD2 */
 #define STM32_TAMP_BASE      0x4000b000     /* 0x4000b000-0x4000b3ff TAMP */
+#define STM32_CANRAM_BASE    0x4000b400     /* 0x4000b400-0x4000bbff FDCAN 
message RAM */
 
 /* APB2 Base Addresses ******************************************************/
 
diff --git a/arch/arm/src/stm32g0/hardware/stm32g0_pinmap.h 
b/arch/arm/src/stm32g0/hardware/stm32g0_pinmap.h
index bbd5e79cedd..1d75c4eb6c2 100644
--- a/arch/arm/src/stm32g0/hardware/stm32g0_pinmap.h
+++ b/arch/arm/src/stm32g0/hardware/stm32g0_pinmap.h
@@ -96,6 +96,15 @@
 
 /* TODO: DAC */
 
+/* FDCAN (STM32G0B1/G0C1) */
+
+#define GPIO_FDCAN1_RX_1         (GPIO_ALT | GPIO_AF3 | GPIO_PORTA | 
GPIO_PIN11)
+#define GPIO_FDCAN1_TX_1         (GPIO_ALT | GPIO_AF3 | GPIO_PORTA | 
GPIO_PIN12)
+#define GPIO_FDCAN1_RX_2         (GPIO_ALT | GPIO_AF3 | GPIO_PORTB | GPIO_PIN8)
+#define GPIO_FDCAN1_TX_2         (GPIO_ALT | GPIO_AF3 | GPIO_PORTB | GPIO_PIN9)
+#define GPIO_FDCAN1_RX_3         (GPIO_ALT | GPIO_AF3 | GPIO_PORTD | GPIO_PIN0)
+#define GPIO_FDCAN1_TX_3         (GPIO_ALT | GPIO_AF3 | GPIO_PORTD | GPIO_PIN1)
+
 /* I2C */
 
 #define GPIO_I2C1_SMBA_1          (GPIO_ALT | GPIO_AF6 | GPIO_PORTA | 
GPIO_PIN1)
diff --git a/arch/arm/src/stm32g0/stm32.h b/arch/arm/src/stm32g0/stm32.h
index 9e70f1bf95f..88957ddd420 100644
--- a/arch/arm/src/stm32g0/stm32.h
+++ b/arch/arm/src/stm32g0/stm32.h
@@ -51,4 +51,11 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* FDCAN1 shares interrupt vectors with TIM16 and TIM17. */
+
+#if defined(CONFIG_STM32_FDCAN1) && \
+    (defined(CONFIG_STM32_TIM16) || defined(CONFIG_STM32_TIM17))
+#  error "FDCAN1 cannot be used with TIM16 or TIM17"
+#endif
+
 #endif /* __ARCH_ARM_SRC_STM32G0_STM32_H */
diff --git a/arch/arm/src/stm32g0/stm32g0_rcc.c 
b/arch/arm/src/stm32g0/stm32g0_rcc.c
index 0bee1359cc9..ee54212a635 100644
--- a/arch/arm/src/stm32g0/stm32g0_rcc.c
+++ b/arch/arm/src/stm32g0/stm32g0_rcc.c
@@ -211,6 +211,12 @@ static inline void rcc_enableapb1(void)
   regval |= RCC_APB1ENR_USBEN;
 #endif
 
+#ifdef CONFIG_STM32_FDCAN
+  /* FDCAN clock enable */
+
+  regval |= RCC_APB1ENR_FDCANEN;
+#endif
+
 #ifdef CONFIG_STM32_WWDG
   /* Window watchdog clock enable */
 
@@ -679,6 +685,13 @@ static void stm32_stdclockconfig(void)
   regval |= STM32_RCC_CCIPR_ADCSEL;
   putreg32(regval, STM32_RCC_CCIPR);
 #endif
+
+#if defined(STM32_FDCAN_SEL)
+  regval = getreg32(STM32_RCC_CCIPR2);
+  regval &= ~RCC_CCIPR2_FDCANSEL_MASK;
+  regval |= STM32_FDCAN_SEL;
+  putreg32(regval, STM32_RCC_CCIPR2);
+#endif
 }
 #endif
 

Reply via email to