1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-21 07:15:18 +03:00
This commit is contained in:
Sami Korhonen 2017-08-31 21:01:36 +03:00
parent df6b2dc1be
commit f8469ae40e
7 changed files with 124 additions and 12 deletions

View file

@ -108,6 +108,9 @@ typedef enum {
typedef struct { typedef struct {
TIM_TypeDef *timer; TIM_TypeDef *timer;
uint16_t timerDmaSources; uint16_t timerDmaSources;
#ifdef USE_DSHOT_DMAR
uint32_t dmaBurstBuffer[DSHOT_DMA_BUFFER_SIZE * 4];
#endif
} motorDmaTimer_t; } motorDmaTimer_t;
typedef struct { typedef struct {
@ -126,6 +129,7 @@ typedef struct {
TIM_HandleTypeDef TimHandle; TIM_HandleTypeDef TimHandle;
DMA_HandleTypeDef hdma_tim; DMA_HandleTypeDef hdma_tim;
uint16_t timerDmaIndex; uint16_t timerDmaIndex;
uint8_t timerIndex;
#endif #endif
} motorDmaOutput_t; } motorDmaOutput_t;

View file

@ -52,29 +52,61 @@ uint8_t getTimerIndex(TIM_TypeDef *timer)
void pwmWriteDshotInt(uint8_t index, uint16_t value) void pwmWriteDshotInt(uint8_t index, uint16_t value)
{ {
motorDmaOutput_t *const motor = &dmaMotors[index]; motorDmaOutput_t *const motor = &dmaMotors[index];
#ifdef USE_DSHOT_DMAR
if (!motor->timerHardware || !motor->timerHardware->dmaTimUPRef) {
return;
}
#else
if (!motor->timerHardware || !motor->timerHardware->dmaRef) { if (!motor->timerHardware || !motor->timerHardware->dmaRef) {
return; return;
} }
#endif
uint16_t packet = prepareDshotPacket(motor, value); uint16_t packet = prepareDshotPacket(motor, value);
uint8_t bufferSize = loadDmaBuffer(motor, packet); uint8_t bufferSize = loadDmaBuffer(motor, packet);
#ifdef USE_DSHOT_DMAR
STATIC_ASSERT(TIM_CHANNEL_1==0, tim_channel_0_indexing);
uint8_t channel_index = motor->timerHardware->channel / TIM_CHANNEL_2;
// load channel data into burst buffer
for(int i = 0; i < bufferSize; i++) {
dmaMotorTimers[motor->timerIndex].dmaBurstBuffer[channel_index + i * 4] = motor->dmaBuffer[i];
}
if(HAL_DMA_STATE_READY == motor->TimHandle.hdma[motor->timerDmaIndex]->State) {
HAL_DMA_Start_IT(motor->TimHandle.hdma[motor->timerDmaIndex], (uint32_t)dmaMotorTimers[motor->timerIndex].dmaBurstBuffer, (uint32_t)&motor->TimHandle.Instance->DMAR, bufferSize * 4);
}
#else
if (DMA_SetCurrDataCounter(&motor->TimHandle, motor->timerHardware->channel, motor->dmaBuffer, bufferSize) != HAL_OK) { if (DMA_SetCurrDataCounter(&motor->TimHandle, motor->timerHardware->channel, motor->dmaBuffer, bufferSize) != HAL_OK) {
/* DMA set error */ /* DMA set error */
return; return;
} }
#endif
} }
void pwmCompleteDshotMotorUpdate(uint8_t motorCount) void pwmCompleteDshotMotorUpdate(uint8_t motorCount)
{ {
UNUSED(motorCount); UNUSED(motorCount);
for (int i = 0; i < dmaMotorTimerCount; i++) { for (int i = 0; i < dmaMotorTimerCount; i++) {
#ifdef USE_DSHOT_DMAR
/* configure the DMA Burst Mode */
LL_TIM_ConfigDMABurst(dmaMotorTimers[i].timer, LL_TIM_DMABURST_BASEADDR_CCR1, LL_TIM_DMABURST_LENGTH_4TRANSFERS);
/* Enable the TIM DMA Request */
LL_TIM_EnableDMAReq_UPDATE(dmaMotorTimers[i].timer);
/* Reset timer counter */
LL_TIM_SetCounter(dmaMotorTimers[i].timer, 0);
if(IS_TIM_ADVANCED_INSTANCE(dmaMotorTimers[i].timer) != RESET) {
/* Enable the main output */
LL_TIM_EnableAllOutputs(dmaMotorTimers[i].timer);
}
/* Enable the counter */
LL_TIM_EnableCounter(dmaMotorTimers[i].timer);
#else
/* Reset timer counter */ /* Reset timer counter */
LL_TIM_SetCounter(dmaMotorTimers[i].timer, 0); LL_TIM_SetCounter(dmaMotorTimers[i].timer, 0);
/* Enable channel DMA requests */ /* Enable channel DMA requests */
dmaMotorTimers[i].timer->DIER |= dmaMotorTimers[i].timerDmaSources; dmaMotorTimers[i].timer->DIER |= dmaMotorTimers[i].timerDmaSources;
#endif
} }
} }
@ -82,8 +114,13 @@ static void motor_DMA_IRQHandler(dmaChannelDescriptor_t* descriptor)
{ {
motorDmaOutput_t * const motor = &dmaMotors[descriptor->userParam]; motorDmaOutput_t * const motor = &dmaMotors[descriptor->userParam];
HAL_DMA_IRQHandler(motor->TimHandle.hdma[motor->timerDmaIndex]); HAL_DMA_IRQHandler(motor->TimHandle.hdma[motor->timerDmaIndex]);
#ifdef USE_DSHOT_DMAR
LL_TIM_DisableCounter(motor->timerHardware->tim);
LL_TIM_DisableDMAReq_UPDATE(motor->timerHardware->tim);
#else
__HAL_DMA_DISABLE(&motor->hdma_tim); __HAL_DMA_DISABLE(&motor->hdma_tim);
TIM_DMACmd(&motor->TimHandle, motor->timerHardware->channel, DISABLE); TIM_DMACmd(&motor->TimHandle, motor->timerHardware->channel, DISABLE);
#endif
} }
void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType, uint8_t output) void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType, uint8_t output)
@ -115,6 +152,34 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
return; return;
} }
#ifdef USE_DSHOT_DMAR
motor->timerDmaIndex = TIM_DMA_ID_UPDATE;
/* Set the parameters to be configured */
motor->hdma_tim.Init.Channel = timerHardware->dmaTimUPChannel;
motor->hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
motor->hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
motor->hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
motor->hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
motor->hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
motor->hdma_tim.Init.Mode = DMA_NORMAL;
motor->hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
motor->hdma_tim.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
motor->hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
motor->hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
motor->hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
/* Set hdma_tim instance */
if (timerHardware->dmaTimUPRef == NULL) {
/* Initialization Error */
return;
}
motor->hdma_tim.Instance = timerHardware->dmaTimUPRef;
/* Link hdma_tim to hdma[x] (channelx) */
__HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaIndex], motor->hdma_tim);
dmaInit(timerHardware->dmaTimUPIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex));
dmaSetHandler(timerHardware->dmaTimUPIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex);
#else
motor->timerDmaIndex = timerDmaIndex(timerHardware->channel); motor->timerDmaIndex = timerDmaIndex(timerHardware->channel);
motor->timer = &dmaMotorTimers[timerIndex]; motor->timer = &dmaMotorTimers[timerIndex];
dmaMotorTimers[timerIndex].timerDmaSources |= timerDmaSource(timerHardware->channel); dmaMotorTimers[timerIndex].timerDmaSources |= timerDmaSource(timerHardware->channel);
@ -139,12 +204,12 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
return; return;
} }
motor->hdma_tim.Instance = timerHardware->dmaRef; motor->hdma_tim.Instance = timerHardware->dmaRef;
/* Link hdma_tim to hdma[x] (channelx) */ /* Link hdma_tim to hdma[x] (channelx) */
__HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaIndex], motor->hdma_tim); __HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaIndex], motor->hdma_tim);
dmaInit(timerHardware->dmaIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex)); dmaInit(timerHardware->dmaIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex));
dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex); dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex);
#endif
/* Initialize TIMx DMA handle */ /* Initialize TIMx DMA handle */
if (HAL_DMA_Init(motor->TimHandle.hdma[motor->timerDmaIndex]) != HAL_OK) { if (HAL_DMA_Init(motor->TimHandle.hdma[motor->timerDmaIndex]) != HAL_OK) {
@ -167,6 +232,26 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
/* Configuration Error */ /* Configuration Error */
return; return;
} }
#ifdef USE_DSHOT_DMAR
/* Enable the Output compare channel */
uint32_t channels = 0;
switch(motor->timerHardware->channel) {
case TIM_CHANNEL_1:
channels = LL_TIM_CHANNEL_CH1;
break;
case TIM_CHANNEL_2:
channels = LL_TIM_CHANNEL_CH2;
break;
case TIM_CHANNEL_3:
channels = LL_TIM_CHANNEL_CH3;
break;
case TIM_CHANNEL_4:
channels = LL_TIM_CHANNEL_CH4;
break;
}
motor->timerIndex = timerIndex;
LL_TIM_CC_EnableChannel(motor->timerHardware->tim, channels);
#else
if (output & TIMER_OUTPUT_N_CHANNEL) { if (output & TIMER_OUTPUT_N_CHANNEL) {
if (HAL_TIMEx_PWMN_Start(&motor->TimHandle, motor->timerHardware->channel) != HAL_OK) { if (HAL_TIMEx_PWMN_Start(&motor->TimHandle, motor->timerHardware->channel) != HAL_OK) {
/* Starting PWM generation Error */ /* Starting PWM generation Error */
@ -178,6 +263,7 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
return; return;
} }
} }
#endif
} }
#endif #endif

