Skip to content

Commit d7cd1d2

Browse files
committed
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.
1 parent da8c4c2 commit d7cd1d2

2 files changed

Lines changed: 81 additions & 67 deletions

File tree

ports/stm32/mpconfigport.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,11 @@ extern const struct _mp_obj_module_t mp_module_onewire;
232232

233233
#if defined(MCU_SERIES_F7)
234234
#define PYB_EXTI_NUM_VECTORS (24)
235+
#define MICROPY_HW_MAX_TIMER (17)
235236
#define MICROPY_HW_MAX_UART (8)
236237
#else
237238
#define PYB_EXTI_NUM_VECTORS (23)
239+
#define MICROPY_HW_MAX_TIMER (14)
238240
#define MICROPY_HW_MAX_UART (6)
239241
#endif
240242

@@ -254,8 +256,8 @@ extern const struct _mp_obj_module_t mp_module_onewire;
254256
\
255257
mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \
256258
\
257-
/* Used to do callbacks to Python code on interrupt */ \
258-
struct _pyb_timer_obj_t *pyb_timer_obj_all[14]; \
259+
/* pointers to all Timer objects (if they have been created) */ \
260+
struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]; \
259261
\
260262
/* stdio is repeated on this UART object if it's not null */ \
261263
struct _pyb_uart_obj_t *pyb_stdio_uart; \

ports/stm32/timer.c

Lines changed: 77 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,62 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons
629629
return mp_const_none;
630630
}
631631

632+
// This table encodes the timer instance and irq number.
633+
// It assumes that timer instance pointer has the lower 8 bits cleared.
634+
#define TIM_ENTRY(id, irq) [id - 1] = (uint32_t)TIM##id | irq
635+
STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = {
636+
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
637+
TIM_ENTRY(1, TIM1_UP_TIM10_IRQn),
638+
#elif defined(MCU_SERIES_L4)
639+
TIM_ENTRY(1, TIM1_UP_TIM16_IRQn),
640+
#endif
641+
TIM_ENTRY(2, TIM2_IRQn),
642+
TIM_ENTRY(3, TIM3_IRQn),
643+
TIM_ENTRY(4, TIM4_IRQn),
644+
TIM_ENTRY(5, TIM5_IRQn),
645+
#if defined(TIM6)
646+
TIM_ENTRY(6, TIM6_DAC_IRQn),
647+
#endif
648+
#if defined(TIM7)
649+
TIM_ENTRY(7, TIM7_IRQn),
650+
#endif
651+
#if defined(TIM8)
652+
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
653+
TIM_ENTRY(8, TIM8_UP_TIM13_IRQn),
654+
#elif defined(MCU_SERIES_L4)
655+
TIM_ENTRY(8, TIM8_UP_IRQn),
656+
#endif
657+
#endif
658+
#if defined(TIM9)
659+
TIM_ENTRY(9, TIM1_BRK_TIM9_IRQn),
660+
#endif
661+
#if defined(TIM10)
662+
TIM_ENTRY(10, TIM1_UP_TIM10_IRQn),
663+
#endif
664+
#if defined(TIM11)
665+
TIM_ENTRY(11, TIM1_TRG_COM_TIM11_IRQn),
666+
#endif
667+
#if defined(TIM12)
668+
TIM_ENTRY(12, TIM8_BRK_TIM12_IRQn),
669+
#endif
670+
#if defined(TIM13)
671+
TIM_ENTRY(13, TIM8_UP_TIM13_IRQn),
672+
#endif
673+
#if defined(TIM14)
674+
TIM_ENTRY(14, TIM8_TRG_COM_TIM14_IRQn),
675+
#endif
676+
#if defined(TIM15)
677+
TIM_ENTRY(15, TIM1_BRK_TIM15_IRQn),
678+
#endif
679+
#if defined(TIM16)
680+
TIM_ENTRY(16, TIM1_UP_TIM16_IRQn),
681+
#endif
682+
#if defined(TIM17)
683+
TIM_ENTRY(17, TIM1_TRG_COM_TIM17_IRQn),
684+
#endif
685+
};
686+
#undef TIM_ENTRY
687+
632688
/// \classmethod \constructor(id, ...)
633689
/// Construct a new timer object of the given id. If additional
634690
/// 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
637693
// check arguments
638694
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
639695

640-
// create new Timer object
641-
pyb_timer_obj_t *tim = m_new_obj(pyb_timer_obj_t);
642-
memset(tim, 0, sizeof(*tim));
643-
644-
tim->base.type = &pyb_timer_type;
645-
tim->callback = mp_const_none;
646-
tim->channel = NULL;
647-
648-
// get TIM number
649-
tim->tim_id = mp_obj_get_int(args[0]);
650-
tim->is_32bit = false;
696+
// get the timer id
697+
mp_int_t tim_id = mp_obj_get_int(args[0]);
651698

