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
