void gpdrive_deinit(void) { if (!m_init_done) { return; } m_init_done = false; timer_thd_stop = true; while (timer_thd_stop) { chThdSleepMilliseconds(1); } TIM_DeInit(TIM1); TIM_DeInit(TIM12); ADC_DeInit(); DMA_DeInit(DMA2_Stream4); nvicDisableVector(ADC_IRQn); dmaStreamRelease(STM32_DMA_STREAM(STM32_DMA_STREAM_ID(2, 4))); // Restore pins palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(GPIO_AF_TIM1) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUDR_FLOATING); palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(GPIO_AF_TIM1) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUDR_FLOATING); }
void gpdrive_init(volatile mc_configuration *configuration) { utils_sys_lock_cnt(); m_init_done = false; // Restore timers TIM_DeInit(TIM1); TIM1->CNT = 0; // Disable channel 2 pins palSetPadMode(GPIOA, 9, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 9); palSetPadMode(GPIOB, 14, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOB, 14); m_conf = configuration; m_fsw_now = 40000; m_mod_now = 0.0; m_current_now = 0.0; m_current_now_filtered = 0.0; m_output_mode = GPD_OUTPUT_MODE_NONE; memset((void*)&m_sample_buffer, 0, sizeof(m_sample_buffer)); m_buffer_int_scale = 1.0 / 128.0; m_is_running = false; m_output_now = 0.0; m_curr0_sum = 0; m_curr1_sum = 0; m_curr_samples = 0; m_curr0_offset = 0; m_curr1_offset = 0; m_dccal_done = false; #ifdef HW_HAS_3_SHUNTS m_curr2_sum = 0; m_curr2_offset = 0; #endif m_last_adc_isr_duration = 0; memset((void*)&m_current_state, 0, sizeof(m_current_state)); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_BDTRInitTypeDef TIM_BDTRInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = SYSTEM_CORE_CLOCK / (int)m_fsw_now; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; TIM_OCInitStructure.TIM_Pulse = TIM1->ARR / 2; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_OC2Init(TIM1, &TIM_OCInitStructure); TIM_OC3Init(TIM1, &TIM_OCInitStructure); TIM_OC4Init(TIM1, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable; TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable; TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF; TIM_BDTRInitStructure.TIM_DeadTime = conf_general_calculate_deadtime(HW_DEAD_TIME_NSEC, SYSTEM_CORE_CLOCK); TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable; TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable; TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure); TIM_CCPreloadControl(TIM1, ENABLE); TIM_ARRPreloadConfig(TIM1, ENABLE); ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef DMA_InitStructure; ADC_InitTypeDef ADC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE); dmaStreamAllocate(STM32_DMA_STREAM(STM32_DMA_STREAM_ID(2, 4)), 3, (stm32_dmaisr_t)adc_int_handler, (void *)0); DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC_Value; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC->CDR; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = HW_ADC_CHANNELS; 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_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream4, &DMA_InitStructure); DMA_Cmd(DMA2_Stream4, ENABLE); DMA_ITConfig(DMA2_Stream4, DMA_IT_TC, ENABLE); // Note that the ADC is running at 42MHz, which is higher than the // specified 36MHz in the data sheet, but it works. ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure); ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Falling; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC2; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = HW_ADC_NBR_CONV; ADC_Init(ADC1, &ADC_InitStructure); ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv = 0; ADC_Init(ADC2, &ADC_InitStructure); ADC_Init(ADC3, &ADC_InitStructure); ADC_TempSensorVrefintCmd(ENABLE); ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE); hw_setup_adc_channels(); ADC_Cmd(ADC1, ENABLE); ADC_Cmd(ADC2, ENABLE); ADC_Cmd(ADC3, ENABLE); TIM_Cmd(TIM1, ENABLE); TIM_CtrlPWMOutputs(TIM1, ENABLE); // Always sample ADC in the beginning of the PWM cycle TIM1->CCR2 = 200; utils_sys_unlock_cnt(); ENABLE_GATE(); DCCAL_OFF(); do_dc_cal(); // Start threads timer_thd_stop = false; chThdCreateStatic(timer_thread_wa, sizeof(timer_thread_wa), NORMALPRIO, timer_thread, NULL); stop_pwm_hw(); // Check if the system has resumed from IWDG reset if (timeout_had_IWDG_reset()) { mc_interface_fault_stop(FAULT_CODE_BOOTING_FROM_WATCHDOG_RESET); } m_init_done = true; }
#include "ch.h" // needs for all ChibiOS programs #include "hal.h" // hardware abstraction layer header #include "vex.h" // vex library header // number of samples we use for the basic sine wave that all sounds are // created from // If this changes then change the pre-calculated sin values #define WAVE_SAMPLES 32 // global storage for sine wave static uint16_t Sine12bit[WAVE_SAMPLES]; // dma STREAM FOR dac static const stm32_dma_stream_t *vsl_dma = STM32_DMA_STREAM(STM32_DMA_STREAM_ID(2, 3)); // counter for sound output timer static volatile uint32_t VSL_Counter = 0; // the audio task static Thread *vslThread = NULL; // event source to indicate sound is finished. static EVENTSOURCE_DECL(sound_done); // semaphore used to wake audio thread static Semaphore vslSem; // working area for background thread #define AUDIO_WA_SIZE THD_WA_SIZE(AUDIO_TASK_STACK_SIZE)