From c6983e3ce0bb9708afabb9fb7cbdf54ba46fb594 Mon Sep 17 00:00:00 2001 From: Dave Hylands Date: Thu, 18 Aug 2016 20:47:49 -0700 Subject: [PATCH 1/5] stmhal: Fix timer capture/compare interrupt handling for TIM1 and TIM8. It turns out that TIM1 and TIM8 have their own Capture/Compare interrupt vector. For all of the other timers, the capture/compare interrupt vector is the same as the update vector. So we need to add handlers for these vectors and enable them when using capture/compare callbacks. During testing of this, I also found that passing a channel callback into the channel constructor would not enable interrupts properly. I tested using: ``` >>> pyb.Timer(1, freq=4).channel(1, pyb.Timer.OC_TOGGLE, callback=lambda t: print('.', end='')) ``` I tested the above with channels 1, 4, and 8 --- stmhal/stm32_it.c | 18 ++++++++++++++++++ stmhal/timer.c | 24 ++++++++++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/stmhal/stm32_it.c b/stmhal/stm32_it.c index c9af20ce58..d2f8c271c4 100644 --- a/stmhal/stm32_it.c +++ b/stmhal/stm32_it.c @@ -556,6 +556,12 @@ void TIM1_TRG_COM_TIM17_IRQHandler(void) { } #endif +void TIM1_CC_IRQHandler(void) { + IRQ_ENTER(TIM1_CC_IRQn); + timer_irq_handler(1); + IRQ_EXIT(TIM1_CC_IRQn); +} + void TIM2_IRQHandler(void) { IRQ_ENTER(TIM2_IRQn); timer_irq_handler(2); @@ -581,18 +587,23 @@ void TIM5_IRQHandler(void) { IRQ_EXIT(TIM5_IRQn); } +#if defined(TIM6) // STM32F401 doesn't have TIM6 void TIM6_DAC_IRQHandler(void) { IRQ_ENTER(TIM6_DAC_IRQn); timer_irq_handler(6); IRQ_EXIT(TIM6_DAC_IRQn); } +#endif +#if defined(TIM7) // STM32F401 doesn't have TIM7 void TIM7_IRQHandler(void) { IRQ_ENTER(TIM7_IRQn); timer_irq_handler(7); IRQ_EXIT(TIM7_IRQn); } +#endif +#if defined(TIM8) // STM32F401 doesn't have TIM8 void TIM8_BRK_TIM12_IRQHandler(void) { IRQ_ENTER(TIM8_BRK_TIM12_IRQn); timer_irq_handler(12); @@ -614,11 +625,18 @@ void TIM8_UP_IRQHandler(void) { } #endif +void TIM8_CC_IRQHandler(void) { + IRQ_ENTER(TIM8_CC_IRQn); + timer_irq_handler(8); + IRQ_EXIT(TIM8_CC_IRQn); +} + void TIM8_TRG_COM_TIM14_IRQHandler(void) { IRQ_ENTER(TIM8_TRG_COM_TIM14_IRQn); timer_irq_handler(14); IRQ_EXIT(TIM8_TRG_COM_TIM14_IRQn); } +#endif // UART/USART IRQ handlers void USART1_IRQHandler(void) { diff --git a/stmhal/timer.c b/stmhal/timer.c index f1f14f3315..e8b29eb97f 100644 --- a/stmhal/timer.c +++ b/stmhal/timer.c @@ -603,6 +603,13 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, mp_uint_t n_args, c // set IRQ priority (if not a special timer) if (self->tim_id != 3 && self->tim_id != 5) { HAL_NVIC_SetPriority(self->irqn, IRQ_PRI_TIMX, IRQ_SUBPRI_TIMX); + if (self->tim_id == 1) { + HAL_NVIC_SetPriority(TIM1_CC_IRQn, IRQ_PRI_TIMX, IRQ_SUBPRI_TIMX); + #if defined(TIM8) + } else if (self->tim_id == 8) { + HAL_NVIC_SetPriority(TIM8_CC_IRQn, IRQ_PRI_TIMX, IRQ_SUBPRI_TIMX); + #endif + } } // init TIM @@ -932,7 +939,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp if (chan->callback == mp_const_none) { HAL_TIM_PWM_Start(&self->tim, TIMER_CHANNEL(chan)); } else { - HAL_TIM_PWM_Start_IT(&self->tim, TIMER_CHANNEL(chan)); + pyb_timer_channel_callback(chan, chan->callback); } // Start the complimentary channel too (if its supported) if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) { @@ -970,7 +977,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp if (chan->callback == mp_const_none) { HAL_TIM_OC_Start(&self->tim, TIMER_CHANNEL(chan)); } else { - HAL_TIM_OC_Start_IT(&self->tim, TIMER_CHANNEL(chan)); + pyb_timer_channel_callback(chan, chan->callback); } // Start the complimentary channel too (if its supported) if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) { @@ -997,7 +1004,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp if (chan->callback == mp_const_none) { HAL_TIM_IC_Start(&self->tim, TIMER_CHANNEL(chan)); } else { - HAL_TIM_IC_Start_IT(&self->tim, TIMER_CHANNEL(chan)); + pyb_timer_channel_callback(chan, chan->callback); } break; } @@ -1294,7 +1301,16 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback) self->callback = mp_const_none; } else if (mp_obj_is_callable(callback)) { self->callback = callback; - HAL_NVIC_EnableIRQ(self->timer->irqn); + uint8_t tim_id = self->timer->tim_id; + if (tim_id == 1) { + HAL_NVIC_EnableIRQ(TIM1_CC_IRQn); + #if defined(TIM8) // STM32F401 doesn't have a TIM8 + } else if (tim_id == 8) { + HAL_NVIC_EnableIRQ(TIM8_CC_IRQn); + #endif + } else { + HAL_NVIC_EnableIRQ(self->timer->irqn); + } // start timer, so that it interrupts on overflow switch (self->mode) { case CHANNEL_MODE_PWM_NORMAL: From d2d9dfcd40caafa99177ca36bd3e3faf52ee05b3 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 22 Aug 2016 12:24:49 +1000 Subject: [PATCH 2/5] stmhal: Remove obsolete code for special handling of TIM3 irq settings. TIM3 is no longer special, or at least does not have special IRQ settings. --- stmhal/irq.h | 3 --- stmhal/timer.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/stmhal/irq.h b/stmhal/irq.h index f3a8a2cc9e..5a08a7d501 100644 --- a/stmhal/irq.h +++ b/stmhal/irq.h @@ -126,9 +126,6 @@ MP_DECLARE_CONST_FUN_OBJ(pyb_irq_stats_obj); #define IRQ_PRI_OTG_HS 6 #define IRQ_SUBPRI_OTG_HS 0 -#define IRQ_PRI_TIM3 6 -#define IRQ_SUBPRI_TIM3 0 - #define IRQ_PRI_TIM5 6 #define IRQ_SUBPRI_TIM5 0 diff --git a/stmhal/timer.c b/stmhal/timer.c index e8b29eb97f..5727a95b73 100644 --- a/stmhal/timer.c +++ b/stmhal/timer.c @@ -601,7 +601,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, mp_uint_t n_args, c } // set IRQ priority (if not a special timer) - if (self->tim_id != 3 && self->tim_id != 5) { + if (self->tim_id != 5) { HAL_NVIC_SetPriority(self->irqn, IRQ_PRI_TIMX, IRQ_SUBPRI_TIMX); if (self->tim_id == 1) { HAL_NVIC_SetPriority(TIM1_CC_IRQn, IRQ_PRI_TIMX, IRQ_SUBPRI_TIMX); From 253e1a6f6771c09db742c22a25ab53ffbd68eab2 Mon Sep 17 00:00:00 2001 From: Dave Hylands Date: Fri, 19 Aug 2016 21:09:52 -0700 Subject: [PATCH 3/5] teensy: Fix execution of frozen boot.py and main.py --- teensy/main.c | 4 ++-- teensy/memzip_files/main.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/teensy/main.c b/teensy/main.c index 41e445cb59..890ee81493 100644 --- a/teensy/main.c +++ b/teensy/main.c @@ -302,7 +302,7 @@ soft_reset: #endif #if MICROPY_MODULE_FROZEN - pyexec_frozen_module("boot"); + pyexec_frozen_module("boot.py"); #else if (!pyexec_file("/boot.py")) { flash_error(4); @@ -314,7 +314,7 @@ soft_reset: // run main script #if MICROPY_MODULE_FROZEN - pyexec_frozen_module("main"); + pyexec_frozen_module("main.py"); #else { vstr_t *vstr = vstr_new(); diff --git a/teensy/memzip_files/main.py b/teensy/memzip_files/main.py index 4f30f2fc5f..b652377f97 100644 --- a/teensy/memzip_files/main.py +++ b/teensy/memzip_files/main.py @@ -1,3 +1,5 @@ +import pyb + print("Executing main.py") led = pyb.LED(1) From 5a5449d4eb46465e5d47fb20104e13122ea4110b Mon Sep 17 00:00:00 2001 From: Krzysztof Blazewicz Date: Sat, 20 Aug 2016 16:59:53 +0200 Subject: [PATCH 4/5] extmod/modbtree: do CHECK_ERROR after __bt_seq() In `btree_seq()`, when `__bt_seq()` gets called with invalid `flags` argument it will return `RET_ERROR` and it won't initialize `val`. If field `data` of uninitialized `val` is passed to `mp_obj_new_bytes()` it causes a segfault. --- extmod/modbtree.c | 1 + 1 file changed, 1 insertion(+) diff --git a/extmod/modbtree.c b/extmod/modbtree.c index f21e7e4421..ea2ea582c8 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -133,6 +133,7 @@ STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) { } int res = __bt_seq(self->db, &key, &val, flags); + CHECK_ERROR(res); if (res == RET_SPECIAL) { return mp_const_none; } From 656207645485295477411224fdf41cfd4d598a88 Mon Sep 17 00:00:00 2001 From: Krzysztof Blazewicz Date: Sat, 20 Aug 2016 13:45:25 +0200 Subject: [PATCH 5/5] py/stream.c: use mp_obj_get_type in mp_get_stream_raise In current state `mp_get_stream_raise` assumes that `self_in` is an object and always performs a pointer derefence which may cause a segfault. This function shall throw an exception whenever `self_in` does not implement a stream protocol, that includes qstr's and numbers. fixes #2331 --- py/stream.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/py/stream.c b/py/stream.c index 473eb96904..eef9080b7b 100644 --- a/py/stream.c +++ b/py/stream.c @@ -94,8 +94,8 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode } const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { - mp_obj_base_t *o = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); - const mp_stream_p_t *stream_p = o->type->protocol; + mp_obj_type_t *type = mp_obj_get_type(self_in); + const mp_stream_p_t *stream_p = type->protocol; if (stream_p == NULL || ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) @@ -167,7 +167,7 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl // TODO what if we have read only half a non-ASCII char? vstr_cut_tail_bytes(&vstr, more_bytes - out_sz); if (out_sz == 0) { - break; + break; } }