blob: 062f8c689e263d46734bf503435e67efbcc73577 [file] [log] [blame]
Damienbd8e1102013-11-06 23:04:33 +00001#include <stdint.h>
2#include <stdio.h>
3
4#include "stm_misc.h"
5#include "stm32f4xx_rcc.h"
6#include "stm32f4xx_tim.h"
7
8#include "nlr.h"
9#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +000010#include "mpconfig.h"
Damienbd8e1102013-11-06 23:04:33 +000011#include "parse.h"
Damiend99b0522013-12-21 18:17:45 +000012#include "obj.h"
Damienbd8e1102013-11-06 23:04:33 +000013#include "runtime.h"
14
15#include "timer.h"
16
17// TIM6 is used as an internal interrup to schedule something at a specific rate
Damiend99b0522013-12-21 18:17:45 +000018mp_obj_t timer_py_callback;
Damienbd8e1102013-11-06 23:04:33 +000019
Damiend99b0522013-12-21 18:17:45 +000020mp_obj_t timer_py_set_callback(mp_obj_t f) {
Damienbd8e1102013-11-06 23:04:33 +000021 timer_py_callback = f;
Damiend99b0522013-12-21 18:17:45 +000022 return mp_const_none;
Damienbd8e1102013-11-06 23:04:33 +000023}
24
Damiend99b0522013-12-21 18:17:45 +000025mp_obj_t timer_py_set_period(mp_obj_t period) {
26 TIM6->ARR = mp_obj_get_int(period) & 0xffff;
27 return mp_const_none;
Damien6d42ab62013-11-09 11:29:49 +000028}
29
Damiend99b0522013-12-21 18:17:45 +000030mp_obj_t timer_py_set_prescaler(mp_obj_t prescaler) {
31 TIM6->PSC = mp_obj_get_int(prescaler) & 0xffff;
32 return mp_const_none;
Damienbd8e1102013-11-06 23:04:33 +000033}
34
Damiend99b0522013-12-21 18:17:45 +000035mp_obj_t timer_py_get_value(void) {
36 return mp_obj_new_int(TIM6->CNT & 0xfffff);
Damienbd8e1102013-11-06 23:04:33 +000037}
38
39void timer_init(void) {
Damiend99b0522013-12-21 18:17:45 +000040 timer_py_callback = mp_const_none;
Damienbd8e1102013-11-06 23:04:33 +000041
42 // TIM6 clock enable
43 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
44
Damien6d42ab62013-11-09 11:29:49 +000045 // Compute the prescaler value so TIM6 runs at 20kHz
46 uint16_t PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / 20000) - 1;
Damienbd8e1102013-11-06 23:04:33 +000047
48 // Time base configuration
49 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
Damien6d42ab62013-11-09 11:29:49 +000050 TIM_TimeBaseStructure.TIM_Period = 20000; // timer cycles at 1Hz
Damienbd8e1102013-11-06 23:04:33 +000051 TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
52 TIM_TimeBaseStructure.TIM_ClockDivision = 0; // unused for TIM6
53 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // unused for TIM6
54 TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
55
56 // enable perhipheral preload register
57 TIM_ARRPreloadConfig(TIM6, ENABLE);
58
59 // enable interrupt when counter overflows
60 TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
61
62 // set up interrupt
63 NVIC_InitTypeDef NVIC_InitStructure;
64 NVIC_InitStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
65 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0f; // lowest priority
66 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0f; // lowest priority
67 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
68 NVIC_Init(&NVIC_InitStructure);
69
70 // TIM6 enable counter
71 TIM_Cmd(TIM6, ENABLE);
72
73 // Python interface
Damien Georgeaae78472014-01-03 00:10:22 +000074 mp_obj_t m = mp_obj_new_module(qstr_from_str_static("timer"));
Damien Georgef62d33a2014-01-13 19:50:05 +000075 rt_store_attr(m, qstr_from_str_static("callback"), rt_make_function_n(1, timer_py_set_callback));
76 rt_store_attr(m, qstr_from_str_static("period"), rt_make_function_n(1, timer_py_set_period));
77 rt_store_attr(m, qstr_from_str_static("prescaler"), rt_make_function_n(1, timer_py_set_prescaler));
78 rt_store_attr(m, qstr_from_str_static("value"), rt_make_function_n(0, timer_py_get_value));
Damienbd8e1102013-11-06 23:04:33 +000079 rt_store_name(qstr_from_str_static("timer"), m);
80}
81
82void timer_interrupt(void) {
Damiend99b0522013-12-21 18:17:45 +000083 if (timer_py_callback != mp_const_none) {
Damienbd8e1102013-11-06 23:04:33 +000084 nlr_buf_t nlr;
85 if (nlr_push(&nlr) == 0) {
Damien6d42ab62013-11-09 11:29:49 +000086 // XXX what to do if the GC is in the middle of running??
Damienbd8e1102013-11-06 23:04:33 +000087 rt_call_function_0(timer_py_callback);
88 nlr_pop();
89 } else {
90 // uncaught exception
91 printf("exception in timer interrupt\n");
Paul Sokolovsky76d982e2014-01-13 19:19:16 +020092 mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
Damienbd8e1102013-11-06 23:04:33 +000093 printf("\n");
94 }
95 }
96}