diff --git a/src/main/drivers/dshot_bitbang.c b/src/main/drivers/dshot_bitbang.c index 7b54528dce..728bd2ca41 100644 --- a/src/main/drivers/dshot_bitbang.c +++ b/src/main/drivers/dshot_bitbang.c @@ -79,6 +79,9 @@ dshotBitbangStatus_e bbStatus; #elif defined(STM32H7) #define BB_OUTPUT_BUFFER_ATTRIBUTE DMA_RAM #define BB_INPUT_BUFFER_ATTRIBUTE DMA_RAM +#elif defined(STM32G4) +#define BB_OUTPUT_BUFFER_ATTRIBUTE DMA_RAM_W +#define BB_INPUT_BUFFER_ATTRIBUTE DMA_RAM_R #endif BB_OUTPUT_BUFFER_ATTRIBUTE uint32_t bbOutputBuffer[MOTOR_DSHOT_BUFFER_SIZE * MAX_SUPPORTED_MOTOR_PORTS]; @@ -101,6 +104,25 @@ const timerHardware_t bbTimerHardware[] = { DEF_TIM(TIM1, CH2, NONE, TIM_USE_NONE, 0, 1), DEF_TIM(TIM1, CH3, NONE, TIM_USE_NONE, 0, 1), DEF_TIM(TIM1, CH4, NONE, TIM_USE_NONE, 0, 0), +#elif defined(STM32G4) + // XXX TODO: STM32G4 can use any timer for pacing + + // DMA request numbers are duplicated for TIM1 and TIM8: + // - Any pacer can serve a GPIO port. + // - For quads (or less), 4 pacers can cover the worst case scenario of + // 4 motors scattered across 4 different GPIO ports. + // - For hexas (and larger), more channels may become necessary, + // in which case the DMA request numbers should be modified. + DEF_TIM(TIM8, CH1, NONE, TIM_USE_NONE, 0, 0, 0), + DEF_TIM(TIM8, CH2, NONE, TIM_USE_NONE, 0, 1, 0), + DEF_TIM(TIM8, CH3, NONE, TIM_USE_NONE, 0, 2, 0), + DEF_TIM(TIM8, CH4, NONE, TIM_USE_NONE, 0, 3, 0), + DEF_TIM(TIM1, CH1, NONE, TIM_USE_NONE, 0, 0, 0), + DEF_TIM(TIM1, CH2, NONE, TIM_USE_NONE, 0, 1, 0), + DEF_TIM(TIM1, CH3, NONE, TIM_USE_NONE, 0, 2, 0), + DEF_TIM(TIM1, CH4, NONE, TIM_USE_NONE, 0, 3, 0), +#else +#error MCU dependent code required #endif }; @@ -649,6 +671,8 @@ motorDevice_t *dshotBitbangDevInit(const motorDevConfig_t *motorConfig, uint8_t useDshotTelemetry = motorConfig->useDshotTelemetry; #endif + memset(bbOutputBuffer, 0, sizeof(bbOutputBuffer)); + for (int motorIndex = 0; motorIndex < MAX_SUPPORTED_MOTORS && motorIndex < motorCount; motorIndex++) { const unsigned reorderedMotorIndex = motorConfig->motorOutputReordering[motorIndex]; const timerHardware_t *timerHardware = timerGetByTag(motorConfig->ioTags[reorderedMotorIndex]); @@ -679,7 +703,7 @@ motorDevice_t *dshotBitbangDevInit(const motorDevConfig_t *motorConfig, uint8_t bbMotors[motorIndex].output = output; #if defined(STM32F4) || defined(STM32F3) bbMotors[motorIndex].iocfg = IO_CONFIG(GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, bbPuPdMode); -#elif defined(STM32F7) +#elif defined(STM32F7) || defined(STM32G4) bbMotors[motorIndex].iocfg = IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_VERY_HIGH, bbPuPdMode); #endif diff --git a/src/main/drivers/dshot_bitbang_impl.h b/src/main/drivers/dshot_bitbang_impl.h index fefb258659..6067103441 100644 --- a/src/main/drivers/dshot_bitbang_impl.h +++ b/src/main/drivers/dshot_bitbang_impl.h @@ -80,6 +80,11 @@ typedef struct dmaRegCache_s { uint32_t NDTR; uint32_t PAR; uint32_t M0AR; +#elif defined(STM32G4) + uint32_t CCR; + uint32_t CNDTR; + uint32_t CPAR; + uint32_t CMAR; #else #error No MCU dependent code here #endif diff --git a/src/main/drivers/dshot_bitbang_ll.c b/src/main/drivers/dshot_bitbang_ll.c index 4cb5eeafdc..2f0550693c 100644 --- a/src/main/drivers/dshot_bitbang_ll.c +++ b/src/main/drivers/dshot_bitbang_ll.c @@ -73,7 +73,7 @@ void bbGpioSetup(bbMotor_t *bbMotor) IOWrite(bbMotor->io, 0); } -#if defined(STM32F7) +#if defined(STM32F7) || defined(STM32G4) IOConfigGPIO(bbMotor->io, IO_CONFIG(GPIO_MODE_OUTPUT_PP, GPIO_SPEED_FREQ_HIGH, bbPuPdMode)); #else #error MCU dependent code required @@ -127,20 +127,38 @@ void bbTimerChannelInit(bbPort_t *bbPort) #ifdef USE_DMA_REGISTER_CACHE void bbLoadDMARegs(dmaResource_t *dmaResource, dmaRegCache_t *dmaRegCache) { +#if defined(STM32F7) ((DMA_ARCH_TYPE *)dmaResource)->CR = dmaRegCache->CR; ((DMA_ARCH_TYPE *)dmaResource)->FCR = dmaRegCache->FCR; ((DMA_ARCH_TYPE *)dmaResource)->NDTR = dmaRegCache->NDTR; ((DMA_ARCH_TYPE *)dmaResource)->PAR = dmaRegCache->PAR; ((DMA_ARCH_TYPE *)dmaResource)->M0AR = dmaRegCache->M0AR; +#elif defined(STM32G4) + ((DMA_ARCH_TYPE *)dmaResource)->CCR = dmaRegCache->CCR; + ((DMA_ARCH_TYPE *)dmaResource)->CNDTR = dmaRegCache->CNDTR; + ((DMA_ARCH_TYPE *)dmaResource)->CPAR = dmaRegCache->CPAR; + ((DMA_ARCH_TYPE *)dmaResource)->CMAR = dmaRegCache->CMAR; +#else +#error MCU dependent code required +#endif } static void bbSaveDMARegs(dmaResource_t *dmaResource, dmaRegCache_t *dmaRegCache) { +#if defined(STM32F7) dmaRegCache->CR = ((DMA_ARCH_TYPE *)dmaResource)->CR; dmaRegCache->FCR = ((DMA_ARCH_TYPE *)dmaResource)->FCR; dmaRegCache->NDTR = ((DMA_ARCH_TYPE *)dmaResource)->NDTR; dmaRegCache->PAR = ((DMA_ARCH_TYPE *)dmaResource)->PAR; dmaRegCache->M0AR = ((DMA_ARCH_TYPE *)dmaResource)->M0AR; +#elif defined(STM32G4) + ((DMA_ARCH_TYPE *)dmaResource)->CCR = dmaRegCache->CCR; + ((DMA_ARCH_TYPE *)dmaResource)->CNDTR = dmaRegCache->CNDTR; + ((DMA_ARCH_TYPE *)dmaResource)->CPAR = dmaRegCache->CPAR; + ((DMA_ARCH_TYPE *)dmaResource)->CMAR = dmaRegCache->CMAR; +#else +#error MCU dependent code required +#endif } #endif @@ -224,15 +242,15 @@ void bbDMAPreconfigure(bbPort_t *bbPort, uint8_t direction) LL_DMA_StructInit(dmainit); dmainit->Mode = LL_DMA_MODE_NORMAL; +#if defined(STM32G4) + dmainit->PeriphRequest = bbPort->dmaChannel; +#else dmainit->Channel = bbPort->dmaChannel; + dmainit->FIFOMode = LL_DMA_FIFOMODE_ENABLE ; +#endif + dmainit->PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; dmainit->MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - dmainit->FIFOMode = LL_DMA_FIFOMODE_ENABLE ; -#if 0 - dmainit->DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ; - dmainit->DMA_MemoryBurst = DMA_MemoryBurst_Single ; - dmainit->DMA_PeripheralBurst = DMA_PeripheralBurst_Single; -#endif if (direction == DSHOT_BITBANG_DIRECTION_OUTPUT) { dmainit->Priority = LL_DMA_PRIORITY_VERYHIGH; @@ -255,7 +273,13 @@ void bbDMAPreconfigure(bbPort_t *bbPort, uint8_t direction) dmainit->PeriphOrM2MSrcAddress = (uint32_t)&bbPort->gpio->IDR; dmainit->PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_HALFWORD; dmainit->MemoryOrM2MDstAddress = (uint32_t)bbPort->portInputBuffer; + +#ifdef STM32G4 + // XXX G4 seems to require 16-bit transfer + dmainit->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_HALFWORD; +#else dmainit->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; +#endif #ifdef USE_DMA_REGISTER_CACHE xLL_EX_DMA_Init(bbPort->dmaResource, dmainit); @@ -293,7 +317,11 @@ void bbDMA_ITConfig(bbPort_t *bbPort) xLL_EX_DMA_EnableIT_TC(bbPort->dmaResource); +#if defined(STM32G4) + SET_BIT(((DMA_Channel_TypeDef *)(bbPort->dmaResource))->CCR, DMA_CCR_TCIE|DMA_CCR_TEIE); +#else SET_BIT(((DMA_Stream_TypeDef *)(bbPort->dmaResource))->CR, DMA_SxCR_TCIE|DMA_SxCR_TEIE); +#endif } void bbDMA_Cmd(bbPort_t *bbPort, FunctionalState NewState)