diff options
author | Damien <damien.p.george@gmail.com> | 2013-11-06 23:04:33 +0000 |
---|---|---|
committer | Damien <damien.p.george@gmail.com> | 2013-11-06 23:04:33 +0000 |
commit | bd8e110207ad6a03134b5ae8c12053778649fc8f (patch) | |
tree | 9903217ac3b4875c3c4e6d3ecc89525300b80aa8 /stm/timer.c | |
parent | f72fd0e875a67576e2e93285877bee8e0e5147ad (diff) |
Add to STM code timer functionality to call Python on interrupt.
Diffstat (limited to 'stm/timer.c')
-rw-r--r-- | stm/timer.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/stm/timer.c b/stm/timer.c new file mode 100644 index 000000000..31807d0ce --- /dev/null +++ b/stm/timer.c @@ -0,0 +1,90 @@ +#include <stdint.h> +#include <stdio.h> + +#include "stm_misc.h" +#include "stm32f4xx_rcc.h" +#include "stm32f4xx_tim.h" + +#include "nlr.h" +#include "misc.h" +#include "mpyconfig.h" +#include "parse.h" +#include "compile.h" +#include "runtime.h" + +#include "timer.h" + +// TIM6 is used as an internal interrup to schedule something at a specific rate +py_obj_t timer_py_callback; + +py_obj_t timer_py_set_callback(py_obj_t f) { + timer_py_callback = f; + return py_const_none; +} + +py_obj_t timer_py_set_period(py_obj_t period) { + TIM6->ARR = py_obj_get_int(period) & 0xffff; + //TIM6->PSC = prescaler & 0xffff; + return py_const_none; +} + +py_obj_t timer_py_get_value(void) { + return py_obj_new_int(TIM6->CNT & 0xfffff); +} + +void timer_init(void) { + timer_py_callback = py_const_none; + + // TIM6 clock enable + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); + + // Compute the prescaler value so TIM6 runs at 10kHz + uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 10000) - 1; + + // Time base configuration + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + TIM_TimeBaseStructure.TIM_Period = 10000; // timer cycles at 1Hz + TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; + TIM_TimeBaseStructure.TIM_ClockDivision = 0; // unused for TIM6 + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // unused for TIM6 + TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); + + // enable perhipheral preload register + TIM_ARRPreloadConfig(TIM6, ENABLE); + + // enable interrupt when counter overflows + TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); + + // set up interrupt + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0f; // lowest priority + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0f; // lowest priority + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + // TIM6 enable counter + TIM_Cmd(TIM6, ENABLE); + + // Python interface + py_obj_t m = py_module_new(); + rt_store_attr(m, qstr_from_str_static("callback"), rt_make_function_1(timer_py_set_callback)); + rt_store_attr(m, qstr_from_str_static("period"), rt_make_function_1(timer_py_set_period)); + rt_store_attr(m, qstr_from_str_static("value"), rt_make_function_0(timer_py_get_value)); + rt_store_name(qstr_from_str_static("timer"), m); +} + +void timer_interrupt(void) { + if (timer_py_callback != py_const_none) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + rt_call_function_0(timer_py_callback); + nlr_pop(); + } else { + // uncaught exception + printf("exception in timer interrupt\n"); + py_obj_print((py_obj_t)nlr.ret_val); + printf("\n"); + } + } +} |