void rtt_poweron(void) { #ifdef RCC_APB1ENR1_LPTIM1EN periph_clk_en(APB1, RCC_APB1ENR1_LPTIM1EN); #else periph_clk_en(APB1, RCC_APB1ENR_LPTIM1EN); #endif }
void uart_poweron(uart_t uart) { assert(uart < UART_NUMOF); #ifdef STM32_PM_STOP if (isr_ctx[uart].rx_cb) { pm_block(STM32_PM_STOP); } #endif periph_clk_en(uart_config[uart].bus, uart_config[uart].rcc_mask); }
int i2c_acquire(i2c_t dev) { assert(dev < I2C_NUMOF); mutex_lock(&locks[dev]); periph_clk_en(i2c_config[dev].bus, i2c_config[dev].rcc_mask); return 0; }
void hwrng_read(void *buf, unsigned int num) { unsigned int count = 0; uint8_t *b = (uint8_t *)buf; /* power on and enable the device */ #if defined(CPU_MODEL_STM32F410RB) periph_clk_en(AHB1, RCC_AHB1ENR_RNGEN); #elif defined(CPU_FAM_STM32L0) periph_clk_en(AHB, RCC_AHBENR_RNGEN); #else periph_clk_en(AHB2, RCC_AHB2ENR_RNGEN); #endif RNG->CR = RNG_CR_RNGEN; /* get random data */ while (count < num) { /* wait for random data to be ready to read */ while (!(RNG->SR & RNG_SR_DRDY)) {} /* read next 4 bytes */ uint32_t tmp = RNG->DR; /* copy data into result vector */ for (int i = 0; i < 4 && count < num; i++) { b[count++] = (uint8_t)tmp; tmp = tmp >> 8; } } /* finally disable the device again */ RNG->CR = 0; #if defined(CPU_MODEL_STM32F410RB) periph_clk_dis(AHB1, RCC_AHB1ENR_RNGEN); #elif defined(CPU_FAM_STM32L0) periph_clk_dis(AHB, RCC_AHBENR_RNGEN); #else periph_clk_dis(AHB2, RCC_AHB2ENR_RNGEN); #endif }
int i2c_acquire(i2c_t dev) { assert(dev < I2C_NUMOF); mutex_lock(&locks[dev]); #ifdef STM32_PM_STOP /* block STOP mode */ pm_block(STM32_PM_STOP); #endif periph_clk_en(i2c_config[dev].bus, i2c_config[dev].rcc_mask); return 0; }
/** * @brief Configure the clock system of the stm32f1 */ static void clk_init(void) { /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ /* Set MSION bit */ RCC->CR |= RCC_CR_MSION; /* Reset SW, HPRE, PPRE1, PPRE2, MCOSEL and MCOPRE bits */ RCC->CFGR &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLDIV | RCC_CFGR_PLLMUL); /* Reset HSION, HSEON, CSSON and PLLON bits */ RCC->CR &= ~(RCC_CR_HSION | RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_CSSON | RCC_CR_PLLON); /* Disable all interrupts */ RCC->CIR = 0x0; /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration */ /* Enable high speed clock source */ RCC->CR |= CLOCK_CR_SOURCE; /* Wait till the high speed clock source is ready * NOTE: the MCU will stay here forever if you use an external clock source and it's not connected */ while (!(RCC->CR & CLOCK_CR_SOURCE_RDY)) {} FLASH->ACR |= FLASH_ACR_ACC64; /* Enable Prefetch Buffer */ FLASH->ACR |= FLASH_ACR_PRFTEN; /* Flash 1 wait state */ FLASH->ACR |= CLOCK_FLASH_LATENCY; /* Power enable */ periph_clk_en(APB1, RCC_APB1ENR_PWREN); /* Select the Voltage Range 1 (1.8 V) */ PWR->CR = PWR_CR_VOS_0; /* Wait Until the Voltage Regulator is ready */ while((PWR->CSR & PWR_CSR_VOSF) != 0) {} /* HCLK = SYSCLK */ RCC->CFGR |= (uint32_t)CLOCK_AHB_DIV; /* PCLK2 = HCLK */ RCC->CFGR |= (uint32_t)CLOCK_APB2_DIV; /* PCLK1 = HCLK */ RCC->CFGR |= (uint32_t)CLOCK_APB1_DIV; /* PLL configuration: PLLCLK = CLOCK_SOURCE / PLL_DIV * PLL_MUL */ RCC->CFGR &= ~((uint32_t)(RCC_CFGR_PLLSRC | RCC_CFGR_PLLDIV | RCC_CFGR_PLLMUL)); RCC->CFGR |= (uint32_t)(CLOCK_PLL_SOURCE | CLOCK_PLL_DIV | CLOCK_PLL_MUL); /* Enable PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till PLL is ready */ while ((RCC->CR & RCC_CR_PLLRDY) == 0) {} /* Select PLL as system clock source */ RCC->CFGR &= ~((uint32_t)(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; /* Wait till PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {} }
/** * @brief Initialize the boards standard LEDs (RED, YELLOW, GREEN) * * The LED initialization is hard-coded in this function. As the LEDs are soldered * onto the board they are fixed to their CPU pins. * * The LEDs are connected to the following pins: * - LED RED: PB8 * - LED YELLOW: PB14 * - LED GREEN: PB15 */ static void leds_init(void) { /* enable clock for port GPIOB */ periph_clk_en(AHB1, RCC_AHB1ENR_GPIOBEN); /* set output speed to 50MHz */ LED_PORT->OSPEEDR &= ~(0xF0030000); LED_PORT->OSPEEDR |= 0xA0020000; /* set output type to push-pull */ LED_PORT->OTYPER &= ~(0x0000C100); /* configure pins as general outputs */ LED_PORT->MODER &= ~(0xF0030000); LED_PORT->MODER |= 0x50010000; /* disable pull resistors */ LED_PORT->PUPDR &= ~(0xF0030000); /* turn all LEDs off */ LED_PORT->BSRRL = 0xC100; }
void i2c_init(i2c_t dev) { assert(dev < I2C_NUMOF); DEBUG("[i2c] init: initializing device\n"); mutex_init(&locks[dev]); I2C_TypeDef *i2c = i2c_config[dev].dev; periph_clk_en(i2c_config[dev].bus, i2c_config[dev].rcc_mask); NVIC_SetPriority(i2c_config[dev].irqn, I2C_IRQ_PRIO); NVIC_EnableIRQ(i2c_config[dev].irqn); #if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) /* Set I2CSW bits to enable I2C clock source */ RCC->CFGR3 |= i2c_config[dev].rcc_sw_mask; #endif DEBUG("[i2c] init: configuring pins\n"); /* configure pins */ gpio_init(i2c_config[dev].scl_pin, GPIO_OD_PU); gpio_init_af(i2c_config[dev].scl_pin, i2c_config[dev].scl_af); gpio_init(i2c_config[dev].sda_pin, GPIO_OD_PU); gpio_init_af(i2c_config[dev].sda_pin, i2c_config[dev].sda_af); DEBUG("[i2c] init: configuring device\n"); /* set the timing register value from predefined values */ i2c_timing_param_t tp = timing_params[i2c_config[dev].speed]; uint32_t timing = (( (uint32_t)tp.presc << I2C_TIMINGR_PRESC_Pos) | ( (uint32_t)tp.scldel << I2C_TIMINGR_SCLDEL_Pos) | ( (uint32_t)tp.sdadel << I2C_TIMINGR_SDADEL_Pos) | ( (uint16_t)tp.sclh << I2C_TIMINGR_SCLH_Pos) | tp.scll); _i2c_init(i2c, timing); }
void stmclk_bdp_unlock(void) { periph_clk_en(APB1, RCC_APB1ENR_PWREN); PWR->CR1 |= PWR_CR1_DBP; }
void uart_poweron(uart_t uart) { periph_clk_en(uart_config[uart].bus, uart_config[uart].rcc_mask); }
static inline void prep(adc_t line) { mutex_lock(&locks[adc_config[line].dev]); periph_clk_en(APB2, (RCC_APB2ENR_ADC1EN << adc_config[line].dev)); }
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) { uint16_t mantissa; uint8_t fraction; uint32_t clk; assert(uart < UART_NUMOF); /* save ISR context */ isr_ctx[uart].rx_cb = rx_cb; isr_ctx[uart].arg = arg; /* configure TX pin */ gpio_init(uart_config[uart].tx_pin, GPIO_OUT); /* set TX pin high to avoid garbage during further initialization */ gpio_set(uart_config[uart].tx_pin); #ifdef CPU_FAM_STM32F1 gpio_init_af(uart_config[uart].tx_pin, GPIO_AF_OUT_PP); #else gpio_init_af(uart_config[uart].tx_pin, uart_config[uart].tx_af); #endif /* configure RX pin */ if (rx_cb) { gpio_init(uart_config[uart].rx_pin, GPIO_IN); #ifndef CPU_FAM_STM32F1 gpio_init_af(uart_config[uart].rx_pin, uart_config[uart].rx_af); #endif } #ifdef UART_USE_HW_FC if (uart_config[uart].cts_pin != GPIO_UNDEF) { gpio_init(uart_config[uart].cts_pin, GPIO_IN); gpio_init(uart_config[uart].rts_pin, GPIO_OUT); #ifdef CPU_FAM_STM32F1 gpio_init_af(uart_config[uart].rts_pin, GPIO_AF_OUT_PP); #else gpio_init_af(uart_config[uart].cts_pin, uart_config[uart].cts_af); gpio_init_af(uart_config[uart].rts_pin, uart_config[uart].rts_af); #endif } #endif /* enable the clock */ periph_clk_en(uart_config[uart].bus, uart_config[uart].rcc_mask); /* reset UART configuration -> defaults to 8N1 mode */ dev(uart)->CR1 = 0; dev(uart)->CR2 = 0; dev(uart)->CR3 = 0; /* calculate and apply baudrate */ clk = periph_apb_clk(uart_config[uart].bus) / baudrate; mantissa = (uint16_t)(clk / 16); fraction = (uint8_t)(clk - (mantissa * 16)); dev(uart)->BRR = ((mantissa & 0x0fff) << 4) | (fraction & 0x0f); /* enable RX interrupt if applicable */ if (rx_cb) { NVIC_EnableIRQ(uart_config[uart].irqn); dev(uart)->CR1 = (USART_CR1_UE | USART_CR1_TE | RXENABLE); } else { dev(uart)->CR1 = (USART_CR1_UE | USART_CR1_TE); } #ifdef UART_USE_HW_FC if (uart_config[uart].cts_pin != GPIO_UNDEF) { /* configure hardware flow control */ dev(uart)->CR3 = (USART_CR3_RTSE | USART_CR3_CTSE); } #endif return UART_OK; }
void uart_poweroff(uart_t uart) { assert(uart < UART_NUMOF); periph_clk_en(uart_config[uart].bus, uart_config[uart].rcc_mask); }
void i2c_init(i2c_t dev) { assert(dev < I2C_NUMOF); mutex_init(&locks[dev]); I2C_TypeDef *i2c = i2c_config[dev].dev; assert(i2c != NULL); uint32_t ccr; /* read speed configuration */ switch (i2c_config[dev].speed) { case I2C_SPEED_LOW: /* 10Kbit/s */ ccr = i2c_config[dev].clk / 20000; break; case I2C_SPEED_NORMAL: /* 100Kbit/s */ ccr = i2c_config[dev].clk / 200000; break; case I2C_SPEED_FAST: ccr = i2c_config[dev].clk / 800000; break; default: return; } periph_clk_en(i2c_config[dev].bus, i2c_config[dev].rcc_mask); NVIC_SetPriority(i2c_config[dev].irqn, I2C_IRQ_PRIO); NVIC_EnableIRQ(i2c_config[dev].irqn); /* configure pins */ gpio_init(i2c_config[dev].scl_pin, GPIO_OD_PU); gpio_init(i2c_config[dev].sda_pin, GPIO_OD_PU); #ifdef CPU_FAM_STM32F1 /* This is needed in case the remapped pins are used */ if (i2c_config[dev].scl_pin == GPIO_PIN(PORT_B, 8) || i2c_config[dev].sda_pin == GPIO_PIN(PORT_B, 9)) { /* The remapping periph clock must first be enabled */ RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; /* Then the remap can occur */ AFIO->MAPR |= AFIO_MAPR_I2C1_REMAP; } gpio_init_af(i2c_config[dev].scl_pin, GPIO_AF_OUT_OD); gpio_init_af(i2c_config[dev].sda_pin, GPIO_AF_OUT_OD); #else gpio_init_af(i2c_config[dev].scl_pin, i2c_config[dev].scl_af); gpio_init_af(i2c_config[dev].sda_pin, i2c_config[dev].sda_af); #endif /* configure device */ _i2c_init(i2c, i2c_config[dev].clk, ccr); #if defined(CPU_FAM_STM32F4) /* make sure the analog filters don't hang -> see errata sheet 2.14.7 */ if (i2c->SR2 & I2C_SR2_BUSY) { /* disable peripheral */ i2c->CR1 &= ~I2C_CR1_PE; /* toggle both pins to reset analog filter */ gpio_init(i2c_config[dev].scl_pin, GPIO_OD); gpio_init(i2c_config[dev].sda_pin, GPIO_OD); gpio_set(i2c_config[dev].sda_pin); gpio_set(i2c_config[dev].scl_pin); gpio_clear(i2c_config[dev].sda_pin); gpio_clear(i2c_config[dev].scl_pin); gpio_set(i2c_config[dev].sda_pin); gpio_set(i2c_config[dev].scl_pin); /* reset pins for alternate function */ gpio_init(i2c_config[dev].scl_pin, GPIO_OD_PU); gpio_init(i2c_config[dev].sda_pin, GPIO_OD_PU); gpio_init_af(i2c_config[dev].scl_pin, i2c_config[dev].scl_af); gpio_init_af(i2c_config[dev].sda_pin, i2c_config[dev].sda_af); /* make peripheral soft reset */ i2c->CR1 |= I2C_CR1_SWRST; i2c->CR1 &= ~I2C_CR1_SWRST; /* enable device */ _i2c_init(i2c, i2c_config[dev].clk, ccr); } #endif }
void pwm_poweron(pwm_t pwm) { assert(pwm < PWM_NUMOF); periph_clk_en(pwm_config[pwm].bus, pwm_config[pwm].rcc_mask); }
/** * @brief Configure the STM32L4's clock system * * We use the following configuration: * - we always enable the 32kHz low speed clock (LSI or LSE) * - we configure the MSI clock to 48MHz (for USB and RNG) and enable it * - if LSE present, we use it to stabilize the 48MHz MSI clock (MSIPLLEN) * - use either MSI @ 48MHz or HSE (4 to 48MHZ) as base clock * - we use the PLL as main clock provider * - we don't enable any ASI clock * * For the computation of the PLL configuration, see defines above. */ static void cpu_clock_init(void) { /* disable any interrupts. Global interrupts could be enabled if this is * called from some kind of bootloader... */ unsigned is = irq_disable(); RCC->CIER = 0; /* for the duration of the configuration, we fall-back to the maximum number * of flash wait states */ FLASH->ACR = (FLASH_ACR_LATENCY_4WS); /* reset clock to MSI with 48MHz, disables all other clocks */ RCC->CR = (RCC_CR_MSIRANGE_11 | RCC_CR_MSION | RCC_CR_MSIRGSEL); while (!(RCC->CR & RCC_CR_MSIRDY)) {} /* use MSI as system clock while we do any further configuration and * configure the AHB and APB clock dividers as configure by the board */ RCC->CFGR = (RCC_CFGR_SW_MSI | CLOCK_AHB_DIV | CLOCK_APB1_DIV | CLOCK_APB2_DIV); while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_MSI) {} /* configure the low speed clock domain (LSE vs LSI) */ #if CLOCK_LSE /* allow write access to backup domain */ periph_clk_en(APB1, RCC_APB1ENR1_PWREN); PWR->CR1 |= PWR_CR1_DBP; /* enable LSE */ RCC->BDCR = RCC_BDCR_LSEON; while (!(RCC->BDCR & RCC_BDCR_LSERDY)) {} /* disable write access to back domain when done */ PWR->CR1 &= ~(PWR_CR1_DBP); periph_clk_dis(APB1, RCC_APB1ENR1_PWREN); /* now we can enable the MSI PLL mode */ RCC->CR |= RCC_CR_MSIPLLEN; while (!(RCC->CR & RCC_CR_MSIRDY)) {} #else RCC->CSR = RCC_CSR_LSION; while (!(RCC->CSR & RCC_CSR_LSIRDY)) {} #endif /* select the MSI clock for the 48MHz clock tree (USB, RNG) */ RCC->CCIPR = (RCC_CCIPR_CLK48SEL_0 | RCC_CCIPR_CLK48SEL_1); /* if configured: enable the HSE clock */ #if CLOCK_HSE RCC->CR |= RCC_CR_HSEON; while (!(RCC->CR & RCC_CR_HSERDY)) {} #endif /* next we configure and enable the PLL */ RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_R | RCC_PLLCFGR_PLLREN); RCC->CR |= RCC_CR_PLLON; while (!(RCC->CR & RCC_CR_PLLRDY)) {} /* now tell the system to use the PLL as main clock */ RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL) {} /* finally we enable I+D cashes, pre-fetch, and we set the actual number of * needed flash wait states */ FLASH->ACR = (FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN | FLASH_WAITSTATES); irq_restore(is); }