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 \
|
usart.c \
|
||||||
usb.c \
|
usb.c \
|
||||||
sdio.c \
|
sdio.c \
|
||||||
|
timer.c \
|
||||||
audio.c \
|
audio.c \
|
||||||
lexerstm.c \
|
lexerstm.c \
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,13 @@
|
||||||
|
|
||||||
#include "nlr.h"
|
#include "nlr.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
//#include "lexer.h"
|
|
||||||
//#include "lexerstm.h"
|
|
||||||
#include "mpyconfig.h"
|
#include "mpyconfig.h"
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
#include "compile.h"
|
#include "compile.h"
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
|
||||||
|
#include "audio.h"
|
||||||
|
|
||||||
#define SAMPLE_BUF_SIZE (32)
|
#define SAMPLE_BUF_SIZE (32)
|
||||||
|
|
||||||
// sample_buf_in is always the same or ahead of sample_buf_out
|
// 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 "usart.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
#include "timer.h"
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
|
|
||||||
static FATFS fatfs0;
|
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)
|
#define MMA_ADDR (0x4c)
|
||||||
|
|
||||||
py_obj_t pyb_mma_read() {
|
py_obj_t pyb_mma_read(void) {
|
||||||
mma_start(MMA_ADDR, 1);
|
mma_start(MMA_ADDR, 1);
|
||||||
mma_send_byte(0);
|
mma_send_byte(0);
|
||||||
mma_restart(MMA_ADDR, 0);
|
mma_restart(MMA_ADDR, 0);
|
||||||
|
@ -731,6 +732,8 @@ int main(void) {
|
||||||
storage_init();
|
storage_init();
|
||||||
usart_init();
|
usart_init();
|
||||||
|
|
||||||
|
int first_soft_reset = true;
|
||||||
|
|
||||||
soft_reset:
|
soft_reset:
|
||||||
|
|
||||||
// LCD init
|
// LCD init
|
||||||
|
@ -749,6 +752,9 @@ soft_reset:
|
||||||
// audio
|
// audio
|
||||||
audio_init();
|
audio_init();
|
||||||
|
|
||||||
|
// timer
|
||||||
|
timer_init();
|
||||||
|
|
||||||
// add some functions to the python namespace
|
// add some functions to the python namespace
|
||||||
{
|
{
|
||||||
py_obj_t m = py_module_new();
|
py_obj_t m = py_module_new();
|
||||||
|
@ -846,7 +852,7 @@ soft_reset:
|
||||||
usb_init();
|
usb_init();
|
||||||
|
|
||||||
// MMA
|
// MMA
|
||||||
{
|
if (first_soft_reset) {
|
||||||
// init and reset address to zero
|
// init and reset address to zero
|
||||||
mma_init();
|
mma_init();
|
||||||
mma_start(MMA_ADDR, 1);
|
mma_start(MMA_ADDR, 1);
|
||||||
|
@ -1123,6 +1129,8 @@ soft_reset:
|
||||||
pyb_sync();
|
pyb_sync();
|
||||||
|
|
||||||
printf("PYB: soft reboot\n");
|
printf("PYB: soft reboot\n");
|
||||||
|
|
||||||
|
first_soft_reset = false;
|
||||||
goto soft_reset;
|
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****/
|
/************************ (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