From a8883d83e377c5ab348099641498b2a621dd4c7b Mon Sep 17 00:00:00 2001 From: BIGTREETECH <38851044+bigtreetech@users.noreply.github.com> Date: Wed, 24 Aug 2022 05:53:35 +0800 Subject: [PATCH] stm32: add FDCAN support for STM32H743 (SKR-3 Series) (#5668) Signed-off-by: Chen.BJ from BigTreeTech --- src/stm32/Kconfig | 26 ++++++++++++++++++++--- src/stm32/fdcan.c | 52 ++++++++++++++++++++++++++++++++++++++++++--- src/stm32/stm32h7.c | 15 +++++++++++-- 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/src/stm32/Kconfig b/src/stm32/Kconfig index 355b132e..f78580f5 100644 --- a/src/stm32/Kconfig +++ b/src/stm32/Kconfig @@ -107,7 +107,7 @@ config HAVE_STM32_CANBUS default y if MACH_STM32F1 || MACH_STM32F2 || MACH_STM32F4x5 || MACH_STM32F446 || MACH_STM32F0x2 config HAVE_STM32_FDCANBUS bool - default y if MACH_STM32G0 + default y if MACH_STM32G0 || MACH_STM32H7 config HAVE_STM32_USBCANBUS bool depends on HAVE_STM32_USBFS || HAVE_STM32_USBOTG @@ -351,12 +351,20 @@ choice select CANSERIAL config STM32_MMENU_CANBUS_PD0_PD1 bool "CAN bus (on PD0/PD1)" if LOW_LEVEL_OPTIONS - depends on HAVE_STM32_CANBUS + depends on HAVE_STM32_CANBUS || HAVE_STM32_FDCANBUS select CANSERIAL config STM32_MMENU_CANBUS_PB0_PB1 bool "CAN bus (on PB0/PB1)" depends on HAVE_STM32_FDCANBUS select CANSERIAL + config STM32_MMENU_CANBUS_PD12_PD13 + bool "CAN bus (on PD12/PD13)" + depends on HAVE_STM32_FDCANBUS + select CANSERIAL + config STM32_MMENU_CANBUS_PC2_PC3 + bool "CAN bus (on PC2/PC3)" + depends on HAVE_STM32_FDCANBUS + select CANSERIAL config STM32_USBCANBUS_PA11_PA12 bool "USB to CAN bus bridge (USB on PA11/PA12)" depends on HAVE_STM32_USBCANBUS @@ -377,10 +385,16 @@ choice depends on HAVE_STM32_CANBUS && MACH_STM32F4 config STM32_CMENU_CANBUS_PD0_PD1 bool "CAN bus (on PD0/PD1)" - depends on HAVE_STM32_CANBUS + depends on HAVE_STM32_CANBUS || HAVE_STM32_FDCANBUS config STM32_CMENU_CANBUS_PB0_PB1 bool "CAN bus (on PB0/PB1)" depends on HAVE_STM32_FDCANBUS + config STM32_CMENU_CANBUS_PD12_PD13 + bool "CAN bus (on PD12/PD13)" + depends on HAVE_STM32_FDCANBUS + config STM32_CMENU_CANBUS_PC2_PC3 + bool "CAN bus (on PC2/PC3)" + depends on HAVE_STM32_FDCANBUS endchoice @@ -402,5 +416,11 @@ config STM32_CANBUS_PD0_PD1 config STM32_CANBUS_PB0_PB1 bool default y if STM32_MMENU_CANBUS_PB0_PB1 || STM32_CMENU_CANBUS_PB0_PB1 +config STM32_CANBUS_PD12_PD13 + bool + default y if STM32_MMENU_CANBUS_PD12_PD13 || STM32_CMENU_CANBUS_PD12_PD13 +config STM32_CANBUS_PC2_PC3 + bool + default y if STM32_MMENU_CANBUS_PC2_PC3 || STM32_CMENU_CANBUS_PC2_PC3 endif diff --git a/src/stm32/fdcan.c b/src/stm32/fdcan.c index c142420e..7eac761b 100755 --- a/src/stm32/fdcan.c +++ b/src/stm32/fdcan.c @@ -55,13 +55,25 @@ FDCAN_RAM_TypeDef *fdcan_ram = (FDCAN_RAM_TypeDef *)(SRAMCAN_BASE); DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB8,PB9"); #define GPIO_Rx GPIO('B', 8) #define GPIO_Tx GPIO('B', 9) +#elif CONFIG_STM32_CANBUS_PD0_PD1 + DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PD0,PD1"); + #define GPIO_Rx GPIO('D', 0) + #define GPIO_Tx GPIO('D', 1) +#elif CONFIG_STM32_CANBUS_PD12_PD13 + DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PD12,PD13"); + #define GPIO_Rx GPIO('D', 12) + #define GPIO_Tx GPIO('D', 13) #elif CONFIG_STM32_CANBUS_PB0_PB1 DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PB0,PB1"); #define GPIO_Rx GPIO('B', 0) #define GPIO_Tx GPIO('B', 1) +#elif CONFIG_STM32_CANBUS_PC2_PC3 + DECL_CONSTANT_STR("RESERVE_PINS_CAN", "PC2,PC3"); + #define GPIO_Rx GPIO('C', 2) + #define GPIO_Tx GPIO('C', 3) #endif -#if !CONFIG_STM32_CANBUS_PB0_PB1 +#if !(CONFIG_STM32_CANBUS_PB0_PB1 || CONFIG_STM32_CANBUS_PC2_PC3) #define SOC_CAN FDCAN1 #define MSG_RAM fdcan_ram->fdcan1 #else @@ -69,8 +81,13 @@ FDCAN_RAM_TypeDef *fdcan_ram = (FDCAN_RAM_TypeDef *)(SRAMCAN_BASE); #define MSG_RAM fdcan_ram->fdcan2 #endif -#define CAN_IT0_IRQn TIM16_FDCAN_IT0_IRQn -#define CAN_FUNCTION GPIO_FUNCTION(3) // Alternative function mapping number +#if CONFIG_MACH_STM32G0 + #define CAN_IT0_IRQn TIM16_FDCAN_IT0_IRQn + #define CAN_FUNCTION GPIO_FUNCTION(3) // Alternative function mapping number +#elif CONFIG_MACH_STM32H7 + #define CAN_IT0_IRQn FDCAN1_IT0_IRQn + #define CAN_FUNCTION GPIO_FUNCTION(9) // Alternative function mapping number +#endif #ifndef SOC_CAN #error No known CAN device for configured MCU @@ -128,8 +145,14 @@ canbus_set_filter(uint32_t id) can_filter(0, CANBUS_ID_ADMIN); can_filter(1, id); can_filter(2, id + 1); + +#if CONFIG_MACH_STM32G0 SOC_CAN->RXGFC = ((id ? 3 : 1) << FDCAN_RXGFC_LSS_Pos | 0x02 << FDCAN_RXGFC_ANFS_Pos); +#elif CONFIG_MACH_STM32H7 + SOC_CAN->SIDFC |= (id ? 3 : 1) << FDCAN_SIDFC_LSS_Pos; + SOC_CAN->GFC = 0x02 << FDCAN_GFC_ANFS_Pos; +#endif /* Leave the initialisation mode for the filter */ SOC_CAN->CCCR &= ~FDCAN_CCCR_CCE; @@ -251,6 +274,29 @@ can_init(void) SOC_CAN->NBTP = btr; +#if CONFIG_MACH_STM32H7 + /* + The Message RAM of STM32H7 is settable + So we set it to be consistent with STM32G0 + */ + uint32_t flssa = (uint32_t)&MSG_RAM - (uint32_t)&fdcan_ram->fdcan1; + uint32_t f0sa = flssa + + (((uint32_t)MSG_RAM.RXF0 - (uint32_t)MSG_RAM.FLS) / 4); + uint32_t tbsa = f0sa + + (((uint32_t)MSG_RAM.TXFIFO - (uint32_t)MSG_RAM.RXF0) / 4); + + SOC_CAN->SIDFC = flssa << FDCAN_SIDFC_FLSSA_Pos; + + SOC_CAN->RXF0C = ((f0sa << FDCAN_RXF0C_F0SA_Pos) + | (3 << FDCAN_RXF0C_F0S_Pos)); + SOC_CAN->RXESC = ((7 << FDCAN_RXESC_F1DS_Pos) + | (7 << FDCAN_RXESC_F0DS_Pos)); + + SOC_CAN->TXBC = ((tbsa << FDCAN_TXBC_TBSA_Pos) + | (3 << FDCAN_TXBC_TFQS_Pos)); + SOC_CAN->TXESC = 7 << FDCAN_TXESC_TBDS_Pos; +#endif + /* Leave the initialisation mode */ SOC_CAN->CCCR &= ~FDCAN_CCCR_CCE; SOC_CAN->CCCR &= ~FDCAN_CCCR_INIT; diff --git a/src/stm32/stm32h7.c b/src/stm32/stm32h7.c index 122ce64b..056f7be2 100644 --- a/src/stm32/stm32h7.c +++ b/src/stm32/stm32h7.c @@ -46,8 +46,16 @@ lookup_clock_line(uint32_t periph_base) uint32_t bit = 1 << ((periph_base - D2_APB2PERIPH_BASE) / 0x400); return (struct cline){.en=&RCC->APB2ENR, .rst=&RCC->APB2RSTR, .bit=bit}; } else { - uint32_t bit = 1 << ((periph_base - D2_APB1PERIPH_BASE) / 0x400); - return (struct cline){.en=&RCC->APB1LENR,.rst=&RCC->APB1LRSTR,.bit=bit}; + uint32_t offset = ((periph_base - D2_APB1PERIPH_BASE) / 0x400); + if (offset < 32) { + uint32_t bit = 1 << offset; + return (struct cline){ + .en=&RCC->APB1LENR, .rst=&RCC->APB1LRSTR, .bit=bit}; + } else { + uint32_t bit = 1 << (offset - 32); + return (struct cline){ + .en=&RCC->APB1HENR, .rst=&RCC->APB1HRSTR, .bit=bit}; + } } } @@ -170,6 +178,9 @@ clock_setup(void) while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL1) ; + // Set the source of FDCAN clock + MODIFY_REG(RCC->D2CCIP1R, RCC_D2CCIP1R_FDCANSEL, RCC_D2CCIP1R_FDCANSEL_0); + // Configure HSI48 clock for USB if (CONFIG_USB) { SET_BIT(RCC->CR, RCC_CR_HSI48ON);