mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-21 15:25:36 +03:00
TIM_UP
This commit is contained in:
parent
df6b2dc1be
commit
f8469ae40e
7 changed files with 124 additions and 12 deletions
|
@ -108,6 +108,9 @@ typedef enum {
|
|||
typedef struct {
|
||||
TIM_TypeDef *timer;
|
||||
uint16_t timerDmaSources;
|
||||
#ifdef USE_DSHOT_DMAR
|
||||
uint32_t dmaBurstBuffer[DSHOT_DMA_BUFFER_SIZE * 4];
|
||||
#endif
|
||||
} motorDmaTimer_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -126,6 +129,7 @@ typedef struct {
|
|||
TIM_HandleTypeDef TimHandle;
|
||||
DMA_HandleTypeDef hdma_tim;
|
||||
uint16_t timerDmaIndex;
|
||||
uint8_t timerIndex;
|
||||
#endif
|
||||
} motorDmaOutput_t;
|
||||
|
||||
|
|
|
@ -52,29 +52,61 @@ uint8_t getTimerIndex(TIM_TypeDef *timer)
|
|||
void pwmWriteDshotInt(uint8_t index, uint16_t value)
|
||||
{
|
||||
motorDmaOutput_t *const motor = &dmaMotors[index];
|
||||
|
||||
#ifdef USE_DSHOT_DMAR
|
||||
if (!motor->timerHardware || !motor->timerHardware->dmaTimUPRef) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (!motor->timerHardware || !motor->timerHardware->dmaRef) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t packet = prepareDshotPacket(motor, value);
|
||||
|
||||
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) {
|
||||
/* DMA set error */
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void pwmCompleteDshotMotorUpdate(uint8_t motorCount)
|
||||
{
|
||||
UNUSED(motorCount);
|
||||
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 */
|
||||
LL_TIM_SetCounter(dmaMotorTimers[i].timer, 0);
|
||||
/* Enable channel DMA requests */
|
||||
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];
|
||||
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);
|
||||
TIM_DMACmd(&motor->TimHandle, motor->timerHardware->channel, DISABLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#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->timer = &dmaMotorTimers[timerIndex];
|
||||
dmaMotorTimers[timerIndex].timerDmaSources |= timerDmaSource(timerHardware->channel);
|
||||
|
@ -139,12 +204,12 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
|
|||
return;
|
||||
}
|
||||
motor->hdma_tim.Instance = timerHardware->dmaRef;
|
||||
|
||||
/* Link hdma_tim to hdma[x] (channelx) */
|
||||
__HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaIndex], motor->hdma_tim);
|
||||
|
||||
dmaInit(timerHardware->dmaIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex));
|
||||
dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex);
|
||||
#endif
|
||||
|
||||
/* Initialize TIMx DMA handle */
|
||||
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 */
|
||||
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 (HAL_TIMEx_PWMN_Start(&motor->TimHandle, motor->timerHardware->channel) != HAL_OK) {
|
||||
/* Starting PWM generation Error */
|
||||
|
@ -178,6 +263,7 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m
|
|||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -104,6 +104,12 @@ typedef struct timerHardware_s {
|
|||
DMA_Channel_TypeDef *dmaRef;
|
||||
#endif
|
||||
uint8_t dmaIrqHandler;
|
||||
#if defined(STM32F7)
|
||||
// TIMUP
|
||||
DMA_Stream_TypeDef *dmaTimUPRef;
|
||||
uint32_t dmaTimUPChannel;
|
||||
uint8_t dmaTimUPIrqHandler;
|
||||
#endif
|
||||
#endif
|
||||
} timerHardware_t;
|
||||
|
||||
|
|
|
@ -459,6 +459,11 @@
|
|||
DEF_TIM_DMA_STREAM(dmaopt, TCH_## tim ## _ ## chan), \
|
||||
DEF_TIM_DMA_CHANNEL(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
|
||||
|
||||
// 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
|
||||
|
||||
//PORTA
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
switch (Channel) {
|
||||
case TIM_CHANNEL_1: {
|
||||
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)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
if ((htim->State == HAL_TIM_STATE_BUSY)) {
|
||||
return HAL_BUSY;
|
||||
} else if ((htim->State == HAL_TIM_STATE_READY)) {
|
||||
|
|
|
@ -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(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(TIM2, CH4, PA3, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 1 ), // S1_OUT 4 DMA1_ST7 DMA1_ST6
|
||||
DEF_TIM(TIM3, CH2, PB5, TIM_USE_MOTOR | TIM_USE_LED, TIMER_OUTPUT_ENABLED, 0 ), // S4_OUT DMA1_ST5
|
||||
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, 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(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(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
|
||||
};
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
|
||||
#ifdef STM32F7
|
||||
#define USE_DSHOT
|
||||
#define USE_DSHOT_DMAR
|
||||
#define USE_ESC_SENSOR
|
||||
#define I2C3_OVERCLOCK true
|
||||
#define I2C4_OVERCLOCK true
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue