URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [cortexm/] [stm32/] [var/] [current/] [src/] [stm32_misc.c] - Rev 839
Go to most recent revision | Compare with Previous | Blame | View Log
/*========================================================================== // // stm32_misc.c // // Cortex-M STM32 HAL functions // //========================================================================== // ####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later // version. // // eCos is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License // along with eCos; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // As a special exception, if other files instantiate templates or use // macros or inline functions from this file, or you compile this file // and link it with other works to produce a work based on this file, // this file does not by itself cause the resulting work to be covered by // the GNU General Public License. However the source code for this file // must still be made available in accordance with section (3) of the GNU // General Public License v2. // // This exception does not invalidate any other reasons why a work based // on this file might be covered by the GNU General Public License. // ------------------------------------------- // ####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): nickg // Contributors: jld // Date: 2008-07-30 // Description: // //####DESCRIPTIONEND#### // //========================================================================*/ #include <pkgconf/hal.h> #include <pkgconf/hal_cortexm.h> #include <pkgconf/hal_cortexm_stm32.h> #ifdef CYGPKG_KERNEL #include <pkgconf/kernel.h> #endif #include <cyg/infra/diag.h> #include <cyg/infra/cyg_type.h> #include <cyg/infra/cyg_trac.h> // tracing macros #include <cyg/infra/cyg_ass.h> // assertion macros #include <cyg/hal/hal_arch.h> // HAL header #include <cyg/hal/hal_intr.h> // HAL header #include <cyg/hal/hal_if.h> // HAL header #ifdef CYGFUN_HAL_CORTEXM_STM32_PROFILE_TIMER #include <cyg/hal/drv_api.h> // CYG_ISR_HANDLED #include <cyg/profile/profile.h> // __profile_hit() #endif //========================================================================== // Clock Initialization values #if CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV == 1 # define CYGHWR_HAL_STM32_RCC_CFGR_HPRE CYGHWR_HAL_STM32_RCC_CFGR_HPRE_1 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV == 2 # define CYGHWR_HAL_STM32_RCC_CFGR_HPRE CYGHWR_HAL_STM32_RCC_CFGR_HPRE_2 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV == 4 # define CYGHWR_HAL_STM32_RCC_CFGR_HPRE CYGHWR_HAL_STM32_RCC_CFGR_HPRE_4 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV == 8 # define CYGHWR_HAL_STM32_RCC_CFGR_HPRE CYGHWR_HAL_STM32_RCC_CFGR_HPRE_8 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV == 16 # define CYGHWR_HAL_STM32_RCC_CFGR_HPRE CYGHWR_HAL_STM32_RCC_CFGR_HPRE_16 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV == 64 # define CYGHWR_HAL_STM32_RCC_CFGR_HPRE CYGHWR_HAL_STM32_RCC_CFGR_HPRE_64 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV == 128 # define CYGHWR_HAL_STM32_RCC_CFGR_HPRE CYGHWR_HAL_STM32_RCC_CFGR_HPRE_128 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV == 256 # define CYGHWR_HAL_STM32_RCC_CFGR_HPRE CYGHWR_HAL_STM32_RCC_CFGR_HPRE_256 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV == 512 # define CYGHWR_HAL_STM32_RCC_CFGR_HPRE CYGHWR_HAL_STM32_RCC_CFGR_HPRE_512 #endif #if CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV == 1 # define CYGHWR_HAL_STM32_RCC_CFGR_PPRE1 CYGHWR_HAL_STM32_RCC_CFGR_PPRE1_1 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV == 2 # define CYGHWR_HAL_STM32_RCC_CFGR_PPRE1 CYGHWR_HAL_STM32_RCC_CFGR_PPRE1_2 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV == 4 # define CYGHWR_HAL_STM32_RCC_CFGR_PPRE1 CYGHWR_HAL_STM32_RCC_CFGR_PPRE1_4 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV == 8 # define CYGHWR_HAL_STM32_RCC_CFGR_PPRE1 CYGHWR_HAL_STM32_RCC_CFGR_PPRE1_8 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV == 16 # define CYGHWR_HAL_STM32_RCC_CFGR_PPRE1 CYGHWR_HAL_STM32_RCC_CFGR_PPRE1_16 #endif #if CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV == 1 # define CYGHWR_HAL_STM32_RCC_CFGR_PPRE2 CYGHWR_HAL_STM32_RCC_CFGR_PPRE2_1 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV == 2 # define CYGHWR_HAL_STM32_RCC_CFGR_PPRE2 CYGHWR_HAL_STM32_RCC_CFGR_PPRE2_2 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV == 4 # define CYGHWR_HAL_STM32_RCC_CFGR_PPRE2 CYGHWR_HAL_STM32_RCC_CFGR_PPRE2_4 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV == 8 # define CYGHWR_HAL_STM32_RCC_CFGR_PPRE2 CYGHWR_HAL_STM32_RCC_CFGR_PPRE2_8 #elif CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV == 16 # define CYGHWR_HAL_STM32_RCC_CFGR_PPRE2 CYGHWR_HAL_STM32_RCC_CFGR_PPRE2_16 #endif //========================================================================== // Clock frequencies // // These are set to the frequencies of the various system clocks. cyg_uint32 hal_stm32_sysclk; cyg_uint32 hal_stm32_hclk; cyg_uint32 hal_stm32_pclk1; cyg_uint32 hal_stm32_pclk2; cyg_uint32 hal_cortexm_systick_clock; void hal_start_clocks( void ); cyg_uint32 hal_exti_isr( cyg_uint32 vector, CYG_ADDRWORD data ); //========================================================================== void hal_variant_init( void ) { CYG_ADDRESS rcc = CYGHWR_HAL_STM32_RCC; // Enable all devices in RCC HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_APB2ENR, 0xFFFFFFFF ); HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_APB1ENR, 0xFFFFFFFF ); #if 1 //!defined(CYG_HAL_STARTUP_RAM) hal_start_clocks(); #endif // Attach EXTI springboard to interrupt vectors HAL_INTERRUPT_ATTACH( CYGNUM_HAL_INTERRUPT_EXTI9_5, hal_exti_isr, 0, 0 ); HAL_INTERRUPT_ATTACH( CYGNUM_HAL_INTERRUPT_EXTI15_10, hal_exti_isr, 0, 0 ); #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT hal_if_init(); #endif } //========================================================================== // Setup up system clocks // // Set up clocks from configuration. In the future this should be extended so // that clock rates can be changed at runtime. void hal_start_clocks( void ) { CYG_ADDRESS rcc = CYGHWR_HAL_STM32_RCC; cyg_uint32 cr, cfgr; // Reset RCC HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, 0x00000001 ); // Start up HSE clock HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); cr &= ~(CYGHWR_HAL_STM32_RCC_CR_HSEON|CYGHWR_HAL_STM32_RCC_CR_HSEBYP); HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); cr |= CYGHWR_HAL_STM32_RCC_CR_HSEON; HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); // Wait for HSE clock to startup do { HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); } while( !(cr & CYGHWR_HAL_STM32_RCC_CR_HSERDY) ); // Configure clocks hal_stm32_sysclk = CYGARC_HAL_CORTEXM_STM32_INPUT_CLOCK; cfgr = 0; #if defined(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_SOURCE_HSE) cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PLLSRC_HSE; #elif defined(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_SOURCE_HSE_HALF) cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PLLSRC_HSE | CYGHWR_HAL_STM32_RCC_CFGR_PLLXTPRE; hal_stm32_sysclk /= 2; #elif defined(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_SOURCE_HSI_HALF) hal_stm32_sysclk /= 2; #endif cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PLLMUL(CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_MUL); cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_HPRE; cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PPRE1; cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_PPRE2; HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CFGR, cfgr ); // Enable the PLL and wait for it to lock cr |= CYGHWR_HAL_STM32_RCC_CR_PLLON; HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); do { HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CR, cr ); } while( !(cr & CYGHWR_HAL_STM32_RCC_CR_PLLRDY) ); // Now switch to use PLL as SYSCLK cfgr |= CYGHWR_HAL_STM32_RCC_CFGR_SW_PLL; HAL_WRITE_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CFGR, cfgr ); do { HAL_READ_UINT32( rcc+CYGHWR_HAL_STM32_RCC_CFGR, cfgr ); } while( (cfgr & CYGHWR_HAL_STM32_RCC_CFGR_SWS_XXX) != CYGHWR_HAL_STM32_RCC_CFGR_SWS_PLL ); // Calculate clocks from configuration hal_stm32_sysclk *= CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_MUL; hal_stm32_hclk = hal_stm32_sysclk / CYGHWR_HAL_CORTEXM_STM32_CLOCK_HCLK_DIV; hal_stm32_pclk1 = hal_stm32_hclk / CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV; hal_stm32_pclk2 = hal_stm32_hclk / CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV; #ifdef CYGHWR_HAL_CORTEXM_SYSTICK_CLK_SOURCE_INTERNAL hal_cortexm_systick_clock = hal_stm32_hclk; #else hal_cortexm_systick_clock = hal_stm32_hclk / 8; #endif } //========================================================================== // ISR springboard // // This is attached to the ISR table entries for EXTI9_5 and EXTI15_10 // to decode the contents of the EXTI registers and deliver the // interrupt to the correct ISR. cyg_uint32 hal_exti_isr( cyg_uint32 vector, CYG_ADDRWORD data ) { CYG_ADDRESS base = CYGHWR_HAL_STM32_EXTI; cyg_uint32 imr, pr; // Get EXTI pending and interrupt mask registers HAL_READ_UINT32( base+CYGHWR_HAL_STM32_EXTI_IMR, imr ); HAL_READ_UINT32( base+CYGHWR_HAL_STM32_EXTI_PR, pr ); // Mask PR by IMR and lose ls 5 bits pr &= imr; pr &= 0xFFFFFFE0; // Isolate LS pending bit and translate into interrupt vector // number. HAL_LSBIT_INDEX( vector, pr ); vector += CYGNUM_HAL_INTERRUPT_EXTI5 - 5; // Deliver it hal_deliver_interrupt( vector ); return 0; } //========================================================================== // GPIO support // // These functions provide configuration and IO for GPIO pins. __externC void hal_stm32_gpio_set( cyg_uint32 pin ) { cyg_uint32 port = CYGHWR_HAL_STM32_GPIO_PORT(pin); int bit = CYGHWR_HAL_STM32_GPIO_BIT(pin); cyg_uint32 cm = CYGHWR_HAL_STM32_GPIO_CFG(pin); cyg_uint32 cr; if( pin == CYGHWR_HAL_STM32_GPIO_NONE ) return; if( bit > 7 ) port += 4, bit -= 8; HAL_READ_UINT32( port, cr ); cr &= ~(0xF<<(bit*4)); cr |= cm<<(bit*4); HAL_WRITE_UINT32( port, cr ); // If this is a pullup/down input, set the ODR bit to switch on // the appropriate pullup/down resistor. if( cm == (CYGHWR_HAL_STM32_GPIO_MODE_IN|CYGHWR_HAL_STM32_GPIO_CNF_PULL) ) { cyg_uint32 odr; port = CYGHWR_HAL_STM32_GPIO_PORT( pin ); bit = CYGHWR_HAL_STM32_GPIO_BIT(pin); HAL_READ_UINT32( port+CYGHWR_HAL_STM32_GPIO_ODR, odr ); if( pin & CYGHWR_HAL_STM32_GPIO_PULLUP ) odr |= (1<<bit); else odr &= ~(1<<bit); HAL_WRITE_UINT32( port+CYGHWR_HAL_STM32_GPIO_ODR, odr ); } } __externC void hal_stm32_gpio_out( cyg_uint32 pin, int val ) { cyg_uint32 port = CYGHWR_HAL_STM32_GPIO_PORT(pin); int bit = CYGHWR_HAL_STM32_GPIO_BIT(pin); port += CYGHWR_HAL_STM32_GPIO_BSRR; if( (val&1) == 0 ) port += 4; HAL_WRITE_UINT32( port, 1<<bit ); } __externC void hal_stm32_gpio_in ( cyg_uint32 pin, int *val ) { cyg_uint32 port = CYGHWR_HAL_STM32_GPIO_PORT(pin); int bit = CYGHWR_HAL_STM32_GPIO_BIT(pin); cyg_uint32 pd; HAL_READ_UINT32( port+CYGHWR_HAL_STM32_GPIO_IDR, pd ); *val = (pd>>bit)&1; } //========================================================================== // Backup domain void hal_stm32_bd_protect( int protect ) { CYG_ADDRESS pwr = CYGHWR_HAL_STM32_PWR; cyg_uint32 cr; HAL_READ_UINT32( pwr+CYGHWR_HAL_STM32_PWR_CR, cr ); if( protect ) cr &= ~CYGHWR_HAL_STM32_PWR_CR_DBP; else cr |= CYGHWR_HAL_STM32_PWR_CR_DBP; HAL_WRITE_UINT32( pwr+CYGHWR_HAL_STM32_PWR_CR, cr ); } //========================================================================== // UART baud rate // // Set the baud rate divider of a UART based on the requested rate and // the current APB clock settings. void hal_stm32_uart_setbaud( cyg_uint32 base, cyg_uint32 baud ) { cyg_uint32 apbclk = hal_stm32_pclk1; cyg_uint32 int_div, frac_div; cyg_uint32 brr; if( base == CYGHWR_HAL_STM32_UART1 ) apbclk = hal_stm32_pclk2; int_div = (25 * apbclk ) / (4 * baud ); brr = ( int_div / 100 ) << 4; frac_div = int_div - (( brr >> 4 ) * 100 ); brr |= (((frac_div * 16 ) + 50 ) / 100) & 0xF; HAL_WRITE_UINT32( base+CYGHWR_HAL_STM32_UART_BRR, brr ); } //========================================================================== // Timer clock rate // // Returns the current timer clock rate of a timer. cyg_uint32 hal_stm32_timer_clock( CYG_ADDRESS base ) { if( base == CYGHWR_HAL_STM32_TIM1 || base == CYGHWR_HAL_STM32_TIM8 ) { #if CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK2_DIV == 1 return hal_stm32_pclk2; #else return hal_stm32_pclk2 << 1; #endif } else { #if CYGHWR_HAL_CORTEXM_STM32_CLOCK_PCLK1_DIV == 1 return hal_stm32_pclk1; #else return hal_stm32_pclk1 << 1; #endif } } //========================================================================== // Profiling timer // // Implementation of profiling support using general-purpose timer TIM2. #ifdef CYGFUN_HAL_CORTEXM_STM32_PROFILE_TIMER // Use TIM2 for profiling #define STM32_TIMER_PROFILE CYGHWR_HAL_STM32_TIM2 #define HAL_INTERRUPT_PROFILE CYGNUM_HAL_INTERRUPT_TIM2 // Profiling timer ISR static cyg_uint32 profile_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) { extern HAL_SavedRegisters *hal_saved_interrupt_state; HAL_WRITE_UINT32(STM32_TIMER_PROFILE+CYGHWR_HAL_STM32_TIM_SR, 0); // clear interrupt pending flag HAL_INTERRUPT_ACKNOWLEDGE(HAL_INTERRUPT_PROFILE); __profile_hit(hal_saved_interrupt_state->u.interrupt.pc); return CYG_ISR_HANDLED; } // Profiling timer setup int hal_enable_profile_timer(int resolution) { CYG_ASSERT(resolution < 0x10000, "Invalid profile timer resolution"); // 16 bits only // Attach ISR HAL_INTERRUPT_ATTACH(HAL_INTERRUPT_PROFILE, &profile_isr, 0x1111, 0); HAL_INTERRUPT_UNMASK(HAL_INTERRUPT_PROFILE); // Setup timer HAL_WRITE_UINT32(STM32_TIMER_PROFILE+CYGHWR_HAL_STM32_TIM_PSC, (hal_stm32_timer_clock(STM32_TIMER_PROFILE) / 1000000) - 1); // prescale to microseconds HAL_WRITE_UINT32(STM32_TIMER_PROFILE+CYGHWR_HAL_STM32_TIM_CR2, 0); HAL_WRITE_UINT32(STM32_TIMER_PROFILE+CYGHWR_HAL_STM32_TIM_DIER, CYGHWR_HAL_STM32_TIM_DIER_UIE); HAL_WRITE_UINT32(STM32_TIMER_PROFILE+CYGHWR_HAL_STM32_TIM_ARR, resolution); HAL_WRITE_UINT32(STM32_TIMER_PROFILE+CYGHWR_HAL_STM32_TIM_CR1, CYGHWR_HAL_STM32_TIM_CR1_CEN); return resolution; } #endif // CYGFUN_HAL_CORTEXM_STM32_PROFILE_TIMER //========================================================================== // EOF stm32_misc.c
Go to most recent revision | Compare with Previous | Blame | View Log