/** * @brief Deactivates the PWM peripheral. * * @param[in] pwmp pointer to a @p PWMDriver object */ void pwm_lld_stop(PWMDriver *pwmp) { /* If in ready state then disables the PWM clock.*/ if (pwmp->pd_state == PWM_READY) { stop_channels(pwmp); pwmp->pd_tim->CR1 = 0; pwmp->pd_tim->BDTR = 0; pwmp->pd_tim->DIER = 0; #if USE_STM32_PWM1 if (&PWMD1 == pwmp) { NVICDisableVector(TIM1_UP_IRQn); NVICDisableVector(TIM1_CC_IRQn); RCC->APB2ENR &= ~RCC_APB2ENR_TIM1EN; } #endif #if USE_STM32_PWM2 if (&PWMD2 == pwmp) { NVICDisableVector(TIM2_IRQn); RCC->APB1ENR &= ~RCC_APB1ENR_TIM2EN; } #endif #if USE_STM32_PWM3 if (&PWMD3 == pwmp) { NVICDisableVector(TIM3_IRQn); RCC->APB1ENR &= ~RCC_APB1ENR_TIM3EN; } #endif #if USE_STM32_PWM2 if (&PWMD4 == pwmp) { NVICDisableVector(TIM4_IRQn); RCC->APB1ENR &= ~RCC_APB1ENR_TIM4EN; } #endif } }
/*! * \brief * Callback for when new data is available in a pipe * * \param[in] source the event source * \param[in] condition the condition which has been satisfied * \param[in] data an unsigned integer as specified by #CHANNEL_ID, * converted to a \c gpointer using * \c GUINT_TO_POINTER() * * \return * \c FALSE when the event source should be removed, otherwise \c TRUE */ static gboolean io_watch_callback(GIOChannel *source, GIOCondition condition, gpointer data) { const guint8 input_type = GPOINTER_TO_UINT(data); gchar buffer[BUFFER_SIZE]; gsize bytes_read; GError *error = NULL; GIOStatus status; GIOChannel *write_to = NULL; if (IS_STDOUT(input_type)) { write_to = channel_stdin[1 ^ CLIENT_ID(input_type)]; } do { status = g_io_channel_read_chars(source, buffer, BUFFER_SIZE, &bytes_read, &error); if (error != NULL) { stop_channels(source, write_to); print_error(error->message); return FALSE; } if (bytes_read == 0) continue; if (write_to != NULL) { g_io_channel_write_chars(write_to, buffer, bytes_read, NULL, NULL); g_io_channel_flush(write_to, NULL); } append_text(buffer, bytes_read, input_type); } while (status == G_IO_STATUS_NORMAL); if ((condition & ~G_IO_IN) != 0) { stop_channels(source, write_to); return FALSE; } /* for some reason I can't figure out, this function is called repeatedly with condition==G_IO_IN when the client process ends - this check should prevent the program from becoming unresponsive and consuming 100% CPU */ return clients[CLIENT_ID(input_type)].is_running; }
/** * @brief Configures and activates the PWM peripheral. * * @param[in] pwmp pointer to a @p PWMDriver object */ void pwm_lld_start(PWMDriver *pwmp) { uint16_t ccer; if (pwmp->pd_state == PWM_STOP) { /* Clock activation.*/ #if USE_STM32_PWM1 if (&PWMD1 == pwmp) { NVICEnableVector(TIM1_UP_IRQn, CORTEX_PRIORITY_MASK(STM32_PWM1_IRQ_PRIORITY)); NVICEnableVector(TIM1_CC_IRQn, CORTEX_PRIORITY_MASK(STM32_PWM1_IRQ_PRIORITY)); RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; } #endif #if USE_STM32_PWM2 if (&PWMD2 == pwmp) { NVICEnableVector(TIM2_IRQn, CORTEX_PRIORITY_MASK(STM32_PWM2_IRQ_PRIORITY)); RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; } #endif #if USE_STM32_PWM3 if (&PWMD3 == pwmp) { NVICEnableVector(TIM3_IRQn, CORTEX_PRIORITY_MASK(STM32_PWM3_IRQ_PRIORITY)); RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; } #endif #if USE_STM32_PWM4 if (&PWMD4 == pwmp) { NVICEnableVector(TIM4_IRQn, CORTEX_PRIORITY_MASK(STM32_PWM4_IRQ_PRIORITY)); RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; } #endif } /* Reset channels.*/ stop_channels(pwmp); /* Configuration or reconfiguration.*/ pwmp->pd_tim->CR1 = 0; /* Timer stopped. */ pwmp->pd_tim->SMCR = 0; /* Slave mode disabled. */ pwmp->pd_tim->CR2 = pwmp->pd_config->pc_cr2; pwmp->pd_tim->PSC = pwmp->pd_config->pc_psc; pwmp->pd_tim->CNT = 0; pwmp->pd_tim->ARR = pwmp->pd_config->pc_arr; /* Output enables and polarities setup.*/ ccer = 0; switch (pwmp->pd_config->pc_channels[0].pcc_mode) { case PWM_OUTPUT_ACTIVE_LOW: ccer |= TIM_CCER_CC1P; case PWM_OUTPUT_ACTIVE_HIGH: ccer |= TIM_CCER_CC1E; default: ; } switch (pwmp->pd_config->pc_channels[1].pcc_mode) { case PWM_OUTPUT_ACTIVE_LOW: ccer |= TIM_CCER_CC2P; case PWM_OUTPUT_ACTIVE_HIGH: ccer |= TIM_CCER_CC2E; default: ; } switch (pwmp->pd_config->pc_channels[2].pcc_mode) { case PWM_OUTPUT_ACTIVE_LOW: ccer |= TIM_CCER_CC3P; case PWM_OUTPUT_ACTIVE_HIGH: ccer |= TIM_CCER_CC3E; default: ; } switch (pwmp->pd_config->pc_channels[3].pcc_mode) { case PWM_OUTPUT_ACTIVE_LOW: ccer |= TIM_CCER_CC4P; case PWM_OUTPUT_ACTIVE_HIGH: ccer |= TIM_CCER_CC4E; default: ; } pwmp->pd_tim->CCER = ccer; pwmp->pd_tim->EGR = TIM_EGR_UG; /* Update event. */ pwmp->pd_tim->SR = 0; /* Clear pending IRQs. */ pwmp->pd_tim->DIER = pwmp->pd_config->pc_callback == NULL ? 0 : TIM_DIER_UIE; pwmp->pd_tim->BDTR = TIM_BDTR_MOE; pwmp->pd_tim->CR1 = TIM_CR1_ARPE | TIM_CR1_URS | TIM_CR1_CEN; /* Timer configured and started.*/ }