static void serialTimerConfigureTimebase(const timerHardware_t *timerHardwarePtr, uint32_t baud) { uint32_t baseClock = SystemCoreClock / timerClockDivisor(timerHardwarePtr->tim); uint32_t clock = baseClock; uint32_t timerPeriod; do { timerPeriod = clock / baud; if (isTimerPeriodTooLarge(timerPeriod)) { if (clock > 1) { clock = clock / 2; // this is wrong - mhz stays the same ... This will double baudrate until ok (but minimum baudrate is < 1200) } else { // TODO unable to continue, unable to determine clock and timerPeriods for the given baud } } } while (isTimerPeriodTooLarge(timerPeriod)); uint8_t mhz = baseClock / 1000000; timerConfigure(timerHardwarePtr, timerPeriod, mhz); }
void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType) { 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_INDEX(motorIndex)); IOConfigGPIOAF(motorIO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP), timerHardware->alternateFunction); __DMA1_CLK_ENABLE(); if (configureTimer) { RCC_ClockCmd(timerRCC(timer), ENABLE); uint32_t hz; switch (pwmProtocolType) { case(PWM_TYPE_DSHOT600): hz = MOTOR_DSHOT600_MHZ * 1000000; break; case(PWM_TYPE_DSHOT300): hz = MOTOR_DSHOT300_MHZ * 1000000; break; default: case(PWM_TYPE_DSHOT150): hz = MOTOR_DSHOT150_MHZ * 1000000; } motor->TimHandle.Instance = timerHardware->tim; motor->TimHandle.Init.Prescaler = (SystemCoreClock / timerClockDivisor(timer) / hz) - 1;; motor->TimHandle.Init.Period = MOTOR_BITLENGTH; motor->TimHandle.Init.RepetitionCounter = 0; motor->TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; motor->TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; if(HAL_TIM_PWM_Init(&motor->TimHandle) != HAL_OK) { /* Initialization Error */ return; } } else { motor->TimHandle = dmaMotors[timerIndex].TimHandle; } switch (timerHardware->channel) { case TIM_CHANNEL_1: motor->timerDmaSource = TIM_DMA_ID_CC1; break; case TIM_CHANNEL_2: motor->timerDmaSource = TIM_DMA_ID_CC2; break; case TIM_CHANNEL_3: motor->timerDmaSource = TIM_DMA_ID_CC3; break; case TIM_CHANNEL_4: motor->timerDmaSource = TIM_DMA_ID_CC4; break; } dmaMotorTimers[timerIndex].timerDmaSources |= motor->timerDmaSource; /* Set the parameters to be configured */ motor->hdma_tim.Init.Channel = timerHardware->dmaChannel; 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_DISABLE; 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->dmaStream == NULL) { /* Initialization Error */ return; } motor->hdma_tim.Instance = timerHardware->dmaStream; /* Link hdma_tim to hdma[x] (channelx) */ __HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaSource], motor->hdma_tim); dmaInit(timerHardware->dmaIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex)); dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex); /* Initialize TIMx DMA handle */ if(HAL_DMA_Init(motor->TimHandle.hdma[motor->timerDmaSource]) != HAL_OK) { /* Initialization Error */ return; } TIM_OC_InitTypeDef TIM_OCInitStructure; /* PWM1 Mode configuration: Channel1 */ TIM_OCInitStructure.OCMode = TIM_OCMODE_PWM1; TIM_OCInitStructure.OCPolarity = TIM_OCPOLARITY_HIGH; TIM_OCInitStructure.OCIdleState = TIM_OCIDLESTATE_RESET; TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET; TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE; TIM_OCInitStructure.Pulse = 0; if(HAL_TIM_PWM_ConfigChannel(&motor->TimHandle, &TIM_OCInitStructure, motor->timerHardware->channel) != HAL_OK) { /* Configuration Error */ return; } }
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_INDEX(motorIndex)); IOConfigGPIOAF(motorIO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerHardware->alternateFunction); if (configureTimer) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); RCC_ClockCmd(timerRCC(timer), ENABLE); TIM_Cmd(timer, DISABLE); uint32_t hz; switch (pwmProtocolType) { case(PWM_TYPE_DSHOT600): hz = MOTOR_DSHOT600_MHZ * 1000000; break; case(PWM_TYPE_DSHOT300): hz = MOTOR_DSHOT300_MHZ * 1000000; break; default: case(PWM_TYPE_DSHOT150): hz = MOTOR_DSHOT150_MHZ * 1000000; } 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_RepetitionCounter = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure); } TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) { TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; TIM_OCInitStructure.TIM_OCNPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCNPolarity_Low : TIM_OCNPolarity_High; } else { TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; TIM_OCInitStructure.TIM_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High; } TIM_OCInitStructure.TIM_Pulse = 0; timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure); timerOCPreloadConfig(timer, timerHardware->channel, TIM_OCPreload_Enable); motor->timerDmaSource = timerDmaSource(timerHardware->channel); dmaMotorTimers[timerIndex].timerDmaSources |= motor->timerDmaSource; TIM_CCxCmd(timer, timerHardware->channel, TIM_CCx_Enable); if (configureTimer) { TIM_CtrlPWMOutputs(timer, ENABLE); TIM_ARRPreloadConfig(timer, ENABLE); TIM_Cmd(timer, ENABLE); } DMA_Channel_TypeDef *channel = timerHardware->dmaChannel; if (channel == NULL) { /* trying to use a non valid channel */ return; } dmaInit(timerHardware->dmaIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex)); dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex); DMA_Cmd(channel, DISABLE); DMA_DeInit(channel); DMA_StructInit(&DMA_InitStructure); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerChCCR(timerHardware); 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_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; DMA_Init(channel, &DMA_InitStructure); DMA_ITConfig(channel, DMA_IT_TC, ENABLE); }