From 4e529642d159136bd6063d17548ee47df5347df2 Mon Sep 17 00:00:00 2001 From: blckmn Date: Thu, 13 Oct 2016 22:03:37 +1100 Subject: [PATCH 1/6] Initial implementation of DSHOT protocol (600 and 150) --- src/main/drivers/pwm_output.c | 67 ++++++--- src/main/drivers/pwm_output.h | 37 ++++- src/main/drivers/pwm_stm32f3xx.c | 200 ++++++++++++++++++++++++++ src/main/drivers/pwm_stm32f4xx.c | 216 ++++++++++++++++++++++++++++ src/main/drivers/timer.c | 18 +-- src/main/drivers/timer.h | 11 ++ src/main/drivers/timer_stm32f10x.c | 6 + src/main/drivers/timer_stm32f30x.c | 4 + src/main/drivers/timer_stm32f4xx.c | 48 +++++++ src/main/flight/mixer.c | 36 ++--- src/main/flight/mixer.h | 4 +- src/main/io/serial_cli.c | 5 +- src/main/main.c | 8 +- src/main/target/BLUEJAYF4/target.c | 17 +-- src/main/target/BLUEJAYF4/target.h | 1 + src/main/target/BLUEJAYF4/target.mk | 1 + src/main/target/KISSFC/target.c | 25 ++-- src/main/target/KISSFC/target.h | 2 + src/main/target/KISSFC/target.mk | 3 +- src/main/target/REVO/target.c | 25 ++-- src/main/target/REVO/target.h | 2 + src/main/target/REVO/target.mk | 1 + 22 files changed, 637 insertions(+), 100 deletions(-) create mode 100644 src/main/drivers/pwm_stm32f3xx.c create mode 100644 src/main/drivers/pwm_stm32f4xx.c diff --git a/src/main/drivers/pwm_output.c b/src/main/drivers/pwm_output.c index af832c00e..82a286417 100644 --- a/src/main/drivers/pwm_output.c +++ b/src/main/drivers/pwm_output.c @@ -29,6 +29,7 @@ #define MULTISHOT_20US_MULT (MULTISHOT_TIMER_MHZ * 20 / 1000.0f) static pwmOutputPort_t motors[MAX_SUPPORTED_MOTORS]; +static pwmCompleteWriteFuncPtr pwmCompleteWritePtr = NULL; #ifdef USE_SERVOS static pwmOutputPort_t servos[MAX_SUPPORTED_SERVOS]; @@ -153,7 +154,7 @@ void pwmEnableMotors(void) pwmMotorsEnabled = true; } -void pwmCompleteOneshotMotorUpdate(uint8_t motorCount) +static void pwmCompleteOneshotMotorUpdate(uint8_t motorCount) { for (int index = 0; index < motorCount; index++) { bool overflowed = false; @@ -173,40 +174,59 @@ void pwmCompleteOneshotMotorUpdate(uint8_t motorCount) } } +void pwmCompleteMotorUpdate(uint8_t motorCount) +{ + if (pwmCompleteWritePtr) { + pwmCompleteWritePtr(motorCount); + } +} + void motorInit(const motorConfig_t *motorConfig, uint16_t idlePulse, uint8_t motorCount) { uint32_t timerMhzCounter; pwmWriteFuncPtr pwmWritePtr; bool useUnsyncedPwm = motorConfig->useUnsyncedPwm; - + bool isDigital = false; + switch (motorConfig->motorPwmProtocol) { default: - case (PWM_TYPE_ONESHOT125): + case PWM_TYPE_ONESHOT125: timerMhzCounter = ONESHOT125_TIMER_MHZ; pwmWritePtr = pwmWriteOneShot125; break; - case (PWM_TYPE_ONESHOT42): + case PWM_TYPE_ONESHOT42: timerMhzCounter = ONESHOT42_TIMER_MHZ; pwmWritePtr = pwmWriteOneShot42; break; - case (PWM_TYPE_MULTISHOT): + case PWM_TYPE_MULTISHOT: timerMhzCounter = MULTISHOT_TIMER_MHZ; pwmWritePtr = pwmWriteMultiShot; break; - case (PWM_TYPE_BRUSHED): + case PWM_TYPE_BRUSHED: timerMhzCounter = PWM_BRUSHED_TIMER_MHZ; pwmWritePtr = pwmWriteBrushed; useUnsyncedPwm = true; idlePulse = 0; break; - case (PWM_TYPE_STANDARD): + case PWM_TYPE_STANDARD: timerMhzCounter = PWM_TIMER_MHZ; pwmWritePtr = pwmWriteStandard; useUnsyncedPwm = true; idlePulse = 0; break; +#ifdef USE_DSHOT + case PWM_TYPE_DSHOT600: + case PWM_TYPE_DSHOT150: + pwmCompleteWritePtr = pwmCompleteDigitalMotorUpdate; + isDigital = true; + break; +#endif } + if (!useUnsyncedPwm && !isDigital) { + pwmCompleteWritePtr = pwmCompleteOneshotMotorUpdate; + } + for (int motorIndex = 0; motorIndex < MAX_SUPPORTED_MOTORS && motorIndex < motorCount; motorIndex++) { const ioTag_t tag = motorConfig->ioTags[motorIndex]; @@ -214,30 +234,43 @@ void motorInit(const motorConfig_t *motorConfig, uint16_t idlePulse, uint8_t mot break; } + const timerHardware_t *timerHardware = timerGetByTag(tag, TIMER_OUTPUT_ENABLED); + + if (timerHardware == NULL) { + /* flag failure and disable ability to arm */ + break; + } + +#ifdef USE_DSHOT + if (isDigital) { + pwmDigitalMotorHardwareConfig(timerHardware, motorIndex, motorConfig->motorPwmProtocol); + motors[motorIndex].pwmWritePtr = pwmWriteDigital; + motors[motorIndex].enabled = true; + continue; + } +#endif motors[motorIndex].io = IOGetByTag(tag); IOInit(motors[motorIndex].io, OWNER_MOTOR, RESOURCE_OUTPUT, RESOURCE_INDEX(motorIndex)); IOConfigGPIO(motors[motorIndex].io, IOCFG_AF_PP); - const timerHardware_t *timer = timerGetByTag(tag, TIMER_OUTPUT_ENABLED); - - if (timer == NULL) { - /* flag failure and disable ability to arm */ - break; - } - motors[motorIndex].pwmWritePtr = pwmWritePtr; if (useUnsyncedPwm) { const uint32_t hz = timerMhzCounter * 1000000; - pwmOutConfig(&motors[motorIndex], timer, timerMhzCounter, hz / motorConfig->motorPwmProtocol, idlePulse); + pwmOutConfig(&motors[motorIndex], timerHardware, timerMhzCounter, hz / motorConfig->motorPwmProtocol, idlePulse); } else { - pwmOutConfig(&motors[motorIndex], timer, timerMhzCounter, 0xFFFF, 0); + pwmOutConfig(&motors[motorIndex], timerHardware, timerMhzCounter, 0xFFFF, 0); } motors[motorIndex].enabled = true; } } -pwmOutputPort_t *pwmGetMotors() +bool pwmIsSynced(void) +{ + return pwmCompleteWritePtr != NULL; +} + +pwmOutputPort_t *pwmGetMotors(void) { return motors; } diff --git a/src/main/drivers/pwm_output.h b/src/main/drivers/pwm_output.h index fc3e9518d..507ed519e 100644 --- a/src/main/drivers/pwm_output.h +++ b/src/main/drivers/pwm_output.h @@ -26,10 +26,12 @@ typedef enum { PWM_TYPE_ONESHOT125, PWM_TYPE_ONESHOT42, PWM_TYPE_MULTISHOT, - PWM_TYPE_BRUSHED + PWM_TYPE_BRUSHED, + PWM_TYPE_DSHOT600, + PWM_TYPE_DSHOT150 } motorPwmProtocolTypes_e; -#define PWM_TIMER_MHZ 1 +#define PWM_TIMER_MHZ 1 #if defined(STM32F40_41xxx) // must be multiples of timer clock #define ONESHOT125_TIMER_MHZ 12 @@ -43,8 +45,28 @@ typedef enum { #define PWM_BRUSHED_TIMER_MHZ 24 #endif +#define MOTOR_DMA_BUFFER_SIZE 18 /* resolution + frame reset (2us) */ + +typedef struct { + TIM_TypeDef *timer; + uint16_t timerDmaSources; +} motorDmaTimer_t; + +typedef struct { + ioTag_t ioTag; + const timerHardware_t *timerHardware; + uint16_t value; + uint16_t timerDmaSource; +#if defined(STM32F4) + uint32_t dmaBuffer[MOTOR_DMA_BUFFER_SIZE]; +#else + uint8_t dmaBuffer[MOTOR_DMA_BUFFER_SIZE]; +#endif +} motorDmaOutput_t; + struct timerHardware_s; typedef void(*pwmWriteFuncPtr)(uint8_t index, uint16_t value); // function pointer used to write motors +typedef void(*pwmCompleteWriteFuncPtr)(uint8_t motorCount); // function pointer used after motors are written typedef struct { volatile timCCR_t *ccr; @@ -60,13 +82,20 @@ void servoInit(const servoConfig_t *servoConfig); void pwmServoConfig(const struct timerHardware_s *timerHardware, uint8_t servoIndex, uint16_t servoPwmRate, uint16_t servoCenterPulse); +#ifdef USE_DSHOT +void pwmWriteDigital(uint8_t index, uint16_t value); +void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType); +void pwmCompleteDigitalMotorUpdate(uint8_t motorCount); +#endif + void pwmWriteMotor(uint8_t index, uint16_t value); void pwmShutdownPulsesForAllMotors(uint8_t motorCount); -void pwmCompleteOneshotMotorUpdate(uint8_t motorCount); +void pwmCompleteMotorUpdate(uint8_t motorCount); void pwmWriteServo(uint8_t index, uint16_t value); -pwmOutputPort_t *pwmGetMotors(); +pwmOutputPort_t *pwmGetMotors(void); +bool pwmIsSynced(void); void pwmDisableMotors(void); void pwmEnableMotors(void); diff --git a/src/main/drivers/pwm_stm32f3xx.c b/src/main/drivers/pwm_stm32f3xx.c new file mode 100644 index 000000000..047b721d4 --- /dev/null +++ b/src/main/drivers/pwm_stm32f3xx.c @@ -0,0 +1,200 @@ +/* + * This file is part of Betaflight. + * + * Betaflight is free software: you can redistribute it and/or modify + * it 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. + * + * Betaflight is distributed in the hope that it 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 Betaflight. If not, see . + */ +#include +#include +#include + +#include "platform.h" + +#include "io.h" +#include "timer.h" +#include "pwm_mapping.h" +#include "pwm_output.h" +#include "nvic.h" +#include "dma.h" +#include "system.h" +#include "rcc.h" + +#define MAX_DMA_TIMERS 8 + +#define MOTOR_DSHOT600_MHZ 24 +#define MOTOR_DSHOT150_MHZ 6 + +#define MOTOR_BIT_0 14 +#define MOTOR_BIT_1 29 +#define MOTOR_BITLENGTH 39 + +static uint8_t dmaMotorTimerCount = 0; +static motorDmaTimer_t dmaMotorTimers[MAX_DMA_TIMERS]; +static motorDmaOutput_t dmaMotors[MAX_PWM_MOTORS]; + +uint8_t getTimerIndex(TIM_TypeDef *timer) +{ + for (int i = 0; i < dmaMotorTimerCount; i++) { + if (dmaMotorTimers[i].timer == timer) { + return i; + } + } + dmaMotorTimers[dmaMotorTimerCount++].timer = timer; + return dmaMotorTimerCount-1; +} + +void pwmWriteDigital(uint8_t index, uint16_t value) +{ + motorDmaOutput_t * const motor = &dmaMotors[index]; + + value = (value - 1000) * 2; + motor->value = value; + + motor->dmaBuffer[0] = (value & 0x400) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[1] = (value & 0x200) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[2] = (value & 0x100) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[3] = (value & 0x80) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[4] = (value & 0x40) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[5] = (value & 0x20) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[6] = (value & 0x10) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[7] = (value & 0x8) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[8] = (value & 0x4) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[9] = (value & 0x2) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[10] = (value & 0x1) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[11] = MOTOR_BIT_0; /* telemetry is always false for the moment */ + + /* check sum */ + motor->dmaBuffer[12] = (value & 0x400) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[13] = (value & 0x200) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[14] = (value & 0x100) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[15] = (value & 0x80) ? MOTOR_BIT_1 : MOTOR_BIT_0; + + DMA_SetCurrDataCounter(motor->timerHardware->dmaChannel, MOTOR_DMA_BUFFER_SIZE); + DMA_Cmd(motor->timerHardware->dmaChannel, ENABLE); +} + +void pwmCompleteDigitalMotorUpdate(uint8_t motorCount) +{ + UNUSED(motorCount); + + for (uint8_t i = 0; i < dmaMotorTimerCount; i++) { + TIM_SetCounter(dmaMotorTimers[i].timer, 0); + TIM_DMACmd(dmaMotorTimers[i].timer, dmaMotorTimers[i].timerDmaSources, ENABLE); + } +} + +static void motor_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) +{ + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { + DMA_Cmd(descriptor->channel, DISABLE); + DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); + } +} + +void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType) +{ + TIM_OCInitTypeDef TIM_OCInitStructure; + DMA_InitTypeDef DMA_InitStructure; + + motorDmaOutput_t * const motor = &dmaMotors[motorIndex]; + motor->timerHardware = timerHardware; + + TIM_TypeDef *timer = timerHardware->tim; + const IO_t motorIO = IOGetByTag(timerHardware->tag); + + const uint8_t timerIndex = getTimerIndex(timer); + const bool configureTimer = (timerIndex == dmaMotorTimerCount-1); + + IOInit(motorIO, OWNER_MOTOR, RESOURCE_OUTPUT, 0); + IOConfigGPIOAF(motorIO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerGPIOAF(timer)); + + if (configureTimer) { + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + + RCC_ClockCmd(timerRCC(timer), ENABLE); + TIM_Cmd(timer, DISABLE); + + uint32_t hz = (pwmProtocolType == PWM_TYPE_DSHOT600 ? MOTOR_DSHOT600_MHZ : MOTOR_DSHOT150_MHZ) * 1000000; + TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / timerClockDivisor(timer) / hz) - 1; + TIM_TimeBaseStructure.TIM_Period = MOTOR_BITLENGTH; + TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure); + } + + TIM_OCStructInit(&TIM_OCInitStructure); + TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; + TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; + TIM_OCInitStructure.TIM_Pulse = 0; + TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; + + uint32_t timerChannelAddress = 0; + switch (timerHardware->channel) { + case TIM_Channel_1: + TIM_OC1Init(timer, &TIM_OCInitStructure); + motor->timerDmaSource = TIM_DMA_CC1; + timerChannelAddress = (uint32_t)(&timer->CCR1); + TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable); + break; + case TIM_Channel_2: + TIM_OC2Init(timer, &TIM_OCInitStructure); + motor->timerDmaSource = TIM_DMA_CC2; + timerChannelAddress = (uint32_t)(&timer->CCR2); + TIM_OC2PreloadConfig(timer, TIM_OCPreload_Enable); + break; + case TIM_Channel_3: + TIM_OC3Init(timer, &TIM_OCInitStructure); + motor->timerDmaSource = TIM_DMA_CC3; + timerChannelAddress = (uint32_t)(&timer->CCR3); + TIM_OC3PreloadConfig(timer, TIM_OCPreload_Enable); + break; + case TIM_Channel_4: + TIM_OC4Init(timer, &TIM_OCInitStructure); + motor->timerDmaSource = TIM_DMA_CC4; + timerChannelAddress = (uint32_t)(&timer->CCR4); + TIM_OC4PreloadConfig(timer, TIM_OCPreload_Enable); + break; + } + + if (configureTimer) { + TIM_CtrlPWMOutputs(timer, ENABLE); + TIM_ARRPreloadConfig(timer, ENABLE); + TIM_Cmd(timer, ENABLE); + } + + DMA_Channel_TypeDef *channel = timerHardware->dmaChannel; + + DMA_Cmd(channel, DISABLE); + DMA_DeInit(channel); + DMA_StructInit(&DMA_InitStructure); + DMA_InitStructure.DMA_PeripheralBaseAddr = timerChannelAddress; + DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)motor->dmaBuffer; + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; + DMA_InitStructure.DMA_BufferSize = MOTOR_DMA_BUFFER_SIZE; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_Priority = DMA_Priority_High; + DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; + + TIM_DMACmd(timer, motor->timerDmaSource, ENABLE); + + DMA_ITConfig(channel, DMA_IT_TC, ENABLE); + DMA_Init(channel, &DMA_InitStructure); + + dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex); +} + + diff --git a/src/main/drivers/pwm_stm32f4xx.c b/src/main/drivers/pwm_stm32f4xx.c new file mode 100644 index 000000000..e514b7200 --- /dev/null +++ b/src/main/drivers/pwm_stm32f4xx.c @@ -0,0 +1,216 @@ +/* + * This file is part of Betaflight. + * + * Betaflight is free software: you can redistribute it and/or modify + * it 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. + * + * Betaflight is distributed in the hope that it 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 Betaflight. If not, see . + */ +#include +#include +#include + +#include "platform.h" + +#include "io.h" +#include "timer.h" +#include "pwm_output.h" +#include "nvic.h" +#include "dma.h" +#include "system.h" +#include "rcc.h" + +#define MAX_DMA_TIMERS 8 + +#define MOTOR_DSHOT600_MHZ 12 +#define MOTOR_DSHOT150_MHZ 3 + +#define MOTOR_BIT_0 7 +#define MOTOR_BIT_1 14 +#define MOTOR_BITLENGTH 19 + +static uint8_t dmaMotorTimerCount = 0; +static motorDmaTimer_t dmaMotorTimers[MAX_DMA_TIMERS]; +static motorDmaOutput_t dmaMotors[MAX_SUPPORTED_MOTORS]; + +uint8_t getTimerIndex(TIM_TypeDef *timer) +{ + for (int i = 0; i < dmaMotorTimerCount; i++) { + if (dmaMotorTimers[i].timer == timer) { + return i; + } + } + dmaMotorTimers[dmaMotorTimerCount++].timer = timer; + return dmaMotorTimerCount-1; +} + +void pwmWriteDigital(uint8_t index, uint16_t value) +{ + motorDmaOutput_t * const motor = &dmaMotors[index]; + + value = (value - 1000) * 2; + motor->value = value; + + motor->dmaBuffer[0] = (value & 0x400) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[1] = (value & 0x200) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[2] = (value & 0x100) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[3] = (value & 0x80) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[4] = (value & 0x40) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[5] = (value & 0x20) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[6] = (value & 0x10) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[7] = (value & 0x8) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[8] = (value & 0x4) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[9] = (value & 0x2) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[10] = (value & 0x1) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[11] = MOTOR_BIT_0; /* telemetry is always false for the moment */ + + /* check sum */ + motor->dmaBuffer[12] = (value & 0x400) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[13] = (value & 0x200) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[14] = (value & 0x100) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[15] = (value & 0x80) ? MOTOR_BIT_1 : MOTOR_BIT_0; + + DMA_SetCurrDataCounter(motor->timerHardware->dmaStream, MOTOR_DMA_BUFFER_SIZE); + DMA_Cmd(motor->timerHardware->dmaStream, ENABLE); +} + +void pwmCompleteDigitalMotorUpdate(uint8_t motorCount) +{ + UNUSED(motorCount); + + for (uint8_t i = 0; i < dmaMotorTimerCount; i++) { + TIM_SetCounter(dmaMotorTimers[i].timer, 0); + TIM_DMACmd(dmaMotorTimers[i].timer, dmaMotorTimers[i].timerDmaSources, ENABLE); + } +} + +static void motor_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) +{ + if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { + motorDmaOutput_t * const motor = &dmaMotors[descriptor->userParam]; + DMA_Cmd(descriptor->stream, DISABLE); + TIM_DMACmd(motor->timerHardware->tim, motor->timerDmaSource, DISABLE); + DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); + } +} + +void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType) +{ + TIM_OCInitTypeDef TIM_OCInitStructure; + DMA_InitTypeDef DMA_InitStructure; + + motorDmaOutput_t * const motor = &dmaMotors[motorIndex]; + motor->timerHardware = timerHardware; + + TIM_TypeDef *timer = timerHardware->tim; + const IO_t motorIO = IOGetByTag(timerHardware->tag); + + const uint8_t timerIndex = getTimerIndex(timer); + const bool configureTimer = (timerIndex == dmaMotorTimerCount-1); + + IOInit(motorIO, OWNER_MOTOR, RESOURCE_OUTPUT, 0); + IOConfigGPIOAF(motorIO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerGPIOAF(timer)); + + if (configureTimer) { + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + + RCC_ClockCmd(timerRCC(timer), ENABLE); + TIM_Cmd(timer, DISABLE); + + uint32_t hz = (pwmProtocolType == PWM_TYPE_DSHOT600 ? MOTOR_DSHOT600_MHZ : MOTOR_DSHOT150_MHZ) * 1000000; + TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / timerClockDivisor(timer) / hz) - 1; + TIM_TimeBaseStructure.TIM_Period = MOTOR_BITLENGTH; + TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure); + } + + TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; + TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; + TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; + TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_High; + TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; + TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; + TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; + TIM_OCInitStructure.TIM_Pulse = 0; + + uint32_t timerChannelAddress = 0; + uint32_t dmaItFlag = 0; + switch (timerHardware->channel) { + case TIM_Channel_1: + TIM_OC1Init(timer, &TIM_OCInitStructure); + motor->timerDmaSource = TIM_DMA_CC1; + timerChannelAddress = (uint32_t)(&timer->CCR1); + TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable); + dmaItFlag = DMA_IT_TCIF1; + break; + case TIM_Channel_2: + TIM_OC2Init(timer, &TIM_OCInitStructure); + motor->timerDmaSource = TIM_DMA_CC2; + timerChannelAddress = (uint32_t)(&timer->CCR2); + TIM_OC2PreloadConfig(timer, TIM_OCPreload_Enable); + dmaItFlag = DMA_IT_TCIF2; + break; + case TIM_Channel_3: + TIM_OC3Init(timer, &TIM_OCInitStructure); + motor->timerDmaSource = TIM_DMA_CC3; + timerChannelAddress = (uint32_t)(&timer->CCR3); + TIM_OC3PreloadConfig(timer, TIM_OCPreload_Enable); + dmaItFlag = DMA_IT_TCIF3; + break; + case TIM_Channel_4: + TIM_OC4Init(timer, &TIM_OCInitStructure); + motor->timerDmaSource = TIM_DMA_CC4; + timerChannelAddress = (uint32_t)(&timer->CCR4); + TIM_OC4PreloadConfig(timer, TIM_OCPreload_Enable); + dmaItFlag = DMA_IT_TCIF4; + break; + } + dmaMotorTimers[timerIndex].timerDmaSources |= motor->timerDmaSource; + + TIM_CCxCmd(timer, motor->timerHardware->channel, TIM_CCx_Enable); + + if (configureTimer) { + TIM_CtrlPWMOutputs(timer, ENABLE); + TIM_ARRPreloadConfig(timer, ENABLE); + TIM_Cmd(timer, ENABLE); + } + + DMA_Stream_TypeDef *stream = timerHardware->dmaStream; + + DMA_Cmd(stream, DISABLE); + DMA_DeInit(stream); + DMA_StructInit(&DMA_InitStructure); + DMA_InitStructure.DMA_Channel = timerHardware->dmaChannel; + DMA_InitStructure.DMA_PeripheralBaseAddr = timerChannelAddress; + DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)motor->dmaBuffer; + DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; + DMA_InitStructure.DMA_BufferSize = MOTOR_DMA_BUFFER_SIZE; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; + DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; + DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; + DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; + DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; + + DMA_Init(stream, &DMA_InitStructure); + + DMA_ITConfig(stream, DMA_IT_TC, ENABLE); + DMA_ClearITPendingBit(stream, dmaItFlag); + + dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex); +} + + diff --git a/src/main/drivers/timer.c b/src/main/drivers/timer.c index 701ea1499..c0425eb13 100755 --- a/src/main/drivers/timer.c +++ b/src/main/drivers/timer.c @@ -227,23 +227,7 @@ void configTimeBase(TIM_TypeDef *tim, uint16_t period, uint8_t mhz) // "The counter clock frequency (CK_CNT) is equal to f CK_PSC / (PSC[15:0] + 1)." - STM32F10x Reference Manual 14.4.11 // Thus for 1Mhz: 72000000 / 1000000 = 72, 72 - 1 = 71 = TIM_Prescaler -#if defined (STM32F40_41xxx) - if (tim == TIM1 || tim == TIM8 || tim == TIM9 || tim == TIM10 || tim == TIM11) { - TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / ((uint32_t)mhz * 1000000)) - 1; - } - else { - TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 2 / ((uint32_t)mhz * 1000000)) - 1; - } -#elif defined (STM32F411xE) - if (tim == TIM1 || tim == TIM9 || tim == TIM10 || tim == TIM11) { - TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / ((uint32_t)mhz * 1000000)) - 1; - } - else { - TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 2 / ((uint32_t)mhz * 1000000)) - 1; - } -#else - TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / ((uint32_t)mhz * 1000000)) - 1; -#endif + TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / timerClockDivisor(tim) / ((uint32_t)mhz * 1000000)) - 1; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; diff --git a/src/main/drivers/timer.h b/src/main/drivers/timer.h index 50ff96f32..244ca3bec 100644 --- a/src/main/drivers/timer.h +++ b/src/main/drivers/timer.h @@ -80,6 +80,15 @@ typedef struct timerHardware_s { #if defined(STM32F3) || defined(STM32F4) uint8_t alternateFunction; #endif +#if defined(USE_DSHOT) +#if defined(STM32F4) + DMA_Stream_TypeDef *dmaStream; + uint32_t dmaChannel; +#elif defined(STM32F3) + DMA_Channel_TypeDef *dmaChannel; +#endif + uint8_t dmaIrqHandler; +#endif } timerHardware_t; typedef enum { @@ -149,6 +158,8 @@ void timerInit(void); void timerStart(void); void timerForceOverflow(TIM_TypeDef *tim); +uint8_t timerClockDivisor(TIM_TypeDef *tim); + void configTimeBase(TIM_TypeDef *tim, uint16_t period, uint8_t mhz); // TODO - just for migration rccPeriphTag_t timerRCC(TIM_TypeDef *tim); diff --git a/src/main/drivers/timer_stm32f10x.c b/src/main/drivers/timer_stm32f10x.c index d918b0711..2d366e501 100644 --- a/src/main/drivers/timer_stm32f10x.c +++ b/src/main/drivers/timer_stm32f10x.c @@ -37,6 +37,12 @@ const timerDef_t timerDefinitions[HARDWARE_TIMER_DEFINITION_COUNT] = { #endif }; +uint8_t timerClockDivisor(TIM_TypeDef *tim) +{ + UNUSED(tim); + return 1; +} + /** * @brief Selects the TIM Output Compare Mode. * @note This function does NOT disable the selected channel before changing the Output diff --git a/src/main/drivers/timer_stm32f30x.c b/src/main/drivers/timer_stm32f30x.c index 3f7107b4c..bdb70bb63 100644 --- a/src/main/drivers/timer_stm32f30x.c +++ b/src/main/drivers/timer_stm32f30x.c @@ -29,6 +29,10 @@ const timerDef_t timerDefinitions[HARDWARE_TIMER_DEFINITION_COUNT] = { { .TIMx = TIM17, .rcc = RCC_APB2(TIM17) }, }; +uint8_t timerClockDivisor(TIM_TypeDef *tim) +{ + return 1; +} /** * @brief Selects the TIM Output Compare Mode. diff --git a/src/main/drivers/timer_stm32f4xx.c b/src/main/drivers/timer_stm32f4xx.c index 810b3a428..be299b116 100644 --- a/src/main/drivers/timer_stm32f4xx.c +++ b/src/main/drivers/timer_stm32f4xx.c @@ -58,6 +58,54 @@ const timerDef_t timerDefinitions[HARDWARE_TIMER_DEFINITION_COUNT] = { { .TIMx = TIM14, .rcc = RCC_APB1(TIM14) }, }; +/* + need a mapping from dma and timers to pins, and the values should all be set here to the dmaMotors array. + this mapping could be used for both these motors and for led strip. + + only certain pins have OC output (already used in normal PWM et al) but then + there are only certain DMA streams/channels available for certain timers and channels. + *** (this may highlight some hardware limitations on some targets) *** + + DMA1 + + Channel Stream0 Stream1 Stream2 Stream3 Stream4 Stream5 Stream6 Stream7 + 0 + 1 + 2 TIM4_CH1 TIM4_CH2 TIM4_CH3 + 3 TIM2_CH3 TIM2_CH1 TIM2_CH1 TIM2_CH4 + TIM2_CH4 + 4 + 5 TIM3_CH4 TIM3_CH1 TIM3_CH2 TIM3_CH3 + 6 TIM5_CH3 TIM5_CH4 TIM5_CH1 TIM5_CH4 TIM5_CH2 + 7 + + DMA2 + + Channel Stream0 Stream1 Stream2 Stream3 Stream4 Stream5 Stream6 Stream7 + 0 TIM8_CH1 TIM1_CH1 + TIM8_CH2 TIM1_CH2 + TIM8_CH3 TIM1_CH3 + 1 + 2 + 3 + 4 + 5 + 6 TIM1_CH1 TIM1_CH2 TIM1_CH1 TIM1_CH4 TIM1_CH3 + 7 TIM8_CH1 TIM8_CH2 TIM8_CH3 TIM8_CH4 +*/ + +uint8_t timerClockDivisor(TIM_TypeDef *tim) +{ +#if defined (STM32F40_41xxx) + if (tim == TIM8) return 1; +#endif + if (tim == TIM1 || tim == TIM9 || tim == TIM10 || tim == TIM11) { + return 1; + } else { + return 2; + } +} + void TIM_SelectOCxM_NoDisable(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode) { uint32_t tmp = 0; diff --git a/src/main/flight/mixer.c b/src/main/flight/mixer.c index 77e627540..a4f441161 100755 --- a/src/main/flight/mixer.c +++ b/src/main/flight/mixer.c @@ -331,7 +331,6 @@ const mixerRules_t servoMixers[] = { static servoMixer_t *customServoMixers; #endif - static motorMixer_t *customMixers; void mixerUseConfigs( @@ -404,14 +403,12 @@ void mixerInit(mixerMode_e mixerMode, motorMixer_t *initialCustomMixers) void loadCustomServoMixer(void) { - uint8_t i; - // reset settings servoRuleCount = 0; memset(currentServoMixer, 0, sizeof(currentServoMixer)); // load custom mixer into currentServoMixer - for (i = 0; i < MAX_SERVO_RULES; i++) { + for (uint8_t i = 0; i < MAX_SERVO_RULES; i++) { // check if done if (customServoMixers[i].rate == 0) break; @@ -421,13 +418,13 @@ void loadCustomServoMixer(void) } } -void mixerUsePWMOutputConfiguration(bool use_unsyncedPwm) +void mixerConfigureOutput(void) { int i; motorCount = 0; - syncMotorOutputWithPidLoop = !use_unsyncedPwm; + syncMotorOutputWithPidLoop = pwmIsSynced(); if (currentMixerMode == MIXER_CUSTOM || currentMixerMode == MIXER_CUSTOM_TRI || currentMixerMode == MIXER_CUSTOM_AIRPLANE) { // load custom mixer into currentMixer @@ -518,18 +515,14 @@ void mixerLoadMix(int index, motorMixer_t *customMixers) customMixers[i] = mixers[index].motor[i]; } } - #else - -void mixerUsePWMOutputConfiguration(bool use_unsyncedPwm) +void mixerConfigureOutput(void) { + syncMotorOutputWithPidLoop = pwmIsSynced(); - syncMotorOutputWithPidLoop = !use_unsyncedPwm; - - motorCount = 4; + motorCount = QUAD_MOTOR_COUNT; - uint8_t i; - for (i = 0; i < motorCount; i++) { + for (uint8_t i = 0; i < motorCount; i++) { currentMixer[i] = mixerQuadX[i]; } @@ -631,23 +624,22 @@ void writeServos(void) void writeMotors(void) { - uint8_t i; - - for (i = 0; i < motorCount; i++) + for (uint8_t i = 0; i < motorCount; i++) { pwmWriteMotor(i, motor[i]); + } if (syncMotorOutputWithPidLoop) { - pwmCompleteOneshotMotorUpdate(motorCount); + pwmCompleteMotorUpdate(motorCount); } } void writeAllMotors(int16_t mc) { - uint8_t i; - // Sends commands to all motors - for (i = 0; i < motorCount; i++) + for (uint8_t i = 0; i < motorCount; i++) { motor[i] = mc; + } + writeMotors(); } @@ -658,7 +650,7 @@ void stopMotors(void) delay(50); // give the timers and ESCs a chance to react. } -void stopPwmAllMotors() +void stopPwmAllMotors(void) { pwmShutdownPulsesForAllMotors(motorCount); delayMicroseconds(1500); diff --git a/src/main/flight/mixer.h b/src/main/flight/mixer.h index a6a7cee6d..4622cfd3f 100644 --- a/src/main/flight/mixer.h +++ b/src/main/flight/mixer.h @@ -20,6 +20,8 @@ #define MAX_SUPPORTED_MOTORS 12 #define MAX_SUPPORTED_SERVOS 8 +#define QUAD_MOTOR_COUNT 4 + // Note: this is called MultiType/MULTITYPE_* in baseflight. typedef enum mixerMode { @@ -213,7 +215,7 @@ int servoDirection(int servoIndex, int fromChannel); #endif void mixerInit(mixerMode_e mixerMode, motorMixer_t *customMotorMixers); -void mixerUsePWMOutputConfiguration(bool use_unsyncedPwm); +void mixerConfigureOutput(void); void mixerResetDisarmedMotors(void); void mixTable(void *pidProfilePtr); diff --git a/src/main/io/serial_cli.c b/src/main/io/serial_cli.c index 8fd14951a..613a8366b 100755 --- a/src/main/io/serial_cli.c +++ b/src/main/io/serial_cli.c @@ -520,7 +520,10 @@ static const char * const lookupTableSuperExpoYaw[] = { }; static const char * const lookupTablePwmProtocol[] = { - "OFF", "ONESHOT125", "ONESHOT42", "MULTISHOT", "BRUSHED" + "OFF", "ONESHOT125", "ONESHOT42", "MULTISHOT", "BRUSHED", +#ifdef USE_DSHOT + "DSHOT600", "DSHOT150" +#endif }; static const char * const lookupTableDeltaMethod[] = { diff --git a/src/main/main.c b/src/main/main.c index c495a2eb5..5ba35ecea 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -259,8 +259,9 @@ void init(void) featureClear(FEATURE_3D); idlePulse = 0; // brushed motors } + #ifdef USE_QUAD_MIXER_ONLY - motorInit(&masterConfig.motorConfig, idlePulse, 4); + motorInit(&masterConfig.motorConfig, idlePulse, QUAD_MOTOR_COUNT); #else motorInit(&masterConfig.motorConfig, idlePulse, mixers[masterConfig.mixerMode].motorCount); #endif @@ -281,10 +282,7 @@ void init(void) pwmRxSetInputFilteringMode(masterConfig.inputFilteringMode); #endif - bool usingUnsyncedOutput = (masterConfig.motorConfig.useUnsyncedPwm - || masterConfig.motorConfig.motorPwmProtocol == PWM_TYPE_BRUSHED - || masterConfig.motorConfig.motorPwmProtocol == PWM_TYPE_STANDARD); - mixerUsePWMOutputConfiguration(usingUnsyncedOutput); + mixerConfigureOutput(); systemState |= SYSTEM_STATE_MOTORS_READY; diff --git a/src/main/target/BLUEJAYF4/target.c b/src/main/target/BLUEJAYF4/target.c index a725c47a3..2e1d85f2b 100644 --- a/src/main/target/BLUEJAYF4/target.c +++ b/src/main/target/BLUEJAYF4/target.c @@ -20,14 +20,15 @@ #include #include "drivers/io.h" #include "drivers/timer.h" +#include "drivers/dma.h" -const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { - { TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8 }, // PPM IN - { TIM5, IO_TAG(PA0), TIM_Channel_1, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5 }, // S1_OUT - { TIM5, IO_TAG(PA1), TIM_Channel_2, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5 }, // S2_OUT - { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2 }, // S3_OUT - { TIM9, IO_TAG(PA3), TIM_Channel_2, TIM1_BRK_TIM9_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM9 }, // S4_OUT - { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3 }, // S5_OUT - { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3 }, // S6_OUT +const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { + { TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8, NULL, 0, 0 }, // PPM IN + { TIM5, IO_TAG(PA0), TIM_Channel_1, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5, DMA1_Stream2, DMA_Channel_6, DMA1_ST2_HANDLER }, // S1_OUT + { TIM5, IO_TAG(PA1), TIM_Channel_2, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5, DMA1_Stream4, DMA_Channel_6, DMA1_ST4_HANDLER }, // S2_OUT + { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2, DMA1_Stream1, DMA_Channel_3, DMA1_ST1_HANDLER }, // S3_OUT + { TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM9, DMA1_Stream6, DMA_Channel_3, DMA1_ST6_HANDLER }, // S4_OUT + { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3, DMA1_Stream2, DMA_Channel_5, DMA1_ST2_HANDLER }, // S5_OUT + { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3, DMA1_Stream7, DMA_Channel_5, DMA1_ST7_HANDLER }, // S6_OUT }; diff --git a/src/main/target/BLUEJAYF4/target.h b/src/main/target/BLUEJAYF4/target.h index d860ee66a..a013e3fb2 100644 --- a/src/main/target/BLUEJAYF4/target.h +++ b/src/main/target/BLUEJAYF4/target.h @@ -140,6 +140,7 @@ #define USE_ADC #define VBAT_ADC_PIN PC3 +#define USE_DSHOT #define LED_STRIP // LED Strip can run off Pin 6 (PB1) of the ESC outputs. #define WS2811_PIN PB1 diff --git a/src/main/target/BLUEJAYF4/target.mk b/src/main/target/BLUEJAYF4/target.mk index 5714bce5b..78e762476 100644 --- a/src/main/target/BLUEJAYF4/target.mk +++ b/src/main/target/BLUEJAYF4/target.mk @@ -5,4 +5,5 @@ TARGET_SRC = \ drivers/accgyro_spi_mpu6500.c \ drivers/accgyro_mpu6500.c \ drivers/barometer_ms5611.c + drivers/pwm_stm32f4xx.c diff --git a/src/main/target/KISSFC/target.c b/src/main/target/KISSFC/target.c index 743f531e3..d36fa9903 100644 --- a/src/main/target/KISSFC/target.c +++ b/src/main/target/KISSFC/target.c @@ -19,22 +19,23 @@ #include #include "drivers/io.h" +#include "drivers/dma.h" #include "drivers/timer.h" const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { - { TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, TIMER_OUTPUT_ENABLED|TIMER_OUTPUT_INVERTED, IOCFG_AF_PP, GPIO_AF_6}, - { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, TIMER_OUTPUT_ENABLED|TIMER_OUTPUT_INVERTED, IOCFG_AF_PP, GPIO_AF_2}, - { TIM15, IO_TAG(PB14), TIM_Channel_1, TIM1_BRK_TIM15_IRQn, TIMER_OUTPUT_ENABLED|TIMER_OUTPUT_INVERTED, IOCFG_AF_PP, GPIO_AF_1}, - { TIM15, IO_TAG(PB15), TIM_Channel_2, TIM1_BRK_TIM15_IRQn, TIMER_OUTPUT_ENABLED|TIMER_OUTPUT_INVERTED, IOCFG_AF_PP, GPIO_AF_1}, - { TIM16, IO_TAG(PA6), TIM_Channel_1, TIM1_UP_TIM16_IRQn, TIMER_OUTPUT_ENABLED|TIMER_OUTPUT_INVERTED, IOCFG_AF_PP, GPIO_AF_1}, - { TIM17, IO_TAG(PA7), TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, TIMER_OUTPUT_ENABLED|TIMER_OUTPUT_INVERTED, IOCFG_AF_PP, GPIO_AF_1}, + { TIM15, IO_TAG(PB15), TIM_Channel_1, TIM1_BRK_TIM15_IRQn, TIMER_OUTPUT_ENABLED, IOCFG_AF_PP, GPIO_AF_6, DMA1_Channel5, DMA1_CH5_HANDLER }, + { TIM8, IO_TAG(PB0), TIM_Channel_2, TIM8_CC_IRQn, TIMER_OUTPUT_ENABLED, IOCFG_AF_PP, GPIO_AF_2, DMA2_Channel5, DMA2_CH5_HANDLER }, + { TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, TIMER_OUTPUT_ENABLED|TIMER_OUTPUT_INVERTED, IOCFG_AF_PP, GPIO_AF_1, DMA1_Channel2, DMA1_CH2_HANDLER }, + { TIM1, IO_TAG(PB14), TIM_Channel_2, TIM1_CC_IRQn, TIMER_OUTPUT_ENABLED, IOCFG_AF_PP, GPIO_AF_1, DMA1_Channel3, DMA1_CH3_HANDLER }, + { TIM3, IO_TAG(PA6), TIM_Channel_1, TIM3_IRQn, TIMER_OUTPUT_ENABLED|TIMER_OUTPUT_INVERTED, IOCFG_AF_PP, GPIO_AF_1, DMA1_Channel6, DMA1_CH6_HANDLER }, + { TIM17, IO_TAG(PA7), TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, TIMER_OUTPUT_ENABLED|TIMER_OUTPUT_INVERTED, IOCFG_AF_PP, GPIO_AF_1, DMA1_Channel7, DMA1_CH7_HANDLER }, - { TIM2, IO_TAG(PB3), TIM_Channel_2, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1}, // TODO - Cleanup. KISS FC uses the same pin for serial and PPM - { TIM2, IO_TAG(PA15), TIM_Channel_1, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1}, - { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1}, - { TIM2, IO_TAG(PB11), TIM_Channel_4, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1}, - { TIM4, IO_TAG(PA13), TIM_Channel_2, TIM4_IRQn, 0, IOCFG_AF_PP, GPIO_AF_10}, - { TIM8, IO_TAG(PA14), TIM_Channel_3, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_5}, + { TIM2, IO_TAG(PB3), TIM_Channel_2, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1, NULL, 0}, // TODO - Cleanup. KISS FC uses the same pin for serial and PPM + { TIM2, IO_TAG(PA15), TIM_Channel_1, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1, NULL, 0}, + { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1, NULL, 0}, + { TIM2, IO_TAG(PB11), TIM_Channel_4, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1, NULL, 0}, + { TIM4, IO_TAG(PA13), TIM_Channel_2, TIM4_IRQn, 0, IOCFG_AF_PP, GPIO_AF_10, NULL, 0}, + { TIM8, IO_TAG(PA14), TIM_Channel_3, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_5, NULL, 0}, }; diff --git a/src/main/target/KISSFC/target.h b/src/main/target/KISSFC/target.h index 7eff58c7b..f8a606277 100644 --- a/src/main/target/KISSFC/target.h +++ b/src/main/target/KISSFC/target.h @@ -23,6 +23,8 @@ #define SBUS_PORT_OPTIONS (SERIAL_STOPBITS_2 | SERIAL_PARITY_EVEN | SERIAL_INVERTED | SERIAL_BIDIR) +#define USE_DSHOT + #define LED0 PB1 #define BEEPER PB13 diff --git a/src/main/target/KISSFC/target.mk b/src/main/target/KISSFC/target.mk index c59af03e5..aa0490b07 100644 --- a/src/main/target/KISSFC/target.mk +++ b/src/main/target/KISSFC/target.mk @@ -4,5 +4,6 @@ FEATURES = VCP TARGET_SRC = \ drivers/accgyro_mpu.c \ drivers/display_ug2864hsweg01.c \ - drivers/accgyro_mpu6050.c + drivers/accgyro_mpu6050.c \ + drivers/pwm_stm32f3xx.c diff --git a/src/main/target/REVO/target.c b/src/main/target/REVO/target.c index 31d22875b..f8be6e2ea 100644 --- a/src/main/target/REVO/target.c +++ b/src/main/target/REVO/target.c @@ -19,20 +19,21 @@ #include #include "drivers/io.h" +#include "drivers/dma.h" #include "drivers/timer.h" const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { - { TIM12, IO_TAG(PB14), TIM_Channel_1, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM12 }, // PPM (5th pin on FlexiIO port) - { TIM12, IO_TAG(PB15), TIM_Channel_2, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM12 }, // S2_IN - GPIO_PartialRemap_TIM3 - { TIM8, IO_TAG(PC6), TIM_Channel_1, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8 }, // S3_IN - { TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8 }, // S4_IN - { TIM8, IO_TAG(PC8), TIM_Channel_3, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8 }, // S5_IN - { TIM8, IO_TAG(PC9), TIM_Channel_4, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8 }, // S6_IN - { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3 }, // S1_OUT - { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3 }, // S2_OUT - { TIM9, IO_TAG(PA3), TIM_Channel_2, TIM1_BRK_TIM9_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM9 }, // S3_OUT - { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2 }, // S4_OUT - { TIM5, IO_TAG(PA1), TIM_Channel_2, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5 }, // S5_OUT - GPIO_PartialRemap_TIM3 - { TIM5, IO_TAG(PA0), TIM_Channel_1, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5 }, // S6_OUT + { TIM12, IO_TAG(PB14), TIM_Channel_1, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM12, NULL, 0, 0 }, // PPM (5th pin on FlexiIO port) + { TIM12, IO_TAG(PB15), TIM_Channel_2, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM12, NULL, 0, 0 }, // S2_IN + { TIM8, IO_TAG(PC6), TIM_Channel_1, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8, NULL, 0, 0 }, // S3_IN + { TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8, NULL, 0, 0 }, // S4_IN + { TIM8, IO_TAG(PC8), TIM_Channel_3, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8, NULL, 0, 0 }, // S5_IN + { TIM8, IO_TAG(PC9), TIM_Channel_4, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8, NULL, 0, 0 }, // S6_IN + { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3, DMA1_Stream7, DMA_Channel_5, DMA1_ST7_HANDLER }, // S1_OUT + { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3, DMA1_Stream2, DMA_Channel_5, DMA1_ST2_HANDLER }, // S2_OUT + { TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2, DMA1_Stream6, DMA_Channel_3, DMA1_ST6_HANDLER }, // S3_OUT + { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2, DMA1_Stream1, DMA_Channel_3, DMA1_ST1_HANDLER }, // S4_OUT + { TIM5, IO_TAG(PA1), TIM_Channel_2, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5, DMA1_Stream4, DMA_Channel_6, DMA1_ST4_HANDLER }, // S5_OUT + { TIM5, IO_TAG(PA0), TIM_Channel_1, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5, DMA1_Stream2, DMA_Channel_6, DMA1_ST2_HANDLER }, // S6_OUT }; diff --git a/src/main/target/REVO/target.h b/src/main/target/REVO/target.h index 8a20b31bb..97b66191d 100644 --- a/src/main/target/REVO/target.h +++ b/src/main/target/REVO/target.h @@ -26,6 +26,8 @@ #define USBD_SERIALNUMBER_STRING "0x8020000" #endif +#define USE_DSHOT + #define LED0 PB5 // Disable LED1, conflicts with AirbotF4/Flip32F4 beeper //#define LED1 PB4 diff --git a/src/main/target/REVO/target.mk b/src/main/target/REVO/target.mk index 2711b19da..377ad79bc 100644 --- a/src/main/target/REVO/target.mk +++ b/src/main/target/REVO/target.mk @@ -5,3 +5,4 @@ TARGET_SRC = \ drivers/accgyro_spi_mpu6000.c \ drivers/barometer_ms5611.c \ drivers/compass_hmc5883l.c + drivers/pwm_stm32f4xx.c From 712985a7aaea6cb3438dc8eb51ddd79327159370 Mon Sep 17 00:00:00 2001 From: blckmn Date: Fri, 14 Oct 2016 04:40:01 +1100 Subject: [PATCH 2/6] Cleaned up filenames to better reflect purpose Fixed build issue following rebase --- src/main/drivers/{pwm_stm32f3xx.c => pwm_output_stm32f3xx.c} | 3 +-- src/main/drivers/{pwm_stm32f4xx.c => pwm_output_stm32f4xx.c} | 0 src/main/drivers/timer_stm32f30x.c | 1 + src/main/target/BLUEJAYF4/target.mk | 4 ++-- src/main/target/KISSFC/target.mk | 2 +- src/main/target/REVO/target.mk | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) rename src/main/drivers/{pwm_stm32f3xx.c => pwm_output_stm32f3xx.c} (99%) rename src/main/drivers/{pwm_stm32f4xx.c => pwm_output_stm32f4xx.c} (100%) diff --git a/src/main/drivers/pwm_stm32f3xx.c b/src/main/drivers/pwm_output_stm32f3xx.c similarity index 99% rename from src/main/drivers/pwm_stm32f3xx.c rename to src/main/drivers/pwm_output_stm32f3xx.c index 047b721d4..11737cf88 100644 --- a/src/main/drivers/pwm_stm32f3xx.c +++ b/src/main/drivers/pwm_output_stm32f3xx.c @@ -22,7 +22,6 @@ #include "io.h" #include "timer.h" -#include "pwm_mapping.h" #include "pwm_output.h" #include "nvic.h" #include "dma.h" @@ -40,7 +39,7 @@ static uint8_t dmaMotorTimerCount = 0; static motorDmaTimer_t dmaMotorTimers[MAX_DMA_TIMERS]; -static motorDmaOutput_t dmaMotors[MAX_PWM_MOTORS]; +static motorDmaOutput_t dmaMotors[MAX_SUPPORTED_MOTORS]; uint8_t getTimerIndex(TIM_TypeDef *timer) { diff --git a/src/main/drivers/pwm_stm32f4xx.c b/src/main/drivers/pwm_output_stm32f4xx.c similarity index 100% rename from src/main/drivers/pwm_stm32f4xx.c rename to src/main/drivers/pwm_output_stm32f4xx.c diff --git a/src/main/drivers/timer_stm32f30x.c b/src/main/drivers/timer_stm32f30x.c index bdb70bb63..6265d7fd7 100644 --- a/src/main/drivers/timer_stm32f30x.c +++ b/src/main/drivers/timer_stm32f30x.c @@ -31,6 +31,7 @@ const timerDef_t timerDefinitions[HARDWARE_TIMER_DEFINITION_COUNT] = { uint8_t timerClockDivisor(TIM_TypeDef *tim) { + UNUSED(tim); return 1; } diff --git a/src/main/target/BLUEJAYF4/target.mk b/src/main/target/BLUEJAYF4/target.mk index 78e762476..c208a0e7b 100644 --- a/src/main/target/BLUEJAYF4/target.mk +++ b/src/main/target/BLUEJAYF4/target.mk @@ -4,6 +4,6 @@ FEATURES += SDCARD VCP ONBOARDFLASH TARGET_SRC = \ drivers/accgyro_spi_mpu6500.c \ drivers/accgyro_mpu6500.c \ - drivers/barometer_ms5611.c - drivers/pwm_stm32f4xx.c + drivers/barometer_ms5611.c \ + drivers/pwm_output_stm32f4xx.c diff --git a/src/main/target/KISSFC/target.mk b/src/main/target/KISSFC/target.mk index aa0490b07..c346388e0 100644 --- a/src/main/target/KISSFC/target.mk +++ b/src/main/target/KISSFC/target.mk @@ -5,5 +5,5 @@ TARGET_SRC = \ drivers/accgyro_mpu.c \ drivers/display_ug2864hsweg01.c \ drivers/accgyro_mpu6050.c \ - drivers/pwm_stm32f3xx.c + drivers/pwm_output_stm32f3xx.c diff --git a/src/main/target/REVO/target.mk b/src/main/target/REVO/target.mk index 377ad79bc..0ff56bee7 100644 --- a/src/main/target/REVO/target.mk +++ b/src/main/target/REVO/target.mk @@ -4,5 +4,5 @@ FEATURES += VCP ONBOARDFLASH TARGET_SRC = \ drivers/accgyro_spi_mpu6000.c \ drivers/barometer_ms5611.c \ - drivers/compass_hmc5883l.c - drivers/pwm_stm32f4xx.c + drivers/compass_hmc5883l.c \ + drivers/pwm_output_stm32f4xx.c From f2cb0d5ddea63c04bc90f1f3468d510bdb23a844 Mon Sep 17 00:00:00 2001 From: blckmn Date: Sat, 15 Oct 2016 17:37:37 +1100 Subject: [PATCH 3/6] Updated to utilise new CRC --- src/main/drivers/pwm_output_stm32f3xx.c | 8 ++++---- src/main/drivers/pwm_output_stm32f4xx.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/drivers/pwm_output_stm32f3xx.c b/src/main/drivers/pwm_output_stm32f3xx.c index 11737cf88..5c215f779 100644 --- a/src/main/drivers/pwm_output_stm32f3xx.c +++ b/src/main/drivers/pwm_output_stm32f3xx.c @@ -73,10 +73,10 @@ void pwmWriteDigital(uint8_t index, uint16_t value) motor->dmaBuffer[11] = MOTOR_BIT_0; /* telemetry is always false for the moment */ /* check sum */ - motor->dmaBuffer[12] = (value & 0x400) ? MOTOR_BIT_1 : MOTOR_BIT_0; - motor->dmaBuffer[13] = (value & 0x200) ? MOTOR_BIT_1 : MOTOR_BIT_0; - motor->dmaBuffer[14] = (value & 0x100) ? MOTOR_BIT_1 : MOTOR_BIT_0; - motor->dmaBuffer[15] = (value & 0x80) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[12] = (value & 0x400) ^ (value & 0x40) ^ (value & 0x4) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[13] = (value & 0x200) ^ (value & 0x20) ^ (value & 0x2) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[14] = (value & 0x100) ^ (value & 0x10) ^ (value & 0x1) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[15] = (value & 0x80) ^ (value & 0x8) ^ (0x0) ? MOTOR_BIT_1 : MOTOR_BIT_0; DMA_SetCurrDataCounter(motor->timerHardware->dmaChannel, MOTOR_DMA_BUFFER_SIZE); DMA_Cmd(motor->timerHardware->dmaChannel, ENABLE); diff --git a/src/main/drivers/pwm_output_stm32f4xx.c b/src/main/drivers/pwm_output_stm32f4xx.c index e514b7200..28222200c 100644 --- a/src/main/drivers/pwm_output_stm32f4xx.c +++ b/src/main/drivers/pwm_output_stm32f4xx.c @@ -73,10 +73,10 @@ void pwmWriteDigital(uint8_t index, uint16_t value) motor->dmaBuffer[11] = MOTOR_BIT_0; /* telemetry is always false for the moment */ /* check sum */ - motor->dmaBuffer[12] = (value & 0x400) ? MOTOR_BIT_1 : MOTOR_BIT_0; - motor->dmaBuffer[13] = (value & 0x200) ? MOTOR_BIT_1 : MOTOR_BIT_0; - motor->dmaBuffer[14] = (value & 0x100) ? MOTOR_BIT_1 : MOTOR_BIT_0; - motor->dmaBuffer[15] = (value & 0x80) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[12] = (value & 0x400) ^ (value & 0x40) ^ (value & 0x4) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[13] = (value & 0x200) ^ (value & 0x20) ^ (value & 0x2) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[14] = (value & 0x100) ^ (value & 0x10) ^ (value & 0x1) ? MOTOR_BIT_1 : MOTOR_BIT_0; + motor->dmaBuffer[15] = (value & 0x80) ^ (value & 0x8) ^ (0x0) ? MOTOR_BIT_1 : MOTOR_BIT_0; DMA_SetCurrDataCounter(motor->timerHardware->dmaStream, MOTOR_DMA_BUFFER_SIZE); DMA_Cmd(motor->timerHardware->dmaStream, ENABLE); From 631408e90bc2cb615d91fe61f28299c064187492 Mon Sep 17 00:00:00 2001 From: kc10kevin Date: Tue, 18 Oct 2016 20:27:09 +1100 Subject: [PATCH 4/6] FURYF3 and F4 support --- src/main/target/FURYF3/target.c | 19 +++++++++++-------- src/main/target/FURYF3/target.h | 2 ++ src/main/target/FURYF3/target.mk | 3 ++- src/main/target/FURYF4/target.c | 13 +++++++------ src/main/target/FURYF4/target.h | 4 +++- src/main/target/FURYF4/target.mk | 3 ++- 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/main/target/FURYF3/target.c b/src/main/target/FURYF3/target.c index 7de36bf96..5f2d3185b 100644 --- a/src/main/target/FURYF3/target.c +++ b/src/main/target/FURYF3/target.c @@ -21,17 +21,20 @@ #include "drivers/io.h" #include "drivers/timer.h" +#include "drivers/dma.h" const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { - { TIM2, IO_TAG(PB3), TIM_Channel_2, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1 }, // PPM IN - { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2 }, // SS1 - PB0 - *TIM3_CH3, TIM1_CH2N, TIM8_CH2N - { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2 }, // SS1 - PB1 - *TIM3_CH4, TIM1_CH3N, TIM8_CH3N - { TIM4, IO_TAG(PB7), TIM_Channel_2, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2 }, // PWM4 - S1 - { TIM4, IO_TAG(PB6), TIM_Channel_1, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2 }, // PWM5 - S2 - { TIM17, IO_TAG(PB5), TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, 1, IOCFG_AF_PP, GPIO_AF_10}, // PWM6 - S3 - { TIM16, IO_TAG(PB4), TIM_Channel_1, TIM1_UP_TIM16_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1 }, // PWM7 - S4 + { TIM2, IO_TAG(PB3), TIM_Channel_2, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1, NULL, 0 }, // PPM IN + { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, // SS1 - PB0 - *TIM3_CH3, TIM1_CH2N, TIM8_CH2N + { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, // SS1 - PB1 - *TIM3_CH4, TIM1_CH3N, TIM8_CH3N + + { TIM4, IO_TAG(PB7), TIM_Channel_2, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2, DMA1_Channel4, DMA1_CH4_HANDLER }, // PWM4 - S1 + { TIM4, IO_TAG(PB6), TIM_Channel_1, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2, DMA1_Channel1, DMA1_CH1_HANDLER }, // PWM5 - S2 + { TIM17, IO_TAG(PB5), TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, 1, IOCFG_AF_PP, GPIO_AF_10, DMA1_Channel7, DMA1_CH7_HANDLER }, // PWM6 - S3 + { TIM16, IO_TAG(PB4), TIM_Channel_1, TIM1_UP_TIM16_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, DMA1_Channel3, DMA1_CH3_HANDLER }, // PWM7 - S4 + + { TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, 1, IOCFG_AF_PP, GPIO_AF_6, NULL, 0 }, // GPIO TIMER - LED_STRIP - { TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, 1, IOCFG_AF_PP, GPIO_AF_6 }, // GPIO TIMER - LED_STRIP }; diff --git a/src/main/target/FURYF3/target.h b/src/main/target/FURYF3/target.h index bd9a09eca..beb71269e 100644 --- a/src/main/target/FURYF3/target.h +++ b/src/main/target/FURYF3/target.h @@ -167,6 +167,8 @@ #define USE_SERIAL_4WAY_BLHELI_INTERFACE +#define USE_DSHOT + #define TARGET_IO_PORTA 0xffff #define TARGET_IO_PORTB 0xffff #define TARGET_IO_PORTC 0xffff diff --git a/src/main/target/FURYF3/target.mk b/src/main/target/FURYF3/target.mk index 1cbb887de..b7049e346 100644 --- a/src/main/target/FURYF3/target.mk +++ b/src/main/target/FURYF3/target.mk @@ -8,5 +8,6 @@ TARGET_SRC = \ drivers/accgyro_spi_mpu6000.c \ drivers/accgyro_mpu6500.c \ drivers/accgyro_spi_mpu6500.c \ - drivers/accgyro_spi_icm20689.c + drivers/accgyro_spi_icm20689.c \ + drivers/pwm_output_stm32f3xx.c diff --git a/src/main/target/FURYF4/target.c b/src/main/target/FURYF4/target.c index 90db896c5..af6feb53c 100644 --- a/src/main/target/FURYF4/target.c +++ b/src/main/target/FURYF4/target.c @@ -19,16 +19,17 @@ #include #include "drivers/io.h" - +#include "drivers/dma.h" #include "drivers/timer.h" const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { - { TIM8, IO_TAG(PC9), TIM_Channel_4, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8 }, // PPM_IN - { TIM9, IO_TAG(PA3), TIM_Channel_2, TIM1_BRK_TIM9_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM9 }, // S1_OUT - { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3 }, // S2_OUT - { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3 }, // S3_OUT - { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2 }, // S4_OUT + { TIM8, IO_TAG(PC9), TIM_Channel_4, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8, NULL, 0, 0 }, // PPM_IN + + { TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2, DMA1_Stream6, DMA_Channel_3, DMA1_ST6_HANDLER }, // S1_OUT + { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3, DMA1_Stream7, DMA_Channel_5, DMA1_ST7_HANDLER }, // S2_OUT + { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3, DMA1_Stream2, DMA_Channel_5, DMA1_ST2_HANDLER }, // S3_OUT + { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2, DMA1_Stream1, DMA_Channel_3, DMA1_ST1_HANDLER }, // S4_OUT // { TIM5, GPIOA, Pin_0, TIM_Channel_1, TIM5_IRQn, 1, GPIO_Mode_AF, GPIO_PinSource0, GPIO_AF_TIM5 }, // LED Strip }; diff --git a/src/main/target/FURYF4/target.h b/src/main/target/FURYF4/target.h index 8b767e865..64091a079 100644 --- a/src/main/target/FURYF4/target.h +++ b/src/main/target/FURYF4/target.h @@ -183,11 +183,13 @@ #define USE_SERIAL_4WAY_BLHELI_INTERFACE +#define USE_DSHOT + #define TARGET_IO_PORTA 0xffff #define TARGET_IO_PORTB 0xffff #define TARGET_IO_PORTC 0xffff #define TARGET_IO_PORTD (BIT(2)) #define USABLE_TIMER_CHANNEL_COUNT 5 -#define USED_TIMERS ( TIM_N(2) | TIM_N(3) | TIM_N(8) | TIM_N(9)) +#define USED_TIMERS ( TIM_N(2) | TIM_N(3) | TIM_N(8) ) diff --git a/src/main/target/FURYF4/target.mk b/src/main/target/FURYF4/target.mk index b35c30a57..e1fb3c41b 100644 --- a/src/main/target/FURYF4/target.mk +++ b/src/main/target/FURYF4/target.mk @@ -6,5 +6,6 @@ TARGET_SRC = \ drivers/accgyro_spi_mpu6500.c \ drivers/accgyro_mpu6500.c \ drivers/accgyro_spi_icm20689.c \ - drivers/barometer_ms5611.c + drivers/barometer_ms5611.c \ + drivers/pwm_output_stm32f4xx.c From 9f742b017dd978ce40c166fd49415e87c20a7a69 Mon Sep 17 00:00:00 2001 From: blckmn Date: Tue, 18 Oct 2016 20:27:45 +1100 Subject: [PATCH 5/6] OMNIBUS Support, and updates to filenames etc for cleanliness --- Makefile | 2 ++ src/main/drivers/pwm_output.h | 2 +- src/main/drivers/pwm_output_stm32f3xx.c | 40 +++++++++++++++---------- src/main/drivers/pwm_output_stm32f4xx.c | 8 +++-- src/main/target/BLUEJAYF4/target.c | 2 +- src/main/target/BLUEJAYF4/target.mk | 3 +- src/main/target/KISSFC/target.mk | 3 +- src/main/target/OMNIBUS/target.c | 18 ++++++----- src/main/target/OMNIBUS/target.h | 3 +- src/main/target/OMNIBUSF4/target.c | 25 ++++++++-------- src/main/target/OMNIBUSF4/target.h | 2 ++ src/main/target/REVO/target.mk | 3 +- 12 files changed, 65 insertions(+), 46 deletions(-) diff --git a/Makefile b/Makefile index 1266aadf7..2bfcbd30c 100644 --- a/Makefile +++ b/Makefile @@ -536,6 +536,7 @@ STM32F30x_COMMON_SRC = \ drivers/dma.c \ drivers/gpio_stm32f30x.c \ drivers/light_ws2811strip_stm32f30x.c \ + drivers/pwm_output_stm32f3xx.c \ drivers/serial_uart_stm32f30x.c \ drivers/system_stm32f30x.c \ drivers/timer_stm32f30x.c @@ -550,6 +551,7 @@ STM32F4xx_COMMON_SRC = \ drivers/gpio_stm32f4xx.c \ drivers/inverter.c \ drivers/light_ws2811strip_stm32f4xx.c \ + drivers/pwm_output_stm32f4xx.c \ drivers/serial_uart_stm32f4xx.c \ drivers/system_stm32f4xx.c \ drivers/timer_stm32f4xx.c diff --git a/src/main/drivers/pwm_output.h b/src/main/drivers/pwm_output.h index 507ed519e..7bc478af7 100644 --- a/src/main/drivers/pwm_output.h +++ b/src/main/drivers/pwm_output.h @@ -57,7 +57,7 @@ typedef struct { const timerHardware_t *timerHardware; uint16_t value; uint16_t timerDmaSource; -#if defined(STM32F4) +#if defined(STM32F3) || defined(STM32F4) uint32_t dmaBuffer[MOTOR_DMA_BUFFER_SIZE]; #else uint8_t dmaBuffer[MOTOR_DMA_BUFFER_SIZE]; diff --git a/src/main/drivers/pwm_output_stm32f3xx.c b/src/main/drivers/pwm_output_stm32f3xx.c index 5c215f779..30ac9dcc0 100644 --- a/src/main/drivers/pwm_output_stm32f3xx.c +++ b/src/main/drivers/pwm_output_stm32f3xx.c @@ -28,6 +28,8 @@ #include "system.h" #include "rcc.h" +#ifdef USE_DSHOT + #define MAX_DMA_TIMERS 8 #define MOTOR_DSHOT600_MHZ 24 @@ -56,7 +58,7 @@ void pwmWriteDigital(uint8_t index, uint16_t value) { motorDmaOutput_t * const motor = &dmaMotors[index]; - value = (value - 1000) * 2; + value = (value <= 1000) ? 0 : ((value - 1000) * 2); motor->value = value; motor->dmaBuffer[0] = (value & 0x400) ? MOTOR_BIT_1 : MOTOR_BIT_0; @@ -95,7 +97,9 @@ void pwmCompleteDigitalMotorUpdate(uint8_t motorCount) static void motor_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { + motorDmaOutput_t * const motor = &dmaMotors[descriptor->userParam]; DMA_Cmd(descriptor->channel, DISABLE); + TIM_DMACmd(motor->timerHardware->tim, motor->timerDmaSource, DISABLE); DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); } } @@ -115,7 +119,7 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t const bool configureTimer = (timerIndex == dmaMotorTimerCount-1); IOInit(motorIO, OWNER_MOTOR, RESOURCE_OUTPUT, 0); - IOConfigGPIOAF(motorIO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerGPIOAF(timer)); + IOConfigGPIOAF(motorIO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerHardware->alternateFunction); if (configureTimer) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; @@ -124,7 +128,7 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t TIM_Cmd(timer, DISABLE); uint32_t hz = (pwmProtocolType == PWM_TYPE_DSHOT600 ? MOTOR_DSHOT600_MHZ : MOTOR_DSHOT150_MHZ) * 1000000; - TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / timerClockDivisor(timer) / hz) - 1; + TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)((SystemCoreClock / timerClockDivisor(timer) / hz) - 1); TIM_TimeBaseStructure.TIM_Period = MOTOR_BITLENGTH; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; @@ -133,9 +137,13 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; + TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; + TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; + TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_High; + TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; + TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; TIM_OCInitStructure.TIM_Pulse = 0; - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; uint32_t timerChannelAddress = 0; switch (timerHardware->channel) { @@ -164,15 +172,20 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t TIM_OC4PreloadConfig(timer, TIM_OCPreload_Enable); break; } - + dmaMotorTimers[timerIndex].timerDmaSources |= motor->timerDmaSource; + + TIM_CCxCmd(timer, motor->timerHardware->channel, TIM_CCx_Enable); + if (configureTimer) { - TIM_CtrlPWMOutputs(timer, ENABLE); + TIM_CtrlPWMOutputs(timer, ENABLE); TIM_ARRPreloadConfig(timer, ENABLE); - TIM_Cmd(timer, ENABLE); + TIM_Cmd(timer, ENABLE); } DMA_Channel_TypeDef *channel = timerHardware->dmaChannel; - + + dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex); + DMA_Cmd(channel, DISABLE); DMA_DeInit(channel); DMA_StructInit(&DMA_InitStructure); @@ -182,18 +195,15 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t DMA_InitStructure.DMA_BufferSize = MOTOR_DMA_BUFFER_SIZE; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; - TIM_DMACmd(timer, motor->timerDmaSource, ENABLE); + DMA_Init(channel, &DMA_InitStructure); DMA_ITConfig(channel, DMA_IT_TC, ENABLE); - DMA_Init(channel, &DMA_InitStructure); - - dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex); } - +#endif \ No newline at end of file diff --git a/src/main/drivers/pwm_output_stm32f4xx.c b/src/main/drivers/pwm_output_stm32f4xx.c index 28222200c..4f0baa546 100644 --- a/src/main/drivers/pwm_output_stm32f4xx.c +++ b/src/main/drivers/pwm_output_stm32f4xx.c @@ -28,6 +28,8 @@ #include "system.h" #include "rcc.h" +#ifdef USE_DSHOT + #define MAX_DMA_TIMERS 8 #define MOTOR_DSHOT600_MHZ 12 @@ -56,7 +58,7 @@ void pwmWriteDigital(uint8_t index, uint16_t value) { motorDmaOutput_t * const motor = &dmaMotors[index]; - value = (value - 1000) * 2; + value = (value <= 1000) ? 0 : ((value - 1000) * 2); motor->value = value; motor->dmaBuffer[0] = (value & 0x400) ? MOTOR_BIT_1 : MOTOR_BIT_0; @@ -117,7 +119,7 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t const bool configureTimer = (timerIndex == dmaMotorTimerCount-1); IOInit(motorIO, OWNER_MOTOR, RESOURCE_OUTPUT, 0); - IOConfigGPIOAF(motorIO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerGPIOAF(timer)); + IOConfigGPIOAF(motorIO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerHardware->alternateFunction); if (configureTimer) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; @@ -213,4 +215,4 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex); } - +#endif \ No newline at end of file diff --git a/src/main/target/BLUEJAYF4/target.c b/src/main/target/BLUEJAYF4/target.c index 2e1d85f2b..c82953b22 100644 --- a/src/main/target/BLUEJAYF4/target.c +++ b/src/main/target/BLUEJAYF4/target.c @@ -27,7 +27,7 @@ const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { { TIM5, IO_TAG(PA0), TIM_Channel_1, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5, DMA1_Stream2, DMA_Channel_6, DMA1_ST2_HANDLER }, // S1_OUT { TIM5, IO_TAG(PA1), TIM_Channel_2, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5, DMA1_Stream4, DMA_Channel_6, DMA1_ST4_HANDLER }, // S2_OUT { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2, DMA1_Stream1, DMA_Channel_3, DMA1_ST1_HANDLER }, // S3_OUT - { TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM9, DMA1_Stream6, DMA_Channel_3, DMA1_ST6_HANDLER }, // S4_OUT + { TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2, DMA1_Stream6, DMA_Channel_3, DMA1_ST6_HANDLER }, // S4_OUT { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3, DMA1_Stream2, DMA_Channel_5, DMA1_ST2_HANDLER }, // S5_OUT { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3, DMA1_Stream7, DMA_Channel_5, DMA1_ST7_HANDLER }, // S6_OUT }; diff --git a/src/main/target/BLUEJAYF4/target.mk b/src/main/target/BLUEJAYF4/target.mk index c208a0e7b..f4802c88b 100644 --- a/src/main/target/BLUEJAYF4/target.mk +++ b/src/main/target/BLUEJAYF4/target.mk @@ -4,6 +4,5 @@ FEATURES += SDCARD VCP ONBOARDFLASH TARGET_SRC = \ drivers/accgyro_spi_mpu6500.c \ drivers/accgyro_mpu6500.c \ - drivers/barometer_ms5611.c \ - drivers/pwm_output_stm32f4xx.c + drivers/barometer_ms5611.c diff --git a/src/main/target/KISSFC/target.mk b/src/main/target/KISSFC/target.mk index c346388e0..4b307e198 100644 --- a/src/main/target/KISSFC/target.mk +++ b/src/main/target/KISSFC/target.mk @@ -4,6 +4,5 @@ FEATURES = VCP TARGET_SRC = \ drivers/accgyro_mpu.c \ drivers/display_ug2864hsweg01.c \ - drivers/accgyro_mpu6050.c \ - drivers/pwm_output_stm32f3xx.c + drivers/accgyro_mpu6050.c diff --git a/src/main/target/OMNIBUS/target.c b/src/main/target/OMNIBUS/target.c index ee0185282..c194fc975 100644 --- a/src/main/target/OMNIBUS/target.c +++ b/src/main/target/OMNIBUS/target.c @@ -21,18 +21,22 @@ #include "drivers/io.h" #include "drivers/timer.h" +#include "drivers/dma.h" const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { // PPM Pad - { TIM3, IO_TAG(PB4), TIM_Channel_1, TIM3_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2 }, // PPM - PB4 + { TIM3, IO_TAG(PB4), TIM_Channel_1, TIM3_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, // PPM - PB4 // PB5 / TIM3 CH2 is connected to USBPresent - { TIM4, IO_TAG(PB8), TIM_Channel_3, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2 }, // PWM1 - PB8 - { TIM4, IO_TAG(PB9), TIM_Channel_4, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2 }, // PWM2 - PB9 - { TIM15, IO_TAG(PA3), TIM_Channel_2, TIM1_BRK_TIM15_IRQn, 1, IOCFG_AF_PP, GPIO_AF_9 }, // PWM3 - PA3 - { TIM15, IO_TAG(PA2), TIM_Channel_1, TIM1_BRK_TIM15_IRQn, 1, IOCFG_AF_PP, GPIO_AF_9 }, // PWM4 - PA2 + { TIM8, IO_TAG(PB8), TIM_Channel_2, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_10, DMA2_Channel5, DMA2_CH5_HANDLER }, // PWM1 - PB8 + { TIM8, IO_TAG(PB9), TIM_Channel_3, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_10, DMA2_Channel1, DMA2_CH1_HANDLER }, // PWM2 - PB9 + { TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, DMA1_Channel7, DMA1_CH7_HANDLER }, // PWM3 - PA3 + { TIM15, IO_TAG(PA2), TIM_Channel_1, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_9, DMA1_Channel5, DMA1_CH5_HANDLER }, // PWM4 - PA2 // UART3 RX/TX - { TIM2, IO_TAG(PB10), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1 }, // PWM5 - PB10 - TIM2_CH3 / UART3_TX (AF7) - { TIM2, IO_TAG(PB11), TIM_Channel_4, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1 }, // PWM6 - PB11 - TIM2_CH4 / UART3_RX (AF7) + //{ TIM2, IO_TAG(PB10), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, NULL, 0 }, // PWM5 - PB10 - TIM2_CH3 / UART3_TX (AF7) + //{ TIM2, IO_TAG(PB11), TIM_Channel_4, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, NULL, 0 }, // PWM6 - PB11 - TIM2_CH4 / UART3_RX (AF7) + { TIM4, IO_TAG(PB7), TIM_Channel_2, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, // PWM7 - PB7 + { TIM4, IO_TAG(PB6), TIM_Channel_1, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, // PWM8 - PB6 + //{ TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, 1, IOCFG_AF_PP, GPIO_AF_6, DMA1_Channel2, DMA1_CH2_HANDLER }, // GPIO_TIMER / LED_STRIP }; diff --git a/src/main/target/OMNIBUS/target.h b/src/main/target/OMNIBUS/target.h index 97a2c7c87..4b392c32f 100644 --- a/src/main/target/OMNIBUS/target.h +++ b/src/main/target/OMNIBUS/target.h @@ -140,6 +140,7 @@ //#define RSSI_ADC_PIN PB1 //#define ADC_INSTANCE ADC3 +#define USE_DSHOT #define LED_STRIP #define WS2811_PIN PA8 @@ -193,4 +194,4 @@ #define TARGET_IO_PORTF (BIT(0)|BIT(1)|BIT(4)) #define USABLE_TIMER_CHANNEL_COUNT 7 // PPM + 6 Outputs (2 shared with UART3) -#define USED_TIMERS (TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(4) | TIM_N(15)) +#define USED_TIMERS (TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(4) | TIM_N(8) | TIM_N(15)) diff --git a/src/main/target/OMNIBUSF4/target.c b/src/main/target/OMNIBUSF4/target.c index b289fb5ee..5e63b9059 100644 --- a/src/main/target/OMNIBUSF4/target.c +++ b/src/main/target/OMNIBUSF4/target.c @@ -21,19 +21,20 @@ #include "drivers/io.h" #include "drivers/timer.h" +#include "drivers/dma.h" const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { - { TIM12, IO_TAG(PB14), TIM_Channel_1, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM12 },// PPM (5th pin on FlexiIO port) - { TIM12, IO_TAG(PB15), TIM_Channel_2, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM12 },// S2_IN - GPIO_PartialRemap_TIM3 - { TIM8, IO_TAG(PC6), TIM_Channel_1, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8 }, // S3_IN - { TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8 }, // S4_IN - { TIM8, IO_TAG(PC8), TIM_Channel_3, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8 }, // S5_IN - { TIM8, IO_TAG(PC9), TIM_Channel_4, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8 }, // S6_IN + { TIM12, IO_TAG(PB14), TIM_Channel_1, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM12, NULL, 0, 0 }, // PPM (5th pin on FlexiIO port) + { TIM12, IO_TAG(PB15), TIM_Channel_2, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM12, NULL, 0, 0 }, // S2_IN - GPIO_PartialRemap_TIM3 + { TIM8, IO_TAG(PC6), TIM_Channel_1, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8, NULL, 0, 0 }, // S3_IN + { TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8, NULL, 0, 0 }, // S4_IN + { TIM8, IO_TAG(PC8), TIM_Channel_3, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8, NULL, 0, 0 }, // S5_IN + { TIM8, IO_TAG(PC9), TIM_Channel_4, TIM8_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_TIM8, NULL, 0, 0 }, // S6_IN - { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3 }, // S1_OUT - { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3 }, // S2_OUT - { TIM9, IO_TAG(PA3), TIM_Channel_2, TIM1_BRK_TIM9_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM9 }, // S4_OUT - { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2 }, // S4_OUT - { TIM5, IO_TAG(PA1), TIM_Channel_2, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5 }, // S5_OUT - GPIO_PartialRemap_TIM3 - { TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM1 }, // S6_OUT + { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3, DMA1_Stream7, DMA_Channel_5, DMA1_ST7_HANDLER }, // S1_OUT + { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM3, DMA1_Stream2, DMA_Channel_5, DMA1_ST2_HANDLER }, // S2_OUT + { TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2, DMA1_Stream6, DMA_Channel_3, DMA1_ST6_HANDLER }, // S4_OUT + { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM2, DMA1_Stream1, DMA_Channel_3, DMA1_ST1_HANDLER }, // S4_OUT + { TIM5, IO_TAG(PA1), TIM_Channel_2, TIM5_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM5, NULL, 0, 0 }, // S5_OUT - GPIO_PartialRemap_TIM3 + { TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, 1, IOCFG_AF_PP, GPIO_AF_TIM1, NULL, 0, 0 }, // S6_OUT }; diff --git a/src/main/target/OMNIBUSF4/target.h b/src/main/target/OMNIBUSF4/target.h index 9fd6c180c..d1e205b8d 100644 --- a/src/main/target/OMNIBUSF4/target.h +++ b/src/main/target/OMNIBUSF4/target.h @@ -116,6 +116,8 @@ #define VBAT_ADC_PIN PC2 //#define RSSI_ADC_PIN PA0 +#define USE_DSHOT + #define LED_STRIP // LED Strip can run off Pin 5 (PA1) of the MOTOR outputs. #define WS2811_PIN PA1 diff --git a/src/main/target/REVO/target.mk b/src/main/target/REVO/target.mk index 0ff56bee7..2711b19da 100644 --- a/src/main/target/REVO/target.mk +++ b/src/main/target/REVO/target.mk @@ -4,5 +4,4 @@ FEATURES += VCP ONBOARDFLASH TARGET_SRC = \ drivers/accgyro_spi_mpu6000.c \ drivers/barometer_ms5611.c \ - drivers/compass_hmc5883l.c \ - drivers/pwm_output_stm32f4xx.c + drivers/compass_hmc5883l.c From 927a842d8ae473829d2ca54fc2d3572024f1cf4d Mon Sep 17 00:00:00 2001 From: blckmn Date: Tue, 18 Oct 2016 23:01:11 +1100 Subject: [PATCH 6/6] FURYF3 fix and STM32F3DISCOVERY DSHOT --- src/main/drivers/pwm_output_stm32f3xx.c | 21 +++++++++++----- src/main/target/FURYF3/target.c | 10 ++++---- src/main/target/FURYF3/target.h | 2 +- src/main/target/STM32F3DISCOVERY/target.c | 29 ++++++++++++----------- src/main/target/STM32F3DISCOVERY/target.h | 2 ++ 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/main/drivers/pwm_output_stm32f3xx.c b/src/main/drivers/pwm_output_stm32f3xx.c index 30ac9dcc0..9fae6b555 100644 --- a/src/main/drivers/pwm_output_stm32f3xx.c +++ b/src/main/drivers/pwm_output_stm32f3xx.c @@ -137,12 +137,21 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; - TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; - TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_High; - TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; - TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; + if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) { + TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; + TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; + TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; + TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; + TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_Low; + TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; + } else { + TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; + TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; + TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; + TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; + TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_High; + TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; + } TIM_OCInitStructure.TIM_Pulse = 0; uint32_t timerChannelAddress = 0; diff --git a/src/main/target/FURYF3/target.c b/src/main/target/FURYF3/target.c index 5f2d3185b..504e3b6c2 100644 --- a/src/main/target/FURYF3/target.c +++ b/src/main/target/FURYF3/target.c @@ -27,12 +27,12 @@ const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { { TIM2, IO_TAG(PB3), TIM_Channel_2, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1, NULL, 0 }, // PPM IN { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, // SS1 - PB0 - *TIM3_CH3, TIM1_CH2N, TIM8_CH2N - { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, // SS1 - PB1 - *TIM3_CH4, TIM1_CH3N, TIM8_CH3N + { TIM1, IO_TAG(PB1), TIM_Channel_3, TIM1_CC_IRQn, 0, IOCFG_AF_PP, GPIO_AF_6, NULL, 0 }, // SS1 - PB1 - *TIM3_CH4, TIM1_CH3N, TIM8_CH3N - { TIM4, IO_TAG(PB7), TIM_Channel_2, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2, DMA1_Channel4, DMA1_CH4_HANDLER }, // PWM4 - S1 - { TIM4, IO_TAG(PB6), TIM_Channel_1, TIM4_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2, DMA1_Channel1, DMA1_CH1_HANDLER }, // PWM5 - S2 - { TIM17, IO_TAG(PB5), TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, 1, IOCFG_AF_PP, GPIO_AF_10, DMA1_Channel7, DMA1_CH7_HANDLER }, // PWM6 - S3 - { TIM16, IO_TAG(PB4), TIM_Channel_1, TIM1_UP_TIM16_IRQn, 1, IOCFG_AF_PP, GPIO_AF_1, DMA1_Channel3, DMA1_CH3_HANDLER }, // PWM7 - S4 + { TIM3, IO_TAG(PB7), TIM_Channel_4, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_10, DMA1_Channel3, DMA1_CH3_HANDLER }, // PWM4 - S1 + { TIM8, IO_TAG(PB6), TIM_Channel_1, TIM8_CC_IRQn, 1, IOCFG_AF_PP, GPIO_AF_5, DMA2_Channel3, DMA2_CH3_HANDLER }, // PWM5 - S2 + { TIM8, IO_TAG(PB5), TIM_Channel_3, TIM8_CC_IRQn, (1 | TIMER_OUTPUT_N_CHANNEL), IOCFG_AF_PP, GPIO_AF_3, DMA2_Channel1, DMA2_CH1_HANDLER }, // PWM6 - S3 + { TIM3, IO_TAG(PB4), TIM_Channel_1, TIM3_IRQn, 1, IOCFG_AF_PP, GPIO_AF_2, DMA1_Channel6, DMA1_CH6_HANDLER }, // PWM7 - S4 { TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, 1, IOCFG_AF_PP, GPIO_AF_6, NULL, 0 }, // GPIO TIMER - LED_STRIP diff --git a/src/main/target/FURYF3/target.h b/src/main/target/FURYF3/target.h index beb71269e..f8c74899e 100644 --- a/src/main/target/FURYF3/target.h +++ b/src/main/target/FURYF3/target.h @@ -176,5 +176,5 @@ #define TARGET_IO_PORTF (BIT(4)) #define USABLE_TIMER_CHANNEL_COUNT 8 -#define USED_TIMERS (TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(4) | TIM_N(16) |TIM_N(17)) +#define USED_TIMERS (TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(4) | TIM_N(8) | TIM_N(16) | TIM_N(17)) diff --git a/src/main/target/STM32F3DISCOVERY/target.c b/src/main/target/STM32F3DISCOVERY/target.c index 182056592..8cd9a3584 100644 --- a/src/main/target/STM32F3DISCOVERY/target.c +++ b/src/main/target/STM32F3DISCOVERY/target.c @@ -21,21 +21,22 @@ #include "drivers/io.h" #include "drivers/timer.h" +#include "drivers/dma.h" const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { - { TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, 1, IOCFG_AF_PP_PD, GPIO_AF_6 }, // PWM1 - PA8 - { TIM16, IO_TAG(PB8), TIM_Channel_1, TIM1_UP_TIM16_IRQn, 0, IOCFG_AF_PP_PD, GPIO_AF_1 }, // PWM2 - PB8 - { TIM17, IO_TAG(PB9), TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, 0, IOCFG_AF_PP_PD, GPIO_AF_1 }, // PWM3 - PB9 - { TIM8, IO_TAG(PC6), TIM_Channel_1, TIM8_CC_IRQn, 1, IOCFG_AF_PP_PD, GPIO_AF_4 }, // PWM4 - PC6 - { TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, 1, IOCFG_AF_PP_PD, GPIO_AF_4 }, // PWM5 - PC7 - { TIM8, IO_TAG(PC8), TIM_Channel_3, TIM8_CC_IRQn, 1, IOCFG_AF_PP_PD, GPIO_AF_4 }, // PWM6 - PC8 - { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 0, IOCFG_AF_PP_PD, GPIO_AF_2 }, // PWM7 - PB1 - { TIM3, IO_TAG(PA4), TIM_Channel_2, TIM3_IRQn, 0, IOCFG_AF_PP_PD, GPIO_AF_2 }, // PWM8 - PA2 - { TIM4, IO_TAG(PD12), TIM_Channel_1, TIM4_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2 }, // PWM9 - PD12 - { TIM4, IO_TAG(PD13), TIM_Channel_2, TIM4_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2 }, // PWM10 - PD13 - { TIM4, IO_TAG(PD14), TIM_Channel_3, TIM4_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2 }, // PWM11 - PD14 - { TIM4, IO_TAG(PD15), TIM_Channel_4, TIM4_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2 }, // PWM12 - PD15 - { TIM2, IO_TAG(PA1), TIM_Channel_2, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1 }, // PWM13 - PA1 - { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1 } // PWM14 - PA2 + { TIM16, IO_TAG(PB8), TIM_Channel_1, TIM1_UP_TIM16_IRQn, 0, IOCFG_AF_PP_PD, GPIO_AF_1, NULL, 0 }, + { TIM17, IO_TAG(PB9), TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, 0, IOCFG_AF_PP_PD, GPIO_AF_1, NULL, 0 }, + { TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, 1, IOCFG_AF_PP_PD, GPIO_AF_6, DMA1_Channel2, DMA1_CH2_HANDLER }, + { TIM8, IO_TAG(PC6), TIM_Channel_1, TIM8_CC_IRQn, 1, IOCFG_AF_PP_PD, GPIO_AF_4, DMA2_Channel3, DMA2_CH3_HANDLER }, + { TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, 1, IOCFG_AF_PP_PD, GPIO_AF_4, DMA2_Channel5, DMA2_CH5_HANDLER }, + { TIM8, IO_TAG(PC8), TIM_Channel_3, TIM8_CC_IRQn, 1, IOCFG_AF_PP_PD, GPIO_AF_4, DMA2_Channel1, DMA2_CH1_HANDLER }, + { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, 0, IOCFG_AF_PP_PD, GPIO_AF_2, NULL, 0 }, + { TIM3, IO_TAG(PA4), TIM_Channel_2, TIM3_IRQn, 0, IOCFG_AF_PP_PD, GPIO_AF_2, NULL, 0 }, + { TIM4, IO_TAG(PD12), TIM_Channel_1, TIM4_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, + { TIM4, IO_TAG(PD13), TIM_Channel_2, TIM4_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, + { TIM4, IO_TAG(PD14), TIM_Channel_3, TIM4_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, + { TIM4, IO_TAG(PD15), TIM_Channel_4, TIM4_IRQn, 0, IOCFG_AF_PP, GPIO_AF_2, NULL, 0 }, + { TIM2, IO_TAG(PA1), TIM_Channel_2, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1, NULL, 0 }, + { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, 0, IOCFG_AF_PP, GPIO_AF_1, NULL, 0 } }; diff --git a/src/main/target/STM32F3DISCOVERY/target.h b/src/main/target/STM32F3DISCOVERY/target.h index 9cba1c51f..687fa1924 100644 --- a/src/main/target/STM32F3DISCOVERY/target.h +++ b/src/main/target/STM32F3DISCOVERY/target.h @@ -164,6 +164,8 @@ #define RSSI_ADC_PIN PC2 #define EXTERNAL1_ADC_PIN PC3 +#define USE_DSHOT + #define LED_STRIP #define WS2811_PIN PB8 // TIM16_CH1 #define WS2811_TIMER TIM16