OpenCores
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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.