View file

@ -104,6 +104,12 @@ typedef struct timerHardware_s {
DMA_Channel_TypeDef *dmaRef; DMA_Channel_TypeDef *dmaRef;
#endif #endif
uint8_t dmaIrqHandler; uint8_t dmaIrqHandler;
#if defined(STM32F7)
// TIMUP
DMA_Stream_TypeDef *dmaTimUPRef;
uint32_t dmaTimUPChannel;
uint8_t dmaTimUPIrqHandler;
#endif
#endif #endif
} timerHardware_t; } timerHardware_t;

View file

@ -459,6 +459,11 @@
DEF_TIM_DMA_STREAM(dmaopt, TCH_## tim ## _ ## chan), \ DEF_TIM_DMA_STREAM(dmaopt, TCH_## tim ## _ ## chan), \
DEF_TIM_DMA_CHANNEL(dmaopt, TCH_## tim ## _ ## chan), \ DEF_TIM_DMA_CHANNEL(dmaopt, TCH_## tim ## _ ## chan), \
DEF_TIM_DMA_HANDLER(dmaopt, TCH_## tim ## _ ## chan) \ DEF_TIM_DMA_HANDLER(dmaopt, TCH_## tim ## _ ## chan) \
), \
DEF_TIM_DMA_COND( \
DEF_TIM_DMA_STREAM(0, TCH_## tim ## _UP), \
DEF_TIM_DMA_CHANNEL(0, TCH_## tim ## _UP), \
DEF_TIM_DMA_HANDLER(0, TCH_## tim ## _UP) \
) \ ) \
} \ } \
/**/ /**/
@ -531,6 +536,22 @@
#define DEF_TIM_DMA__BTCH_TIM14_CH1 NONE #define DEF_TIM_DMA__BTCH_TIM14_CH1 NONE
// TIM_UP table
#define DEF_TIM_DMA__BTCH_TIM1_UP D(2, 5, 6)
#define DEF_TIM_DMA__BTCH_TIM2_UP D(1, 7, 3)
#define DEF_TIM_DMA__BTCH_TIM3_UP D(1, 2, 5)
#define DEF_TIM_DMA__BTCH_TIM4_UP D(1, 6, 2)
#define DEF_TIM_DMA__BTCH_TIM5_UP D(1, 0, 6)
#define DEF_TIM_DMA__BTCH_TIM6_UP D(1, 1, 7)
#define DEF_TIM_DMA__BTCH_TIM7_UP D(1, 4, 1)
#define DEF_TIM_DMA__BTCH_TIM8_UP D(2, 1, 7)
#define DEF_TIM_DMA__BTCH_TIM9_UP NONE
#define DEF_TIM_DMA__BTCH_TIM10_UP NONE
#define DEF_TIM_DMA__BTCH_TIM11_UP NONE
#define DEF_TIM_DMA__BTCH_TIM12_UP NONE
#define DEF_TIM_DMA__BTCH_TIM13_UP NONE
#define DEF_TIM_DMA__BTCH_TIM14_UP NONE
// AF table // AF table
//PORTA //PORTA

View file

@ -929,9 +929,6 @@ uint16_t timerGetPrescalerByDesiredHertz(TIM_TypeDef *tim, uint32_t hz)
HAL_StatusTypeDef TIM_DMACmd(TIM_HandleTypeDef *htim, uint32_t Channel, FunctionalState NewState) HAL_StatusTypeDef TIM_DMACmd(TIM_HandleTypeDef *htim, uint32_t Channel, FunctionalState NewState)
{ {
/* Check the parameters */
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
switch (Channel) { switch (Channel) {
case TIM_CHANNEL_1: { case TIM_CHANNEL_1: {
if (NewState != DISABLE) { if (NewState != DISABLE) {
@ -988,9 +985,6 @@ HAL_StatusTypeDef TIM_DMACmd(TIM_HandleTypeDef *htim, uint32_t Channel, Function
HAL_StatusTypeDef DMA_SetCurrDataCounter(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) HAL_StatusTypeDef DMA_SetCurrDataCounter(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
{ {
/* Check the parameters */
assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
if ((htim->State == HAL_TIM_STATE_BUSY)) { if ((htim->State == HAL_TIM_STATE_BUSY)) {
return HAL_BUSY; return HAL_BUSY;
} else if ((htim->State == HAL_TIM_STATE_READY)) { } else if ((htim->State == HAL_TIM_STATE_READY)) {

View file

@ -33,13 +33,13 @@ const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = {
DEF_TIM(TIM8, CH4, PC9, TIM_USE_PWM, TIMER_INPUT_ENABLED, 0 ), // S6_IN DMA2_ST7 DEF_TIM(TIM8, CH4, PC9, TIM_USE_PWM, TIMER_INPUT_ENABLED, 0 ), // S6_IN DMA2_ST7
DEF_TIM(TIM4, CH3, PB8, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S10_OUT 1 DMA1_ST7 DEF_TIM(TIM4, CH3, PB8, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S10_OUT 1 DMA1_ST7
DEF_TIM(TIM2, CH3, PA2, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S6_OUT 2 DMA1_ST1 DEF_TIM(TIM5, CH3, PA2, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S6_OUT 2 DMA1_ST0
DEF_TIM(TIM5, CH2, PA1, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S2_OUT 3 DMA1_ST4 DEF_TIM(TIM5, CH2, PA1, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S2_OUT 3 DMA1_ST4
DEF_TIM(TIM2, CH4, PA3, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 1 ), // S1_OUT 4 DMA1_ST7 DMA1_ST6 DEF_TIM(TIM5, CH4, PA3, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S1_OUT 4 DMA1_ST1 DMA1_ST3
DEF_TIM(TIM3, CH2, PB5, TIM_USE_MOTOR | TIM_USE_LED, TIMER_OUTPUT_ENABLED, 0 ), // S4_OUT DMA1_ST5 DEF_TIM(TIM3, CH2, PB5, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S4_OUT DMA1_ST5
DEF_TIM(TIM5, CH1, PA0, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S7_OUT DMA1_ST2 DEF_TIM(TIM5, CH1, PA0, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S7_OUT DMA1_ST2
DEF_TIM(TIM4, CH4, PB9, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S5_OUT DEF_TIM(TIM4, CH4, PB9, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S5_OUT
DEF_TIM(TIM9, CH2, PE6, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S3_OUT DEF_TIM(TIM9, CH2, PE6, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S3_OUT
DEF_TIM(TIM2, CH2, PB3, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S8_OUT DMA1_ST6 DEF_TIM(TIM2, CH2, PB3, TIM_USE_MOTOR | TIM_USE_LED, TIMER_OUTPUT_ENABLED, 0 ), // S8_OUT DMA1_ST6
DEF_TIM(TIM3, CH1, PB4, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S9_OUT DMA1_ST4 DEF_TIM(TIM3, CH1, PB4, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S9_OUT DMA1_ST4
}; };

View file

@ -54,6 +54,7 @@
#ifdef STM32F7 #ifdef STM32F7
#define USE_DSHOT #define USE_DSHOT
#define USE_DSHOT_DMAR
#define USE_ESC_SENSOR #define USE_ESC_SENSOR
#define I2C3_OVERCLOCK true #define I2C3_OVERCLOCK true
#define I2C4_OVERCLOCK true #define I2C4_OVERCLOCK true