From bd8e110207ad6a03134b5ae8c12053778649fc8f Mon Sep 17 00:00:00 2001 From: Damien Date: Wed, 6 Nov 2013 23:04:33 +0000 Subject: [PATCH] Add to STM code timer functionality to call Python on interrupt. --- stm/Makefile | 1 + stm/audio.c | 4 +-- stm/main.c | 12 +++++-- stm/stm32fxxx_it.c | 15 ++++++++ stm/timer.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++ stm/timer.h | 1 + 6 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 stm/timer.c create mode 100644 stm/timer.h diff --git a/stm/Makefile b/stm/Makefile index 6203e9f4af..3752e694ab 100644 --- a/stm/Makefile +++ b/stm/Makefile @@ -26,6 +26,7 @@ SRC_C = \ usart.c \ usb.c \ sdio.c \ + timer.c \ audio.c \ lexerstm.c \ diff --git a/stm/audio.c b/stm/audio.c index 2df4e07941..41614416e2 100644 --- a/stm/audio.c +++ b/stm/audio.c @@ -6,13 +6,13 @@ #include "nlr.h" #include "misc.h" -//#include "lexer.h" -//#include "lexerstm.h" #include "mpyconfig.h" #include "parse.h" #include "compile.h" #include "runtime.h" +#include "audio.h" + #define SAMPLE_BUF_SIZE (32) // sample_buf_in is always the same or ahead of sample_buf_out diff --git a/stm/main.c b/stm/main.c index 996684cb89..4184b389ca 100644 --- a/stm/main.c +++ b/stm/main.c @@ -20,6 +20,7 @@ #include "usart.h" #include "usb.h" #include "ff.h" +#include "timer.h" #include "audio.h" static FATFS fatfs0; @@ -525,7 +526,7 @@ py_obj_t pyb_pwm_set(py_obj_t period, py_obj_t pulse) { #define MMA_ADDR (0x4c) -py_obj_t pyb_mma_read() { +py_obj_t pyb_mma_read(void) { mma_start(MMA_ADDR, 1); mma_send_byte(0); mma_restart(MMA_ADDR, 0); @@ -731,6 +732,8 @@ int main(void) { storage_init(); usart_init(); + int first_soft_reset = true; + soft_reset: // LCD init @@ -749,6 +752,9 @@ soft_reset: // audio audio_init(); + // timer + timer_init(); + // add some functions to the python namespace { py_obj_t m = py_module_new(); @@ -846,7 +852,7 @@ soft_reset: usb_init(); // MMA - { + if (first_soft_reset) { // init and reset address to zero mma_init(); mma_start(MMA_ADDR, 1); @@ -1123,6 +1129,8 @@ soft_reset: pyb_sync(); printf("PYB: soft reboot\n"); + + first_soft_reset = false; goto soft_reset; } diff --git a/stm/stm32fxxx_it.c b/stm/stm32fxxx_it.c index 41e2f7b735..01be0da4af 100644 --- a/stm/stm32fxxx_it.c +++ b/stm/stm32fxxx_it.c @@ -251,4 +251,19 @@ void SDIO_IRQHandler(void) { }*/ +// TIM6 Update event +#include "stm32f4xx_tim.h" +void TIM6_DAC_IRQHandler(void) { + // work out if it's TIM6 that had the interrupt + if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET) { + extern void timer_interrupt(void); + timer_interrupt(); + TIM_ClearITPendingBit(TIM6, TIM_IT_Update); + } else { + // it seems we get 2 calls to this interrupt handler, and only 1 is the TIM_IT_Update... + // TODO work out what the other one is, and if we can disable it + //printf("unhandled TIM6_DAC\n"); + } +} + /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm/timer.c b/stm/timer.c new file mode 100644 index 0000000000..31807d0ce2 --- /dev/null +++ b/stm/timer.c @@ -0,0 +1,90 @@ +#include +#include + +#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"); + } + } +} diff --git a/stm/timer.h b/stm/timer.h new file mode 100644 index 0000000000..117cff3c97 --- /dev/null +++ b/stm/timer.h @@ -0,0 +1 @@ +void timer_init(void);