/** * @brief Initialize wave recording * @param AudioFreq Audio frequency acquisition. * Note: On STM32L1 evaluation board, the microphone acquisition is * done through an analong amplifier with a band-pass filter * centered at 32kHz. * Therefore, this parameter value should be set at maximum * to 32kHz (value "32000"). * @param BitRes Audio frequency to be configured for the I2S peripheral. * Note: On STM32L1 evaluation board, this parameter is not used, but * kept as parameter for compatibility with other STM32 BSP * drivers. * @param ChnlNbr Audio frequency to be configured for the I2S peripheral. * Note: On STM32L1 evaluation board, this parameter is not used, but * kept as parameter for compatibility with other STM32 BSP * drivers. * @retval AUDIO_OK if correct communication, else wrong communication */ uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) { /*## Configure the OPAMP ###################################################*/ /* Set OPAMP instance */ hAudioInOpamp.Instance = OPAMP1; /* Configure the OPAMP if not already configured (on the first occurrence */ /* of this function (). */ if(HAL_OPAMP_GetState(&hAudioInOpamp) == HAL_OPAMP_STATE_RESET) { /* Configuration of OPAMP */ hAudioInOpamp.Init.Mode = OPAMP_STANDALONE_MODE; hAudioInOpamp.Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_IO0; hAudioInOpamp.Init.InvertingInput = OPAMP_INVERTINGINPUT_IO0; hAudioInOpamp.Init.PowerMode = OPAMP_POWERMODE_NORMAL; hAudioInOpamp.Init.PowerSupplyRange = OPAMP_POWERSUPPLY_HIGH; hAudioInOpamp.Init.UserTrimming = OPAMP_TRIMMING_FACTORY; /* Init MSP of OPAMPx */ OPAMPx_MspInit(&hAudioInOpamp); /* Init OPAMPx */ if (HAL_OPAMP_Init(&hAudioInOpamp) != HAL_OK) { return AUDIO_ERROR; } } /* Enable OPAMPx */ if (HAL_OPAMP_Start(&hAudioInOpamp) != HAL_OK) { return AUDIO_ERROR; } /*## Configure the ADC #####################################################*/ /* Set ADC instance */ hAudioInAdc.Instance = ADC1; /* Deinitialize the ADC peripheral registers to its default reset values */ HAL_ADC_DeInit(&hAudioInAdc); /* Configure the ADC */ /* Configuration of ADCx init structure: ADC parameters and regular group */ hAudioInAdc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; /* ADC clock equal to HSI frequency: 16MHz */ hAudioInAdc.Init.Resolution = ADC_RESOLUTION_12B; hAudioInAdc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hAudioInAdc.Init.ScanConvMode = DISABLE; /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */ hAudioInAdc.Init.EOCSelection = ADC_EOC_SEQ_CONV; hAudioInAdc.Init.LowPowerAutoWait = ADC_AUTOWAIT_DISABLE; hAudioInAdc.Init.LowPowerAutoPowerOff = ADC_AUTOPOWEROFF_DISABLE; hAudioInAdc.Init.ChannelsBank = ADC_CHANNELS_BANK_A; hAudioInAdc.Init.ContinuousConvMode = DISABLE; /* Continuous mode disabled to have only 1 conversion at each ADC external event trig */ hAudioInAdc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO; /* Trig of conversion start done by external event */ hAudioInAdc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; hAudioInAdc.Init.DMAContinuousRequests = ENABLE; /* Init MSP of ADCx */ ADCx_MspInit(&hAudioInAdc); /* Init ADCx */ if (HAL_ADC_Init(&hAudioInAdc) != HAL_OK) { return AUDIO_ERROR; } /* Configuration of channel on ADCx regular group on rank 1 */ hAudioInConfigAdc.Channel = AUDIO_IN_ADC_CHANNEL; hAudioInConfigAdc.SamplingTime = ADC_SAMPLETIME_384CYCLES; /* With ADC frequency of 16MHz, conversion time will be 24.75us. This is compliant with sampling time of 32kHz (31.25us) or below */ hAudioInConfigAdc.Rank = ADC_REGULAR_RANK_1; HAL_ADC_ConfigChannel(&hAudioInAdc, &hAudioInConfigAdc); /*## Configure the Timer ###################################################*/ /* Set TIM3 period to AudioFreq using system clock 32Mhz */ hAudioInTim3.Instance = TIM3; hAudioInTim3.Init.Period = (HAL_RCC_GetPCLK1Freq() / (AudioFreq)) -1; hAudioInTim3.Init.Prescaler = 0; hAudioInTim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; hAudioInTim3.Init.CounterMode = TIM_COUNTERMODE_UP; /* Init MSP of TIMx */ TIMx_Base_MspInit(&hAudioInTim3); /* Init TIMx time base */ HAL_TIM_Base_Init(&hAudioInTim3); /* Return 0 if all operations are OK */ return AUDIO_OK; }
/// \function info([dump_alloc_table]) /// Print out lots of information about the board. STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) { // get and print unique id; 96 bits { byte *id = (byte*)0x1fff7a10; printf("ID=%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x\n", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11]); } // get and print clock speeds // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz { printf("S=%lu\nH=%lu\nP1=%lu\nP2=%lu\n", HAL_RCC_GetSysClockFreq(), HAL_RCC_GetHCLKFreq(), HAL_RCC_GetPCLK1Freq(), HAL_RCC_GetPCLK2Freq()); } // to print info about memory { printf("_etext=%p\n", &_etext); printf("_sidata=%p\n", &_sidata); printf("_sdata=%p\n", &_sdata); printf("_edata=%p\n", &_edata); printf("_sbss=%p\n", &_sbss); printf("_ebss=%p\n", &_ebss); printf("_estack=%p\n", &_estack); printf("_ram_start=%p\n", &_ram_start); printf("_heap_start=%p\n", &_heap_start); printf("_heap_end=%p\n", &_heap_end); printf("_ram_end=%p\n", &_ram_end); } // qstr info { uint n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); printf("qstr:\n n_pool=%u\n n_qstr=%u\n n_str_data_bytes=%u\n n_total_bytes=%u\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes); } // GC info { gc_info_t info; gc_info(&info); printf("GC:\n"); printf(" " UINT_FMT " total\n", info.total); printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); } // free space on flash { DWORD nclst; FATFS *fatfs; f_getfree("/flash", &nclst, &fatfs); printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512)); } if (n_args == 1) { // arg given means dump gc allocation table gc_dump_alloc_table(); } return mp_const_none; }
/** * @brief This function configures the TIM3 as a time base source. * The time source is configured to have 1ms time base with a dedicated * Tick interrupt priority. * @note This function is called automatically at the beginning of program after * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). * @param TickPriority: Tick interrupt priority. * @retval HAL status */ HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority) { RCC_ClkInitTypeDef clkconfig; uint32_t uwTimclock, uwAPB1Prescaler = 0; uint32_t uwPrescalerValue = 0; uint32_t pFLatency; /*Configure the TIM3 IRQ priority */ HAL_NVIC_SetPriority(TIM3_IRQn, TickPriority ,0); /* Enable the TIM3 global Interrupt */ HAL_NVIC_EnableIRQ(TIM3_IRQn); /* Enable TIM3 clock */ __HAL_RCC_TIM3_CLK_ENABLE(); /* Get clock configuration */ HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); /* Get APB1 prescaler */ uwAPB1Prescaler = clkconfig.APB1CLKDivider; /* Compute TIM3 clock */ if (uwAPB1Prescaler == RCC_HCLK_DIV1) { uwTimclock = HAL_RCC_GetPCLK1Freq(); } else { uwTimclock = 2*HAL_RCC_GetPCLK1Freq(); } /* Compute the prescaler value to have TIM3 counter clock equal to 1MHz */ uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1); /* Initialize TIM3 */ TimHandle.Instance = TIM3; /* Initialize TIMx peripheral as follow: + Period = [(TIM3CLK/1000) - 1]. to have a (1/1000) s time base. + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock. + ClockDivision = 0 + Counter direction = Up */ TimHandle.Init.Period = (1000000 / 1000) - 1; TimHandle.Init.Prescaler = uwPrescalerValue; TimHandle.Init.ClockDivision = 0; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; if(HAL_TIM_Base_Init(&TimHandle) != HAL_OK) { /* Initialization Error */ Error_Handler(); } /* Start the TIM time Base generation in interrupt mode */ if(HAL_TIM_Base_Start_IT(&TimHandle) != HAL_OK) { /* Starting Error */ Error_Handler(); } /* Return function status */ return HAL_OK; }
/** * @brief Configures TIM5 to measure the LSI oscillator frequency. * @param None * @retval LSI Frequency */ static uint32_t GetLSIFrequency(void) { uint32_t pclk1 = 0, latency = 0; TIM_IC_InitTypeDef timinputconfig = {0}; RCC_OscInitTypeDef oscinit = {0}; RCC_ClkInitTypeDef clkinit = {0}; /* Enable LSI Oscillator */ oscinit.OscillatorType = RCC_OSCILLATORTYPE_LSI; oscinit.LSIState = RCC_LSI_ON; oscinit.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&oscinit)!= HAL_OK) { Error_Handler(); } /* Configure the TIM peripheral */ /* Set TIMx instance */ TimInputCaptureHandle.Instance = TIMx; /* TIMx configuration: Input Capture mode --------------------- The LSI clock is connected to TIM5 CH4. The Rising edge is used as active edge. The TIM5 CCR4 is used to compute the frequency value. ------------------------------------------------------------ */ TimInputCaptureHandle.Init.Prescaler = 0; TimInputCaptureHandle.Init.CounterMode = TIM_COUNTERMODE_UP; TimInputCaptureHandle.Init.Period = 0xFFFF; TimInputCaptureHandle.Init.ClockDivision = 0; TimInputCaptureHandle.Init.RepetitionCounter = 0; if (HAL_TIM_IC_Init(&TimInputCaptureHandle) != HAL_OK) { /* Initialization Error */ Error_Handler(); } /* Connect internally the TIM5 CH4 Input Capture to the LSI clock output */ HAL_TIMEx_RemapConfig(&TimInputCaptureHandle, TIMx_REMAP); /* Configure the Input Capture of channel 4 */ timinputconfig.ICPolarity = TIM_ICPOLARITY_RISING; timinputconfig.ICSelection = TIM_ICSELECTION_DIRECTTI; timinputconfig.ICPrescaler = TIM_ICPSC_DIV8; timinputconfig.ICFilter = 0; if (HAL_TIM_IC_ConfigChannel(&TimInputCaptureHandle, &timinputconfig, TIM_CHANNEL_4) != HAL_OK) { /* Initialization Error */ Error_Handler(); } /* Reset the flags */ TimInputCaptureHandle.Instance->SR = 0; /* Start the TIM Input Capture measurement in interrupt mode */ if (HAL_TIM_IC_Start_IT(&TimInputCaptureHandle, TIM_CHANNEL_4) != HAL_OK) { /* Starting Error */ Error_Handler(); } /* Wait until the TIM5 get 2 LSI edges (refer to TIM5_IRQHandler() in stm32f4xx_it.c file) */ while (uwMeasurementDone == 0) { } uwCaptureNumber = 0; /* Deinitialize the TIM5 peripheral registers to their default reset values */ HAL_TIM_IC_DeInit(&TimInputCaptureHandle); /* Compute the LSI frequency, depending on TIM5 input clock frequency (PCLK1)*/ /* Get PCLK1 frequency */ pclk1 = HAL_RCC_GetPCLK1Freq(); HAL_RCC_GetClockConfig(&clkinit, &latency); /* Get PCLK1 prescaler */ if ((clkinit.APB1CLKDivider) == RCC_HCLK_DIV1) { /* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */ return ((pclk1 / uwPeriodValue) * 8); } else { /* PCLK1 prescaler different from 1 => TIMCLK = 2 * PCLK1 */ return (((2 * pclk1) / uwPeriodValue) * 8) ; } }
static rt_err_t stm32_spi_init(struct stm32_spi *spi_drv, struct rt_spi_configuration *cfg) { RT_ASSERT(spi_drv != RT_NULL); RT_ASSERT(cfg != RT_NULL); SPI_HandleTypeDef *spi_handle = &spi_drv->handle; if (cfg->mode & RT_SPI_SLAVE) { spi_handle->Init.Mode = SPI_MODE_SLAVE; } else { spi_handle->Init.Mode = SPI_MODE_MASTER; } if (cfg->mode & RT_SPI_3WIRE) { spi_handle->Init.Direction = SPI_DIRECTION_1LINE; } else { spi_handle->Init.Direction = SPI_DIRECTION_2LINES; } if (cfg->data_width == 8) { spi_handle->Init.DataSize = SPI_DATASIZE_8BIT; spi_handle->TxXferSize = 8; spi_handle->RxXferSize = 8; } else if (cfg->data_width == 16) { spi_handle->Init.DataSize = SPI_DATASIZE_16BIT; } else { return RT_EIO; } if (cfg->mode & RT_SPI_CPHA) { spi_handle->Init.CLKPhase = SPI_PHASE_2EDGE; } else { spi_handle->Init.CLKPhase = SPI_PHASE_1EDGE; } if (cfg->mode & RT_SPI_CPOL) { spi_handle->Init.CLKPolarity = SPI_POLARITY_HIGH; } else { spi_handle->Init.CLKPolarity = SPI_POLARITY_LOW; } if (cfg->mode & RT_SPI_NO_CS) { spi_handle->Init.NSS = SPI_NSS_SOFT; } else { spi_handle->Init.NSS = SPI_NSS_SOFT; } uint32_t SPI_APB_CLOCK; #if defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0) SPI_APB_CLOCK = HAL_RCC_GetPCLK1Freq(); #else SPI_APB_CLOCK = HAL_RCC_GetPCLK2Freq(); #endif if (cfg->max_hz >= SPI_APB_CLOCK / 2) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; } else if (cfg->max_hz >= SPI_APB_CLOCK / 4) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; } else if (cfg->max_hz >= SPI_APB_CLOCK / 8) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; } else if (cfg->max_hz >= SPI_APB_CLOCK / 16) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; } else if (cfg->max_hz >= SPI_APB_CLOCK / 32) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; } else if (cfg->max_hz >= SPI_APB_CLOCK / 64) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; } else if (cfg->max_hz >= SPI_APB_CLOCK / 128) { spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; } else { /* min prescaler 256 */ spi_handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; } LOG_D("sys freq: %d, pclk2 freq: %d, SPI limiting freq: %d, BaudRatePrescaler: %d", HAL_RCC_GetSysClockFreq(), SPI_APB_CLOCK, cfg->max_hz, spi_handle->Init.BaudRatePrescaler); if (cfg->mode & RT_SPI_MSB) { spi_handle->Init.FirstBit = SPI_FIRSTBIT_MSB; } else { spi_handle->Init.FirstBit = SPI_FIRSTBIT_LSB; } spi_handle->Init.TIMode = SPI_TIMODE_DISABLE; spi_handle->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; spi_handle->State = HAL_SPI_STATE_RESET; #if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0) spi_handle->Init.NSSPMode = SPI_NSS_PULSE_DISABLE; #endif if (HAL_SPI_Init(spi_handle) != HAL_OK) { return RT_EIO; } #if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F0) \ || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32G0) SET_BIT(spi_handle->Instance->CR2, SPI_RXFIFO_THRESHOLD_HF); #endif /* DMA configuration */ if (spi_drv->spi_dma_flag & SPI_USING_RX_DMA_FLAG) { HAL_DMA_Init(&spi_drv->dma.handle_rx); __HAL_LINKDMA(&spi_drv->handle, hdmarx, spi_drv->dma.handle_rx); /* NVIC configuration for DMA transfer complete interrupt */ HAL_NVIC_SetPriority(spi_drv->config->dma_rx->dma_irq, 0, 0); HAL_NVIC_EnableIRQ(spi_drv->config->dma_rx->dma_irq); } if (spi_drv->spi_dma_flag & SPI_USING_TX_DMA_FLAG) { HAL_DMA_Init(&spi_drv->dma.handle_tx); __HAL_LINKDMA(&spi_drv->handle, hdmatx, spi_drv->dma.handle_tx); /* NVIC configuration for DMA transfer complete interrupt */ HAL_NVIC_SetPriority(spi_drv->config->dma_tx->dma_irq, 0, 1); HAL_NVIC_EnableIRQ(spi_drv->config->dma_tx->dma_irq); } __HAL_SPI_ENABLE(spi_handle); LOG_D("%s init done", spi_drv->config->bus_name); return RT_EOK; }
/// \function freq([sys_freq]) /// /// If given no arguments, returns a tuple of clock frequencies: /// (SYSCLK, HCLK, PCLK1, PCLK2). /// /// If given an argument, sets the system frequency to that value in Hz. /// Eg freq(120000000) gives 120MHz. Note that not all values are /// supported and the largest supported frequency not greater than /// the given sys_freq will be selected. STATIC mp_obj_t pyb_freq(mp_uint_t n_args, const mp_obj_t *args) { if (n_args == 0) { // get mp_obj_t tuple[4] = { mp_obj_new_int(HAL_RCC_GetSysClockFreq()), mp_obj_new_int(HAL_RCC_GetHCLKFreq()), mp_obj_new_int(HAL_RCC_GetPCLK1Freq()), mp_obj_new_int(HAL_RCC_GetPCLK2Freq()), }; return mp_obj_new_tuple(4, tuple); } else { // set mp_int_t wanted_sysclk = mp_obj_get_int(args[0]) / 1000000; // search for a valid PLL configuration that keeps USB at 48MHz for (; wanted_sysclk > 0; wanted_sysclk--) { for (mp_uint_t p = 2; p <= 8; p += 2) { if (wanted_sysclk * p % 48 != 0) { continue; } mp_uint_t q = wanted_sysclk * p / 48; if (q < 2 || q > 15) { continue; } if (wanted_sysclk * p % (HSE_VALUE / 1000000) != 0) { continue; } mp_uint_t n_by_m = wanted_sysclk * p / (HSE_VALUE / 1000000); mp_uint_t m = 192 / n_by_m; while (m < (HSE_VALUE / 2000000) || n_by_m * m < 192) { m += 1; } if (m > (HSE_VALUE / 1000000)) { continue; } mp_uint_t n = n_by_m * m; if (n < 192 || n > 432) { continue; } // found values! // let the USB CDC have a chance to process before we change the clock HAL_Delay(USBD_CDC_POLLING_INTERVAL + 2); // set HSE as system clock source to allow modification of the PLL configuration RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { goto fail; } // re-configure PLL RCC_OscInitTypeDef RCC_OscInitStruct; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = m; RCC_OscInitStruct.PLL.PLLN = n; RCC_OscInitStruct.PLL.PLLP = p; RCC_OscInitStruct.PLL.PLLQ = q; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { goto fail; } // set PLL as system clock source RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { goto fail; } // re-init TIM3 for USB CDC rate timer_tim3_init(); return mp_const_none; void __fatal_error(const char *msg); fail: __fatal_error("can't change freq"); } } nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "can't make valid freq")); } }
/// \function freq([sys_freq]) /// /// If given no arguments, returns a tuple of clock frequencies: /// (SYSCLK, HCLK, PCLK1, PCLK2). /// /// If given an argument, sets the system frequency to that value in Hz. /// Eg freq(120000000) gives 120MHz. Note that not all values are /// supported and the largest supported frequency not greater than /// the given sys_freq will be selected. STATIC mp_obj_t pyb_freq(mp_uint_t n_args, const mp_obj_t *args) { if (n_args == 0) { // get mp_obj_t tuple[4] = { mp_obj_new_int(HAL_RCC_GetSysClockFreq()), mp_obj_new_int(HAL_RCC_GetHCLKFreq()), mp_obj_new_int(HAL_RCC_GetPCLK1Freq()), mp_obj_new_int(HAL_RCC_GetPCLK2Freq()), }; return mp_obj_new_tuple(4, tuple); } else { // set mp_int_t wanted_sysclk = mp_obj_get_int(args[0]) / 1000000; // default PLL parameters that give 48MHz on PLL48CK uint32_t m = HSE_VALUE / 1000000, n = 336, p = 2, q = 7; uint32_t sysclk_source; // the following logic assumes HSE < HSI if (HSE_VALUE / 1000000 <= wanted_sysclk && wanted_sysclk < HSI_VALUE / 1000000) { // use HSE as SYSCLK sysclk_source = RCC_SYSCLKSOURCE_HSE; } else if (HSI_VALUE / 1000000 <= wanted_sysclk && wanted_sysclk < 24) { // use HSI as SYSCLK sysclk_source = RCC_SYSCLKSOURCE_HSI; } else { // search for a valid PLL configuration that keeps USB at 48MHz for (; wanted_sysclk > 0; wanted_sysclk--) { for (p = 2; p <= 8; p += 2) { // compute VCO_OUT mp_uint_t vco_out = wanted_sysclk * p; // make sure VCO_OUT is between 192MHz and 432MHz if (vco_out < 192 || vco_out > 432) { continue; } // make sure Q is an integer if (vco_out % 48 != 0) { continue; } // solve for Q to get PLL48CK at 48MHz q = vco_out / 48; // make sure Q is in range if (q < 2 || q > 15) { continue; } // make sure N/M is an integer if (vco_out % (HSE_VALUE / 1000000) != 0) { continue; } // solve for N/M mp_uint_t n_by_m = vco_out / (HSE_VALUE / 1000000); // solve for M, making sure VCO_IN (=HSE/M) is between 1MHz and 2MHz m = 192 / n_by_m; while (m < (HSE_VALUE / 2000000) || n_by_m * m < 192) { m += 1; } if (m > (HSE_VALUE / 1000000)) { continue; } // solve for N n = n_by_m * m; // make sure N is in range if (n < 192 || n > 432) { continue; } // found values! sysclk_source = RCC_SYSCLKSOURCE_PLLCLK; goto set_clk; } } nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "can't make valid freq")); } set_clk: //printf("%lu %lu %lu %lu %lu\n", sysclk_source, m, n, p, q); // let the USB CDC have a chance to process before we change the clock HAL_Delay(USBD_CDC_POLLING_INTERVAL + 2); // desired system clock source is in sysclk_source RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); if (sysclk_source == RCC_SYSCLKSOURCE_PLLCLK) { // set HSE as system clock source to allow modification of the PLL configuration // we then change to PLL after re-configuring PLL RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE; } else { // directly set the system clock source as desired RCC_ClkInitStruct.SYSCLKSource = sysclk_source; } RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { goto fail; } // re-configure PLL // even if we don't use the PLL for the system clock, we still need it for USB, RNG and SDIO RCC_OscInitTypeDef RCC_OscInitStruct; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = m; RCC_OscInitStruct.PLL.PLLN = n; RCC_OscInitStruct.PLL.PLLP = p; RCC_OscInitStruct.PLL.PLLQ = q; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { goto fail; } // set PLL as system clock source if wanted if (sysclk_source == RCC_SYSCLKSOURCE_PLLCLK) { RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { goto fail; } } // re-init TIM3 for USB CDC rate timer_tim3_init(); return mp_const_none; fail:; void NORETURN __fatal_error(const char *msg); __fatal_error("can't change freq"); } }
void pwmout_period_us(pwmout_t* obj, int us) { TimHandle.Instance = (TIM_TypeDef *)(obj->pwm); RCC_ClkInitTypeDef RCC_ClkInitStruct; uint32_t PclkFreq; uint32_t APBxCLKDivider; float dc = pwmout_read(obj); __HAL_TIM_DISABLE(&TimHandle); // Get clock configuration // Note: PclkFreq contains here the Latency (not used after) HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &PclkFreq); // Get the PCLK and APBCLK divider related to the timer switch (obj->pwm) { // APB1 clock #if defined(TIM2_BASE) case PWM_2: #endif #if defined(TIM3_BASE) case PWM_3: #endif #if defined(TIM4_BASE) case PWM_4: #endif #if defined(TIM5_BASE) case PWM_5: #endif #if defined(TIM12_BASE) case PWM_12: #endif #if defined(TIM13_BASE) case PWM_13: #endif #if defined(TIM14_BASE) case PWM_14: #endif PclkFreq = HAL_RCC_GetPCLK1Freq(); APBxCLKDivider = RCC_ClkInitStruct.APB1CLKDivider; break; // APB2 clock #if defined(TIM1_BASE) case PWM_1: #endif #if defined(TIM8_BASE) case PWM_8: #endif #if defined(TIM9_BASE) case PWM_9: #endif #if defined(TIM10_BASE) case PWM_10: #endif #if defined(TIM11_BASE) case PWM_11: #endif PclkFreq = HAL_RCC_GetPCLK2Freq(); APBxCLKDivider = RCC_ClkInitStruct.APB2CLKDivider; break; default: return; } TimHandle.Init.Period = us - 1; // TIMxCLK = PCLKx when the APB prescaler = 1 else TIMxCLK = 2 * PCLKx if (APBxCLKDivider == RCC_HCLK_DIV1) TimHandle.Init.Prescaler = (uint16_t)((PclkFreq) / 1000000) - 1; // 1 us tick else TimHandle.Init.Prescaler = (uint16_t)((PclkFreq * 2) / 1000000) - 1; // 1 us tick TimHandle.Init.ClockDivision = 0; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) { error("Cannot initialize PWM\n"); } // Set duty cycle again pwmout_write(obj, dc); // Save for future use obj->period = us; __HAL_TIM_ENABLE(&TimHandle); }
/** * @brief Configure the SMARTCARD associated USART peripheral * @param hsc: SMARTCARD handle * @retval None */ static void SMARTCARD_SetConfig(SMARTCARD_HandleTypeDef *hsc) { uint32_t tmpreg = 0x00000000U; uint32_t clocksource = 0x00000000U; /* Check the parameters */ assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance)); assert_param(IS_SMARTCARD_BAUDRATE(hsc->Init.BaudRate)); assert_param(IS_SMARTCARD_WORD_LENGTH(hsc->Init.WordLength)); assert_param(IS_SMARTCARD_STOPBITS(hsc->Init.StopBits)); assert_param(IS_SMARTCARD_PARITY(hsc->Init.Parity)); assert_param(IS_SMARTCARD_MODE(hsc->Init.Mode)); assert_param(IS_SMARTCARD_POLARITY(hsc->Init.CLKPolarity)); assert_param(IS_SMARTCARD_PHASE(hsc->Init.CLKPhase)); assert_param(IS_SMARTCARD_LASTBIT(hsc->Init.CLKLastBit)); assert_param(IS_SMARTCARD_ONE_BIT_SAMPLE(hsc->Init.OneBitSampling)); assert_param(IS_SMARTCARD_NACK(hsc->Init.NACKState)); assert_param(IS_SMARTCARD_TIMEOUT(hsc->Init.TimeOutEnable)); assert_param(IS_SMARTCARD_AUTORETRY_COUNT(hsc->Init.AutoRetryCount)); /*-------------------------- USART CR1 Configuration -----------------------*/ /* In SmartCard mode, M and PCE are forced to 1 (8 bits + parity). * Oversampling is forced to 16 (OVER8 = 0). * Configure the Parity and Mode: * set PS bit according to hsc->Init.Parity value * set TE and RE bits according to hsc->Init.Mode value */ tmpreg = (uint32_t) hsc->Init.Parity | hsc->Init.Mode; /* in case of TX-only mode, if NACK is enabled, the USART must be able to monitor the bidirectional line to detect a NACK signal in case of parity error. Therefore, the receiver block must be enabled as well (RE bit must be set). */ if((hsc->Init.Mode == SMARTCARD_MODE_TX) && (hsc->Init.NACKState == SMARTCARD_NACK_ENABLE)) { tmpreg |= USART_CR1_RE; } tmpreg |= (uint32_t) hsc->Init.WordLength; MODIFY_REG(hsc->Instance->CR1, USART_CR1_FIELDS, tmpreg); /*-------------------------- USART CR2 Configuration -----------------------*/ /* Stop bits are forced to 1.5 (STOP = 11) */ tmpreg = hsc->Init.StopBits; /* Synchronous mode is activated by default */ tmpreg |= (uint32_t) USART_CR2_CLKEN | hsc->Init.CLKPolarity; tmpreg |= (uint32_t) hsc->Init.CLKPhase | hsc->Init.CLKLastBit; tmpreg |= (uint32_t) hsc->Init.TimeOutEnable; MODIFY_REG(hsc->Instance->CR2, USART_CR2_FIELDS, tmpreg); /*-------------------------- USART CR3 Configuration -----------------------*/ /* Configure * - one-bit sampling method versus three samples' majority rule * according to hsc->Init.OneBitSampling * - NACK transmission in case of parity error according * to hsc->Init.NACKEnable * - autoretry counter according to hsc->Init.AutoRetryCount */ tmpreg = (uint32_t) hsc->Init.OneBitSampling | hsc->Init.NACKState; tmpreg |= (uint32_t) (hsc->Init.AutoRetryCount << SMARTCARD_CR3_SCARCNT_LSB_POS); MODIFY_REG(hsc->Instance-> CR3,USART_CR3_FIELDS, tmpreg); /*-------------------------- USART GTPR Configuration ----------------------*/ tmpreg = (uint32_t) (hsc->Init.Prescaler | (hsc->Init.GuardTime << SMARTCARD_GTPR_GT_LSB_POS)); MODIFY_REG(hsc->Instance->GTPR, (uint32_t)(USART_GTPR_GT|USART_GTPR_PSC), tmpreg); /*-------------------------- USART RTOR Configuration ----------------------*/ tmpreg = (uint32_t) (hsc->Init.BlockLength << SMARTCARD_RTOR_BLEN_LSB_POS); if(hsc->Init.TimeOutEnable == SMARTCARD_TIMEOUT_ENABLE) { assert_param(IS_SMARTCARD_TIMEOUT_VALUE(hsc->Init.TimeOutValue)); tmpreg |= (uint32_t) hsc->Init.TimeOutValue; } MODIFY_REG(hsc->Instance->RTOR, (USART_RTOR_RTO|USART_RTOR_BLEN), tmpreg); /*-------------------------- USART BRR Configuration -----------------------*/ SMARTCARD_GETCLOCKSOURCE(hsc, clocksource); switch (clocksource) { case SMARTCARD_CLOCKSOURCE_PCLK1: hsc->Instance->BRR = (uint16_t)((HAL_RCC_GetPCLK1Freq() + (hsc->Init.BaudRate/2))/ hsc->Init.BaudRate); break; case SMARTCARD_CLOCKSOURCE_PCLK2: hsc->Instance->BRR = (uint16_t)((HAL_RCC_GetPCLK2Freq() + (hsc->Init.BaudRate/2))/ hsc->Init.BaudRate); break; case SMARTCARD_CLOCKSOURCE_HSI: hsc->Instance->BRR = (uint16_t)((HSI_VALUE + (hsc->Init.BaudRate/2))/ hsc->Init.BaudRate); break; case SMARTCARD_CLOCKSOURCE_SYSCLK: hsc->Instance->BRR = (uint16_t)((HAL_RCC_GetSysClockFreq() + (hsc->Init.BaudRate/2))/ hsc->Init.BaudRate); break; case SMARTCARD_CLOCKSOURCE_LSE: hsc->Instance->BRR = (uint16_t)((LSE_VALUE + (hsc->Init.BaudRate/2))/ hsc->Init.BaudRate); break; default: break; } }
/** * @brief Configures TIM5 to measure the LSI oscillator frequency. * @param None * @retval LSI Frequency */ static uint32_t GetLSIFrequency(void) { uint32_t pclk1 = 0; TIM_IC_InitTypeDef timinputconfig; /* Configure the TIM peripheral */ /* Set TIM5 instance */ TimInputCaptureHandle.Instance = TIM5; /* TIM5 configuration: Input Capture mode --------------------- The LSI oscillator is connected to TIM5 CH4. The Rising edge is used as active edge. The TIM5 CCR4 is used to compute the frequency value. ------------------------------------------------------------ */ TimInputCaptureHandle.Init.Prescaler = 0; TimInputCaptureHandle.Init.CounterMode = TIM_COUNTERMODE_UP; TimInputCaptureHandle.Init.Period = 0xFFFF; TimInputCaptureHandle.Init.ClockDivision = 0; TimInputCaptureHandle.Init.RepetitionCounter = 0; if(HAL_TIM_IC_Init(&TimInputCaptureHandle) != HAL_OK) {} /* Connect internally the TIM5_CH4 Input Capture to the LSI clock output */ HAL_TIMEx_RemapConfig(&TimInputCaptureHandle, TIM_TIM5_LSI); /* Configure the Input Capture of channel 4 */ timinputconfig.ICPolarity = TIM_ICPOLARITY_RISING; timinputconfig.ICSelection = TIM_ICSELECTION_DIRECTTI; timinputconfig.ICPrescaler = TIM_ICPSC_DIV8; timinputconfig.ICFilter = 0; if(HAL_TIM_IC_ConfigChannel(&TimInputCaptureHandle, &timinputconfig, TIM_CHANNEL_4) != HAL_OK) {} /* Reset the flags */ TimInputCaptureHandle.Instance->SR = 0; /* Start the TIM Input Capture measurement in interrupt mode */ if(HAL_TIM_IC_Start_IT(&TimInputCaptureHandle, TIM_CHANNEL_4) != HAL_OK) { } /* Wait until the TIM5 get 2 LSI edges (refer to TIM5_IRQHandler() in stm32f4xx_it.c file) */ while(uwMeasurementDone == 0) { } uwCaptureNumber = 0; /* Deinitialize the TIM5 peripheral registers to their default reset values */ HAL_TIM_IC_DeInit(&TimInputCaptureHandle); /* Compute the LSI frequency, depending on TIM5 input clock frequency (PCLK1)*/ /* Get PCLK1 frequency */ pclk1 = HAL_RCC_GetPCLK1Freq(); /* Get PCLK1 prescaler */ if((RCC->CFGR & RCC_CFGR_PPRE1) == 0) { /* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */ return ((pclk1 / uwPeriodValue) * 8); } else { /* PCLK1 prescaler different from 1 => TIMCLK = 2 * PCLK1 */ return (((2 * pclk1) / uwPeriodValue) * 8); } }
// Reconfigure the HAL tick using a standard timer instead of systick. HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) { RCC_ClkInitTypeDef RCC_ClkInitStruct; uint32_t PclkFreq; // Get clock configuration // Note: PclkFreq contains here the Latency (not used after) HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &PclkFreq); // Get timer clock value #if TIM_MST_PCLK == 1 PclkFreq = HAL_RCC_GetPCLK1Freq(); #else PclkFreq = HAL_RCC_GetPCLK2Freq(); #endif // Enable timer clock TIM_MST_RCC; // Reset timer TIM_MST_RESET_ON; TIM_MST_RESET_OFF; // Configure time base TimMasterHandle.Instance = TIM_MST; TimMasterHandle.Init.Period = 0xFFFFFFFF; // TIMxCLK = PCLKx when the APB prescaler = 1 else TIMxCLK = 2 * PCLKx #if TIM_MST_PCLK == 1 if (RCC_ClkInitStruct.APB1CLKDivider == RCC_HCLK_DIV1) { #else if (RCC_ClkInitStruct.APB2CLKDivider == RCC_HCLK_DIV1) { #endif TimMasterHandle.Init.Prescaler = (uint16_t)((PclkFreq) / 1000000) - 1; // 1 us tick } else { TimMasterHandle.Init.Prescaler = (uint16_t)((PclkFreq * 2) / 1000000) - 1; // 1 us tick } TimMasterHandle.Init.ClockDivision = 0; TimMasterHandle.Init.CounterMode = TIM_COUNTERMODE_UP; #if !TARGET_STM32L1 TimMasterHandle.Init.RepetitionCounter = 0; #endif #if TARGET_STM32F0||TARGET_STM32F7 TimMasterHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; #endif HAL_TIM_OC_Init(&TimMasterHandle); NVIC_SetVector(TIM_MST_IRQ, (uint32_t)timer_irq_handler); NVIC_EnableIRQ(TIM_MST_IRQ); // Channel 1 for mbed timeout HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_1); // Channel 2 for HAL tick HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_2); PreviousVal = __HAL_TIM_GetCounter(&TimMasterHandle); __HAL_TIM_SetCompare(&TimMasterHandle, TIM_CHANNEL_2, PreviousVal + HAL_TICK_DELAY); __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC2); #if DEBUG_TICK > 0 __GPIOB_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); #endif return HAL_OK; } void HAL_SuspendTick(void) { TimMasterHandle.Instance = TIM_MST; __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC2); }
_Bool CAN_init(void *data) { CAN_HandleTypeDef *handle = data; HAL_StatusTypeDef result = HAL_ERROR; const uint32_t baudRate = 125000; CAN_InitTypeDef ifaceParams = { HAL_RCC_GetPCLK1Freq()/(baudRate*(1+4+3)), //(CAN_SJW + CAN_BS1 + CAN_BS2) CAN_MODE_NORMAL, CAN_SJW_1TQ, CAN_BS1_4TQ, CAN_BS2_3TQ, .TTCM = DISABLE, .ABOM = DISABLE, .AWUM = DISABLE, .NART = DISABLE, .RFLM = DISABLE, .TXFP = DISABLE, }; CAN_FilterConfTypeDef filter = { 0, 0, 0, 0, CAN_FIFO0, 0, CAN_FILTERMODE_IDMASK, CAN_FILTERSCALE_32BIT, ENABLE, 0 }; if (handle) { free(handle->pRxMsg); free(handle->pTxMsg); handle->pRxMsg = NULL; handle->pTxMsg = NULL; memset(handle, 0, sizeof(*handle)); handle->Instance = CAN1; handle->Init = ifaceParams; result = HAL_CAN_Init(handle); if (result == HAL_OK) { HAL_CAN_ConfigFilter(handle, &filter); HAL_NVIC_EnableIRQ(CAN1_TX_IRQn); HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn); HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn); // HAL_NVIC_EnableIRQ(CAN1_SCE_IRQn); handle->pRxMsg = malloc(sizeof(*handle->pRxMsg)); result &= HAL_CAN_Receive_IT(handle, CAN_FIFO0); } s_can1Handle = handle; } return result == HAL_OK; } _Bool CAN_write(const CanMsg_t *data) { HAL_StatusTypeDef result = HAL_ERROR; static const size_t msgSize = sizeof(CanTxMsgTypeDef); if (!data) return false; CanTxMsgTypeDef txMsg = { data->id, data->id, data->isExtended ? CAN_ID_EXT : CAN_ID_STD, data->isRemoteFrame ? CAN_RTR_REMOTE : CAN_RTR_DATA, data->isRemoteFrame ? 0 : data->size > 8 ? 8 : data->size, }; do { if (!s_can1Handle) break; memcpy(txMsg.Data, data->buff, txMsg.DLC); free(s_can1Handle->pTxMsg); s_can1Handle->pTxMsg = malloc(msgSize); if (!s_can1Handle->pTxMsg) break; memcpy(s_can1Handle->pTxMsg, &txMsg, msgSize); result = HAL_CAN_Transmit_IT(s_can1Handle); } while (0); return result == HAL_OK; }
int hal_uart_config(int port, int32_t baudrate, uint8_t databits, uint8_t stopbits, enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl) { struct hal_uart *u; const struct stm32f4_uart_cfg *cfg; uint32_t cr1, cr2, cr3; if (port >= UART_CNT) { return -1; } u = &uarts[port]; if (u->u_open) { return -1; } cfg = bsp_uart_config(port); assert(cfg); /* * RCC * pin config * UART config * nvic config * enable uart */ cr1 = cfg->suc_uart->CR1; cr2 = cfg->suc_uart->CR2; cr3 = cfg->suc_uart->CR3; cr1 &= ~(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_RE | USART_CR1_OVER8); cr2 &= ~(USART_CR2_STOP); cr3 &= ~(USART_CR3_RTSE | USART_CR3_CTSE); switch (databits) { case 8: cr1 |= UART_WORDLENGTH_8B; break; case 9: cr1 |= UART_WORDLENGTH_9B; break; default: assert(0); return -1; } switch (stopbits) { case 1: cr2 |= UART_STOPBITS_1; break; case 2: cr2 |= UART_STOPBITS_2; break; default: return -1; } switch (parity) { case HAL_UART_PARITY_NONE: cr1 |= UART_PARITY_NONE; break; case HAL_UART_PARITY_ODD: cr1 |= UART_PARITY_ODD; break; case HAL_UART_PARITY_EVEN: cr1 |= UART_PARITY_EVEN; break; } switch (flow_ctl) { case HAL_UART_FLOW_CTL_NONE: cr3 |= UART_HWCONTROL_NONE; break; case HAL_UART_FLOW_CTL_RTS_CTS: cr3 |= UART_HWCONTROL_RTS_CTS; if (cfg->suc_pin_rts < 0 || cfg->suc_pin_cts < 0) { /* * Can't turn on HW flow control if pins to do that are not * defined. */ assert(0); return -1; } break; } cr1 |= (UART_MODE_RX | UART_MODE_TX | UART_OVERSAMPLING_16); *cfg->suc_rcc_reg |= cfg->suc_rcc_dev; hal_gpio_init_af(cfg->suc_pin_tx, cfg->suc_pin_af, 0); hal_gpio_init_af(cfg->suc_pin_rx, cfg->suc_pin_af, 0); if (flow_ctl == HAL_UART_FLOW_CTL_RTS_CTS) { hal_gpio_init_af(cfg->suc_pin_rts, cfg->suc_pin_af, 0); hal_gpio_init_af(cfg->suc_pin_cts, cfg->suc_pin_af, 0); } u->u_regs = cfg->suc_uart; u->u_regs->CR3 = cr3; u->u_regs->CR2 = cr2; u->u_regs->CR1 = cr1; if (cfg->suc_uart == USART1 || cfg->suc_uart == USART6) { u->u_regs->BRR = UART_BRR_SAMPLING16(HAL_RCC_GetPCLK2Freq(), baudrate); } else { u->u_regs->BRR = UART_BRR_SAMPLING16(HAL_RCC_GetPCLK1Freq(), baudrate); } (void)u->u_regs->DR; (void)u->u_regs->SR; hal_uart_set_nvic(cfg->suc_irqn, u); u->u_regs->CR1 |= (USART_CR1_RXNEIE | USART_CR1_UE); u->u_open = 1; return 0; }
/** @brief: set registers acc to info in huart * @details: used in HAL_UART3Debug_Init, private ****************************************************************/ static void MyUARTSetConfig(UART_HandleTypeDef *huart) { uint32_t tmpreg = 0x00; /* Check the parameters */ assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate)); assert_param(IS_UART_STOPBITS(huart->Init.StopBits)); assert_param(IS_UART_PARITY(huart->Init.Parity)); assert_param(IS_UART_MODE(huart->Init.Mode)); /*-------------------------- USART CR2 Configuration -----------------------*/ tmpreg = huart->Instance->CR2; /* Clear STOP[13:12] bits */ tmpreg &= (uint32_t) ~((uint32_t) USART_CR2_STOP); /* Configure the UART Stop Bits: Set STOP[13:12] bits according to huart->Init.StopBits value */ tmpreg |= (uint32_t) huart->Init.StopBits; /* Write to USART CR2 */ huart->Instance->CR2 = (uint32_t) tmpreg; /*-------------------------- USART CR1 Configuration -----------------------*/ tmpreg = huart->Instance->CR1; /* Clear M, PCE, PS, TE and RE bits */ tmpreg &= (uint32_t) ~((uint32_t) (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8)); /* Configure the UART Word Length, Parity and mode: Set the M bits according to huart->Init.WordLength value Set PCE and PS bits according to huart->Init.Parity value Set TE and RE bits according to huart->Init.Mode value Set OVER8 bit according to huart->Init.OverSampling value */ tmpreg |= (uint32_t) huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling; /* Write to USART CR1 */ huart->Instance->CR1 = (uint32_t) tmpreg; /*-------------------------- USART CR3 Configuration -----------------------*/ tmpreg = huart->Instance->CR3; /* Clear CTSE and RTSE bits */ tmpreg &= (uint32_t) ~((uint32_t) (USART_CR3_RTSE | USART_CR3_CTSE)); /* Configure the UART HFC: Set CTSE and RTSE bits according to huart->Init.HwFlowCtl value */ tmpreg |= huart->Init.HwFlowCtl; /* Write to USART CR3 */ huart->Instance->CR3 = (uint32_t) tmpreg; /* Check the Over Sampling */ if (huart->Init.OverSampling == UART_OVERSAMPLING_8) { /*-------------------------- USART BRR Configuration ---------------------*/ if ((huart->Instance == USART1) || (huart->Instance == USART6)) { huart->Instance->BRR = UART_DIV_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate); } else { huart->Instance->BRR = UART_DIV_SAMPLING8(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate); } } else { /*-------------------------- USART BRR Configuration ---------------------*/ if ((huart->Instance == USART1) || (huart->Instance == USART6)) { huart->Instance->BRR = UART_DIV_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate); } else { huart->Instance->BRR = UART_DIV_SAMPLING16(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate); } } }
/** * @brief Configure the SMARTCARD peripheral * @param hsc: pointer to a SMARTCARD_HandleTypeDef structure that contains * the configuration information for SMARTCARD module. * @retval None */ static void SMARTCARD_SetConfig(SMARTCARD_HandleTypeDef *hsc) { uint32_t tmpreg = 0x00; /* Check the parameters */ assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance)); assert_param(IS_SMARTCARD_POLARITY(hsc->Init.CLKPolarity)); assert_param(IS_SMARTCARD_PHASE(hsc->Init.CLKPhase)); assert_param(IS_SMARTCARD_LASTBIT(hsc->Init.CLKLastBit)); assert_param(IS_SMARTCARD_BAUDRATE(hsc->Init.BaudRate)); assert_param(IS_SMARTCARD_WORD_LENGTH(hsc->Init.WordLength)); assert_param(IS_SMARTCARD_STOPBITS(hsc->Init.StopBits)); assert_param(IS_SMARTCARD_PARITY(hsc->Init.Parity)); assert_param(IS_SMARTCARD_MODE(hsc->Init.Mode)); assert_param(IS_SMARTCARD_NACK_STATE(hsc->Init.NACKState)); /* The LBCL, CPOL and CPHA bits have to be selected when both the transmitter and the receiver are disabled (TE=RE=0) to ensure that the clock pulses function correctly. */ hsc->Instance->CR1 &= (uint32_t)~((uint32_t)(USART_CR1_TE | USART_CR1_RE)); /*---------------------------- USART CR2 Configuration ---------------------*/ tmpreg = hsc->Instance->CR2; /* Clear CLKEN, CPOL, CPHA and LBCL bits */ tmpreg &= (uint32_t)~((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_LBCL)); /* Configure the SMARTCARD Clock, CPOL, CPHA and LastBit -----------------------*/ /* Set CPOL bit according to hsc->Init.CLKPolarity value */ /* Set CPHA bit according to hsc->Init.CLKPhase value */ /* Set LBCL bit according to hsc->Init.CLKLastBit value */ /* Set Stop Bits: Set STOP[13:12] bits according to hsc->Init.StopBits value */ tmpreg |= (uint32_t)(USART_CR2_CLKEN | hsc->Init.CLKPolarity | hsc->Init.CLKPhase| hsc->Init.CLKLastBit | hsc->Init.StopBits); /* Write to USART CR2 */ hsc->Instance->CR2 = (uint32_t)tmpreg; tmpreg = hsc->Instance->CR2; /* Clear STOP[13:12] bits */ tmpreg &= (uint32_t)~((uint32_t)USART_CR2_STOP); /* Set Stop Bits: Set STOP[13:12] bits according to hsc->Init.StopBits value */ tmpreg |= (uint32_t)(hsc->Init.StopBits); /* Write to USART CR2 */ hsc->Instance->CR2 = (uint32_t)tmpreg; /*-------------------------- USART CR1 Configuration -----------------------*/ tmpreg = hsc->Instance->CR1; /* Clear M, PCE, PS, TE and RE bits */ tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \ USART_CR1_RE)); /* Configure the SMARTCARD Word Length, Parity and mode: Set the M bits according to hsc->Init.WordLength value Set PCE and PS bits according to hsc->Init.Parity value Set TE and RE bits according to hsc->Init.Mode value */ tmpreg |= (uint32_t)hsc->Init.WordLength | hsc->Init.Parity | hsc->Init.Mode; /* Write to USART CR1 */ hsc->Instance->CR1 = (uint32_t)tmpreg; /*-------------------------- USART CR3 Configuration -----------------------*/ /* Clear CTSE and RTSE bits */ hsc->Instance->CR3 &= (uint32_t)~((uint32_t)(USART_CR3_RTSE | USART_CR3_CTSE)); /*-------------------------- USART BRR Configuration -----------------------*/ if((hsc->Instance == USART1) || (hsc->Instance == USART6)) { hsc->Instance->BRR = __SMARTCARD_BRR(HAL_RCC_GetPCLK2Freq(), hsc->Init.BaudRate); } else { hsc->Instance->BRR = __SMARTCARD_BRR(HAL_RCC_GetPCLK1Freq(), hsc->Init.BaudRate); } }
/** * @brief Configures TIM4 Peripheral for LEDs lighting. * @param None * @retval None */ static void TIM_LED_Config(void) { uint16_t prescalervalue = 0; uint32_t tmpvalue = 0; /* TIM4 clock enable */ __HAL_RCC_TIM4_CLK_ENABLE(); /* Enable the TIM4 global Interrupt */ HAL_NVIC_SetPriority(TIM4_IRQn, 7, 0); HAL_NVIC_EnableIRQ(TIM4_IRQn); /* ----------------------------------------------------------------------- TIM4 Configuration: Output Compare Timing Mode: To get TIM4 counter clock at 550 KHz, the prescaler is computed as follows: Prescaler = (TIM4CLK / TIM4 counter clock) - 1 Prescaler = ((f(APB1) * 2) /550 KHz) - 1 CC update rate = TIM4 counter clock / CCR_Val = 32.687 Hz ==> Toggling frequency = 16.343 Hz ----------------------------------------------------------------------- */ /* Compute the prescaler value */ tmpvalue = HAL_RCC_GetPCLK1Freq(); prescalervalue = (uint16_t) ((tmpvalue * 2) / 480000) - 1; //Configurado a 48 KHz /* Time base configuration */ hTimLed.Instance = TIM4; hTimLed.Init.Period = 65535; hTimLed.Init.Prescaler = prescalervalue; hTimLed.Init.ClockDivision = 0; hTimLed.Init.CounterMode = TIM_COUNTERMODE_UP; if(HAL_TIM_OC_Init(&hTimLed) != HAL_OK) { /* Initialization Error */ Error_Handler(); } /* Output Compare Timing Mode configuration: Channel1 */ sConfigLed.OCMode = TIM_OCMODE_TIMING; sConfigLed.OCIdleState = TIM_OCIDLESTATE_SET; sConfigLed.Pulse = CCR1Val; sConfigLed.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigLed.OCNPolarity = TIM_OCNPOLARITY_HIGH; sConfigLed.OCFastMode = TIM_OCFAST_ENABLE; sConfigLed.OCNIdleState = TIM_OCNIDLESTATE_SET; /* Initialize the TIM4 Channel1 with the structure above */ if(HAL_TIM_OC_ConfigChannel(&hTimLed, &sConfigLed, TIM_CHANNEL_1) != HAL_OK) { /* Initialization Error */ Error_Handler(); } /* Start the Output Compare */ if(HAL_TIM_OC_Start_IT(&hTimLed, TIM_CHANNEL_1) != HAL_OK) { /* Start Error */ Error_Handler(); } }
/** * @brief TIM configuration * @param None * @retval None */ static void TIM_Config(void) { TIM_MasterConfigTypeDef master_timer_config; RCC_ClkInitTypeDef clk_init_struct = {0}; /* Temporary variable to retrieve RCC clock configuration */ uint32_t latency; /* Temporary variable to retrieve Flash Latency */ uint32_t timer_clock_frequency = 0; /* Timer clock frequency */ uint32_t timer_prescaler = 0; /* Time base prescaler to have timebase aligned on minimum frequency possible */ /* Configuration of timer as time base: */ /* Caution: Computation of frequency is done for a timer instance on APB1 */ /* (clocked by PCLK1) */ /* Timer frequency is configured from the following constants: */ /* - TIMER_FREQUENCY: timer frequency (unit: Hz). */ /* - TIMER_FREQUENCY_RANGE_MIN: timer minimum frequency possible */ /* (unit: Hz). */ /* Note: Refer to comments at these literals definition for more details. */ /* Retrieve timer clock source frequency */ HAL_RCC_GetClockConfig(&clk_init_struct, &latency); /* If APB1 prescaler is different of 1, timers have a factor x2 on their */ /* clock source. */ if (clk_init_struct.APB1CLKDivider == RCC_HCLK_DIV1) { timer_clock_frequency = HAL_RCC_GetPCLK1Freq(); } else { timer_clock_frequency = HAL_RCC_GetPCLK1Freq() *2; } /* Timer prescaler calculation */ /* (computation for timer 16 bits, additional + 1 to round the prescaler up) */ timer_prescaler = (timer_clock_frequency / (TIMER_PRESCALER_MAX_VALUE * TIMER_FREQUENCY_RANGE_MIN)) +1; /* Set timer instance */ TimHandle.Instance = TIMx; /* Configure timer parameters */ TimHandle.Init.Period = ((timer_clock_frequency / (timer_prescaler * TIMER_FREQUENCY)) - 1); TimHandle.Init.Prescaler = (timer_prescaler - 1); TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; TimHandle.Init.RepetitionCounter = 0x0; if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK) { /* Timer initialization Error */ Error_Handler(); } /* Timer TRGO selection */ master_timer_config.MasterOutputTrigger = TIM_TRGO_UPDATE; master_timer_config.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&TimHandle, &master_timer_config) != HAL_OK) { /* Timer TRGO selection Error */ Error_Handler(); } }
/** * @brief This function configures the TIM5 as a time base source. * The time source is configured to have 1ms time base with a dedicated * Tick interrupt priority. * @note This function is called automatically at the beginning of program after * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). * @param TickPriority: Tick interrupt priority. * @retval HAL status */ HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority) { RCC_ClkInitTypeDef sClokConfig; uint32_t uwTimclock, uwAPB1Prescaler = 0; uint32_t uwPrescalerValue = 0; uint32_t pFLatency; /*##-1- Enable peripherals and GPIO Clocks #################################*/ /* Enable TIM5 clock */ __HAL_RCC_TIM5_CLK_ENABLE(); /*##-2- Configure the NVIC for TIMx ########################################*/ /* Set the TIM5 priority */ HAL_NVIC_SetPriority(TIM5_IRQn, TICK_INT_PRIORITY, 0); /* Enable the TIM5 global Interrupt */ HAL_NVIC_EnableIRQ(TIM5_IRQn); /* Configure the TIM5 IRQ priority */ HAL_NVIC_SetPriority(TIM5_IRQn, TickPriority ,0); /* Get clock configuration */ HAL_RCC_GetClockConfig(&sClokConfig, &pFLatency); /* Get APB1 prescaler */ uwAPB1Prescaler = sClokConfig.APB1CLKDivider; /* Compute TIM5 clock */ if (uwAPB1Prescaler == 0) { uwTimclock = HAL_RCC_GetPCLK1Freq(); } else { uwTimclock = 2*HAL_RCC_GetPCLK1Freq(); } /* Compute the prescaler value to have TIM5 counter clock equal to 1MHz */ uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1); /* Initialize TIM5 */ TimHandle.Instance = TIM5; /* Initialize TIMx peripheral as follow: + Period = [(TIM5CLK/1000) - 1]. to have a (1/1000) s time base. + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock. + ClockDivision = 0 + Counter direction = Up */ TimHandle.Init.Period = (1000000 / 1000) - 1; TimHandle.Init.Prescaler = uwPrescalerValue; TimHandle.Init.ClockDivision = 0; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; if(HAL_TIM_Base_Init(&TimHandle) == HAL_OK) { /* Start the TIM time Base generation in interrupt mode */ return HAL_TIM_Base_Start_IT(&TimHandle); } /* Return function status */ return HAL_OK; }