void gpio_set_af(u32 gpioport, u8 alt_func_num, u16 gpios) { u16 i; u32 afrl, afrh; afrl = GPIO_AFRL(gpioport); afrh = GPIO_AFRH(gpioport); for (i = 0; i < 8; i++) { if (!((1 << i) & gpios)) continue; afrl &= ~GPIO_AFR_MASK(i); afrl |= GPIO_AFR(i, alt_func_num); } for (i = 8; i < 16; i++) { if (!((1 << i) & gpios)) continue; afrl &= ~GPIO_AFR_MASK(i - 8); afrh |= GPIO_AFR(i - 8, alt_func_num); } GPIO_AFRL(gpioport) = afrl; GPIO_AFRH(gpioport) = afrh; }
/** @brief Set GPIO Alternate Function Selection Set the alternate function mapping number for each pin. Most pins have alternate functions associated with them. When set to AF mode, a pin may be used for one of its allocated alternate functions selected by the number given here. To determine the number to be used for the desired function refer to the individual datasheet for the particular device. A table is given under the Pin Selection chapter. Note that a number of pins may be set but only with a single AF number. In practice this would rarely be useful as each pin is likely to require a different number. @param[in] gpioport Unsigned int32. Port identifier @ref gpio_port_id @param[in] alt_func_num Unsigned int8. Pin alternate function number @ref gpio_af_num @param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id If multiple pins are to be set, use bitwise OR '|' to separate them. */ void gpio_set_af(uint32_t gpioport, uint8_t alt_func_num, uint16_t gpios) { uint16_t i; uint32_t afrl, afrh; afrl = GPIO_AFRL(gpioport); afrh = GPIO_AFRH(gpioport); for (i = 0; i < 8; i++) { if (!((1 << i) & gpios)) { continue; } afrl &= ~GPIO_AFR_MASK(i); afrl |= GPIO_AFR(i, alt_func_num); } for (i = 8; i < 16; i++) { if (!((1 << i) & gpios)) { continue; } afrh &= ~GPIO_AFR_MASK(i - 8); afrh |= GPIO_AFR(i - 8, alt_func_num); } GPIO_AFRL(gpioport) = afrl; GPIO_AFRH(gpioport) = afrh; }
int CSysClock::init( TSysClockType source_clock) { switch(source_clock) { case HSE: // Включаем кварцевый генератор if( !( RCC->CR & RCC_CR_HSERDY ) ) { RCC->CR |= RCC_CR_HSEON; while( !( RCC->CR & RCC_CR_HSERDY ) ); } RCC->CFGR |= RCC_CFGR_SW_HSE; // Переход на HSE на случай незапуска PLL RCC->CR &= ~RCC_CR_PLLON; // Останавливаем PLL while ( RCC->CR & RCC_CR_PLLRDY ); // Настраиваем PLL на выходную частоту 48 МГц RCC->CFGR &= ~(RCC_CFGR_PLLMULL | RCC_CFGR_PLLSRC | RCC_CFGR_SW); RCC->CFGR |= RCC_CFGR_PLLMULL4 | RCC_CFGR_SW_PLL | RCC_CFGR_PLLSRC_PREDIV1; RCC->CR |= RCC_CR_PLLON; while (!( RCC->CR & RCC_CR_PLLRDY )); // Ожидает переключения на PLL while ( (RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Отключаем внутренний RC-генератор 8 МГц if( RCC->CR & RCC_CR_HSIRDY ) { RCC->CR &= ~RCC_CR_HSION; while( RCC->CR & RCC_CR_HSIRDY ); } break; case HSI: RCC->CR &= ~RCC_CR_HSEON; while ( RCC->CR & RCC_CR_HSERDY ); if( !(RCC->CR & RCC_CR_HSIRDY) ) { RCC->CR |= RCC_CR_HSION; while (!( RCC->CR & RCC_CR_HSIRDY )); } RCC->CFGR |= RCC_CFGR_SW_HSI; // Переход на HSI на случай незапуска PLL RCC->CR &= ~RCC_CR_PLLON; // Останавливаем PLL while ( RCC->CR & RCC_CR_PLLRDY ); // Настраиваем PLL на выходную частоту 48 МГц RCC->CFGR &= ~(RCC_CFGR_PLLMULL | RCC_CFGR_PLLSRC | RCC_CFGR_SW); RCC->CFGR |= RCC_CFGR_PLLMULL12 | RCC_CFGR_SW_PLL | RCC_CFGR_PLLSRC_HSI_Div2; RCC->CR |= RCC_CR_PLLON; while (!( RCC->CR & RCC_CR_PLLRDY )); // Ожидает переключения на PLL while ( (RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); break; default: for( ;; ); } // Отладочный вывод клока системной шины (SysClk) на порт PA8 #ifdef MCO_ENABLE RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // Подадим тактирование на PORTА GPIO_MODER(GPIOA, 8, ALT_FUNC_MODE); GPIO_OSPEEDR(GPIOA, 8, HIGH_SPEED); GPIO_AFR(GPIOA, 8, ALT_FUNC_0); RCC->CFGR &= ~(RCC_CFGR_MCO | 0x80000000); RCC->CFGR |= RCC_CFGR_MCO_SYSCLK; // System clock selected as MCO source #endif if (SysTick_Config((uint32_t)SYSTEM_CLOCK / 1000)) return 1; return 0; }