From d7cd1d2027504278a58795eefab41c80ea14d5e9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 13 Sep 2017 16:20:42 +1000 Subject: [PATCH] stm32/timer: Make pyb.Timer() instances persistent. Prior to this patch calling pyb.Timer(id) would always create a new timer instance, even if there was an existing one. This patch fixes this behaviour to match other peripherals, like UART, such that constructing a timer with just the id will retrieve any existing instances. The patch also refactors the way timers are validated on construction to simplify and reduce code size. --- ports/stm32/mpconfigport.h | 6 +- ports/stm32/timer.c | 142 ++++++++++++++++++++----------------- 2 files changed, 81 insertions(+), 67 deletions(-) diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h index 21142c17b393..abeaa56f6e58 100644 --- a/ports/stm32/mpconfigport.h +++ b/ports/stm32/mpconfigport.h @@ -232,9 +232,11 @@ extern const struct _mp_obj_module_t mp_module_onewire; #if defined(MCU_SERIES_F7) #define PYB_EXTI_NUM_VECTORS (24) +#define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (8) #else #define PYB_EXTI_NUM_VECTORS (23) +#define MICROPY_HW_MAX_TIMER (14) #define MICROPY_HW_MAX_UART (6) #endif @@ -254,8 +256,8 @@ extern const struct _mp_obj_module_t mp_module_onewire; \ mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \ \ - /* Used to do callbacks to Python code on interrupt */ \ - struct _pyb_timer_obj_t *pyb_timer_obj_all[14]; \ + /* pointers to all Timer objects (if they have been created) */ \ + struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]; \ \ /* stdio is repeated on this UART object if it's not null */ \ struct _pyb_uart_obj_t *pyb_stdio_uart; \ diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 00e9c2a83a9c..f24c2e6bfadb 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -629,6 +629,62 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons return mp_const_none; } +// This table encodes the timer instance and irq number. +// It assumes that timer instance pointer has the lower 8 bits cleared. +#define TIM_ENTRY(id, irq) [id - 1] = (uint32_t)TIM##id | irq +STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { + #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) + TIM_ENTRY(1, TIM1_UP_TIM10_IRQn), + #elif defined(MCU_SERIES_L4) + TIM_ENTRY(1, TIM1_UP_TIM16_IRQn), + #endif + TIM_ENTRY(2, TIM2_IRQn), + TIM_ENTRY(3, TIM3_IRQn), + TIM_ENTRY(4, TIM4_IRQn), + TIM_ENTRY(5, TIM5_IRQn), + #if defined(TIM6) + TIM_ENTRY(6, TIM6_DAC_IRQn), + #endif + #if defined(TIM7) + TIM_ENTRY(7, TIM7_IRQn), + #endif + #if defined(TIM8) + #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) + TIM_ENTRY(8, TIM8_UP_TIM13_IRQn), + #elif defined(MCU_SERIES_L4) + TIM_ENTRY(8, TIM8_UP_IRQn), + #endif + #endif + #if defined(TIM9) + TIM_ENTRY(9, TIM1_BRK_TIM9_IRQn), + #endif + #if defined(TIM10) + TIM_ENTRY(10, TIM1_UP_TIM10_IRQn), + #endif + #if defined(TIM11) + TIM_ENTRY(11, TIM1_TRG_COM_TIM11_IRQn), + #endif + #if defined(TIM12) + TIM_ENTRY(12, TIM8_BRK_TIM12_IRQn), + #endif + #if defined(TIM13) + TIM_ENTRY(13, TIM8_UP_TIM13_IRQn), + #endif + #if defined(TIM14) + TIM_ENTRY(14, TIM8_TRG_COM_TIM14_IRQn), + #endif + #if defined(TIM15) + TIM_ENTRY(15, TIM1_BRK_TIM15_IRQn), + #endif + #if defined(TIM16) + TIM_ENTRY(16, TIM1_UP_TIM16_IRQn), + #endif + #if defined(TIM17) + TIM_ENTRY(17, TIM1_TRG_COM_TIM17_IRQn), + #endif +}; +#undef TIM_ENTRY + /// \classmethod \constructor(id, ...) /// Construct a new timer object of the given id. If additional /// arguments are given, then the timer is initialised by `init(...)`. @@ -637,74 +693,30 @@ STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, siz // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - // create new Timer object - pyb_timer_obj_t *tim = m_new_obj(pyb_timer_obj_t); - memset(tim, 0, sizeof(*tim)); - - tim->base.type = &pyb_timer_type; - tim->callback = mp_const_none; - tim->channel = NULL; - - // get TIM number - tim->tim_id = mp_obj_get_int(args[0]); - tim->is_32bit = false; + // get the timer id + mp_int_t tim_id = mp_obj_get_int(args[0]); - switch (tim->tim_id) { - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) - case 1: tim->tim.Instance = TIM1; tim->irqn = TIM1_UP_TIM10_IRQn; break; - #elif defined(MCU_SERIES_L4) - case 1: tim->tim.Instance = TIM1; tim->irqn = TIM1_UP_TIM16_IRQn; break; - #endif - case 2: tim->tim.Instance = TIM2; tim->irqn = TIM2_IRQn; tim->is_32bit = true; break; - case 3: tim->tim.Instance = TIM3; tim->irqn = TIM3_IRQn; break; - case 4: tim->tim.Instance = TIM4; tim->irqn = TIM4_IRQn; break; - case 5: tim->tim.Instance = TIM5; tim->irqn = TIM5_IRQn; tim->is_32bit = true; break; - #if defined(TIM6) - case 6: tim->tim.Instance = TIM6; tim->irqn = TIM6_DAC_IRQn; break; - #endif - #if defined(TIM7) - case 7: tim->tim.Instance = TIM7; tim->irqn = TIM7_IRQn; break; - #endif - #if defined(TIM8) - #if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7) - case 8: tim->tim.Instance = TIM8; tim->irqn = TIM8_UP_TIM13_IRQn; break; - #elif defined(MCU_SERIES_L4) - case 8: tim->tim.Instance = TIM8; tim->irqn = TIM8_UP_IRQn; break; - #endif - #endif - #if defined(TIM9) - case 9: tim->tim.Instance = TIM9; tim->irqn = TIM1_BRK_TIM9_IRQn; break; - #endif - #if defined(TIM10) - case 10: tim->tim.Instance = TIM10; tim->irqn = TIM1_UP_TIM10_IRQn; break; - #endif - #if defined(TIM11) - case 11: tim->tim.Instance = TIM11; tim->irqn = TIM1_TRG_COM_TIM11_IRQn; break; - #endif - #if defined(TIM12) - case 12: tim->tim.Instance = TIM12; tim->irqn = TIM8_BRK_TIM12_IRQn; break; - #endif - #if defined(TIM13) - case 13: tim->tim.Instance = TIM13; tim->irqn = TIM8_UP_TIM13_IRQn; break; - #endif - #if defined(TIM14) - case 14: tim->tim.Instance = TIM14; tim->irqn = TIM8_TRG_COM_TIM14_IRQn; break; - #endif - #if defined(TIM15) - case 15: tim->tim.Instance = TIM15; tim->irqn = TIM1_BRK_TIM15_IRQn; break; - #endif - #if defined(TIM16) - case 16: tim->tim.Instance = TIM16; tim->irqn = TIM1_UP_TIM16_IRQn; break; - #endif - #if defined(TIM17) - case 17: tim->tim.Instance = TIM17; tim->irqn = TIM1_TRG_COM_TIM17_IRQn; break; - #endif - default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Timer(%d) doesn't exist", tim->tim_id)); + // check if the timer exists + if (tim_id <= 0 || tim_id > MICROPY_HW_MAX_TIMER || tim_instance_table[tim_id - 1] == 0) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Timer(%d) doesn't exist", tim_id)); } - // set the global variable for interrupt callbacks - if (tim->tim_id - 1 < PYB_TIMER_OBJ_ALL_NUM) { - MP_STATE_PORT(pyb_timer_obj_all)[tim->tim_id - 1] = tim; + pyb_timer_obj_t *tim; + if (MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1] == NULL) { + // create new Timer object + tim = m_new_obj(pyb_timer_obj_t); + memset(tim, 0, sizeof(*tim)); + tim->base.type = &pyb_timer_type; + tim->tim_id = tim_id; + tim->is_32bit = tim_id == 2 || tim_id == 5; + tim->callback = mp_const_none; + uint32_t ti = tim_instance_table[tim_id - 1]; + tim->tim.Instance = (TIM_TypeDef*)(ti & 0xffffff00); + tim->irqn = ti & 0xff; + MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1] = tim; + } else { + // reference existing Timer object + tim = MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1]; } if (n_args > 1 || n_kw > 0) {