summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stm/Makefile1
-rw-r--r--stm/audio.c4
-rw-r--r--stm/main.c12
-rw-r--r--stm/stm32fxxx_it.c15
-rw-r--r--stm/timer.c90
-rw-r--r--stm/timer.h1
6 files changed, 119 insertions, 4 deletions
diff --git a/stm/Makefile b/stm/Makefile
index 6203e9f4a..3752e694a 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 2df4e0794..41614416e 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 996684cb8..4184b389c 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 41e2f7b73..01be0da4a 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 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");
+ }
+ }
+}
diff --git a/stm/timer.h b/stm/timer.h
new file mode 100644
index 000000000..117cff3c9
--- /dev/null
+++ b/stm/timer.h
@@ -0,0 +1 @@
+void timer_init(void);