652-
switch (tim->tim_id) {
653-
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
654-
case 1: tim->tim.Instance = TIM1; tim->irqn = TIM1_UP_TIM10_IRQn; break;
655-
#elif defined(MCU_SERIES_L4)
656-
case 1: tim->tim.Instance = TIM1; tim->irqn = TIM1_UP_TIM16_IRQn; break;
657-
#endif
658-
case 2: tim->tim.Instance = TIM2; tim->irqn = TIM2_IRQn; tim->is_32bit = true; break;
659-
case 3: tim->tim.Instance = TIM3; tim->irqn = TIM3_IRQn; break;
660-
case 4: tim->tim.Instance = TIM4; tim->irqn = TIM4_IRQn; break;
661-
case 5: tim->tim.Instance = TIM5; tim->irqn = TIM5_IRQn; tim->is_32bit = true; break;
662-
#if defined(TIM6)
663-
case 6: tim->tim.Instance = TIM6; tim->irqn = TIM6_DAC_IRQn; break;
664-
#endif
665-
#if defined(TIM7)
666-
case 7: tim->tim.Instance = TIM7; tim->irqn = TIM7_IRQn; break;
667-
#endif
668-
#if defined(TIM8)
669-
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
670-
case 8: tim->tim.Instance = TIM8; tim->irqn = TIM8_UP_TIM13_IRQn; break;
671-
#elif defined(MCU_SERIES_L4)
672-
case 8: tim->tim.Instance = TIM8; tim->irqn = TIM8_UP_IRQn; break;
673-
#endif
674-
#endif
675-
#if defined(TIM9)
676-
case 9: tim->tim.Instance = TIM9; tim->irqn = TIM1_BRK_TIM9_IRQn; break;
677-
#endif
678-
#if defined(TIM10)
679-
case 10: tim->tim.Instance = TIM10; tim->irqn = TIM1_UP_TIM10_IRQn; break;
680-
#endif
681-
#if defined(TIM11)
682-
case 11: tim->tim.Instance = TIM11; tim->irqn = TIM1_TRG_COM_TIM11_IRQn; break;
683-
#endif
684-
#if defined(TIM12)
685-
case 12: tim->tim.Instance = TIM12; tim->irqn = TIM8_BRK_TIM12_IRQn; break;
686-
#endif
687-
#if defined(TIM13)
688-
case 13: tim->tim.Instance = TIM13; tim->irqn = TIM8_UP_TIM13_IRQn; break;
689-
#endif
690-
#if defined(TIM14)
691-
case 14: tim->tim.Instance = TIM14; tim->irqn = TIM8_TRG_COM_TIM14_IRQn; break;
692-
#endif
693-
#if defined(TIM15)
694-
case 15: tim->tim.Instance = TIM15; tim->irqn = TIM1_BRK_TIM15_IRQn; break;
695-
#endif
696-
#if defined(TIM16)
697-
case 16: tim->tim.Instance = TIM16; tim->irqn = TIM1_UP_TIM16_IRQn; break;
698-
#endif
699-
#if defined(TIM17)
700-
case 17: tim->tim.Instance = TIM17; tim->irqn = TIM1_TRG_COM_TIM17_IRQn; break;
701-
#endif
702-
default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Timer(%d) doesn't exist", tim->tim_id));
699+
// check if the timer exists
700+
if (tim_id <= 0 || tim_id > MICROPY_HW_MAX_TIMER || tim_instance_table[tim_id - 1] == 0) {
701+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Timer(%d) doesn't exist", tim_id));
703702
}
704703

705-
// set the global variable for interrupt callbacks
706-
if (tim->tim_id - 1 < PYB_TIMER_OBJ_ALL_NUM) {
707-
MP_STATE_PORT(pyb_timer_obj_all)[tim->tim_id - 1] = tim;
704+
pyb_timer_obj_t *tim;
705+
if (MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1] == NULL) {
706+
// create new Timer object
707+
tim = m_new_obj(pyb_timer_obj_t);
708+
memset(tim, 0, sizeof(*tim));
709+
tim->base.type = &pyb_timer_type;
710+
tim->tim_id = tim_id;
711+
tim->is_32bit = tim_id == 2 || tim_id == 5;
712+
tim->callback = mp_const_none;
713+
uint32_t ti = tim_instance_table[tim_id - 1];
714+
tim->tim.Instance = (TIM_TypeDef*)(ti & 0xffffff00);
715+
tim->irqn = ti & 0xff;
716+
MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1] = tim;
717+
} else {
718+
// reference existing Timer object
719+
tim = MP_STATE_PORT(pyb_timer_obj_all)[tim_id - 1];
708720
}
709721

710722
if (n_args > 1 || n_kw > 0) {

0 commit comments

Comments
 (0)