void gpio_mode_setup(u32 gpioport, u8 mode, u8 pull_up_down, u16 gpios) { u16 i; u32 moder, pupd; /* * We want to set the config only for the pins mentioned in gpios, * but keeping the others, so read out the actual config first. */ moder = GPIO_MODER(gpioport); pupd = GPIO_PUPDR(gpioport); for (i = 0; i < 16; i++) { if (!((1 << i) & gpios)) continue; moder &= ~GPIO_MODE_MASK(i); moder |= GPIO_MODE(i, mode); pupd &= ~GPIO_PUPD_MASK(i); pupd |= GPIO_PUPD(i, pull_up_down); } /* Set mode and pull up/down control registers. */ GPIO_MODER(gpioport) = moder; GPIO_PUPDR(gpioport) = pupd; }
inline static void gpio_moder(uint8_t port, uint8_t pin, uint8_t type) { uint32_t reg = *GPIO_MODER(port); reg &= ~(GPIO_MODER_M(pin)); reg |= (type << GPIO_MODER_PIN(pin)); *GPIO_MODER(port) = reg; }
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; }