diff --git a/src/platform/stm32/platform.c b/src/platform/stm32/platform.c index c57269a4..080ac0e3 100755 --- a/src/platform/stm32/platform.c +++ b/src/platform/stm32/platform.c @@ -692,8 +692,10 @@ int platform_s_uart_set_flow_control( unsigned id, int type ) // **************************************************************************** // Timers +u8 stm32_timer_int_periodic_flag[ NUM_PHYS_TIMER ]; + // We leave out TIM6/TIM for now, as they are dedicated -static TIM_TypeDef * const timer[] = { TIM1, TIM2, TIM3, TIM4, TIM5 }; +const TIM_TypeDef * const timer[] = { TIM1, TIM2, TIM3, TIM4, TIM5 }; #define TIM_GET_PRESCALE( id ) ( ( id ) == 0 || ( id ) == 5 ? ( PCLK2_DIV ) : ( PCLK1_DIV ) ) #define TIM_GET_BASE_CLK( id ) ( TIM_GET_PRESCALE( id ) == 1 ? ( HCLK / TIM_GET_PRESCALE( id ) ) : ( HCLK / ( TIM_GET_PRESCALE( id ) / 2 ) ) ) #define TIM_STARTUP_CLOCK 50000 @@ -802,7 +804,44 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data ) int platform_s_timer_set_match_int( unsigned id, u32 period_us, int type ) { - return PLATFORM_TIMER_INT_INVALID_ID; + TIM_TypeDef* base = ( TIM_TypeDef* )timer[ id ]; + u32 freq; + timer_data_type final; + TIM_OCInitTypeDef TIM_OCInitStructure; + + if( period_us == 0 ) + { + TIM_ITConfig( base, TIM_IT_CC1, DISABLE ); + base->CR1 = 0; // Why are we doing this? + base->CR2 = 0; + return PLATFORM_TIMER_INT_OK; + } + timer_set_clock( id, 1000000 ); + freq = timer_get_clock( id ); + final = ( ( u64 )period_us * freq ) / 1000000; + if( final == 0 ) + return PLATFORM_TIMER_INT_TOO_SHORT; + if( final > 0xFFFF ) + return PLATFORM_TIMER_INT_TOO_LONG; + + TIM_Cmd( base, DISABLE ); + + TIM_OCStructInit( &TIM_OCInitStructure ); + TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; + TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; + TIM_OCInitStructure.TIM_Pulse = final; + TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; + TIM_OC1Init( base, &TIM_OCInitStructure ); + + TIM_OC1PreloadConfig( base, TIM_OCPreload_Disable ); + + stm32_timer_int_periodic_flag[ id ] = type; + + TIM_SetCounter( base, 0 ); + TIM_Cmd( base, ENABLE ); + TIM_ITConfig( base, TIM_IT_CC1, ENABLE ); + + return PLATFORM_TIMER_INT_OK; } // **************************************************************************** diff --git a/src/platform/stm32/platform_conf.h b/src/platform/stm32/platform_conf.h index b89dc485..48ede866 100755 --- a/src/platform/stm32/platform_conf.h +++ b/src/platform/stm32/platform_conf.h @@ -112,6 +112,7 @@ #define NUM_SPI 2 #define NUM_UART 5 #define NUM_TIMER 5 +#define NUM_PHYS_TIMER 5 #define NUM_PWM 4 #define NUM_ADC 16 #define NUM_CAN 1 diff --git a/src/platform/stm32/platform_int.c b/src/platform/stm32/platform_int.c index d53ea44f..a4e52e5e 100644 --- a/src/platform/stm32/platform_int.c +++ b/src/platform/stm32/platform_int.c @@ -9,6 +9,10 @@ // Platform-specific headers #include "stm32f10x.h" +#ifndef VTMR_TIMER_ID +#define VTMR_TIMER_ID ( -1 ) +#endif + // **************************************************************************** // Interrupt handlers @@ -128,6 +132,56 @@ void EXTI15_10_IRQHandler() } } +// ---------------------------------------------------------------------------- +// Timer interrupt handlers + +const TIM_TypeDef * const timer[] = { TIM1, TIM2, TIM3, TIM4, TIM5 }; +extern u8 stm32_timer_int_periodic_flag[ NUM_PHYS_TIMER ]; + +static void tmr_int_handler( int id ) +{ + TIM_TypeDef *base = ( TIM_TypeDef* )timer[ id ]; + + TIM_ClearITPendingBit( base, TIM_IT_CC1 ); + if( id == VTMR_TIMER_ID ) + cmn_virtual_timer_cb(); + else + cmn_int_handler( INT_TMR_MATCH, id ); + if( stm32_timer_int_periodic_flag[ id ] != PLATFORM_TIMER_INT_CYCLIC )\ + TIM_ITConfig( base, TIM_IT_CC1, DISABLE ); +} + + +void TIM1_CC_IRQHandler(void) +{ + tmr_int_handler( 0 ); +} + +void TIM2_IRQHandler(void) +{ + tmr_int_handler( 1 ); +} + +void TIM3_IRQHandler(void) +{ + tmr_int_handler( 2 ); +} + +void TIM4_IRQHandler(void) +{ + tmr_int_handler( 3 ); +} + +void TIM5_IRQHandler(void) +{ + tmr_int_handler( 4 ); +} + +void TIM8_CC_IRQHandler(void) +{ + tmr_int_handler( 7 ); +} + // **************************************************************************** // GPIO helper functions @@ -234,19 +288,30 @@ static int int_gpio_negedge_get_flag( elua_int_resnum resnum, int clear ) // **************************************************************************** // Interrupt: INT_TMR_MATCH -static int int_tmr_match_set_status( elua_int_resnum resnum, int status ) -{ - return PLATFORM_INT_NOT_HANDLED; -} - static int int_tmr_match_get_status( elua_int_resnum resnum ) { - return PLATFORM_INT_NOT_HANDLED; + TIM_TypeDef *base = ( TIM_TypeDef* )timer[ resnum ]; + + return ( base->DIER & TIM_IT_CC1 ) != 0; +} + +static int int_tmr_match_set_status( elua_int_resnum resnum, int status ) +{ + int previous = int_tmr_match_get_status( resnum ); + TIM_TypeDef *base = ( TIM_TypeDef* )timer[ resnum ]; + + TIM_ITConfig( base, TIM_IT_CC1, status == PLATFORM_CPU_ENABLE ? ENABLE : DISABLE ); + return previous; } static int int_tmr_match_get_flag( elua_int_resnum resnum, int clear ) { - return PLATFORM_INT_NOT_HANDLED; + TIM_TypeDef *base = ( TIM_TypeDef* )timer[ resnum ]; + int status = TIM_GetFlagStatus( base, TIM_FLAG_CC1 ); + + if( clear ) + TIM_ClearFlag( base, TIM_FLAG_CC1 ); + return status; } // **************************************************************************** @@ -287,6 +352,15 @@ static const u8 uart_irq_table[] = { USART1_IRQn, USART2_IRQn, USART3_IRQn, UART // EXTI IRQ table static const u8 exti_irq_table[] = { EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, EXTI9_5_IRQn, EXTI15_10_IRQn }; +// EXTI IRQ table +#if defined( STM32F10X_LD ) +static const u8 timer_irq_table[] = { TIM1_CC_IRQn, TIM2_IRQn, TIM3_IRQn }; +#elseif defined( STM32F10X_MD ) +static const u8 timer_irq_table[] = { TIM1_CC_IRQn, TIM2_IRQn, TIM3_IRQn, TIM4_IRQn }; +#else +static const u8 timer_irq_table[] = { TIM1_CC_IRQn, TIM2_IRQn, TIM3_IRQn, TIM4_IRQn, TIM5_IRQn }; +#endif + void platform_int_init() { NVIC_InitTypeDef nvic_init_structure; @@ -295,7 +369,8 @@ void platform_int_init() // Enable all USART interrupts in the NVIC nvic_init_structure.NVIC_IRQChannelPreemptionPriority = 0; nvic_init_structure.NVIC_IRQChannelSubPriority = 0; - nvic_init_structure.NVIC_IRQChannelCmd = ENABLE; + nvic_init_structure.NVIC_IRQChannelCmd = ENABLE; + for( i = 0; i < sizeof( uart_irq_table ) / sizeof( u8 ); i ++ ) { nvic_init_structure.NVIC_IRQChannel = uart_irq_table[ i ]; @@ -309,6 +384,15 @@ void platform_int_init() NVIC_Init( &nvic_init_structure ); } +#ifdef INT_TMR_MATCH + for( i = 0; i < sizeof( timer_irq_table ) / sizeof( u8 ); i ++ ) + { + nvic_init_structure.NVIC_IRQChannel = timer_irq_table[ i ]; + nvic_init_structure.NVIC_IRQChannelSubPriority = 1; + NVIC_Init( &nvic_init_structure ); + } +#endif + } // ****************************************************************************