diff --git a/make/mcu/STM32H7.mk b/make/mcu/STM32H7.mk index 50e267dd8f..9682e2d2dd 100644 --- a/make/mcu/STM32H7.mk +++ b/make/mcu/STM32H7.mk @@ -71,7 +71,6 @@ EXCLUDES = \ stm32h7xx_ll_crc.c \ stm32h7xx_ll_dac.c \ stm32h7xx_ll_delayblock.c \ - stm32h7xx_ll_dma.c \ stm32h7xx_ll_dma2d.c \ stm32h7xx_ll_exti.c \ stm32h7xx_ll_fmc.c \ @@ -88,7 +87,6 @@ EXCLUDES = \ stm32h7xx_ll_rtc.c \ stm32h7xx_ll_spi.c \ stm32h7xx_ll_swpmi.c \ - stm32h7xx_ll_tim.c \ stm32h7xx_ll_usart.c \ stm32h7xx_ll_utils.c @@ -151,7 +149,7 @@ endif #Flags ARCH_FLAGS = -mthumb -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-sp-d16 -fsingle-precision-constant -Wdouble-promotion -DEVICE_FLAGS = -DUSE_HAL_DRIVER -DUSE_DMA_RAM +DEVICE_FLAGS = -DUSE_HAL_DRIVER -DUSE_FULL_LL_DRIVER -DUSE_DMA_RAM # # H743xI : 2M FLASH, 1M RAM (H753xI also) @@ -243,7 +241,8 @@ MCU_COMMON_SRC = \ drivers/light_ws2811strip_hal.c \ drivers/adc_stm32h7xx.c \ drivers/bus_i2c_hal.c \ - drivers/pwm_output_dshot_hal_hal.c \ + drivers/pwm_output_dshot_hal.c \ + drivers/pwm_output_dshot_shared.c \ drivers/persistent.c \ drivers/transponder_ir_io_hal.c \ drivers/audio_stm32h7xx.c \ diff --git a/src/main/drivers/pwm_output_dshot_hal.c b/src/main/drivers/pwm_output_dshot_hal.c index 4ec4965e56..416acd00fb 100644 --- a/src/main/drivers/pwm_output_dshot_hal.c +++ b/src/main/drivers/pwm_output_dshot_hal.c @@ -308,7 +308,11 @@ bool pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m motor->timer->dmaBurstBuffer = &dshotBurstDmaBuffer[timerIndex][0]; +#if defined(STM32H7) + DMAINIT.PeriphRequest = dmaChannel; +#else DMAINIT.Channel = dmaChannel; +#endif DMAINIT.MemoryOrM2MDstAddress = (uint32_t)motor->timer->dmaBurstBuffer; DMAINIT.FIFOThreshold = LL_DMA_FIFOTHRESHOLD_FULL; DMAINIT.PeriphOrM2MSrcAddress = (uint32_t)&timerHardware->tim->DMAR; @@ -319,7 +323,11 @@ bool pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m motor->dmaBuffer = &dshotDmaBuffer[motorIndex][0]; +#if defined(STM32H7) + DMAINIT.PeriphRequest = dmaChannel; +#else DMAINIT.Channel = dmaChannel; +#endif DMAINIT.MemoryOrM2MDstAddress = (uint32_t)motor->dmaBuffer; DMAINIT.FIFOThreshold = LL_DMA_FIFOTHRESHOLD_1_4; DMAINIT.PeriphOrM2MSrcAddress = (uint32_t)timerChCCR(timerHardware); diff --git a/src/main/drivers/pwm_output_dshot_shared.h b/src/main/drivers/pwm_output_dshot_shared.h index 56ff7e804f..cd51d40c34 100644 --- a/src/main/drivers/pwm_output_dshot_shared.h +++ b/src/main/drivers/pwm_output_dshot_shared.h @@ -25,14 +25,14 @@ #include #endif -#if defined(STM32F4) || defined(STM32F7) +#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) typedef DMA_Stream_TypeDef dmaStream_t; #else typedef DMA_Channel_TypeDef dmaStream_t; #endif extern FAST_RAM_ZERO_INIT uint8_t dmaMotorTimerCount; -#ifdef STM32F7 +#if defined(STM32F7) || defined(STM32H7) extern FAST_RAM_ZERO_INIT motorDmaTimer_t dmaMotorTimers[MAX_DMA_TIMERS]; extern FAST_RAM_ZERO_INIT motorDmaOutput_t dmaMotors[MAX_SUPPORTED_MOTORS]; #else @@ -59,8 +59,8 @@ void dshotEnableChannels(uint8_t motorCount); FAST_CODE void pwmDshotSetDirectionOutput( motorDmaOutput_t * const motor, bool output #ifndef USE_DSHOT_TELEMETRY -#ifdef STM32F7 - , LL_TIM_OC_InitTypeDef* pOcInit, LL_DMA_InitTypeDef* pDmaInit) +#if defined(STM32F7) || defined(STM32H7) + , LL_TIM_OC_InitTypeDef* pOcInit, LL_DMA_InitTypeDef* pDmaInit #else , TIM_OCInitTypeDef *pOcInit, DMA_InitTypeDef* pDmaInit #endif diff --git a/src/main/drivers/stm32h7xx_ll_ex.h b/src/main/drivers/stm32h7xx_ll_ex.h new file mode 100644 index 0000000000..b846c430f0 --- /dev/null +++ b/src/main/drivers/stm32h7xx_ll_ex.h @@ -0,0 +1,104 @@ +/* + * This file is part of Cleanflight and Betaflight. + * + * Cleanflight and Betaflight are free software. You can redistribute + * this software and/or modify this software under the terms of the + * GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * Cleanflight and Betaflight are distributed in the hope that they + * will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software. + * + * If not, see . + */ + +#pragma once + +#include "stm32h7xx.h" +#include "common/utils.h" + +// XXX Followings are straight copy of stm32f7xx_ll_ex.h. +// XXX Consider consolidation when LL-DShot is stable. + +#define DMA_STREAM_MASK 0xFFU + +__STATIC_INLINE DMA_TypeDef *LL_EX_DMA_Stream_to_DMA(DMA_Stream_TypeDef *DMAx_Streamy) +{ + // clear stream address + return (DMA_TypeDef *) (((uint32_t) DMAx_Streamy) & ((uint32_t) ~DMA_STREAM_MASK)); +} + +__STATIC_INLINE uint32_t LL_EX_DMA_Stream_to_Stream(DMA_Stream_TypeDef *DMAx_Streamy) +{ + STATIC_ASSERT(DMA1_Stream0_BASE - DMA1_BASE == sizeof(DMA_TypeDef), DMA_TypeDef_has_padding); + STATIC_ASSERT(DMA1_Stream1_BASE - DMA1_Stream0_BASE == sizeof(DMA_Stream_TypeDef), DMA_Stream_TypeDef_has_padding); + + const size_t firstStreamOffset = sizeof(DMA_TypeDef); + const size_t streamSize = sizeof(DMA_Stream_TypeDef); + + return (((uint32_t) DMAx_Streamy & DMA_STREAM_MASK) - firstStreamOffset) / streamSize; +} + +#undef DMA_STREAM_MASK + +__STATIC_INLINE uint32_t LL_EX_DMA_Init(DMA_Stream_TypeDef *DMAx_Streamy, LL_DMA_InitTypeDef *DMA_InitStruct) { + DMA_TypeDef *DMA = LL_EX_DMA_Stream_to_DMA(DMAx_Streamy); + const uint32_t Stream = LL_EX_DMA_Stream_to_Stream(DMAx_Streamy); + + return LL_DMA_Init(DMA, Stream, DMA_InitStruct); +} + +__STATIC_INLINE uint32_t LL_EX_DMA_DeInit(DMA_Stream_TypeDef *DMAx_Streamy) { + DMA_TypeDef *DMA = LL_EX_DMA_Stream_to_DMA(DMAx_Streamy); + const uint32_t Stream = LL_EX_DMA_Stream_to_Stream(DMAx_Streamy); + + return LL_DMA_DeInit(DMA, Stream); +} + +__STATIC_INLINE void LL_EX_DMA_EnableResource(DMA_Stream_TypeDef *DMAx_Streamy) +{ + SET_BIT(DMAx_Streamy->CR, DMA_SxCR_EN); +} + +__STATIC_INLINE void LL_EX_DMA_DisableResource(DMA_Stream_TypeDef *DMAx_Streamy) +{ + CLEAR_BIT(DMAx_Streamy->CR, DMA_SxCR_EN); +} + +__STATIC_INLINE void LL_EX_DMA_EnableIT_TC(DMA_Stream_TypeDef *DMAx_Streamy) +{ + SET_BIT(DMAx_Streamy->CR, DMA_SxCR_TCIE); +} + +__STATIC_INLINE void LL_EX_DMA_SetDataLength(DMA_Stream_TypeDef* DMAx_Streamy, uint32_t NbData) +{ + MODIFY_REG(DMAx_Streamy->NDTR, DMA_SxNDT, NbData); +} + +__STATIC_INLINE uint32_t LL_EX_DMA_GetDataLength(DMA_Stream_TypeDef* DMAx_Streamy) +{ + DMA_TypeDef *DMA = LL_EX_DMA_Stream_to_DMA(DMAx_Streamy); + const uint32_t Stream = LL_EX_DMA_Stream_to_Stream(DMAx_Streamy); + return LL_DMA_GetDataLength(DMA, Stream); +} + +__STATIC_INLINE void LL_EX_TIM_EnableIT(TIM_TypeDef *TIMx, uint32_t Sources) +{ + SET_BIT(TIMx->DIER, Sources); +} + +__STATIC_INLINE void LL_EX_TIM_DisableIT(TIM_TypeDef *TIMx, uint32_t Sources) +{ + CLEAR_BIT(TIMx->DIER, Sources); +} + +__STATIC_INLINE void LL_EX_TIM_CC_EnableNChannel(TIM_TypeDef *TIMx, uint32_t Channel) +{ + LL_TIM_CC_EnableChannel(TIMx, 4 * Channel); +} diff --git a/src/main/platform.h b/src/main/platform.h index 1a1989f692..d8a3a4b99e 100644 --- a/src/main/platform.h +++ b/src/main/platform.h @@ -31,6 +31,15 @@ #include "stm32h7xx_hal.h" #include "system_stm32h7xx.h" +#include "stm32h7xx_ll_spi.h" +#include "stm32h7xx_ll_gpio.h" +#include "stm32h7xx_ll_dma.h" +#include "stm32h7xx_ll_rcc.h" +#include "stm32h7xx_ll_bus.h" +#include "stm32h7xx_ll_tim.h" +#include "stm32h7xx_ll_system.h" +#include "drivers/stm32h7xx_ll_ex.h" + // Chip Unique ID on H7 #define U_ID_0 (*(uint32_t*)0x1FF1E800) #define U_ID_1 (*(uint32_t*)0x1FF1E804) diff --git a/src/main/target/common_pre.h b/src/main/target/common_pre.h index e3fb6c0fdb..b66556ce49 100644 --- a/src/main/target/common_pre.h +++ b/src/main/target/common_pre.h @@ -107,6 +107,10 @@ #define USE_ITCM_RAM #define USE_FAST_RAM #define USE_DSHOT +#define USE_DSHOT_TELEMETRY +#define USE_DSHOT_TELEMETRY_STATS +#define USE_RPM_FILTER +#define USE_DYN_IDLE #define USE_GYRO_DATA_ANALYSE #define USE_ADC_INTERNAL #define USE_USB_CDC_HID