Add to STM code timer functionality to call Python on interrupt.
This commit is contained in:
parent
f72fd0e875
commit
bd8e110207
|
@ -26,6 +26,7 @@ SRC_C = \
|
|||
usart.c \
|
||||
usb.c \
|
||||
sdio.c \
|
||||
timer.c \
|
||||
audio.c \
|
||||
lexerstm.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
|
||||
|
|
12
stm/main.c
12
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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****/
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
void timer_init(void);
|
Loading…
Reference in New Issue